Hi Everyone
I'm wanting to play & learn about websockets. My objective is to develop a simple dashboard with a 3d image of my property's floor plans. I want to trigger devices based on images, and switch those images (eg. to show lights on/off, AC units on/off). In the examples below, they are just any old images from the internet as a prototype only, so dont worry about that for now (the vision is to have proper translucent images etc to show the rooms lit/unlit etc). I've put the main floorplan into an iFrame (the idea is there could be several images/floors/rooms on a single page) and the device images are statically placed over the top.
...and the reverse light image, toggled onclick...
I got that working using MakerAPI and the javascript/html shown here (please guys, I'm learning ok, so be gentle). The 2 devices respond on/off when I click on the images and the images update/switch. Cool!
# my html prototype
<!DOCTYPE html>
<html>
<head>
<script>
function swapper(img,deviceID) {
if ( img.src == 'https://previews.123rf.com/images/iulika1/iulika11803/iulika1180300095/97209967-lamp-icon-black-silhouette-on-transparent-background-vector-illustration.jpg') {
img.src = 'https://previews.123rf.com/images/urfandadashov/urfandadashov1808/urfandadashov180824030/109031273-lamp-vector-icon-isolated-on-transparent-background-lamp-logo-concept.jpg'
const Http = new XMLHttpRequest();
const url='http://192.168.0.167/apps/api/2150/devices/' + deviceID + '/on?access_token=lalala';
Http.open("GET", url);
Http.send();
Http.onreadystatechange = (e) => {
console.log(Http.responseText)
}
} else {
img.src = 'https://previews.123rf.com/images/iulika1/iulika11803/iulika1180300095/97209967-lamp-icon-black-silhouette-on-transparent-background-vector-illustration.jpg'
const Http = new XMLHttpRequest();
const url='http://192.168.0.167/apps/api/2150/devices/' + deviceID + '/off?access_token=lalala';
Http.open("GET", url);
Http.send();
Http.onreadystatechange = (e) => {
console.log(Http.responseText)
}
}
};
</script>
</head>
<body style="background-color:black;">
<center>
<br>
<br>
<br>
<iframe scrolling="auto" allowtransparency="true" name="main" style="width:850px;height:500px; background-image:url(https://www.linesgraph.com/images/blogimgs/3D-floor-plan-6-thegem-blog-default.jpg)">
</iframe>
<img id="kitchenLights" style="top:250px; left:600px; position:absolute; z-index:9; width:50px;height:60px; opacity:0.4;filter:alpha(opacity=20);" src="
https://previews.123rf.com/images/iulika1/iulika11803/iulika1180300095/97209967-lamp-icon-black-silhouette-on-transparent-background-vector-illustration.jpg" onclick="swapper(this,'1825');">
<img id="livingLights" style="top:300px; left:300px; position:absolute; z-index:9; width:50px;height:60px; opacity:0.4;filter:alpha(opacity=20);" src="
https://previews.123rf.com/images/iulika1/iulika11803/iulika1180300095/97209967-lamp-icon-black-silhouette-on-transparent-background-vector-illustration.jpg" onclick="swapper(this,'1826');">
</center>
</body>
</html>
It's cool and I learned a lot.
Now I want to achieve 2 more steps:
1 - set the correct images when the page initially loads or is refreshed, depending on the device status
2 - dynamically update the images to reflect the device status if changed (eg. by RM or another HE dashboard)
1 - set correct image onload
I've had some success with this javascript which I run "onload" when the page is loaded, but its not perfect because it's so clunky (eg. its a single device). I tried to set up a loop but quickly got into horrible difficulties and ran out of ability/knowledge. I couldnt find a way to get the array into the getElementById so that I can step through multiple devices. It just won't work so in the example here its hard-coded as one of the devices (kitchenLights).
# javascript to set image onload
function updateDevices() {
for (iii = 0; iii < deviceName_array.length ; iii++) {
var responseString = '';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
responseString = xhttp.responseText;
//alert(responseString);
if (responseString.includes("currentValue\":\"on")) {
//bulb is on
//alert ("kitchen light is on");
document.getElementById("kitchenLights").src = 'https://previews.123rf.com/images/urfandadashov/urfandadashov1808/urfandadashov180824030/109031273-lamp-vector-icon-isolated-on-transparent-background-lamp-logo-concept.jpg';
} else {
//bulb is off
//alert ("kitchen light is off");
document.getElementById("kitchenLights").src = 'https://previews.123rf.com/images/iulika1/iulika11803/iulika1180300095/97209967-lamp-icon-black-silhouette-on-transparent-background-vector-illustration.jpg';
};
};
};
xhttp.open("GET", "http://192.168.0.167/apps/api/2150/devices/" + deviceID_array[iii] + "?access_token=lalala", true);
xhttp.send();
}; // for...
};
2 - dynamically update
I played with using the code above as a poller function (eg. setInterval function around the code, to run every 20-30 seconds). It worked but obviously put some load on the hub. I understand it would be much better to use websockets for this, and so I need node.js? As a keen amateur, but definitely not coder, this next step is a bit overwhelming. I understand I need to install node.js? I have a Pi and tried to do that. Then I found some simple client/server scripts online and played with those along with some example javascript to run inside a webpage. Then I got totally lost.
So, questions:
Is javascript '1' the right way to go about this? Or should use websocket for that initial load/set-up as well as a dynamic update? I guess so. And for websockets, '2', is there a good resource I can use that will walk me through the process step by step? It's quite daunting as a newbie. Or am I mad and there is a better way to do all this (probably!)
Thanks for any and all guidance guys.
Cheers.
Angus