mirror of https://github.com/espruino/BangleApps
New app: hasensors: Home Assistant Sensors
Creates battery level+state sensors in Home Assistant over HTTPpull/2574/head
parent
716af7c18b
commit
f38518fb63
|
@ -0,0 +1 @@
|
||||||
|
0.01: New app!
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Home Assistant Sensors
|
||||||
|
|
||||||
|
Sends sensor values to [Home Assistant](https://www.home-assistant.io/) using
|
||||||
|
the [Android Integration](/?id=android).
|
||||||
|
It doesn't use the Home Assistant app on your phone, but posts directly to
|
||||||
|
Home Assistant, so it only works if Home Assistant can be reached from your phone.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
You need to fill out these fields:
|
||||||
|
|
||||||
|
* *Sensor ID*: This is prefixed to sensor IDs in Home Assistant.
|
||||||
|
If you set this to `banglejs`, the battery sensor will be named `sensor.banglejs_battery_level`.
|
||||||
|
* *Sensor Name*: This is prefixed to human-friendly sensor names.
|
||||||
|
If you set this to `Bangle.js`, the battery sensor will show as `Bangle.js Battery Level`.
|
||||||
|
* *Home Assistant URL*: The URL of your Home Assistant Installation.
|
||||||
|
* *Authentication Token*: You need to generate a Long-Lived Access Token in
|
||||||
|
Home Assistant, at the bottom of [your profile page](https://my.home-assistant.io/redirect/profile/).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Currently creates these sensors:
|
||||||
|
* `<sensor id>_battery_level`: Your watch battery level as percentage
|
||||||
|
* `<sensor id>_battery_state`: `charging` or `discharging`
|
|
@ -0,0 +1,6 @@
|
||||||
|
(function () {
|
||||||
|
const sb = () => require('hasensors').sendBattery();
|
||||||
|
Bangle.on("charging", sb);
|
||||||
|
NRF.on("connect", () => setTimeout(sb, 2000));
|
||||||
|
setInterval(sb, 10 * 60 * 1000);
|
||||||
|
})();
|
|
@ -0,0 +1,89 @@
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||||
|
<title>Home Assistant Sensors configuration</title>
|
||||||
|
<style>
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
label span:first-child {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 20ex;
|
||||||
|
}
|
||||||
|
label span.explanation {
|
||||||
|
display: block;
|
||||||
|
margin-left: 21ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:invalid {
|
||||||
|
outline: 1px solid red;
|
||||||
|
background: lightcoral;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form id="sensorform">
|
||||||
|
<label><span>Sensor ID:</span>
|
||||||
|
<input name="id" size="10" value="banglejs" required pattern="[_a-z0-9]+">
|
||||||
|
<span class="explanation">Lowercase letters, numbers or underscores.</span></label>
|
||||||
|
<label><span>Sensor Name:</span>
|
||||||
|
<input name="name" size="10" value="Bangle.js" required>
|
||||||
|
<span class="explanation">Human-friendly sensor name.</span></label>
|
||||||
|
<label><span>Home Assistant URL:</span>
|
||||||
|
<input name="url" type="url" placeholder="http://home_assistant_url:8123" required>
|
||||||
|
<span class="explanation">Needs to be reachable by your phone.</span></label>
|
||||||
|
<label><span>Authentication Token:</span>
|
||||||
|
<input name="token" required pattern="[\-_\.0-9a-zA-Z]+">
|
||||||
|
<span class="explanation">Create a long-lived access token in Home Assistant at the bottom of
|
||||||
|
<a href="https://my.home-assistant.io/redirect/profile/" target="_blank">your user profile</a>.</span></label>
|
||||||
|
</form>
|
||||||
|
<p>
|
||||||
|
<button id="upload" class="btn btn-primary">Upload</button>
|
||||||
|
</p>
|
||||||
|
<script src="../../core/lib/customize.js"></script>
|
||||||
|
<script>
|
||||||
|
const STORAGE_KEY = 'hasensors-config';
|
||||||
|
const fields = ['id', 'name', 'url', 'token'];
|
||||||
|
const form = document.getElementById('sensorform');
|
||||||
|
|
||||||
|
let stored = localStorage.getItem(STORAGE_KEY);
|
||||||
|
if (stored) {
|
||||||
|
try {
|
||||||
|
stored = JSON.parse(stored);
|
||||||
|
} catch (_) {
|
||||||
|
stored = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stored) {
|
||||||
|
for (const field of fields) {
|
||||||
|
form[field].value = stored[field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("upload").addEventListener("click", function () {
|
||||||
|
let config = {};
|
||||||
|
for (const field of fields) {
|
||||||
|
if (!form[field].validity.valid) {
|
||||||
|
form[field].focus();
|
||||||
|
alert("Please enter a valid " + field);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const field of fields) {
|
||||||
|
config[field] = form[field].value
|
||||||
|
}
|
||||||
|
console.log('config:', config, JSON.stringify(config));
|
||||||
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(config));
|
||||||
|
sendCustomizedApp({
|
||||||
|
id: "hasensors",
|
||||||
|
storage: [
|
||||||
|
{name: "hasensors.boot.js", url: "boot.js"},
|
||||||
|
{name: "hasensors", url: "lib.js"},
|
||||||
|
{name: "hasensors.settings.json", content: JSON.stringify(config)},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Binary file not shown.
After Width: | Height: | Size: 980 B |
|
@ -0,0 +1,35 @@
|
||||||
|
// split out into a separate file to keep bootcode short.
|
||||||
|
function s(key) {
|
||||||
|
return (require('Storage').readJSON('hasensors.settings.js', true) || {})[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
function post(sensor, data) {
|
||||||
|
const url = s('url') + '/api/states/sensor.' + s('id') + '_' + sensor;
|
||||||
|
Bangle.http(url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: 'Bearer ' + s('token'),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.sendBattery = function () {
|
||||||
|
if (!NRF.getSecurityStatus().connected) return;
|
||||||
|
post('battery_level', {
|
||||||
|
state: E.getBattery(),
|
||||||
|
attributes: {
|
||||||
|
friendly_name: s('name') + " Battery Level",
|
||||||
|
unit_of_measurement: "%",
|
||||||
|
device_class: "battery",
|
||||||
|
state_class: "measurement",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
post('battery_state', {
|
||||||
|
state: Bangle.isCharging() ? 'charging' : 'discharging',
|
||||||
|
attributes: {
|
||||||
|
friendly_name: s('name') + " Battery State",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"id": "hasensors",
|
||||||
|
"name": "Home Assistant Sensors",
|
||||||
|
"shortName": "HA sensors",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "Send sensor values to Home Assistant using the Android Integration.",
|
||||||
|
"icon": "ha.png",
|
||||||
|
"type": "bootloader",
|
||||||
|
"tags": "tool,sensors",
|
||||||
|
"dependencies": {"android":"app"},
|
||||||
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"custom": "custom.html",
|
||||||
|
"storage": [
|
||||||
|
{"name":"hasensors","url":"lib.js"},
|
||||||
|
{"name":"hasensors.boot.js","url":"boot.js"}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"hasensors.settings.json"}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue