forked from FOSS/BangleApps
Merge pull request #1995 from peerdavid/master
[HomeAssistant] Trigger HomeAssistant automations with your BangleJsmaster
commit
2659d5f46b
|
@ -0,0 +1 @@
|
|||
0.01: Release
|
|
@ -0,0 +1,63 @@
|
|||
# Home Assistant
|
||||
This app integrates your BangleJs into the HomeAssistant.
|
||||
|
||||
# How to use
|
||||
Click on the left and right side of the screen to select the triggers that you
|
||||
configured. Click in the middle of the screen to send the trigger to HomeAssistant.
|
||||
|
||||

|
||||
|
||||
# First Setup
|
||||
1.) First of all, make sure that HomeAssistant and the HomeAssistant Android App works.
|
||||
|
||||
2.) Open your BangleJs Gadgetbridge App, click on the Settings icon of your BangleJs and enable "Allow Intent Access"
|
||||
|
||||
3.) Enable sensor in HomeAssistant Andoird App/Configuration/Companion App/Manage Sensors/LastUpdate Trigger
|
||||
|
||||
4.) At the bottom of the same screen click on "Add New Intent" and enter "com.espruino.gadgetbridge.banglejs.HA"
|
||||
|
||||
5.) The HomeAssistant Android app must be restarted in order to listen for those actions
|
||||
-- a "Force Stop" is necessary (through Android App settings) or restart your phone!
|
||||
|
||||
This setup must be done only once -- now you are ready to configure your BangleJS to
|
||||
control some devices or entities in your HomeAssistant :)
|
||||
|
||||
# Setup Trigger
|
||||
1.) Upload the app and all corresponding triggers through the AppStore UI. You must specify
|
||||
the display name, the trigger as well as an icon.
|
||||
The following icons are currently supported:
|
||||
- ha (default)
|
||||
- light
|
||||
- door
|
||||
- fire
|
||||
|
||||
|
||||
2.) Create an "automation" in the HomeAssistant WebUI for each trigger that you created on your BangleJs in order to tell HomeAssistant what you want to control. A sample configuration is shown in the image below -- I use this trigger to open the door:
|
||||
|
||||

