diff --git a/apps/hasensors/ChangeLog b/apps/hasensors/ChangeLog index 7b3a630394..7372b1d124 100644 --- a/apps/hasensors/ChangeLog +++ b/apps/hasensors/ChangeLog @@ -1,3 +1,7 @@ 0.01: New app! 0.02: Add sensor icons Customize code directly, remove config file +0.03: Add HRM sensor + Add step count sensor + Add pressure and temperature sensors + Document Home Assistant `unique ID` workaround diff --git a/apps/hasensors/README.md b/apps/hasensors/README.md index e7f6ca98d3..069122b6cf 100644 --- a/apps/hasensors/README.md +++ b/apps/hasensors/README.md @@ -21,4 +21,30 @@ You need to fill out these fields: Currently creates these sensors: * `_battery_level`: Your watch battery level as percentage -* `_battery_state`: `charging` or `discharging` \ No newline at end of file +* `_battery_state`: `charging` or `discharging` +* `_hrm`: Heart rate (only if measured: this app doesn't enable/disable the sensor) +* `_steps`: Step Count +* `_pressure`: Pressure +* `_temperature`: Temperature + +## Home Assistant `unique ID` workaround + +If you try to customize the created entities, Home Assistant will complain that +> This entity ('sensor.…') does not have a unique ID, therefore its settings +> cannot be managed from the UI. + +The problem is that these sensors are created "dynamically", and there is no way +to supply a `unique ID`. +There is a workaround though: +1. Make note of the sensor name you want to customize (e.g. `banglejs_battery_state`). +2. Disconnect your Bangle.js from your phone, so it doesn't send updates. +3. Restart Home Assistant, the sensor is now gone. +4. Create a template sensor: choose "Template a sensor". + - Use the name from step 1 (without `sensor.` prefix). + - Set the state template to `unknown`. +5. Reconnect your Bangle.js: it will now update the new template sensor, which + *does* have a `unique ID`. + +**Warning:** Do not customize the `Entity ID`: the app sends values by sensor +ID, so you end up with both a non-updating template sensor and "dynamic" sensor +without `unique ID`. diff --git a/apps/hasensors/boot.js b/apps/hasensors/boot.js index efafbc8a32..feb7d246c8 100644 --- a/apps/hasensors/boot.js +++ b/apps/hasensors/boot.js @@ -1,6 +1,8 @@ (function () { - const sb = () => require("hasensors").sendBattery(); - Bangle.on("charging", sb); - NRF.on("connect", () => setTimeout(sb, 2000)); - setInterval(sb, 10 * 60 * 1000); -})(); \ No newline at end of file + const su = () => require("hasensors").sendUpdate(); + Bangle.on("charging", su); + NRF.on("connect", () => setTimeout(su, 2000)); + su(); + setInterval(su, 10 * 60 * 1000); + Bangle.on('HRM', h=>require("hasensors").sendHRM(h)); +})(); diff --git a/apps/hasensors/lib.js b/apps/hasensors/lib.js index 83072262c3..5a0cf0cab3 100644 --- a/apps/hasensors/lib.js +++ b/apps/hasensors/lib.js @@ -12,9 +12,8 @@ function post(sensor, data) { }); } -exports.sendBattery = function () { - if (!NRF.getSecurityStatus().connected) return; - const b = E.getBattery(), +function sendBattery() { + const b = E.getBattery(), c = Bangle.isCharging(); let i = "mdi:battery"; if (c) i += "-charging"; @@ -40,4 +39,75 @@ exports.sendBattery = function () { icon: i, } }); -} \ No newline at end of file +} + +function sendSteps() { + post("steps", { + state: Bangle.getStepCount(), + attributes: { + friendly_name: "{name} Step Count", + unit_of_measurement: "steps", + state_class: "total", + icon: "mdi:shoe-print", + } + }); +} + +/** + * Sends pressure *and temperature* + */ +function sendPressure() { + if (!Bangle.getPressure) return; // not a Bangle 2 + const promise = Bangle.getPressure(); + if (!promise) return; // emulator? + promise.then(values=>{ + post("pressure", { + state: Math.round(values.pressure*10)/10, + attributes: { + friendly_name: "{name} Pressure", + unit_of_measurement: "hPa", + device_class: "atmospheric pressure", + state_class: "measurement", + icon: "mdi:gauge", + } + }); + post("temperature", { + state: Math.round(values.temperature*10)/10, + attributes: { + friendly_name: "{name} Temperature", + unit_of_measurement: "°C", + device_class: "temperature", + state_class: "measurement", + icon: "mdi:thermometer", + } + }); + }); +} + +exports.sendUpdate = function() { + if (!NRF.getSecurityStatus().connected) return; + sendBattery(); + sendSteps(); + sendPressure(); +} + + +let hrm_last = 0; +const HRM_INTERVAL = 10*60*1000; +exports.sendHRM = function (hrm) { + if (!NRF.getSecurityStatus().connected) return; + const now = (new Date).getTime(); + if (hrm_last > now-HRM_INTERVAL) return; + post("hrm", { + state: hrm.bpm, + attributes: { + confidence: hrm.confidence, + raw: hrm.raw, + friendly_name: "{name} Heart Rate", + icon: "mdi:heart", + unit_of_measurement: "bpm", + state_class: "measurement", + } + }); + hrm_last = now; +}; diff --git a/apps/hasensors/metadata.json b/apps/hasensors/metadata.json index 5764c61005..550095c765 100644 --- a/apps/hasensors/metadata.json +++ b/apps/hasensors/metadata.json @@ -2,7 +2,7 @@ "id": "hasensors", "name": "Home Assistant Sensors", "shortName": "HA sensors", - "version": "0.02", + "version": "0.03", "description": "Send sensor values to Home Assistant using Android Integration/Gadgetbridge", "icon": "ha.png", "type": "bootloader",