Category Archives: node-red

Speech … the Final Frontier

Ivona speechUpdated 02/01/2017

Buffered, SD-cached high-quality human-like speech working alongside sound effects for your IOT project.

Requirements: Raspberry Pi or similar with audio out, Node-Red and a little of your time.

But you don’t need this blog – there’s a WAY better way to do this – in my latest entry about the Ivona Node.

As you may know I’ve done a couple of blog items on Speech on the Raspberry Pi over time. I was quite happy with the Google Translate API until recently when they stopped making it available for free,  so I was forced to go off in search of alternatives and settled on local synthesizers like eSpeak – the problem being – they generally sound AWFUL. eSpeak sounds like someone’s dog being strangled.

And so it was that one of our readers (thank you for that) contacted me and suggested I take a look at Ivona. https://www.ivona.com/us/

This is new: I’ve just gutted the code from the original blog to produce a much better version, better thought out with cacheing for off-line use, unifying speech and sound effects into an auto-created library. In the event of an external comms failure so that you cannot access the outside world, your Ivona is going to fail and this happened here at Bedrock – SO the idea hit us to CACHE all mp3 files (assuming you’re not going to do unique messages every time). That way the SECOND time you ask for a message you will already have a file with that name – the total file space for dozens or even hundreds of these MP3 files is a tiny fraction of a typical SD storage capability and not even worth taking into consideration in most projects. Currently we are working on modifying the Ivona node to handly dynamically changing voices. More on that soon.

I originally did a video to accompany this blog – https://www.youtube.com/watch?v=qoxPVa48qRw

If you use the link I’ve provided above (to Ivona) and select a suitable voice on their web page then enter some text in the box, you’ll find it does a pretty good job. Ivona is free to developers – just grab a free account and get an API key and secret key. I spent the entire evening playing with the code and when I looked at the percentage of my “free use” – nothing  – so you’re unlikely to run out of free use and with the mods here even less so.

Take a tip when you copy and paste that API code information (which you should immediately on getting an account as you won’t be able to get the same key later) and pass them via NOTEPAD (paste then copy again) to get rid of any hidden characters.

So now you have an API key and secret key to be used in the Node-Red node Ivona (node-red-contrib-ivona) https://www.npmjs.com/package/node-red-contrib-ivona

Your API key for Node-Red is the ACCESS code and the PASSWORD is the secret key !!!!! I used my email address for the username – this is all a bit non-intuitive so beware.

Over to Node-Red. So what this node does is take in your TEXT, send it off to Ivona which returns an MP3 file with your chosen speech. You should also have MPG123 installed on your end computer (I’m using a Raspberry Pi2 for all of this). http://www.mpg123.de/

In the simplest case you would send off your text, get the MP3 file, send that to mpg123 for playback. But then you are stuck with a file… and what if you send 2 in quick succession – they will overlap each other as Node-Red runs asynchronously.

Here’s the solution and it’s a lot better than I had in the past. You can fire off several speech requests including requests for other .mp3 files.  for special effects I have a bunch of MP3 files already stored – such as “alert” and “hailing frequencies open”.

Ivona speech

In the example above (that red block is NOT the Ivona node – it is a subflow I wrote – more in a minute)… let me show you those two INJECTS on the left..

Ivona speech

Ivona speech

The first has “alert” in the topic and some text “Red 1 logged in” – the second simply text.

I can click one, wait for it to speak and then click the second – or I can chose not to wait, clicking wildly – and they will still play in order.  So if you specify speech for the TOPIC AND THE PAYLOAD, simply both will go into the queue in order.

How do I do that – so looking at the red Node-Red SUBFLOW…

flow

The yellow’ish blocks are user functions, the red block is a Node-Red EXEC functions – the purple item is a simple 1 second delay for good measure. The purple item is the node-red-contrib-ivona node.

I take in text… if the topic has the word “alert” in it – I put that on the queue BEFORE the main text – other than that there is NO difference between the two.

If there is no text, just a blank message coming in, I check the queue and if not empty, try to use the items on the queue (first in, first out) one at a time.

The INJECT function is needed to start the ball rolling for the first item in the queue. Once I find text in the queue, it is send to the Ivona node IF such a named file does not exist – and then on to the mpg123 player – either way setting a BUSY flag so that those one-second ticks can’t pull another item off the queue until I’m done.

When done – I  send empty messages back into the input to trigger off any further items in the queue.

