I wrote a while ago about using web sockets as against something like NETIO for controlling the home – most folk liked the article but I think part of it was a little complicated – and at the time I’d not really thought it out to make it as simple as possible.
So, this morning I started again and now I have a decent and easy way to make control interfaces from the mobile phone – to ESP boards. I won’t go into MQTT in detail here – I’ll assume you have an MQTT interface of some description on your WIFI boards – if you need more info on that, look elsewhere on the blog.
I’ll also assume you have node-red running somewhere. In my case I have a Raspberry Pi2 sitting in a corner with battery backup, running node-red, MQTT and Apache web server.
So – in order to make a half-decent looking phone interface, I decided to go for jQuery Mobile – it is cheap, easy to run and there is a theme generator.
I went along to https://themeroller.jquerymobile.com/ and made myself a set of THEMES – that is some CSS. You can’t get any easier – you just drag the colours onto the various items – save the ZIP file – and then refer to the THEMES folder in your web page.
Here’s what I did – you might want less colours, more colours, different colours etc.… you can change all aspects of the jQuery Mobile interface which is basically a bunch of items that work well on mobile phones and tablets. Click on these images for larger versions.
So – what’s needed then is a web page…. that shows a series of buttons (jQuery Mobile), a means to send off button presses to Node-Red (web sockets) and some means of then controlling things (MQTT).
In my case I put the web page and dependencies in a folder within /var/www on my Raspberry Pi (could be anywhere – a Windows PC, whatever). I can access these pages externally and hence there is a password on the folder – that is done in my case with an.htaccess file but you might have other ideas.
The page should begin with a header for accessing jQuery, jQuery Mobile and the themes etc.… I figured as the phone has to have an Internet connection to work anyway, there was no point in filling up the Pi with libraries other than my custom theme..
<head>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<title>Simple Controller</title>
<link rel=”stylesheet” href=”themes/jquery.mobile.icons.min.css” />
<link rel=”stylesheet” href=”http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css” />
<script src=”http://code.jquery.com/jquery-1.11.1.min.js”></script>
<script src=”http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js”></script>
<link rel=”stylesheet” href=”themes/petes.min.css” />
</head>
And so above, in the HEAD section of the web page (which I simply edit with NodePad++) links to the local theme and remote jquery. That local stuff all comes in the zip file from the themeroller site – well it does if you make the title when saving “petes” – you might want to call it something else.
Here’s my test page which works equally well on a mobile phone as in a web browser – I’ve checked this out in Chrome and Edge and on my Android 5 phone – identical results.
As you can see I’ve gone for gross, using matching colours (more or less) for the colour controls I’m actually firing off.
The only difference between the buttons is a simple addition of data-theme=”g” or whatever letter – if you look at the theme image at the top, as you add more themes, they start off as “a” then “b” etc. We’ll see this code later.
Rather than put a ton of code in here – here’s a snippet with the entire page.
https://bitbucket.org/snippets/scargill/jgBnK
You’ll see the header information followed by some setup for web sockets.
The basis of my controller as you’ll know if you’ve read Home Control 2015 in this blog, is to send MQTT data to my ESP8266 boards, so for example to control the RGB output on GPIO0 of a board called RED1, I’ll send the following…. the topic would be red1/toesp and the payload would be for example {rgb:0,255,0,0,70,1}
The above means – send a message to board red1 and tell it to fire out a WS2812b signal on GPIO0 to turn 70 LEDs on fully bright red.
I wanted the web page to be as simple a possible – adding to a button something like….
onClick=’send(“red1″,”rgb:0,255,0,0,70,1”)’
And that is exactly what I’ve done. But firstly the mechanics of the Node-Red web sockets interface.
In Node-Red, I have this:
Simpler than it looks, I’ve dropped in a WS input module (standard node-red node unit) and out – and connected them together.
the input listens to “/myapp2” – could be /fred or anything you like to call it. Yes folks that is ALL there is to the setup – but…. assuming my web page connects to this – I need to do something with incoming data (in this blog I’m ignoring firing data back to the page but that is also easy – I referred to that in the last blog – the point of web sockets of course is that this is a continuous connection between the web page – and node-red web socket control.
So what I need is an incoming MQTT message and topic – and that needs firing out to MQTT to control things. The only bit of code here is in “process commands” – this is a function module (drag and drop) and this is what I put in it.
var jsondata=JSON.parse(msg.payload);
if (jsondata.topic)
{
msg.topic=jsondata.topic+”/toesp”;
msg.payload=jsondata.payload;
return msg;
}
Simple enough – any incoming information is assumed to be in json format and is “parsed” (built in function) so that I can extract a payload and a topic to simply fire off to MQTT and on to my boards.
As I’m always going to need “/toesp” on the end of the topic – I add it in here rather than needlessly replicate it in the web page.
The web page itself needs to fire out something like (in this case)….
{“topic”:”red1”,”payload”:”{rgb:0,255,0,0,70,1}”}
The inner braces are for my boards…
So – my board ends up with:
topic: red1/toesp
payload: {rgb:0,255,0,0,70,1}
I wanted to keep the actual buttons as simple as possible so there is a function in the web page to glue the topic and payload together.
{
ws.send(‘{“topic”:”‘+topic+'”,”payload”:”{‘+payload+’}”}’);
}
and so all we need now is the connection between the web page and node-red web socket interface (simple as they’re both on the same server) hence if you look at the web page you’ll see a definition for wsUriC which is then used in wsConnect() which is called on page load. This makes the connection.
ws.send() sends a string to Node-Red and my function ensures the string is in the right format.
A typical button looks like this..
<div class=”ui-block-a” ><input data-theme=”a” type=”button” value=”red” onClick=’send(“red1″,”rgb:0,255,0,0,70,1”)’></div>
Note the very simple onClick function call to send a command off to a particular board…. and if you study the web page example, putting aside the formatting commands for jQuery Mobile (which you can learn all about here https://jquerymobile.com/) – there is WAY more than just buttons available to you – but I’ll leave that to the reader to explore (or not).
So I press a button on the phone – and the light comes on or changes colour or whatever. There is no feedback – that would be covered by a call-back function in the page and jQuery to alter the shape or colour of elements accordingly – really quite easy once you get started. I thought of putting that in here but I’ve probably given you enough to think about as it is.
Hope you find this useful. When the connection is working incidentally you get a little TICK at the top of the page – or a little cross if not.
Pete.
p.s. If you’re wondering what all this cave reference is about – head over to http://www.bedrock.es
Coming up soon: I hope to review the inexpensive NEXION touch display (one is on it’s way) to make a nice wall-mounted thermostatic control – which will talk via serial to an ESP-01 which in turn will control a relay and have a DHT-22 chip for temperature sensing – and Node-Red for background timing control – and of course I will have phone-based monitoring and over-ride based on code very similar to what you see here.
Hi Pete!
Thank you for this article! I choosed your example as a structure for my own project. But maybe you have a clue for me?
For testing I’d like to switch a RPI on – board GPIO output on and off via a websocket and MQTT. For this test I used your html snippet. For example, I press the “on” switch of “Pergola Central Light” on the webpage and the message “pergola/test”,”out0:1″ is delivered via the web socket and your “Process Commands” (without +toesp for my example) to a MQTT output. Everything fine up to here. I have no clue how to connect my MQTT input to the GPIO output node.
I tried to configure the MQTT input with the pergola/test and wired it directly to the GPIO output but it seems to have the wrong format.
Thanks for your help!
Does MQTT use TCP or UDP? Is it true that sensor data is typically sent via UDP since not every packet must have guaranteed delivery?
I’ve been researching web technologies, but it’s a bit confusing, the lectures seem to be geared for more advanced users.
The reason I ask is that I’ve recently purchased a CC3100 to send data from my Arduino to the web (plot.ly, data.sparkfun, wolfram, or Freeboard.io, etc). I’ve got SPI working on the Arduino , but not sure how to architect the overall system level.
This was a good video I found on MQTT: https://www.youtube.com/watch?v=sCB80DsJfig but they don’t list any code, so not sure if I can use it on the Arduino
So in order…
TCP – I know this as I’ve done port redirects on my router to enable external access to MQTT.
I watched the video on MQTT – which led me to another video of using the Arduino YUN as an MQTT server. I have immense difficulty understanding why anyone would want to spend that much money on a YUN just to get an MQTT Broker up and running when a Raspberry Pi does an excellent and reliable job of that – and can do 100 other things including Node-Red and a web server with MYSQL. If you check out my blog item “Home Control 2015” you’ll see I refer to MQTT a lot. Once you get into it, it is really quite easy. As soon as my Orange Pi turns up I’ll try to replicate my work on that. Don’t get me wrong, I’ve no attachment to the Pi – but it is a cheap and up to now reliable way to get the “nerve centre” of a control system up and running. In MQTT you can chose what kind of package you want to send, from those which are sent once to those which are repeatedly sent until they get through, just by changing one parameter.
Hi Peter
Great stuff…love what you’ve done here.
What is the purpose of the ‘ws out’ node and what does it’s config look like ?
Is it to send state info back to the webpage ?
Config is the same as the input – and yes, it is to send info back to the web page. In an earlier blog on the subject I show how you can pick up information sent back in a callback.
just before ws.onopen you can have a ws.onmessage function
ws.onmessage = function(msg) {
var line = “”;
var info=JSON.parse(msg.data);
if (info.fred!=null) $(“#fred”).html(info.fred);
// so then if you have a button called fred… info.fred contains it’s value etc….
}
All assuming that the returned message is in json format… i.e. {“fred”:”40″,”brian”:”10″}
Did you check out bootstrap as a possible replacement to jquery-mobile? Same idea just slightly different implementation. The HTML is not as concise, but you have more control over things like button size and title bar. Thanks for the article!
No but I will now 🙂
Nice one! Some food for thought there.
I was wondering if you could ditch the need for jQuery and jQuery mobile if you modified the ws.onopen() and ws.onclose() methods to use vanilla JS to modify the class applied to the “Cave Lighting System” status indicator.
Presumably the CSS produced by ThemeRoller would still work without using the jQuery mobile code ?
Andy.
Sorry, I meant ditch jQuery. I guess jQuery mobile provides all the UI buttons etc.
Ok you have me – why would I want to ditch jQuery and jQuery mobile?
I meant ditch jQuery as it’s only being used to toggle a class attribute on a single HTML element. Something that’s easily done in Vanilla Javascript.
Just me with my optimisation head on 🙂
OK, I’m just being stupid as I can now see that jQuery is a prereq for jQuery Mobile. Back in my box now 🙂
Actually, I am looking to see what’s out there… I want to keep this simple – but the buttons are too damned big. For example I want colour buttons one for each colour and I can only get 3 across as far as I can see – they’re the right height but way too wide – the only need be as wide as a large finger.
I’m also having immense difficulty stopping the mobile page from expanding if I touch it the wrong way and I can’t get rid of the title bar having tried all the examples people have put on the web….
So by all means fire comments away.
(I’m onto multi-pages now)