Class BabelEncoderMatrixDemo

java.lang.Object
pt.unl.fct.di.novasys.babel.core.GenericProtocol
pt.unl.fct.di.tardis.babel.iot.demos.BabelEncoderMatrixDemo
All Implemented Interfaces:
BabelDemo

public class BabelEncoderMatrixDemo extends pt.unl.fct.di.novasys.babel.core.GenericProtocol implements BabelDemo
Demo: drive a Grove LED matrix from a Grove rotary encoder. Turning the knob clockwise grows a "bar" on the matrix; turning it counter-clockwise shrinks it. It is a small but complete input → output loop: a reactive input device feeds an output device, both mediated entirely by Babel events.

This is the demo to read to learn the asynchronous notification pattern. Unlike the LED and LCD demos (which only register an output device and drive it on a timer), this one subscribes to an EncoderNotification: the input control protocol pushes one to us every time the knob turns, and we react by updating the matrix. There is no polling.

Devices & control protocols used.

  • Grove LED matrix (DeviceType.GROVE_LED_MATRIX) — output, driven through I2COutputControlProtocol (protocol id 2000).
  • Grove rotary encoder (DeviceType.GROVE_ENCODER) — reactive input, read through DigitalInputControlProtocol (protocol id 2200), which emits EncoderNotifications.
Two control protocols, two registered devices, one application protocol — a single Babel app routinely drives several devices across several buses at once.

The teaching point. The app never touches Pi4J, GPIO or I²C directly. It registers two devices, subscribes to encoder turns, and reacts by sending a DisplayBarRequest; the control protocols do all the hardware work.

To run: java -jar <jar> encoderMatrix (see Main.java).

Configuration. The encoder's GPIO line is read from the encoder.line property (default 5) in paradigmshift.config; the matrix is an I²C device and needs no line.

Based on IoT-control demos originally developed at NOVA FCT for the TaRDIS project; provided and evolved independently by ParadigmShift.

  • Nested Class Summary

    Nested classes/interfaces inherited from class pt.unl.fct.di.novasys.babel.core.GenericProtocol

    pt.unl.fct.di.novasys.babel.core.GenericProtocol.ProtocolMetricsBabelMetrics
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    Config key naming the GPIO line the rotary encoder is wired to.
    static final String
    Default GPIO line for the encoder.

    Fields inherited from class pt.unl.fct.di.novasys.babel.core.GenericProtocol

    babel, babelSecurity

    Fields inherited from interface pt.unl.fct.di.tardis.babel.iot.demos.BabelDemo

    PROTO_ID, PROTO_NAME
  • Constructor Summary

    Constructors
    Constructor
    Description
    Sets the protocol identity shared by all demos (BabelDemo.PROTO_NAME / BabelDemo.PROTO_ID).
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Entry point for this demo (called from Main).
    void
    handleRegisterIoTDeviceReply(pt.unl.fct.di.tardis.babel.iot.api.replies.RegisterIoTDeviceReply rep, short protocolId)
    Shared reply handler for both device registrations.
    void
    Wires this protocol's event handlers and registers both devices.

    Methods inherited from class pt.unl.fct.di.novasys.babel.core.GenericProtocol

    addSecret, addSecret, addSecret, addSecret, cancelTimer, closeConnection, closeConnection, closeConnection, closeConnection, closeConnection, closeConnection, createChannel, createSecureChannel, createSecureChannel, createSecureChannel, createSecureChannelWithAliases, createSecureChannelWithAliases, createSecureChannelWithIdentities, createSecureChannelWithIdentities, createSecureChannelWithProtoIdentities, enableGenericMetrics, generateIdentity, generateIdentity, generateIdentity, generateIdentity, generateIdentity, generateIdentity, generateIdentity, generateSecret, generateSecret, generateSecret, generateSecret, generateSecretFromPassword, generateSecretFromPassword, generateSecretFromPassword, generateSecretFromPassword, getChannelOrThrow, getDefaultChannel, getDefaultProtoIdentity, getDefaultProtoIdentityCrypt, getDefaultProtoSecret, getMillisSinceBabelStart, getOrGenerateDefaultProtoIdentity, getProtoId, getProtoName, hasProtocolThreadStarted, openConnection, openConnection, openConnection, openConnection, registerChannelEventHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageHandler, registerMessageSerializer, registerMetric, registerReplyHandler, registerRequestHandler, registerSharedChannel, registerTimerHandler, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendMessage, sendReply, sendRequest, setDefaultChannel, setDefaultProtoIdentity, setDefaultProtoIdentity, setDefaultProtoSecret, setupPeriodicTimer, setupTimer, startEventThread, subscribeNotification, triggerNotification, unsubscribeNotification

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • ENCODER_PORT

      public static final String ENCODER_PORT
      Config key naming the GPIO line the rotary encoder is wired to.
      See Also:
    • ENCODER_PORT_DEFAULT

      public static final String ENCODER_PORT_DEFAULT
      Default GPIO line for the encoder.
      See Also:
  • Constructor Details

  • Method Details

    • init

      public void init(Properties props) throws pt.unl.fct.di.novasys.babel.exceptions.HandlerRegistrationException, IOException
      Wires this protocol's event handlers and registers both devices.

      The ordering is the key lesson:

      1. Register the RegisterIoTDeviceReply handler before sending any registration request, so the reply cannot arrive first. One reply handler serves both devices; it tells them apart by RegisterIoTDeviceReply.getDeviceType().
      2. subscribeNotification(EncoderNotification...) — this is how the demo receives asynchronous encoder turns. Once the encoder is set up for reactive reporting, the input control protocol pushes an EncoderNotification on every detent.
      3. Send a RegisterIoTDeviceRequest for each device, each to its owning control protocol — the matrix to I2COutputControlProtocol (no GPIO line; it is I²C) and the encoder to DigitalInputControlProtocol (with its GPIO line).
      The handles arrive asynchronously in handleRegisterIoTDeviceReply(pt.unl.fct.di.tardis.babel.iot.api.replies.RegisterIoTDeviceReply, short).
      Specified by:
      init in class pt.unl.fct.di.novasys.babel.core.GenericProtocol
      Throws:
      pt.unl.fct.di.novasys.babel.exceptions.HandlerRegistrationException
      IOException
    • handleRegisterIoTDeviceReply

      public void handleRegisterIoTDeviceReply(pt.unl.fct.di.tardis.babel.iot.api.replies.RegisterIoTDeviceReply rep, short protocolId)
      Shared reply handler for both device registrations. Babel routes every RegisterIoTDeviceReply here; we demux on RegisterIoTDeviceReply.getDeviceType() to learn which device it is for and stash the matching DeviceHandle.

      When the encoder reply arrives we issue a GetReactiveEncoderRequest with a Threshold.none() threshold: that arms the encoder for reactive reporting, so every subsequent turn comes back as an EncoderNotification (handled in handleEncoderNotification(pt.unl.fct.di.tardis.babel.iot.controlprotocols.notifications.EncoderNotification, short)). On any failure the demo bails out, and each branch sanity-checks the alias against what we asked for.

    • execute

      public void execute() throws Exception
      Entry point for this demo (called from Main). Bootstraps Babel: grab the Babel singleton, load paradigmshift.config, instantiate the two control protocols this demo needs (I2COutputControlProtocol for the matrix, DigitalInputControlProtocol for the encoder), register them plus this demo, then init all three in dependency order (control protocols first so their handlers exist before the demo sends to them) and start the event loop.
      Specified by:
      execute in interface BabelDemo
      Throws:
      Exception