Here is the main function:

var frompush=0;
if (typeof context.arr == “undefined” || !(context.arr instanceof Array)) context.arr = [];
if (typeof context.global.speech_busy == “undefined”) context.global.speech_busy=0;
if ((msg.payload===””)&&(context.global.speech_busy===0))
if (context.arr.length)
{
frompush=1;
msg.payload=context.arr.shift();
}

if (msg.payload!==””)
{
// just push but not recursively
if (frompush===0)
{
if (msg.topic!==””)  context.arr.push(msg.topic);
context.arr.push(msg.payload);
return;
}

context.global.speech_busy=1;
msg.fname=msg.payload.replace(/ /g,’_’);
msg.fname=msg.fname.replace(/\./g,”);
msg.fname=msg.fname.replace(/\,/g,”);
msg.fname=msg.fname.toLowerCase();
msg.fname=”/home/pi/recordings/”+msg.fname+”.mp3″;
return msg;
}

 

Note the busy flag and the use of PUSH for the queue.

The “copy file to payload” is trivial – Ivona returns the filename in msg.file which is not where I want it.

msg.payload=msg.file;
return msg;

The reset flag function simply clears the busy flag and returns a blank message.

context.global.speech_busy=0;
msg.payload=””; return msg;

The trigger is the Node-Red DELAY function simply set to delay for one second and then pass the message on.

Ivona speech

 

The MPG123 EXEC node calls mpg123 and passes the file name as parameter. The DELETE node simply deletes the file that Ivona creates… Here’s the Ivona setup. Put your credentials in the top box.

moustache

Note the triple moustache {{{}}} –  Ivona examples use a double – but that then interprets slashes and we don’t want to do that because we have a file path in there.

And that is about it – works a treat and produces high quality buffered speech – for free – for your IOT endeavours.

Pick your own file directory (note that I used /home/pi/recordings but that isn’t in any way special) and any words or phrases you want SOUNDS for instead of voice – simply replace with files of the same name (not that spaces are replaced in files names by underscores).  So “alert 2” as a file name would be “alert_2.mp3”

Of course I’m always on the lookout for alternatives, especially those which profess to need no connection.

https://mimic.mycroft.ai/

This looked great – and the short  example in their videosounded like a human. Sadly, on installing this on the Pi (it can’t play without drivers which don’t come on the Pi as standard – but it can generate files) I gave it my favourite micktake of a certain politician “I’m a little tea-pot short and stout, open my mouth and shite comes out”…  and I have to say it made an UTTER and complete mess of it, sounding like a quite ill Dalek. Think I’ll stick with Ivona.

Facebooktwitterpinterestlinkedin

To Weather or not to Weather

That’s it – I’m giving up with OpenWeatherMap. I’ve been having trouble recently with it accepting Hexham,UK some days and not others and it is getting worse – when you look at it’s search list it says Hexham,GB (despite the fact that I have to put in UK and not GB for it to work at all) – then sometimes it can’t find it at all. Someone is having a laugh. Secondly for 2 days it was MISERABLE here in Bellingham just a few miles North of Hexham – and OpenWeatherMap said it was “clear skies” – I’ve not seen blue sky since Thursday until today.

Meanwhile, forecast.io is spot on – see above. See this blog item for how to extract data – https://tech.scargill.net/the-weather/

So you will have noted that I’ve been messing with weather for some time and one of the issues I’ve had is debugging! The standard debug tool that comes with Node-Red is fine but has limited capacity and has no processing capability – for example if you fire a bunch of JSON at it, it looks HORRIBLE (for those not in the know, JSON is a standard, like XML but in most cases very simple, for sending data – simple text).

And it was with that in mind, when mindlessly trawling the web that I stumbled on a reference to a debugging FLOW for Node-Red which would treat text as text and would format JSON – but more’s the point – in a separate browser window – THAT caught my attention.

So – here is the article that started it all off for me this evening…  http://flows.nodered.org/flow/b0fcb7b72fc05a30e55b

Take PARTICULAR notice of Julian’s “Configuration” notes which came about as I completely messed things up and Julian very kindly helped me and then updated his documentation accordingly.

So what we’re doing here is sending debug info to a Node-Red web page – a great idea – but it involves having access to a static library…. /js/mqttws31.js and Julian in his debug notes now tells you how to ensure that Node-Red knows where to look – I would imagine that this info is also awfully useful for node-red-config-ui if you’re planning on adding libraries!!! Certainly added to my knowledge.

