Thanks Scruff. I followed your suggestion. Im using both Argon and Xenon in “beacon modes” 2 functions for BLE advertising and scanning on Argon and four Xenons. Advertise packets between them are little maybe 1-10 packets a day.
The Argon Scans for the BLE i-beacons and works very well. Im also able to send “trigger relay command” from the Argon to the 4 Xenons if I get message from the i beacon. But sending the batt voltage from Xenons to the Argon is not so reliable.
- I cant listen and transmit at the same time on my Xenons.
- I dont think the “beaconing” setup on my Argon and Xenon is the best method for two way communication. it becomes a timing and timeout problem.
- Would it be better to let the argon connect to each xenon and exchange information (receive battery info and send relay status) in one go? is it possible?
For completeness: my beaconing code below
functions on the Argon to scan both BLE i-beacons and scan for the voltage advertisement from the Xenons
void scanBleBeacons(){
BLE.setScanTimeout(100); //
int count = BLE.scan(scanResults, SCAN_RESULT_MAX);
for (int ii = 0; ii < count; ii++) {
size_t len = scanResults[ii].advertisingData.get(buf, BLE_MAX_ADV_DATA_LEN);//used to get an entire block of 31 bytes
String Beacon_name = results[ii].advertisingData.deviceName();//check if the results have an name
memcpy(buf_copy, buf, sizeof(buf));//make a copy
//build a string out of the MAC char array so we can compare incoming to what is saved in the EEPROM
sprintf (emMacCharToString, "em_MAC_%02x:%02x:%02x:%02x:%02x:%02x",
scanResults[ii].address[5],scanResults[ii].address[4],scanResults[ii].address[3],
scanResults[ii].address[2],scanResults[ii].address[1],scanResults[ii].address[0]);
//make sure its a eddystone TLM beacon so we can extract batt voltages from the beacons
if((buf_copy[11] == 0x20)&&(buf_copy[12] == 0x00)&&(buf_copy[15] == 0x80)&&(buf_copy[16] == 0x00)){
saveVoltage = (buf_copy[13]<<8)|(buf_copy[14]) ;//It is a TLM beacon so ectract the voltage
ExtractBattVoltage();// do something with the voltage that was extracted i.e post to ubidots
}
//We also need to check for Xenon battery voltages.
//check if its a xenon and copy the voltage
if ((buf_copy[5] == 0x19)&&(buf_copy[6] == 0x74)&&(buf_copy[7] == 0x03)&&(buf_copy[8] == 0x29)){
//copy and build the MAC with voltage to post to ubidots
sprintf (xenonMacOne, "xenon_MAC_%02x:%02x:%02x:%02x:%02x:%02x\0",scanResults[ii].address[5], scanResults[ii].address[4], scanResults[ii].address[3],
scanResults[ii].address[2], scanResults[ii].address[1], scanResults[ii].address[0]);
float xenonVoltage;
memcpy(&xenonVoltage, &buf[9], 4);//copy the voltage values out of the buffer
ubidots.add(xenonMacOne, xenonVoltage);//build context for ubidots
PostToUbidot();
}
}//end of for
}// end of scanBleBeacons
Code that transmit the relay on to all the xenons (beacon mode)
//sends the relay message to turn relay on on all Xenons listening
void updateAdvertisingData(bool updateOnly)
{
uint8_t buf[BLE_MAX_ADV_DATA_LEN];
size_t offset = 0;
memcpy(&buf[offset], &gatewayDetonationCommand,
strlen(gatewayDetonationCommand));
offset += strlen(gatewayDetonationCommand);
BleAdvertisingData advData;
advData.appendCustomData(buf, offset);
// Continuously advertise untill time out occurs, specified in setup
BLE.advertise(&advData);
}
On my Xenons I have similar two functions one for receiving the relay command and one for sending the battery voltage however I cant run both these function at the same time (cant listen and speak) need to turn one off.
void scanBleGateway(){
BLE.setScanTimeout(100); //
int count = BLE.scan(scanResults, SCAN_RESULT_MAX);
for (int ii = 0; ii < count; ii++) {
size_t len = scanResults[ii].advertisingData.get(buf, BLE_MAX_ADV_DATA_LEN);//used to get an entire block of 31 bytes
memcpy(gatewayMessage,(void*)&buf[5], 20);//copy only the message sent from the gateway
//convert to string the incoming message from Argon
sprintf (gatewayMessageCharToString, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
gatewayMessage[0], gatewayMessage[1], gatewayMessage[2], gatewayMessage[3], gatewayMessage[4], gatewayMessage[5], gatewayMessage[6], gatewayMessage[7], gatewayMessage[8], gatewayMessage[9], gatewayMessage[10],
gatewayMessage[11], gatewayMessage[12], gatewayMessage[13],gatewayMessage[14], gatewayMessage[15], gatewayMessage[16], gatewayMessage[17], gatewayMessage[18], gatewayMessage[19], gatewayMessage[20]);
/*compare incoming string to const char string in setup, if the same the trigger relay*/
if (!strcmp (BeaconVibrationDetected,gatewayMessageCharToString)){
triggerRelay(); /*triggerRelay*/
}
}
}
//transmit the Xenon battery voltage 2 or 3 times a day to Argon for upload to ubidots
void timerTransmitBattVoltage(void){
battVoltage = analogRead(BATT) * 0.0011224 / 3.7 * 100; /// in percentage
uint8_t buf[BLE_MAX_ADV_DATA_LEN];
size_t offset = 0;
//Copy the battery voltage as well as Custom identifier (19740329) into the buffer for Argon to extract
buf[offset++] = 0x19;
buf[offset++] = 0x74;
buf[offset++] = 0x03;
buf[offset++] = 0x29;
memcpy(&buf[offset], &battVoltage, 5);
offset += 5;
BleAdvertisingData advData;
advData.appendCustomData(buf, offset);
// Continuously advertise till time out occurs as setup in setup function
BLE.advertise(&advData);
}
Im not to familiar with the BLE connectable protocall using characteristics and services but would this be a better solution?
thanks again