|
||||
|
||||
3.) Don't forget to select the action that should be executed at the bottom of each automation.
|
||||
|
||||
# Default Trigger
|
||||
This app also implements two default trigger that can always be used:
|
||||
- APP_STARTED -- Will be sent whenever the app is started. So you could do some actions already when the app is sarted without the need of any user interaction.
|
||||
- TRIGGER -- Will be sent whenever some trigger is executed. So you could generically listen to that.
|
||||
|
||||
|
||||
# FAQ
|
||||
|
||||
## Sometimes the trigger is not executed
|
||||
While playing and testing a bit I found that it is very important that you allow the android HomeAssistant app, as well as BangleJs Gadgetbridge app to (1) run in background and (2), disable energy optimizations for both apps.
|
||||
Otherwise, Android could stop one of both apps and the trigger will never be sent to HomeAssistant...
|
||||
|
||||
If you still have problems, you can try another trick:
|
||||
Install "MacroDroid" from the Android AppStore and start the HomeAssistant App
|
||||
each time the "com.espruino.gadgetbridge.banglejs.HA" intent is send together
|
||||
with the extra trigger: APP_STARTED. Then whenever you open the app on your BangleJs
|
||||
it is ensured that HomeAssistant is running...
|
||||
|
||||
## Thanks to
|
||||
<a href="https://www.flaticon.com/free-icons/" title="Icons">Icons created by Flaticon</a>
|
||||
|
||||
## Creator
|
||||
- [David Peer](https://github.com/peerdavid).
|
|
@ -0,0 +1,51 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<h3>Upload Tigger</h3>
|
||||
<p><textarea id="triggers" style="width:500px; height:300px">
|
||||
[
|
||||
{"display": "Open", "trigger": "OPEN_DOOR", "icon":"door"},
|
||||
{"display": "Office", "trigger": "TOGGLE_LIGHT", "icon":"light"},
|
||||
{"display": "Living Room", "trigger": "OVEN", "icon":"fire"}
|
||||
]</textarea></p>
|
||||
<p><button id="upload" class="btn btn-primary">Upload</button></p>
|
||||
|
||||
<script src="../../core/lib/customize.js"></script>
|
||||
|
||||
<script>
|
||||
/*
|
||||
* Load trigger from BangleJs
|
||||
*/
|
||||
console.log("Loading trigger from BangleJs...");
|
||||
try {
|
||||
Puck.eval(`require("Storage").read(${JSON.stringify("ha.trigger.json")})`,data=>{
|
||||
if(data.length > 0){
|
||||
document.getElementById("triggers").innerHTML = data;
|
||||
console.log("Loaded trigger from BangleJs.");
|
||||
}
|
||||
});
|
||||
} catch(ex) {
|
||||
console.log("(Warning) Could not load trigger from BangleJs.");
|
||||
console.log(ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Upload trigger to BangleJs
|
||||
*/
|
||||
document.getElementById("upload").addEventListener("click", function() {
|
||||
// get the text to add
|
||||
var triggerText = document.getElementById("triggers").value;
|
||||
// send finished app (in addition to contents of app.json)
|
||||
sendCustomizedApp({
|
||||
storage:[
|
||||
{name:"ha.trigger.json", url:"ha.trigger.json", content:triggerText},
|
||||
]
|
||||
});
|
||||
console.log("Sent ha.trigger.json!");
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,137 @@
|
|||
var storage = require("Storage");
|
||||
var W = g.getWidth(), H = g.getHeight();
|
||||
var position=0;
|
||||
|
||||
|
||||
// Note: All icons should have 48x48 pixels
|
||||
function getIcon(icon){
|
||||
if(icon == "light"){
|
||||
return {
|
||||
width : 48, height : 48, bpp : 1,
|
||||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("AAMBwAFE4AFDgYFJjgFBnAFBjwXBvAFBh4jBuAFCAQPwAQMHAQPgEQQCBEgcf/AvDn/8Aof//5GDAoJOBh+BAoOB+EP8YFB4fwgfnAoPnGANHAoPjHYQFBHYQFd44pDg47C4/gh/DIIZNFLIplGgF//wFIgZ9BRIUHRII7Ch4FBUIUOAoKzCjwFEhgCBmDpIVooFFh4oCAA4LFC5b7BAob1BAYI="))
|
||||
};
|
||||
} else if(icon == "door"){
|
||||
return {
|
||||
width : 48, height : 48, bpp : 1,
|
||||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("AAM4Aok/4AED///Aov4Aon8DgQGBAv4FpnIFKJv4FweAQFFAgQFB8AFDnADC"))
|
||||
};
|
||||
} else if (icon == "fire"){
|
||||
return {
|
||||
width : 48, height : 48, bpp : 1,
|
||||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("ABsDAokBwAFE4AFE8AFE+AFE/AFJgf8Aon+AocHAokP/8QAokYAoUfAok//88ApF//4kDAo//AgMQAgIFCjgFEjwFCOYIFFHQIFDn/+AoJ/BAoIqBAoN//xCBAoI5BDIPAgP//gFB8AFChYFBgf//EJAogOBAoSgBAoMHAQIFEFgXAAoJEBv4FCNoQFGVYd/wAFEYYIFIvwCBDoV8UwQCBcgUPwDwDfQMBaIYADA"))
|
||||
};
|
||||
}
|
||||
|
||||
// Default is always the HA icon
|
||||
return {
|
||||
width : 48, height : 48, bpp : 1,
|
||||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("AD8BwAFDg/gAocP+AFDj4FEn/8Aod//wFD/1+FAf4j+8AoMD+EPDAUH+OPAoUP+fPAoUfBYk/C4l/EYIwC//8n//FwIFEgYFD4EH+E8nkP8BdBAonjjk44/wj/nzk58/4gAFDF4PgCIMHAoPwhkwh4FB/EEkEfIIWAHwIFC4A+BAoXgg4FDL4IFDL4IFDLIYFkAEQA=="))
|
||||
};
|
||||
}
|
||||
|
||||
// Try to read custom actions, otherwise use default
|
||||
var triggers = [
|
||||
{display: "Not found.", trigger: "NOP", icon: "ha"},
|
||||
];
|
||||
|
||||
try{
|
||||
triggers = storage.read("ha.trigger.json");
|
||||
triggers = JSON.parse(triggers);
|
||||
} catch(e) {
|
||||
// In case there are no user triggers yet, we show the default...
|
||||
}
|
||||
|
||||
|
||||
function sendIntent(trigger){
|
||||
var retries=3;
|
||||
|
||||
while(retries > 0){
|
||||
try{
|
||||
// Send a startup trigger such that we could also execute
|
||||
// an action when the app is started :)
|
||||
Bluetooth.println(JSON.stringify({
|
||||
t:"intent",
|
||||
action:"com.espruino.gadgetbridge.banglejs.HA",
|
||||
extra:{
|
||||
trigger: trigger
|
||||
}})
|
||||
);
|
||||
retries = -1;
|
||||
|
||||
} catch(e){
|
||||
retries--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function draw() {
|
||||
g.reset().clearRect(Bangle.appRect);
|
||||
|
||||
var h = 22;
|
||||
g.setFont("Vector", h);
|
||||
var trigger = triggers[position];
|
||||
var w = g.stringWidth(trigger.display);
|
||||
|
||||
g.setFontAlign(-1,-1);
|
||||
var icon = getIcon(trigger.icon);
|
||||
g.setColor(g.theme.fg).drawImage(icon, 12, H/5-2);
|
||||
g.drawString("Home", icon.width + 20, H/5);
|
||||
g.drawString("Assistant", icon.width + 18, H/5+24);
|
||||
|
||||
g.setFontAlign(0,0);
|
||||
var ypos = H/5*3+20;
|
||||
g.drawRect(W/2-w/2-8, ypos-h/2-8, W/2+w/2+5, ypos+h/2+5);
|
||||
g.fillRect(W/2-w/2-6, ypos-h/2-6, W/2+w/2+3, ypos+h/2+3);
|
||||
g.setColor(g.theme.bg).drawString(trigger.display, W/2, ypos);
|
||||
}
|
||||
|
||||
|
||||
Bangle.on('touch', function(btn, e){
|
||||
var left = parseInt(g.getWidth() * 0.3);
|
||||
var right = g.getWidth() - left;
|
||||
var isLeft = e.x < left;
|
||||
var isRight = e.x > right;
|
||||
|
||||
if(isRight){
|
||||
Bangle.buzz(40, 0.6);
|
||||
position += 1;
|
||||
position = position >= triggers.length ? 0 : position;
|
||||
draw();
|
||||
}
|
||||
|
||||
if(isLeft){
|
||||
Bangle.buzz(40, 0.6);
|
||||
position -= 1;
|
||||
position = position < 0 ? triggers.length-1 : position;
|
||||
draw();
|
||||
}
|
||||
|
||||
if(!isRight && !isLeft){
|
||||
|
||||
// Send a default intent that we triggered something.
|
||||
sendIntent("TRIGGER");
|
||||
|
||||
// Now send the selected trigger
|
||||
Bangle.buzz(80, 0.6).then(()=>{
|
||||
sendIntent(triggers[position].trigger);
|
||||
setTimeout(()=>{
|
||||
Bangle.buzz(80, 0.6);
|
||||
}, 250);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Send intent that the we started the app.
|
||||
sendIntent("APP_STARTED");
|
||||
|
||||
// Next load the widgets and draw the app
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
draw();
|
||||
setWatch(_=>load(), BTN1);
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwIjggOAAocH8AFDh/wAocfAok//gFDv/+Aof+vwoD/Ef3gFBgfwh4YCg/xx4FCh/z54FCj4LEn4XEv4jBGAX//k//4uBAokDAofAg/wnk8h/gLoIFE8ccnHH+Ef8+cnPn/EAAoYvB8ARBg4FB+EMmEPAoP4gkgj5BCwA+BAoXAHwIFC8EHAoZfBAoZfBAoZZDAsgAiA=="))
|
Binary file not shown.
After Width: | Height: | Size: 980 B |
Binary file not shown.
After Width: | Height: | Size: 71 KiB |
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"id": "ha",
|
||||
"name": "HomeAssistant",
|
||||
"version": "0.01",
|
||||
"description": "Integrates your BangleJS into HomeAssistant.",
|
||||
"icon": "ha.png",
|
||||
"type": "app",
|
||||
"tags": "tool",
|
||||
"readme": "README.md",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"custom": "custom.html",
|
||||
"screenshots": [
|
||||
{"url":"screenshot.png"},
|
||||
{"url":"screenshot_2.png"},
|
||||
{"url":"screenshot_3.png"}
|
||||
],
|
||||
"data": [
|
||||
{"name":"ha.trigger.json" }
|
||||
],
|
||||
"storage": [
|
||||
{"name":"ha.app.js","url":"ha.app.js"},
|
||||
{"name":"ha.img","url":"ha.icon.js","evaluate":true}
|
||||
]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
Loading…
Reference in New Issue