And so NOW when I fire out debug info from forecast.IO…..

 

Using the debugger

“Debugger” is the sub-flow that Julian has created (I just renamed it and stored it all in one sub-flow) and “readable debug” is this…

msg.topic=”weather”;
return msg;

The timestamp just triggers an action every 5 minutes and at power up – sensibly every 15 minutes is actually enough. Then there is the grabbing of data from forecast.io where xxxx  is your API key – freely supplied – and note I output as a “parsed JSON object”.

HTTP node setup

 

Then I bang the stuff into a global variable for later use.

global.set(“weather”,msg.payload);

and finally I add a topic for the new debug

msg.topic=”weather”;
return msg;

And so now instead of garbage coming out of the regular debug when I’m testing the weather I get….. wait for it – in the new debugger…. perfectly readable English!!!

Debugger output

Isn’t that wonderful – and as you have the source you could imagine all sorts of variations on this. I am SO chuffed about this – a genuine reason to buy MORE MONITORS!!

Here’s what the debugger sub-flow looks like…

Debugger subflow

Facebooktwitterpinterestlinkedin

The Weather

I had a chat with my pal Jonathan today about the weather – and more specifically getting it into Node-Red.  If you are building your home control with Node-Red at the centre then it is always nice to have information about the local weather to send off to your various displays (such as the one described earlier today) and forecast.io is a dead easy way to get it!

Go to http://forecast.io/ and sign up – that will give you an API number. No, really it is that easy and as long as you don’t use it 1,000 times a day, it is free. Simples.

Here’s what you do:

forecast.io setup

Using an HTTP node (the yellow one) and fill it in as below substituting XXXXXXX for your API key – and the long/lat coordinates for your own (I got mine off the Google Maps command line when pointing at my village). If you’re not in the UK then you’ll have to try something else. US is probably a good start for our friends in the USA.

forecast.io setup

In the function (orange) you need this..

var weather = JSON.parse(msg.payload);

And that is that. NOW you need to know what is available in your new json object and remember – don’t use that timestamp inject (it is irrelevant what it is injecting – it’s just a trigger) more than 999 times a day Smile

So if you look at the output from the incoming XML it is MASSIVE – but put into a JSON online viewer like jsonviewer.stack.hu once converted it starts to look more reasonable.

forecast.io json

For example if we expand currently – we get…

tmpD60D

And how do we access that? Simples – having called the object “weather” we get the temperature as weather.currently.temperature

and so on. In HOURLY we see timestamps and things like chances of precipitation… a little clever loop and… remember in an earlier blog we looked at showing graphs of history in Imperihome? It would not be beyond the bounds of reason to feed this lot into said graphs!!!

Well, even without digging any further, hopefully there are a few items of interest for you.  weather.currently.summary is good as are weather.hourly.summary and weather.daily.summary.

If you want to check the weather you could look at this – but with your coordinates. . http://forecast.io/#/f/51.6571,-0.0295

And on the subject of weather but otherwise unrelated – this looks like a fun site… http://www.wunderground.com/

Oh, nearly forgot – and you’ll be needing some fancy icons..  http://www.wunderground.com/weather/api/d/docs?d=resources/icon-sets

Have fun. And if you know of something BETTER – leave a link in the comments.

Facebooktwitterpinterestlinkedin

IOT Speech recognition

Here’s a thought – now this might be available – but I can’t find it..

Most of us have phones – some Android, some Apple, few Microsoft. So sticking with Android for now – the latest Android phones (I have the HTC One M8 with Android 6.0 which is marvellous) handle speech recognition well.  “Remind me to turn the cooker off in 5 minutes”.  Mind you it never did actually remind me but never mind.

So all of that works.. but what would be REALLY NICE – if the same exact thing could recognise “NODERED”..

So how about “NODERED turn kitchen light on”.

ALL that is needed is for that entire sentence – but only sentences that begin with NODERED – to end up being sent by whatever – MQTT maybe – to the Node-Red installation – from there the most trivial of line parsers could figure out what you were trying to achieve – and do it for you.

SEE THIS UPDATE: https://tech.scargill.net/from-zero-to-star-trek/

 

Facebooktwitterpinterestlinkedin

Instant Node-Red

