-
Notifications
You must be signed in to change notification settings - Fork 15
Make Your Own Hexabus Device
This document can help you build your own Hexabus compatible device using one of the Hexabus prototype boards.
Keep in mind that the Hexabus software and the Hexabus protocol are work in progress. Things may change, even to the point where different versions become completely incompatible with each other. If you're working on a Hexabus device, please try to stay updated on what happens in the development branch of the repository. And of course, if you find problems or bugs or if you need a new feature, let us know!
This document refers to the development branch of the repository.
You need:
- A Hexabus prototype board or a Hexabus Socket
- A Hexabus USB-Stick (for over-the-air flashing) or a JTAGICE or somehow compatible device (for flashing via JTAG)
- A copy of the source tree from the development branch
- All the related software (avr-gcc, cmake, avrdude, ...)
Notes on how to compile and upload a firmware image to a Hexabus Plug or USB Stick can be found under Compiling-and-uploading-Firmware.
Make yourself at least somehow familiar with how Contiki works, and how the Hexabus specific things work. Get to know the hardware, and which features you need for your specific application.
Compile the firmware: Go to firmware/Hexabus-Socket and run make there. (Use the VM for this if necessary) Flash it onto the board (as described in Compiling-and-uploading-Firmware).
If you have a Hexabus Development Board, you might want to change your Hexabus device's IP address at this point. All the prototype boards default to fe80::50:c4ff:fe04:000a, which becomes a problem if you have multiple ones and forget to change the address. The IP address is generated from the MAC address so it is adjusted by changing the device MAC address.
If you want to connect / send packets from your PC to your Hexabus device, you either need a router setup as the one described in Getting Started, or you put the USB Stick into you PC's USB port and run radvd there. The radvd.conf shown in Getting Started should also work there, just adjust the prefix if you have to.
Compile hexaswitch, and try out the network functions the Hexabus Socket software offers (get the device descriptor, switch the relay, get the power meter reading, wait for a value broadcast, ...). You might want to hook up an FTDI to your board (see Hexabusplugserialinterface) to get an idea of what's going on. This also helps a lot during development, PRINTF is your friend.
In most cases, the functionality you want to add is best implemented as one or multiple Contiki processes. Whether you use a process or just add some functions is up to you.
The connection to the Hexabus world is made through the Endpoint Registry. Once you have implemented everything to your liking, adding an endpoint to control your new code from the network requires only a few simple steps:
- Add your endpoint ID to
shared/endpoints.h
-- use the NAME defined there instead of the literal EID everywhere else. - Include
shared/endpoints.h
andendpoint_registry.h
- Add a
read
function to your code. This will be called whenever your endpoint is read, e.g. by queries. The prototype for such a function isstatic enum hxb_error_code read(struct hxb_value* val)
. Simply assign the current value of your endpoint to the appropriate member ofval
for primitive types (e.g.val->v_float
for floating point values) or copy it into the appropriate member for strings and binary packets. ReturnHXB_ERR_SUCCESS
on success, or another hxb_error_code on error. - If required, add a
write
function. These functions have the prototypestatic enum hxb_error_code write(const hxb_envelope* env)
and will we called whenever the endpoint is written to.env->value
will contain the value written to the endpoint for primitive types, or a pointer to the value for strings and binary packets. Writes from other devices in the network will setev->src_ip
to the ip of the device that sent the write packet, andev->src_port
to the corresponding port. Write from the state machine will be executed withsrc_ip == ::1
andsrc_port == 0
. - Give your endpoint a name. Declare the name as
static const char ep_name[] PROGMEM = "<your name>";
- Describe the endpoint. This is done by declaring an endpoint descriptor:
The endpoint registry will check data types for you, take care of EID matching, packet handling and other mundane tasks.
ENDPOINT_DESCRIPTOR ep_your_name = { .datatype = <your hxb_datatype>, .eid = <your EID>, .name = ep_name, .read = read, // name of your read function .write = write // name of your write function, or 0 if the endpoint is read-only };
- Call
ENDPOINT_REGISTER(ep_your_name)
somewhere. At this point, your endpoint will be known to the system.
If your endpoint is some kind of sensor then its reading might be of interest to other Hexabus devices on the network, you can broadcast its value if you want to. If you want to broadcast it periodically, you can set this up in hexabus_config.h -- just add it to the VALUE_BROADCAST_AUTO_EIDS (and don't forget to update VALUE_BROADCAST_NUMBER_OF_AUTO_EIDS). If the endpoint's value should be broadcast whenever some event occurs, you can do this by calling broadcast_value from the value_broadcast module.