The first 2-way driver

Now that I’ve moved all my receive-only drivers to the Raspberry Pi and all 5 drivers are working great, it’s time for the next step: creating the first 2-way driver, i.e. a driver that can publish information received from the hardware as well as receive commands that have to be executed – for example to switch on a light, open the garage door or control the media player.

The problem with this is that most hardware interfaces only allow 1 connection at a time, so it’s hard to test a new Node.JS based driver while the hardware interface is still in use by the current driver. That can be a real problem… on the other hand, everything in our house can still be operated manually as well, so I’ll start with teaching the kids how to manually switch a light bulb – I think they’ve never done that before 😉 But the more I can prevent things from not working, the better of course.

First I need to take care of some things that are common to all the 2-way drivers I’ll be making in the next couple of months, so I needed a first ‘victim’ interface. For that I prepared a 2nd (spare) PLCBUS interface so that I can connect to it from a RaspBerry Pi over Ethernet. For that I used this TTL to Ethernet converter:

USR-TCP232-TThis way I don’t have to ‘do’ RS-232 or USB on the Raspberry Pi. And with a bit of luck (haven’t tried it yet) I’ll be able to squeeze that module inside the PLCBUS interface enclosure so I won’t have any wires coming out – just mains in & Ethernet out.

I had already made a Node.JS module to keep the driver code clean and re-use code for multiple drivers – this module handles the MQTT publishing stuff but it also prevents duplicate values to be published – so that when multiple identical RF packets are received for a temperature, this temperature value will be published only once and only when it has changed. I had to extend this module a bit regarding the MQTT part so that I could also let the driver subscribe to topics so that it could receive commands, like this:

  tools.mqttSubscribe('command/plcbus', function(topic, payload){

The new parameter, which is in fact a function, will be executed after the MQTT client has successfully connected to the broker. The driver subscribes to the topic on which it will receive its commands and will pass the payload it receives to the processCommand() function. Switching on (from Windows, Linux, Arduino, whatever – anything that can ‘talk’ MQTT) an appliance module with address B02  is now as easy as publishing a payload like:

{address:'B02', command:'ON', data1:100}

Works brilliantly! The code for receiving commands by MQTT, sending commands to the PLCBUS interface, receiving the ACK messages which are sent by the PLCBUS modules, processing those and publishing back (“B02 ON”) is all working since a few days, so all the basic functionality is finished. And again, I’m amazed by how fast I could get working code transformed to Javascript. And the code size is really small and compact, just like with the other drivers I made. Less code, less bugs…

There’s some additional functionality I want to add to the driver though; for instance, with PLCBUS it’s possible to query all the PLCBUS modules to check their on/off status. Another thing that can be usefull is that the signal strength can be requested, which can give an insight in how good the PLCBUS network is performing. Both of these things use polling, which means sending a command to the PLCBUS interface and wait for a reply. But I have to make sure that this polling won’t (or the least possible) interfere with commands from us, the users – I don’t want to wait for a light to turn on 5 seconds (or more) later, because the driver has just started its periodic polling process and put some queries in the send queue! So I’ll probably have to implement multiple queues and use some sort of back-off mechanism so that those polling queries will only be executed after a certain amount of time, without any user interaction with PLCBUS devices.

But for now I think it’s OK to say that I have my first 2-way driver working!