Peter Oakes kindly made a video – you’ll see it in my last post – on installing Node-Red using my script. Well, I was in the process of watching THAT when (as you do) I got side-tracked and discovered a really wonderful online tool for testing out Node-Red instantly – no installation – not even a sign-in!

Check out my new video here. Don’t worry – its a short one 🙂

Facebooktwitterpinterestlinkedin

A successful Techy Day

So much going on today I thought I’d put the lot into one blog entry.

So, I’ve spent the day with my pal playing with one of several IOT solutions – familiar to regular readers – node-red-contrib-ui. This just keeps getting better.

tmp6D4ASo we spent our afternoon getting to grips with the new “template” node which Andrei the designer has been improving recently. We wanted an RGB controller which the UI does not (did not) currently feature. Getting to grips with Angular and how it interfaces with the UI is proving a challenge but the long and short of it is (I know a couple of you are about to get excited) – we have a working RGB controller.

Here it is. Just ignore my FREDDY experiments and the pretty coloured line of buttons…

Well, no, don’t ignore the buttons – I’m finding increasingly frustrating to have to use the big but still limited range of ANGULAR icons – so I’m about to write off to Andrei to see if we can maybe trap HTTP in the icon description to allow us to use any arbitrary online PNG file – preferably transparent ones – imagine you have a row of buttons for +, minus and auto.  The Angular icons do + and –  but how on earth do you represent “AUTO” – I could think of a 1000 examples where you just can’t do it with a limited set of icons… so that needs work…

Update 31/12/2015 – It is now my understanding that soon we will have the ability to use our own images as well as an expanded library – that is just excellent!!!

However I digress – see the bottom line – RED GREEN AND BLUE controllers (ignore the yellow, I’m experimenting). On the right is a BLACK BLOCK which changes colour as you move the sliders. So this TEMPLATE node in Node-Red UI- and this is all down to Andrei, has an input and an output – the output puts out  JSON string with R G B values…. the input expects msg.payload.r, msg.payload.g etc… well I didn’t have a CLUE how to do that so again Andrei helped. So here I will show you an example of use –, the template node and the input to manually set the controls. I CAN CONFIRM that all of this mirrors perfectly if for example you have this running on 2 phones at once – they remain in sync perfectly!!!!  This is just so good!

tmp7074

So above you see an inject (ignore the timestamp) – the function will set up 3 values to put into the template to affect the sliders – so for example you can set up initial conditions.

msg.payload = {
  r: 10,
  g: 50,
  b: 100
};

msg.payload.b=190;
return msg;

So there’s an incoming payload which we’re going to ignore – the bit I was not sure about was adding new stuff – ie msg.payload.r  and again Andrei came to the rescue – you’ll see I’ve initialised RGB values and then proven to myself that you can quickly alter them before sending MSG off to the template node. The output of the template node goes off in this case to a DEBUG node and there’s a JSON string with RGB values going out (that might be used to populate a global variable and off via MQTT to some RGB lighting).

Here is the content of the template.

<div layout=”row” layout-align=”space-between center”>
    <md-slider ng-model=”msg.payload.r” ng-change=”send(msg)” flex=”30″ min=”0″ max=”255″ class=”slider-red”>
    </md-slider>
    <md-slider ng-model=”msg.payload.g” ng-change=”send(msg)” flex=”30″ min=”0″ max=”255″ class=”slider-green”>
    </md-slider>
    <md-slider ng-model=”msg.payload.b” ng-change=”send(msg)” flex=”30″ min=”0″ max=”255″ class=”slider-blue”>
    </md-slider>
    <div style=”width: 32px; height: 32px;” ng-style=”{‘background-color’: (‘rgb(%d, %d, %d)’|sprintf:msg.payload.r:msg.payload.g:msg.payload.b)}”>
    </div>
</div>

<script>
(function(scope) {
    scope.$watch(‘msg.payload’, function (v) {
        if (!v) scope.msg ={ payload: {r:0, g:0, b:0} };
    });
})(scope);
</script>

<style>
    .slider-green .md-track-fill {
        background-color: green !important;
    }
    .slider-green .md-thumb:after {
        background-color: green !important;
        border-color: green !important;
    }
    .slider-blue .md-track-fill {
        background-color: blue !important;
    }
    .slider-blue .md-thumb:after {
        background-color: blue !important;
        border-color: blue !important;
    }
</style>

What you have there is not only the RGB controls – but all you need to know in order to make any custom system you like which has INPUTS and OUTPUTS. This is so very useful.

So there you go – a great new UI gadget.

Strangely enough – I needed that bit of knowledge about adding stuff to MSG as today another pal of mine pointed me to an ANDROID/IOS App called OWNTRACKS. It has a lot of uses but one of it’s features allows you to set up your phone to send regular LONGITUDE/LATITUDE messages to your own MQTT server.

Now, I went off on a crawl and found a NODE-RED node to do GEOFENCING – here it is.

tmp6FBE

So the ORANGE node is a node called GEOFENCE (node-red-contrib-geofence).  This is marvellous – so you feed it longitude and latitude and it compares against a set area and either passes the message through – or not.

On the left you see my MQTT node picking up a topic which I set on the phone. Next you see me convert the data to the right vars – exactly the same issue I had above so I killed 2 birds with one stone – here’s the function.

var fred=JSON.parse(msg.payload);

msg.location = {
  lon: 0,
  lat: 50
};

msg.location.lon=fred.lon;
msg.location.lat=fred.lat;
return msg;

So from my incoming MQTT in a format decided by the App, not me I’ve created 2 items which the geofence node understands – regular updates as to where I am.

Here’s the winner – the Geofence admin page when you click on the orange Geofence node.

tmp2B7F

This is so good I’m betting I don’t have to explain how it works – you simply put a square, circle or shape around a location, town, house or whatever – and if the incoming coordinates are in that area the whole message just gets passed through – if not, nothing gets passed through. There are other options!!

The obvious next move is a function with a check to ensure you were OUT of the area and coming IN and the string “I’m nearly home, get the kettle on” – passed to the speech system I showed you in my last blog. In my case I’d likely get beaten up for doing that but I’m sure you understand the MASSIVE potential for this.

Put welcome lights on when coming home, alarm the house when leaving etc etc etc… actually with an ESP8266 you could put the kettle on yourself!!! HEY that’s a good idea.

All of this takes only minutes to get going when you have info like this (I had to kind of fumble through much of it). You could use multiple nodes from the same MQTT input to do all sorts of analysis on movement. What’s needed next it really tmpFED7cheap GPS transmitters for the cats!! Just so many possibilities.

So – that was that – then when I got home tonight – the post was waiting for me.  This little number arrived in the post.. This bare board was less than £2 on Ebay… http://www.ebay.co.uk/itm/172017546015?_trksid=p2057872.m2749.l2649&var=470889509954&ssPageName=STRK%3AMEBIDX%3AIT

Ok, it needs 2 MOSFETS, a couple of resistors (SMT) and a regulator and an ESP-12 and you have yourself a handy 0.1” centres development board – only for true soldering iron enthusiasts but I thought it would be worth having.

tmpD4F5As well as that, SEED STUDIOS sent me their LinkIT SMART 7699 board and a nice adaptor to go with it… I’ll have to write this up later when I get enough time to do it justice but on the left you see one of the little boards – it has 2 micro-USB sockets – 3 buttons (reset, program, user) and a WIFI module with lots of IO – the accompanying breakout board lets you do the whole thing with wires and connectors without going anywhere near a soldering iron.

Unlike ESPs (which are of course cheaper) these little devils run Linux!! Anyway, it’s late but here’s a link for interested parties.. http://labs.mediatek.com/site/global/developer_tools/mediatek_linkit_smart_7688/whatis_7688/index.gsp

 

And that is about it for one day. I’ve just found a cheap TIMER unit for my upstairs radiators so I can turn them off when we’re sleeping downstairs and by the time that turns up I’ll have a very pretty mobile application for my good lady to control the heating with.

Good night, all.

Facebooktwitterpinterestlinkedin

Some thoughts on Node Red variables

In learning how to use Node-Red I’ve changed my coding countless times as I’ve found better ways to do things.

Please note that in 2017, the way I use global variables here is out of date. It still works but for example context.global.fred=1 is now written as global.set(“fred”,1). Read this later article on using globals and context variables.

I’m currently working on my thermostat code using a Nextion touch-sensitive display, Raspberry Pi2 as controller and ESP8266s for relay and temperature/humidity sensing. This was a slow-running project until my old Arduino-based heating controller packed in yesterday without warning and so now the fate of the household heating is in the hands of an on-going project.

