JeeNodes are RF enabled AVR328P boards using the same development tools as the Arduino. We love the JeeLabs weblog, jcw inspires us.
As JeeNodes are RF based, they make a great way to RF enable a variety of functions. Importantly, the JeeNodes support reliable bi-directional RF comms, so we can both send commands to the JeeNode and receive information from it.
Block diagram of how the JeeNodes are integrated into the HAH livebox
From a code architectural point of view the following layers constitute the JeeNode pluggable system. This framework allows a user to write and build their own nodes minimising the effort required. For example the IR node to code, build and assemble from start to finish was 1hr worth of work.
Each of these layers is written in Lua and the source can be found on your HAH in /usr/share/lua/5.1/xap.
A brief summary of what each layer is responsible for: The xAP layer handles encoding/decoding xAP, fetching values from a packet, creation of timers and multiplexing Filter callbacks. BSC (Basic Status and Control) is a layer that manages endpoints conforming to this specification. JeeNode layer provides support infrastructure for the creation of xAP endpoints, RF bitstream packet decoding, TTL (time-to-live) management and a higher level of abstraction over the BSC framework simplifying the Node implementations. The Node classes implement logic to create endpoints and handle the incoming xAP serial packet from the HAH tethered unit and incoming xAP directed communication for a JeeNode that can receive data.
Each JeeNode class can be plugged in multiple times to the applet, each instance of the class will correspond with a piece of physical hardware, a JeeNode, that has a unique ID. For example you might have multiple room nodes around your house all reporting temperature and light readings, so you would plug in multiple RoomNode classes each with a unique ID and endpoint designator.
In a nutshell
Up to 32 NODES can be present in a single JeeNode group. You may have a mixture of node types.
There is only one place that you can get a JeeNode - from jeelabs.com (or for US based folks).
We might develop a clone variant (lower quality PCB but with some features to ease Airwick integration), and that would be available from our Shop.
The completed kit without port pin female connectors.
The port pinouts are as follows:
The HAHnode design is a variant of the JeeNode design. The BASE Kit contains…
This image shows the correct way to fit the attach/programming cable.
The first thing to do is to connect the PCB to your HAH. To do this you will need the attach/program cable
Next, check that you don't have the xap serial process running. It generally uses the same serial port as you will use for programming the Node PCB. If it is running, kill it off now.
# /etc/init.d/xap stop serial
The popular AVR device programmer, AVRDUDE, in built-in to the HAH firmware at build 284.
We use 'curl' to retrieve the hex file images that will be flashed onto the AVR Mega328P device on the HAHnode PCB.
# cd /root # curl -o roomnode2.hex http://livebox-hah.googlecode.com/files/roomNode2.cpp.hex # curl -o HAHcentral.hex http://livebox-hah.googlecode.com/files/HAHCentral.hex
To flash your HAHnode run following commands:
For the BASE node (that attaches to the HAH)
stty -F /dev/ttyUSB0 hupcl avrdude -v -c arduino -p m328p -P /dev/ttyUSB0 -b 57600 -Uflash:w:HAHCentral.hex
or
For the roomNode (that is standalone)
stty -F /dev/ttyUSB0 hupcl avrdude -v -c arduino -p m328p -P /dev/ttyUSB0 -b 57600 -Uflash:w:roomnode2.hex
Each node must be configured to be in the same GROUP and running the same frequency, and each must have a unique ID. The HAHCENTRAL and RFDEMO sketches allow you to adjust these settings.
Once you have flash either of these configuration sketches you can configure your NODE
Available commands:
<nn> i - set node ID (standard node ids are 1..26)
<n> b - set MHz band (4 = 433, 8 = 868, 9 = 915)
<nnn> g - set network group (RFM12 only allows 212, 0 = any)
...,<nn> a - send data packet to node <nn>, with ack
...,<nn> s - send data packet to node <nn>, no ack
<n> q - set quiet mode (1 = don't report bad packets)
For the CENTRAL node you would want the following configuration - we have assigned this as NODE 1
[HAHCentral.1] D i1 g212 @ 868 MHz
For a roomNode - flash the HAHcentral sketch just to set it up first - then assign it a unique ID. In this case its NODE 2, of the same group and frequency as our central above.
[HAHCentral.1] D i2 g212 @ 868 MHz
For anybody who is flashing their own Mega328P parts 'from scratch', here are the required fusebit settings (if you purchase from the HAH shop, these are already setup on the devices that are on sale).
and the ATMEGA328P EEPROM content should look something like this (depending on your exact configuration) …
There is only one file that you need to modify to expose a HAHnode as a xAP BSC endpoint. This file is held on the HAH in the plugboard directory /etc/plugboard. As it's very small its entire source code has been reproduced here
# cp /etc_ro_fs/plugboard/samples/jeenodeApplet.lua /etc/plugboard
--[[ JeeNode to xAP Endpoint mapping --]] --_DEBUG=1 module(...,package.seeall) monitor = require("xap.jeenode").monitor RoomNode = require("xap.roomnode").RoomNode OutputNode = require("xap.outputnode").OutputNode info={ version="2.0", description="HAHNode" } local jeemon={ port="/dev/ttyUSB0", baud=57600, stop=1, databits=8, parity="none", flow="none" } -- Keyed by NODE ID local nodes = { [3] = RoomNode{base="dbzoo.livebox.jeenode:3", endpoints={temp=1,lobat=1}, ttl=900}, [4] = OutputNode{base="dbzoo.wombat.jeenode:bedroom",endpoints={p1="light",p2="heater",p3="amp",p4=0}}, } function init() monitor(jeemon, nodes) end
There are two configuration sections that you'll need to modify: jeemon and nodes.
jeemon - describes how we are going to communicate with the JeeNode that is attached to the HAH via its USB port, in the configuration section the only value that you'll need to adjust will be the port. Depending on what other USB serial devices you have attached to your HAH this port will move around. Use “dmesg” to see where your JeeNode is located, and verify this using ”microcom -s 57600 /dev/ttyUSBxx”
These settings are used internally to send a message to xap-serial to initialise the port.
By default the target used for xap-serial will be dbzoo.livebox.serial if however you are running an INSTANCE livebox and you want to use the xap-serial message from that box then you need to additionaly supply a target=
In this example we have assumed you have called your instance 1 substitute for your instance name.
local jeemon={
target="dbzoo.livebox.1.serial",
port="/dev/ttyUSB0",
baud=57600,
stop=1,
databits=8,
parity="none",
flow="none"
}
nodes - this is where you configure the layout of your specific installation of HAHNode.
-- [ID] = NodeType
[2] = RoomNode{base="dbzoo.livebox.jeenode:attic", endpoints={temp=1}}
Each JeeNode must have a UNIQUE ID this is configured using RF12Demo like so. This would set the JeeNode as NODE ID 2.
2i
Depending on the SKETCH you have loaded on the JeeNode you must align this with the Node type so that it correctly interprets the data received. Failure to do this will results in STRANGE readings.
Each Node has a different set of initialization parameters but each will start with its TARGET name.
You can choose whatever naming scheme you want but it must be of the form
vendor.device.instance:location
Enable xap-serial
Don't forget to enable the xap-serial service and the plugboard engine, of course.
Example configuration
If a Node defines multiple endpoints these will be appended to this base SOURCE description. For example if the RoomNode was configured like this
[ID] = RoomNode{base="dbzoo.livebox.jeenode:attic", endpoints={lobat=1,temp=1,light=1}}
dbzoo.livebox.jeenode:attic.lobat dbzoo.livebox.jeenode:attic.temp dbzoo.livebox.jeenode:attic.light
A node may have multiple endpoints and not all of them might be needed. For example, the roomnode has: temperature, movement, lo-battery, humidity and light endpoints. Depending upon the hardware configuration you might not have a humidity or movement sensor attached.
How do we specify that we only want: temp, lobat, light? Like this:
[ID] = RoomNode { base = "dbzoo.livebox.jeenode:bedroom1", endpoints = {temp=1,lobat=1,light=1,humi=0,moved=0} } }
Each key=value pair in the endpoint definition table indicates whether this endpoint is needed or not. 1 if it's needed, 0 if it's not. If we don't specify the endpoint in the configuration it's equivalent to setting it to 0.
This code is functional equivalent to that above
[ID] = RoomNode { base = "dbzoo.livebox.jeenode:bedroom1", endpoints = {temp=1,lobat=1,light=1} } }
This would create the following
This syntax also allows us to rename the endpoints. Any other value but 1 is taken to be a new NAME for the endpoint.
[ID] = RoomNode { base = "dbzoo.livebox.jeenode:bedroom1", endpoints = {temp="temperature",lobat=1,light=1} } }
This would create the following
As we use RF to transmit signals it's possible that we may lose connectivity due to dead batteries or just bad placing. What we need is the ability to time-out an endpoint's value if data is not seen. This is accomplished by using the ttl (time-to-live) attribute and specifying a number of seconds that can elapse without seeing the JeeNode report in, before we consider it non-responsive.
When a node expires its state, and its values, get set to '?' this means that the node has not reported in within its TTL setting. A expiring node will generate a xAPBSC.event for EACH endpoint it has then every 2 minutes you'll get a xAPBSC.info until the node comes back online. In the example below we have 3 endpoints (temp, lobat, and light) so we would expect an expiry event for each.
For example: Here we specify that 5 mins can elapse.
[ID] = RoomNode { base = "dbzoo.livebox.jeenode:bedroom1", endpoints = {temp="temperature",lobat=1,light=1}, ttl=300 } }
The mininum TTL is defined by how often the SKETCH that you uploaded is configured to report.
roomNode2.pde
#define MEASURE_PERIOD 300 // how often to measure, in tenths of seconds #define RETRY_PERIOD 10 // how soon to retry if ACK didn't come in #define RETRY_LIMIT 5 // maximum number of times to retry #define ACK_TIME 10 // number of milliseconds to wait for an ack #define REPORT_EVERY 5 // report every N measurement cycles #define SMOOTH 3 // smoothing factor used for running averages
This set of #defines configure this stuff. Measure every 30 seconds, report every 5 cycles = 150 seconds (this is your base minimum TTL).
So 120 is too small… 180 is fine - Personally I would make the TTL at least 2x the reporting cycle, this way you can miss ONE event and it won't time out as the 2nd one will reset things. So I would use a TTL of 300 seconds.
Identical to Room Node but has an additional 1wire sensor for Temperature on JeePort2 (PD.5) See nodule_io_pins for wiring.
Exposes the additional endpoint
RoomNodeTwin = require("xap.roomnodetwin").RoomNode
[3] = RoomNodeTwin{base="dbzoo.livebox.jeenode:3", endpoints={temp=1,temp2=1}, ttl=900},
This Decoder and Sketch is handy if you have Node in a room with temp sensor on an extension cable and want to monitor another room, an heating/air conditioning duct output for the room or simple a sensor outside the window.
The room node is a sensor unit that can monitor the following environmental conditions.
The Arduino sketch has been designed for low power. It's ideal for running from batteries
For example we have a battery powered unit configured as a RoomNode to monitor temperature using a DS18B20 1wire device.
This unit would be minimally configured to expose the following xAP endpoints; temp, lobat
[ID] = RoomNode{base="dbzoo.livebox.jeenode:bedroom2", endpoints = {temp=1,lobat=1}}
In this configuration we have fitted a board with light sensor and temperature sensor but it will be powered from a 5v USB power supply using its programming cable.
The DS18B20 temperature sensor must be plugged into Port 1 - Legend P1 on the PCB and it uses the following connection 'P' (Power), 'D' (Data), 'G' (Ground). As the temp sensor uses a 1-wire bus you need (4.7k) pullup resistor between 'D' and 'P'.
The LDR light sensor fits onto Port 4, legend P4 on the PCB. One leg of the LDR goes to pin 'A' (Analogue) the other goes to 'G' (Ground)
If the above board was configured as ID 2 - we could use the following configuration setting to enable just the Temperature and Light endpoints, there is no point in reporting on Low Battery as this unit would be permanently powered.
[ID] = RoomNode{ base = "dbzoo.livebox.jeenode:bedroom2", endpoints = {temp=1,light=1} }
The OutputNode sketch, and matching Lua class, exposes the digital ports 1-4 as I/O controllable xAPBSC endpoints. If not all ports are not being used they can be individually disabled by leaving them out of the endpoint definition or by setting their value to 0 (zero).
Snippet of configuration information needed in the jeenodeApplet.lua source.
OutputNode = require("xap.outputnode").OutputNode
local nodes = {
[ID]=OutputNode{base="dbzoo.livebox.jeenode:attic"},endpoints={p1=1,p2=1,p3=1,p4=1}}
}
So now we can simply use a xAPBSC.cmd class message to control these newly created endpoints. Here is an example of turning on JeeNode Port 1 from the above configuration.
xap-header
{
v=12
hop=1
uid=FF000F00
class=xAPBSC.cmd
source=dbzoo.livebox.demo
target=dbzoo.livebox.jeenode:attic.p1
}
output.state.1
{
id=*
state=on
}
Controlling an OutputNode from the Joggler in this video we simply toggle 4x LEDs on/off.
HAH remote control of JeeNodes using a Joggler
This node provides the following endpoints (p1,p2,p3,p4) for example:
dbzoo.livebox.jeenode:attic.p1 dbzoo.livebox.jeenode:attic.p2 dbzoo.livebox.jeenode:attic.p3 dbzoo.livebox.jeenode:attic.p4
We can rename them like this to produce dbzoo.livebox.jeenode:attic.port1 etc..
local nodes = {
[ID]=OutputNode{base="dbzoo.livebox.jeenode:attic",endpoints={p1="port1",p2="port2",p3="port3",p4="port4"}}
}
Block diagram of how the IRnode fits into the system
By attaching a Infrared receiver to a JeeNode unit we can relay the signal transmitted from the Remote Control to the HAH and produce an xAP message. This message then becomes the hook for User Applet scripts to attach and take action.
Typical configuration in the JeeNodeApplet.lua
IRNode = require("xap.irnode").IRNode
...
local nodes = {
[2] = IRNode{base="dbzoo.livebox.jeenode:ir"},
}
This configures the JeeNode with ID of 5 and with an attached IR sensor to relay messages, via RF, to the HAH unit.
The IR sensor data pin is connected to
| Port | Type | Arduino | Signal | Chip | |||||
|---|---|---|---|---|---|---|---|---|---|
| Port 2 | DIO | Digital 5 | PD5 | pin 11 |
Once the IRnode.pde sketch is loaded onto your jeenode and the HAH is correctly configured, pressing a button on your remote control should produce a message like this.
xap-header
{
uid=FF08DBFE
source=dbzoo.livebox.jeenode:ir
hop=1
class=IR.Comms
v=12
}
ir.received
{
value=550717623
type=1
bits=32
}
Note that this configuration is better suited to a JeeNode that is not battery powered.
This shows the pin/port allocation for the HANnode/jeenode configurations above
RFM12B at the bottom and FTDI connector at the top