diff --git a/docs/img/KBeacon-app-configuration-moving.jpg b/docs/img/KBeacon-app-configuration-moving.jpg new file mode 100644 index 0000000..8343c47 Binary files /dev/null and b/docs/img/KBeacon-app-configuration-moving.jpg differ diff --git a/docs/img/KBeacon-app-configuration-moving2.jpg b/docs/img/KBeacon-app-configuration-moving2.jpg new file mode 100644 index 0000000..e6da91d Binary files /dev/null and b/docs/img/KBeacon-app-configuration-moving2.jpg differ diff --git a/docs/prerequisites/devices.md b/docs/prerequisites/devices.md index 343111e..2b69025 100644 --- a/docs/prerequisites/devices.md +++ b/docs/prerequisites/devices.md @@ -25,6 +25,8 @@ Added to that it retrieves the measures from the devices below. By default the d | BLE watches with fixed MAC||rssi for presence detection| | BLE beacons keychains||rssi for presence detection| | BlueCharm|BC08|acceleration x/y/z-axis/voltage/temperature| +| BlueCharm|BC04P|acceleration x/y/z-axis/voltage/temperature| +| BlueCharm|BC021|acceleration x/y/z-axis/voltage/temperature| | BlueMaestro|TempoDisc 1 in 1|temperature/battery| | BlueMaestro|TempoDisc 3 in 1|temperature/humidity/dew point/battery| | BlueMaestro|TempoDisc 4 in 1|temperature/humidity/pressure/battery| diff --git a/docs/use/ble.md b/docs/use/ble.md index e463e89..98fb4a0 100644 --- a/docs/use/ble.md +++ b/docs/use/ble.md @@ -52,6 +52,23 @@ Note that you can find apps to simulate beacons and do some tests like [Beacon s iOS version >=10 devices advertise without an extra app MAC address, nevertheless this address [changes randomly](https://github.com/1technophile/OpenMQTTGateway/issues/71) and cannot be used for presence detection. You must install an app to advertise a fixed MAC address. +## Receiving signals from BLE devices with accelerometers for movement detection +The gateway is designed to detect BLE trackers from BlueCharm and automatically create a binary sensor entity in accordance with the Home Assistant discovery convention, provided that auto discovery is enabled. + +The binary sensor entity's state will be set to on or off based on whether the BLE beacon's x-axis acceleration value is detected during the time period defined by the movingtimer parameter. + +By default, the movingtimer parameter is set to 60 seconds (60,000 ms). To modify this value, use the following command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"movingtimer":66000}'` + +To ensure proper functionality, configure the beacon using the KBeacon or KBeaconPro app (depending on your specific sensor) with the following settings: +* In the General tab, set the Trigger Command to "motion". +* In the Slot tab, enable advertisement with the Beacon Type set to "KSensor", the Trigger Only Advertisement option set to "YES", and the Sensor Axis set to "ON". + +![](../img/KBeacon-app-configuration-moving.jpg) + +![](../img/KBeacon-app-configuration-moving2.jpg) + ## Setting a white or black list A black list is a list of MAC addresses that will never be published by OMG to set black list diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index c3b2f32..8d21e32 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -104,6 +104,7 @@ void BTConfig_init() { BTConfig.pubBeaconUuidForTopic = useBeaconUuidForTopic; BTConfig.ignoreWBlist = false; BTConfig.presenceAwayTimer = PresenceAwayTimer; + BTConfig.movingTimer = MovingTimer; } // Watchdog, if there was no change of BLE scanCount, restart BT @@ -149,6 +150,7 @@ String stateBTMeasures(bool start) { jo["pubBeaconUuidForTopic"] = BTConfig.pubBeaconUuidForTopic; jo["ignoreWBlist"] = BTConfig.ignoreWBlist; jo["presenceawaytimer"] = BTConfig.presenceAwayTimer; + jo["movingtimer"] = BTConfig.movingTimer; jo["btqblck"] = btQueueBlocked; jo["btqsum"] = btQueueLengthSum; jo["btqsnd"] = btQueueLengthCount; @@ -227,6 +229,8 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { Config_update(BTdata, "presenceUseBeaconUuid", BTConfig.presenceUseBeaconUuid); // Timer to trigger a device state as offline if not seen Config_update(BTdata, "presenceawaytimer", BTConfig.presenceAwayTimer); + // Timer to trigger a device state as offline if not seen + Config_update(BTdata, "movingtimer", BTConfig.movingTimer); // MinRSSI set Config_update(BTdata, "minrssi", BTConfig.minRssi); // Send undecoded device data @@ -277,6 +281,7 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { jo["pubBeaconUuidForTopic"] = BTConfig.pubBeaconUuidForTopic; jo["ignoreWBlist"] = BTConfig.ignoreWBlist; jo["presenceawaytimer"] = BTConfig.presenceAwayTimer; + jo["movingtimer"] = BTConfig.movingTimer; // Save config into NVS (non-volatile storage) String conf = ""; serializeJson(jsonBuffer, conf); @@ -490,14 +495,15 @@ void updateDevicesStatus() { for (vector::iterator it = devices.begin(); it != devices.end(); ++it) { BLEdevice* p = *it; unsigned long now = millis(); - if (p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::NUT || - p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::MIBAND || - p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::TAGIT || - p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::TILE || - p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::TILEN || - p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::ITAG || - p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::RUUVITAG_RAWV1 || - p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::RUUVITAG_RAWV2) { // We apply the offline status only for tracking device, can be extended further to all the devices + // Device tracker devices + if (BTConfig.presenceEnable && (p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::NUT || + p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::MIBAND || + p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::TAGIT || + p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::TILE || + p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::TILEN || + p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::ITAG || + p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::RUUVITAG_RAWV1 || + p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::RUUVITAG_RAWV2)) { // We apply the offline status only for tracking device, can be extended further to all the devices if ((p->lastUpdate != 0) && (p->lastUpdate < (now - BTConfig.presenceAwayTimer) && (now > BTConfig.presenceAwayTimer)) && (BTConfig.ignoreWBlist || ((!oneWhite || isWhite(p)) && !isBlack(p)))) { // Only if WBlist is disabled OR ((no white MAC OR this MAC is white) AND not a black listed MAC)) { JsonObject BLEdata = getBTJsonObject(); @@ -508,6 +514,18 @@ void updateDevicesStatus() { p->lastUpdate = 0; } } + // Moving detection devices (devices with an accelerometer) + if (p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::BC08) { + if ((p->lastUpdate != 0) && (p->lastUpdate < (now - BTConfig.movingTimer) && (now > BTConfig.movingTimer)) && + (BTConfig.ignoreWBlist || ((!oneWhite || isWhite(p)) && !isBlack(p)))) { // Only if WBlist is disabled OR ((no white MAC OR this MAC is white) AND not a black listed MAC)) { + JsonObject BLEdata = getBTJsonObject(); + BLEdata["id"] = p->macAdr; + BLEdata["state"] = "offline"; + pubBT(BLEdata); + // We set the lastUpdate to 0 to avoid replublishing the offline state + p->lastUpdate = 0; + } + } } } @@ -722,8 +740,7 @@ void procBLETask(void* pvParameters) { } else { Log.trace(F("Filtered MAC device" CR)); } - if (BTConfig.presenceEnable) - updateDevicesStatus(); + updateDevicesStatus(); } delete (advertisedDevice); } @@ -977,6 +994,7 @@ void setupBT() { Log.notice(F("minrssi: %d" CR), -abs(BTConfig.minRssi)); Log.notice(F("Low Power Mode: %d" CR), lowpowermode); Log.notice(F("Presence Away Timer: %d" CR), BTConfig.presenceAwayTimer); + Log.notice(F("Moving Timer: %d" CR), BTConfig.movingTimer); atomic_init(&forceBTScan, 0); // in theory, we don't need this atomic_init(&jsonBTBufferQueueNext, 0); // in theory, we don't need this @@ -1057,6 +1075,17 @@ void launchBTDiscovery(bool overrideDiscovery) { model.c_str(), brand.c_str(), model_id.c_str(), macWOdots.c_str(), false, stateClassNone); } + if (p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::BC08) { + String sensor_name = String(model_id.c_str()) + "-moving"; + String sensor_id = macWOdots + "-moving"; + createDiscovery("binary_sensor", + discovery_topic.c_str(), sensor_name.c_str(), sensor_id.c_str(), + will_Topic, "moving", "{% if value_json.get('accx') -%}on{%- else -%}off{%- endif %}", + "on", "off", "", + 0, "", "", false, "", + model.c_str(), brand.c_str(), model_id.c_str(), macWOdots.c_str(), false, + stateClassNone); + } if (!properties.empty()) { StaticJsonDocument jsonBuffer; deserializeJson(jsonBuffer, properties); diff --git a/main/config_BT.h b/main/config_BT.h index 112a7f5..45dc5c4 100644 --- a/main/config_BT.h +++ b/main/config_BT.h @@ -94,7 +94,10 @@ extern int btQueueLengthCount; # define TimeBtwConnect 3600000 //define default time between BLE connection attempt (not used for immediate actions); in milliseconds #endif #ifndef PresenceAwayTimer -# define PresenceAwayTimer 120000 //define the time between Offline Status update for the sensors +# define PresenceAwayTimer 120000 //define the time between Offline Status update for the tracker sensors +#endif +#ifndef MovingTimer +# define MovingTimer 60000 //define the time between Offline Status update for the moving sensors with an accelerometer #endif #ifndef BLEScanDuplicateCacheSize @@ -168,6 +171,7 @@ struct BTConfig_s { bool pubBeaconUuidForTopic; // Use iBeacon UUID as topic, instead of sender (random) MAC address bool ignoreWBlist; // Disable Whitelist & Blacklist unsigned long presenceAwayTimer; //Timer that trigger a tracker state as offline if not seen + unsigned long movingTimer; //Timer that trigger a moving sensor state as offline if not seen }; // Global struct to store live BT configuration data