So the general idea is easy enough – lots of settings for weekdays and weekends, read sensor, control relay. That’s pretty much it in a nutshell except that on my first attempt I didn’t take into account power cuts – and when the power was restored to the Pi, hardcoded defaults took over instead of the settings I’d put in using the display.

So there’s a need for lots of variables and a means to store them permanently. This is what I’ve come up with and the logic behind it:

In order to pass variables around in Node-Red, you need to use “context.global” variables as these are the only ones that will work from page to page (i.e. from powering up node-red to powering down across all pages of your project). This can make for messy variable names for those of us who like to keep things short because we’re lazy or developing typists finger.

context.global.stat_inside_temperature

etc..

I’m a C person and so a struct is ideal for me – keeps everything together.  The nearest I get to that in JavaScript is an object and that’s fine.

A global object containing everything to do with my stat.

   var stat = {
display_temperature : 22,
display_humidity : 45,
heating : 0,
display_external_temperature : 14,
display_external_humidity : 54,
display_status : “Normal”,
display_target_temperature : 20,
display_enabled : 0,
display_last_page : “home”,
display_last_colour : 0,
pass : “”,
display_dim : 60,
peak : 21,
night : 16,
frost : 12,
hold : 0,
weekon : 480,
weekoff : 720,
weon : 480,
weoff : 720,
week2on : 780,
week2off : 1380,
we2on : 780,
we2off : 1380,
temperature_manual_override : 0,
update : 0
};

That stat var of course is only valid while the relevant function is in use and is invisible outside of that particular page hence…

context.global.stat=stat;

So now we have a nice but somewhat longwinded way to access the variables..

context.global.stat.display_temperature;

(I know I should probably use displayTemperature but there’s no global replace in the Node-Red editor (hint)).

Because JavaScript objects are passed by reference – you can use a reference to this in other pages which makes things a little more readable.

var stat=context.global.stat

Hence

stat.display_temperature;

That’s more like it and you can write to that new variable and it will update the original as they are one and the same.

The obvious solution for storing variables permanently, is a database, but I’m trying to minimise that to keep writes down for the time when I run all of this and much more on an SD (currently using a little 2.5” drive with the Pi2).

The file node lets you read and write text files and so the next challenge was how to get that object into a text file – easy:

msg.payload=JSON.stringify(context.global.stat);

That JSON string can be saved directly to disk and the inverse is true of course…

context.global.stat=JSON.parse(msg.payload);

The good part of that is that the string saved to disk is readable and if need be directly writeable.

Thankfully when the file node reads a file if the file is not there, it returns “undefined” so in my function I check for undefined and if so – create a new one with defaults in it. I added a timeout variable in there and whenever I update any item in the object I also set a counter to 10.  That counter is decremented every second and when it reaches zero, the object is updated on disk. That means I can do all sorts of adjusting of controls on the Nextion display and only when I’m done will there be a single block write to the disk. The READ is only done once when Node-Red powers up.

Seems like a reasonable solution and it’s nice and warm in here.

In an earlier blog you’ll see my Nextion display solution which is quite pretty ( created my own imagery because built-in Nextion options are currently not that good) – here just for reference is the current Node-Red block controlling the display and the stat itself including disk reading and writing.

tmp7866

Facebooktwitterpinterestlinkedin

Raspberry Pi Serial and Node-Red issues

SOLVED: Node-Red serial I/O

serial

Looks simple doesn’t it – tie RX and TX together on your Raspberry Pi and press the button – text comes out of the other end – except that it doesn’t. More likely the Pi will CRASH (not something you see every day).

Serial out seems fine – no error messages, you can change baud rate and according to my scope, all is fine on pin 8 of the RPi2.  Input on the other hand, can cause interrupt issues, messages on the console and crashing – and almost never actually produces any output.

So what is the problem?Well, one of the guys at the Node-Red forum set me onto this link.  http://jeelabs.org/2012/09/20/serial-hookup-jeenode-to-raspberry-pi/

And therein lies the problem – by default – the RPI uses the serial port for communications. Trying to add another hook to the serial in interrupt – kills the Pi.

The solution is simple – extracted from the above link.

  1. edit the file /etc/inittab as root (I used “sudo vi /etc/inittab”)
  2. change this line: T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100 to#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100. I.e. comment it out, and save these changes.
  3. run the command “sudo kill -1 1” to pick up these inittab changes

