Skip to content
Snippets Groups Projects
Commit 411e6a94 authored by Marie Desk's avatar Marie Desk
Browse files

add #define thresholds and change gettime

parent d2c512c9
No related branches found
No related tags found
1 merge request!4My gates ble
...@@ -12,248 +12,235 @@ ...@@ -12,248 +12,235 @@
#define RELAY1 32 #define RELAY1 32
#define NAVETTE_UUID "DEADDEAD-F88F-0042-F88F-010203040506" // same UUID for all vehicles #define NAVETTE_UUID "DEADDEAD-F88F-0042-F88F-010203040506" // same UUID for all vehicles
#define FORCEGATEOPEN 0b01 // minor high bits = 0b01 => force gate to open #define FORCEGATEOPEN 0b01 // minor high bits = 0b01 => force gate to open
#define CLEARGATECALIBRATION 0b11 // minor high bits = 0b11 => clear gate calibration #define CLEARGATECALIBRATION 0b11 // minor high bits = 0b11 => clear gate calibration
#define SCAN_TIME 20 // scan period in second
#define STATE_SCAN 1 #define STATE_SCAN 1 // STATE_SCAN : scanning iBeacon tram with UUID = NAVETTE_UUID. Opening door when the RSSI is high enough. Go to STATE_OPEN_GATE after opening the door.
#define STATE_OPEN_GATE 2 #define STATE_OPEN_GATE 2 // STATE_OPEN_GATE : door is open. Keep the door open while receiving tram. Go to STATE_SCAN when not receiving tram after GO_TO_SCAN_STATE_DELAY
#define RSSI_THRESHOLD_OPEN_GATE -95 #define SCAN_TIME 2 // scan period in second
#define GO_TO_SCAN_STATE_DELAY 4 // if no trame was received during 4 sec, go to STATE_SCAN
#define DELAY_REJECT_TRAM 3 // if the last tram was received more than 3 seconds ago, the average RSSI is not computed and returns an average RSSI of -100
#define RSSI_THRESHOLD_OPEN_GATE -95 // if the average RSSI is above this threshold the gate can be open
// ***** definitions ***** // ***** definitions *****
int STATE; int STATE; // state of the system : can be either STATE_SCAN or STATE_OPEN_GATE
time_t t; // time is seconds
struct RSSI { // table contening the RSSI and time of the last 2 trams. Used to compute the average RSSI.
int val = -100;
time_t time = 0;
} tabRSSI[2];
class IBeaconAdvertised : public BLEAdvertisedDeviceCallbacks {
public:
// BLE
void onResult(BLEAdvertisedDevice device) {
// check if iBeacon tram
if (!isIBeacon(device)) {
return;
}
struct RSSI { // check for NAVETTE_UUID
int val; if (!isNavetteUUID(device)) {
int time; return;
}; }
RSSI tabRSSI[2];
struct timeval tv; // received a trame FORCE GATE OPEN
time_t t; if (HIGH2BITS_U16(getMinor(device)) == FORCEGATEOPEN) {
printIBeacon(device); // DEBUG
Serial.printf(" - force open tram\n"); // DEBUG
openGate();
updateRSSItab(getRSSI(device));
return;
}
class IBeaconAdvertised: public BLEAdvertisedDeviceCallbacks { //check gate state (STATE_SCAN or STATE_OPEN_GATE)
public: switch (STATE) {
// BLE case STATE_OPEN_GATE:
void onResult(BLEAdvertisedDevice device) { // gate is already open, nothing to do
// check if iBeacon tram printIBeacon(device); // DEBUG
if (!isIBeacon(device)) { Serial.printf(" - gate is already open\n"); // DEBUG
return; updateRSSItab(getRSSI(device)); // save RSSI in the table
} STATE = STATE_OPEN_GATE;
break;
// check for NAVETTE_UUID
if (!isNavetteUUID(device)){ case STATE_SCAN:
return; default:
} //check if gate needs to be open
RSSI newRSSI = getRSSI(device); // get RSSI
// received a trame FORCE GATE OPEN int avRSSI = averageRSSI(newRSSI); // compute average RSSI (with 3 last values)
if (HIGH2BITS_U16(getMinor(device))==FORCEGATEOPEN){ if (avRSSI > RSSI_THRESHOLD_OPEN_GATE) { // if the received signal power is above the threshold RSSI_THRESHOLD_OPEN_GATE
printIBeacon(device); // DEBUG printIBeacon(device); // DEBUG
Serial.printf(" - force open tram\n"); // DEBUG Serial.printf(" - RSSI average OK:%d\n", avRSSI); // DEBUG
openGate(); openGate(); // open the gate
updateRSSItab(getRSSI(device)); updateRSSItab(newRSSI); // save received tram RSSI in the table
return; STATE = STATE_OPEN_GATE; // change state and go to state STATE_OPEN_GATE
} } else {
printIBeacon(device); // DEBUG
//check gate state (STATE_SCAN or STATE_OPEN_GATE) Serial.printf(" - RSSI average too low:%d\n", avRSSI); // DEBUG
switch(STATE) { updateRSSItab(newRSSI);
STATE = STATE_SCAN;
case STATE_OPEN_GATE :
// nothing to do
printIBeacon(device); // DEBUG
Serial.printf(" - gate is open\n"); // DEBUG
updateRSSItab(getRSSI(device)); // TODO : to delete to reopen gate after 4 sec ?
STATE = STATE_OPEN_GATE;
break;
case STATE_SCAN :
default:
RSSI newRSSI = getRSSI(device);
int avRSSI = averageRSSI(newRSSI);
if(avRSSI > RSSI_THRESHOLD_OPEN_GATE) {
printIBeacon(device); // DEBUG
Serial.printf(" - RSSI average OK:%d\n",avRSSI); // DEBUG
openGate();
updateRSSItab(newRSSI);
STATE = STATE_OPEN_GATE;
}
else {
printIBeacon(device); // DEBUG
Serial.printf(" - RSSI average too low:%d\n",avRSSI); // DEBUG
updateRSSItab(newRSSI);
}
break;
} }
break;
} }
}
private: private:
// ***** compute average RSSI *****
int averageRSSI(RSSI newRSSI){
if ((newRSSI.time - tabRSSI[0].time) >3){ // if last trame was detected more than 3 sec ago, return an average RSSI of -100 // TODO compare epochtime insted
updateRSSItab(newRSSI);
return -100;
}
else{
int averageRSSI = (newRSSI.val + tabRSSI[0].val + tabRSSI[1].val) /3;
updateRSSItab(newRSSI);
return averageRSSI;
}
}
// ***** update RSSI table ***** // ***** open gate *****
void updateRSSItab (RSSI newRSSI){ void openGate() {
tabRSSI[1]=tabRSSI[0]; Serial.println(" OPENING GATE"); //DEBUG
tabRSSI[0]= newRSSI; digitalWrite(RELAY1, HIGH); //activate relay1 for 1 second
delay(1000);
digitalWrite(RELAY1, LOW);
}
// ***** is frame iBeacon ? *****
bool isIBeacon(BLEAdvertisedDevice device) {
if (device.getManufacturerData().length() < 25) {
return false;
}
if (getCompanyId(device) != 0x004C) {
return false;
} }
if (getIBeaconHeader(device) != 0x1502) {
// ***** open gate ***** return false;
void openGate() {
Serial.println(" OPENING GATE");
digitalWrite (RELAY1, HIGH);
delay (1000);
digitalWrite (RELAY1, LOW);
} }
return true;
// ***** is frame iBeacon ? ***** }
bool isIBeacon(BLEAdvertisedDevice device) {
if (device.getManufacturerData().length() < 25) { // ***** is UUID_NAVETTE ? *****
return false; bool isNavetteUUID(BLEAdvertisedDevice device) { // check if iBeacon tram UUID = NAVETTE_UUID
} if (getProxyUuid(device).equals(BLEUUID(NAVETTE_UUID))) {
if (getCompanyId(device) != 0x004C) {
return false;
}
if (getIBeaconHeader(device) != 0x1502) {
return false;
}
return true; return true;
} else {
return false;
} }
}
// ***** RSSI *****
RSSI getRSSI(BLEAdvertisedDevice device) { // get signal RSSI and reception time
RSSI newRSSI;
time(&t);
newRSSI.val = device.getRSSI();
newRSSI.time = t;
return newRSSI;
}
// ***** update RSSI table *****
void updateRSSItab(RSSI newRSSI) { // save RSSI and time in the table tabRSSI
tabRSSI[1] = tabRSSI[0];
tabRSSI[0] = newRSSI;
}
// ***** is UUID_NAVETTE ? ***** // ***** compute average RSSI *****
bool isNavetteUUID(BLEAdvertisedDevice device) { int averageRSSI(RSSI newRSSI) {
if( getProxyUuid(device).equals(BLEUUID(NAVETTE_UUID))){ if ((newRSSI.time - tabRSSI[0].time) > DELAY_REJECT_TRAM) { // if last trame was detected more than x sec ago, return an average RSSI of -100
return true; updateRSSItab(newRSSI);
} return -100;
else { } else {
return false; int averageRSSI = (newRSSI.val + tabRSSI[0].val + tabRSSI[1].val) / 3; // compute the average RSSI using the last 3 RSSI values
} updateRSSItab(newRSSI);
return averageRSSI;
} }
}
// ***** RSSI *****
RSSI getRSSI(BLEAdvertisedDevice device){ // ***** companyId *****
RSSI newRSSI; unsigned short getCompanyId(BLEAdvertisedDevice device) {
gettimeofday(&tv, NULL); // TODO : save epoch time insted const unsigned short *pCompanyId = (const unsigned short *)&device
newRSSI.val = device.getRSSI();
newRSSI.time = tv.tv_sec;
return newRSSI;
}
// ***** companyId *****
unsigned short getCompanyId(BLEAdvertisedDevice device) {
const unsigned short* pCompanyId = (const unsigned short*)&device
.getManufacturerData() .getManufacturerData()
.c_str()[0]; .c_str()[0];
return *pCompanyId; return *pCompanyId;
} }
// ***** iBeacon Header ***** // ***** iBeacon Header *****
unsigned short getIBeaconHeader(BLEAdvertisedDevice device) { unsigned short getIBeaconHeader(BLEAdvertisedDevice device) {
const unsigned short* pHeader = (const unsigned short*)&device const unsigned short *pHeader = (const unsigned short *)&device
.getManufacturerData() .getManufacturerData()
.c_str()[2]; .c_str()[2];
return *pHeader; return *pHeader;
} }
// ***** iBEACON UUID ***** // ***** iBEACON UUID *****
BLEUUID getProxyUuid(BLEAdvertisedDevice device) { BLEUUID getProxyUuid(BLEAdvertisedDevice device) {
BLEUUID uuid; BLEUUID uuid;
std::string strManufacturerData = device.getManufacturerData(); std::string strManufacturerData = device.getManufacturerData();
uint8_t cManufacturerData[100]; uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
BLEBeacon oBeacon = BLEBeacon(); BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData); oBeacon.setData(strManufacturerData);
uuid = oBeacon.getProximityUUID(); uuid = oBeacon.getProximityUUID();
return uuid; return uuid;
} }
// ***** iBEACON Major ***** // ***** iBEACON Major *****
uint16_t getMajor(BLEAdvertisedDevice device) { uint16_t getMajor(BLEAdvertisedDevice device) {
std::string strManufacturerData = device.getManufacturerData(); std::string strManufacturerData = device.getManufacturerData();
uint8_t cManufacturerData[100]; uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
BLEBeacon oBeacon = BLEBeacon(); BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData); oBeacon.setData(strManufacturerData);
return ENDIAN_CHANGE_U16(oBeacon.getMajor()); return ENDIAN_CHANGE_U16(oBeacon.getMajor());
} }
// ***** iBEACON Minor ***** // ***** iBEACON Minor *****
uint16_t getMinor(BLEAdvertisedDevice device) { uint16_t getMinor(BLEAdvertisedDevice device) {
std::string strManufacturerData = device.getManufacturerData(); std::string strManufacturerData = device.getManufacturerData();
uint8_t cManufacturerData[100]; uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
BLEBeacon oBeacon = BLEBeacon(); BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData); oBeacon.setData(strManufacturerData);
return ENDIAN_CHANGE_U16(oBeacon.getMinor()); return ENDIAN_CHANGE_U16(oBeacon.getMinor());
} }
// ***** iBEACON TxPower ***** // ***** iBEACON TxPower *****
int8_t getTxPower(BLEAdvertisedDevice device) { int8_t getTxPower(BLEAdvertisedDevice device) {
std::string strManufacturerData = device.getManufacturerData(); std::string strManufacturerData = device.getManufacturerData();
uint8_t cManufacturerData[100]; uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
BLEBeacon oBeacon = BLEBeacon(); BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData); oBeacon.setData(strManufacturerData);
return oBeacon.getSignalPower(); return oBeacon.getSignalPower();
} }
// ***** print iBeacon device info ***** // ***** print iBeacon device info *****
void printIBeacon(BLEAdvertisedDevice device) { void printIBeacon(BLEAdvertisedDevice device) {
gettimeofday(&tv, NULL); time(&t);
Serial.printf("time:%d name:%s uuid:%s major:%d minor:%d rssi:%d\r", Serial.printf("time:%d name:%s uuid:%s major:%d minor:%d rssi:%d\r",
(tv.tv_sec), t,
device.getName().c_str(), device.getName().c_str(),
getProxyUuid(device).toString().c_str(), getProxyUuid(device).toString().c_str(),
getMajor(device), getMajor(device),
getMinor(device), getMinor(device),
device.getRSSI() device.getRSSI());
); }
}
}; };
void setup() { void setup() {
//init serial port
Serial.begin(115200); Serial.begin(115200);
//init relay module
pinMode (RELAY1, OUTPUT); pinMode(RELAY1, OUTPUT);
//init state //init state
STATE = STATE_SCAN; STATE = STATE_SCAN;
//init BLE
//init tabRSSI
tabRSSI[0].val = -100;
tabRSSI[1].val = -100;
tabRSSI[0].time = 0;
tabRSSI[1].time = 0;
BLEDevice::init(""); BLEDevice::init("");
} }
void loop() { void loop() {
if(STATE == STATE_OPEN_GATE){ if (STATE == STATE_OPEN_GATE) { // if in STATE_OPEN_GATE (gate is already open)
gettimeofday(&tv, NULL); // TODO : save epoch time insted time(&t); // get time
if((tv.tv_sec - tabRSSI[0].time)>4){ //TODO define time variable if ((t - tabRSSI[0].time) > GO_TO_SCAN_STATE_DELAY) { // if last tram was received more than x seconds ago (GO_TO_SCAN_STATE_DELAY)
STATE = STATE_SCAN; STATE = STATE_SCAN; // change state : go to STATE_SCAN
Serial.printf("time:%d START SCANNING\n", tv.tv_sec); Serial.printf("time:%d GO TO STATE_SCAN, last tram received at t:%d\n", t, tabRSSI[0].time); // DEBUG
} }
} }
BLEScan* scan = BLEDevice::getScan(); BLEScan *scan = BLEDevice::getScan(); // start scanning
scan->setAdvertisedDeviceCallbacks(new IBeaconAdvertised(), true); scan->setAdvertisedDeviceCallbacks(new IBeaconAdvertised(), true);
scan->setActiveScan(true); scan->setActiveScan(true);
scan->start(SCAN_TIME); scan->start(SCAN_TIME);
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment