Drivers, Interfaces. Devices, and Events

It's useful to adopt a strict terminology, to get the core model as clear (and clean) as possible:

  • Drivers are software - this is where actual data processing takes place
  • Interfaces - the built-in hardware which lets us communicate with the outside world
  • Devices are hardware - real-world stuff made of atoms, which you buy or build, and then hook up
  • Events represent "things that happen" - on a busy system, a lot of 'em get created and deleted

In a strictly relational world, each of these would be called an entity, where a device would be consider an association between a driver and an interface. Similarly, events are associated as 1:N to devices. More intuitively: each device is tied to a specific driver and interface, and devices generate events.

There can be many drivers, of which most won't be used in any particular setup (i.e. those for which you don't have the hardware). And the same driver might be in use several times, if you have multiple devices of that particular type.

Interfaces are either real (e.g. built-in serial ports), or virtual and dynamically created (e.g. plugging in a new USB device). At most one driver can be connected with an interface at any point in time.

Devices are mapped at run time by "registering" them. Registration is the act of specifying a driver and an interface, and giving the combination a unique name.

Events is where things start to come alive. Once a device has been registered, it can start generating events as text is received or packets come in. It is up to the interface to define what consitutes an event. Events can also be created outside of devices (by user interaction, the passing of time, or even by changes in state variables), as a way to initiate outbound activity through a driver.

A different way to look at this is:

  • drivers always exist (as source files), even when the system is not running
  • interfaces tend to be fairly stable for any particular computer setup
  • devices are tied to a registration process, which is a configuration choice
  • events are short-lived objects, representing the "real" activity of the system

There's an example called driver-demo, which illustrates how things work together. The first two lines are boilerplate code:

Jm doc "How to decode messages coming from a JeeLink with RF12demo."
Drivers load ./drivers

This is the name of the interface we'll use for the JeeLink running RF12demo:

set interface usb-A700fdxv ;# or COMn or /dev/ttyUSBn

Next step is to register all nodes, to associate them with the proper driver:

Drivers register RF12-868.5.2 roomNode
Drivers register RF12-868.5.3 radioBlip
Drivers register RF12-868.5.4 roomNode
Drivers register RF12-868.5.5 roomNode
Drivers register RF12-868.5.6 roomNode
Drivers register RF12-868.5.17 oneLong
Drivers register RF12-868.5.19 ookRelay2
Drivers register RF12-868.5.23 roomNode
Drivers register RF12-868.5.24 roomNode

The last step is to create a device, i.e. associate the interface with a driver:

Drivers connect $interface RF12demo

At this point the system will come to life. Each incoming line of text will create an event, which then gets dispatched to the RF12demo driver. The RFM12demo driver is a bit special, because it's really more a gateway between a real device and a range of remote devices.

The result of this all is that received packets will be read, dispatched, decoded, and end up as readings updating their correspondign state variables. To see that this is really happening, there is one more line of code which needs to be added:

State subscribe * {apply {x { Log state "$x = [State get $x]" }}}

This calls an anonymous function on every state variable matching the pattern "*", i.e. any change. The anonymous function simply generates a log entry with the name and current (i.e. new) value of the affected state variable.