And that  – was that  – I now have comms in and out  – the idea being to put a serial display such as the NEXTION onto the Pi with simple touch input commands – and an output display showing status, temperature etc. DODDLE in Node-Red once you have serial up and running.

Facebooktwitterpinterestlinkedin

NODE-RED Development

While I’m sitting in a hotel in Birmingham waiting to do my bit in this month’s #FSBCONF I thought I’d drop down a few notes about Node-Red which is definitely my new toy of choice when it comes to a central hub for home control. I say toy, sitting on a Raspberry Pi 2 it is definitely NOT a toy.

nodes

So what you see above is one tiny part of what I’m working on for the home controller. The boards mentioned a couple of articles ago need to know what time it is as they don’t have a clock or battery. So when you plug them in – they need to know the time – and as they are also aware of dusk and dawn which clearly changes from time to time, there’s a whole package goes to them on a regular basis, once a day.

There is a “sunrise” node available to Node-Red, but my requirements are slightly different to that which the standard unit allows – so using the Sunrise node as a base I made my own node.

It turns out that as an absolute mininum you need a .JS file and an HTML file. You put them in a suitable named directory under your pi/node-red/nodes directory and that’s about it – provided you’ve not made any mistakes – it just appears as a block in Node-Red.

So what I wanted was a block which would respond to incoming requests from individual WIFI units with their ID and return time info to the individual nodes, usually after a power up or reset – but also send a message to ALL nodes on a regular basis, say, once a day. The WIFI units are programmed to request info at regular intervals until they get an answer – though I’ve yet to see this miss a beat.

The Boards Login block is an MQTT subscribe block – standard. The Daily Update is a standard inject block – and the Send to Boards is an MQTT publish – against standard.

The bit in the middle is a heavily modified Sunshine block – called duskdawn. I made a directory for it – I put the JS and HTML files in there and started gutting them. So now if you click the block you get…

duskdawn

So here are the two files….

The first is as you can see VERY similar to the suncalc node and uses the same functions – but it does not use it’s own timer – it uses an input.  Also it does not generate simple yes/no outputs but generates a message suitable for MQTT.  If a message comes in that says “fromesp” – it sends out the new message to all. If it comes in from a particular unit, it sends that info back to that unit. The info comprises the time in seconds since 1970, the number of minutes after midnight we call DUSK and the number of minutes past midnight we call DUSK.

module.exports = function(RED) {
    “use strict”;
    var SunCalc = require(‘suncalc’);

    function SunNode(n) {
        RED.nodes.createNode(this,n);
        this.lat = n.lat;
        this.lon = n.lon;
        this.start = n.start;
        this.end = n.end;

        var node = this;

        this.on(“input”, function (msg2) {
            var now = new Date();
            var times = SunCalc.getTimes(now, node.lat, node.lon);
            var nowMillis = Date.UTC(now.getUTCFullYear(),now.getUTCMonth(),now.getUTCDate(),now.getUTCHours(),now.getUTCMinutes(), now.getUTCSeconds());
            var midnightMillis = Date.UTC(now.getUTCFullYear(),now.getUTCMonth(),now.getUTCDate(),0,1);
            var startMillis = Date.UTC(times[node.start].getUTCFullYear(),times[node.start].getUTCMonth(),times[node.start].getUTCDate(),times[node.start].getUTCHours(),times[node.start].getUTCMinutes());
            var endMillis = Date.UTC(times[node.end].getUTCFullYear(),times[node.end].getUTCMonth(),times[node.end].getUTCDate(),times[node.end].getUTCHours(),times[node.end].getUTCMinutes());
            var moon = parseInt(SunCalc.getMoonIllumination(now).fraction*100+0.5)/100;
            var msg = { payload:0, topic:”sun”, moon:moon };
            var dawn = (startMillis – midnightMillis);
            var dusk = (endMillis – midnightMillis);
           

           
            if ((nowMillis>dawn)&& (nowMillis<dusk)) { node.status({fill:”yellow”,shape:”dot”,text:”day”}); }
            else { node.status({fill:”blue”,shape:”dot”,text:”night”}); }

            msg.topic = msg2.payload + ‘toesp’;
            msg.payload = ‘{time:’ + nowMillis/1000 + ‘;dusk:’ + dusk/60000 + ‘;dawn:’ + dawn/60000 + ‘}’;
            node.send(msg);

});

    }
    RED.nodes.registerType(“duskdawn”,SunNode);
}

 

This code is complemented by HTML which identifies what inputs are needed, how many outputs etc. This is even closer to but simpler than the Sunrise files. All of the copyright notices in the originals apply, my modifications are not serious enough to claim any ownership though I should say that when I started playing with this I knew nothing about creating these files and now it seems pretty straightforward.

 

<script type=”text/x-red” data-template-name=”duskdawn”>
  <div class=”form-row”>
    <label for=”node-input-lat”><i class=”fa fa-globe”></i> Latitude</label>
    <input type=”text” id=”node-input-lat” placeholder=”51.025″>
  </div>
  <div class=”form-row”>
    <label for=”node-input-lon”><i class=”fa fa-globe”></i> Longitude</label>
    <input type=”text” id=”node-input-lon” placeholder=”-1.4″>
  </div>
 
  <div class=”form-row”>
    <label for=”node-input-name”><i class=”fa fa-tag”></i> Name</label>
    <input type=”text” id=”node-input-name” placeholder=”Name”>
  </div>
</script>

<script type=”text/x-red” data-help-name=”duskdawn”>
    <p>Uses the suncalc module to generate an MQTT output which contains time, dusk and dawn on demand for a specified longitude and latitude.</p>

</script>

<script type=”text/javascript”>
    RED.nodes.registerType(‘duskdawn’,{
        category: ‘advanced-input’,
        color:”#ffcc66″,
        defaults: {
            name: {value:””},
            lat: {value:””, required:true, validate:RED.validators.number()},
            lon: {value:””, required:true, validate:RED.validators.number()},
            start: {value:”sunrise”, required:true},
            end: {value:”sunset”, required:true}
        },
        inputs:1,
        outputs:1,
        icon: “sun.png”,
        label: function() {
            return this.name||”Sun rise/set”;
        },
        labelStyle: function() {
            return this.name?”node_label_italic”:””;
        },
        oneditprepare: function() {
            if (($(“#node-input-lat”).val() === “”) && ($(“#node-input-lon”).val() === “”)) {
                if (“geolocation” in navigator) {
                    navigator.geolocation.getCurrentPosition(function(position) {
                        $(“#node-input-lat”).val(Number(position.coords.latitude.toFixed(5)));
                        $(“#node-input-lon”).val(Number(position.coords.longitude.toFixed(5)));
                    });
                }
            }
        }
    });
</script>

 

So there you have it – with luck you should find this information useful. I AM told by a very kind reader that I should amend any copyright because of the substantial changes I’ve made – but then without the original I could not have gotten this far (I deal with business forums in another life and people are often very unhelpful – whereas in here I’m constantly amazed at the great feedback and help I get)  so I’ll ask merely this – if you find it useful, please somewhere put a link back to the https://tech.scargill.net blog so that more knowledgeable people will come back to me with potential improvements to everything I’m doing – something that we’ll all benefit from.

And if you happen to spot a Node-Red node that can create a nice web page to set up a central heating system – please DO let me know as that’s my next requirement…

Facebooktwitterpinterestlinkedin

Node-Red Strangeness

node

THIS ONE  HAS BEEN SOLVED – SEE “SOLUTION”.

I freely admit to being utterly stumped. Having spent the day getting node-red on the Blackberry Pi2 I’ve made this simple page… an MQTT message coming in is passed out… and also goes to GPIO 0. This works – send a 1 in the message – the LED comes on – send a 0, the LED goes off. The litttle indicator below GPIO 0 shows the 1 or the 0.

TCP in… I’m using NETIO on my phone to sent a TCP package with 1 or 0 in it.  The TCP reply is necessary or NETIO won’t respond. Send a 0 via TCP – and the light goes off (if, say turned on by MQTT).

Lovely.

But – send 1 via TCP and the light flashes ever so briefly – ending up OFF – even though the little indicator on GPIO 0 says 1.

It’s as if the 1 command I’m sending from the phone is being followed by a 0.

The other strange thing about GPIO is that if you send a blank message or a space from MQTT it also turns off – it’s only supposed to be affected by 1 or 0.

SOLUTION:

Well, it turns out that any whitespace or a RETURN sent to the GPIO module – turns the output OFF – how DAFT is THAT? The solution was simple.. filter whitespace out of the incoming TCP signal.

 

var newMsg = { payload: msg.payload.trim() };
return newMsg;

 

And here it is in action…

 

image

Facebooktwitterpinterestlinkedin