/p44features

A set of C++ classes, driving various hardware "features" using a common JSON API

Primary LanguageC++GNU General Public License v3.0GPL-3.0

p44features

[if you want to support p44features development, please consider to sponsor plan44]

p44features is a set of free (opensource, GPLv3) C++ classes and functions building a library of "features" for various applications in exhibitions, experiments, art and fun projects. Each "feature" usually drives a particular piece of hardware, such as LEDs, solenoids, sensors etc. The features have a common base class and are accessible via a common JSON API. When used in applications with p44script enabled, these features can also be controller from on-devices scripts.

p44features needs some classes and functions from the p44utils and p44lrgraphics libraries.

Projects using p44features (or cointaining roots that led to it) include the ETH digital platform, the "chatty wifi" installation I brought to the 35c3, or the "hermeldon 2018" remote crocket playing installation (both in the hermel branch of lethd). The p44features are also integrated in the vdcd project, which allows for interesting augmentation of home automation and lighting systems.

Usage

p44features sources are meant to be included as .cpp and .hpp files into a project (usually as a git submodule) and compiled together with the project's other sources.

A configuration header file p44features_config.hpp needs to be present in the project, and allows customizing some aspects of p44features.

To get started, just copy the p44features_config_TEMPLATE.hpp to a location in your include path and name it p44features_config.hpp.

License

p44features are licensed under the GPLv3 License (see COPYING).

If that's a problem for your particular application, I am open to provide a commercial license, please contact me at luz@plan44.ch.

Features

List of currently available features, will expand with each new project:

  • indicators: areas in a LED strip or matrix used as indicators with different styles
  • rfids: multiple cheap RFID readers as user-detecting "buttons"
  • dispmatrix: time synchronized LED matrix displays for large scrolling text display
  • inputs: use any GPIO, or pins of some i2c/spi based I/O extensions, or console keys for simulation, as generic inputs
  • light: simple PWM light dimmer
  • splitflaps: RS485 controlled splitflap display modules (as produced by Omega for Swiss Railways (SBB) and also other railways, such as Deutsche Bahn).
  • neuron: sensor triggered "conductance" light effect
  • mixloop: accelerometer triggered ball movement detector and light effect
  • wifitrack: visualizing WiFi SSIDs revealed to the public in probe requests
  • hermel: dual solenoid crocket playing driver

Feature API

Note: this is Work in Progress, not all features are documented here

General

Feature API calls consist of a JSON object. One call can contain one command and/or optionally property values to set.

  • A command consists of a cmd field containing the command name plus possibly some parameters. Commands directed to a specific feature always need the feature parameter.
  • Setting a property consists of a propertyname:value JSON field
  • The init command is special in that it always has a single parameter named after the feature to initialize, it's value being the configuration for the feature (just true in simple features w/o config, but often a JSON object containing config data in a feature specific format.

See below for examples

global commands

{ "cmd":"status" }

  • get status of all features

{ "event":{ ... } }

  • inject an event (that might be processed by custom p44script on device).

common to all features

{ "cmd":"status", "feature": "<featurename>" }

  • get status of all features

{ "logleveloffset":<offset>, "feature": "<featurename>" }

  • set log level offset property for a feature (making its log more/less verbose)

Dispmatrix

Initialisation

{ "cmd":"init", "dispmatrix": { "installationX": <overall-x>, "installationY": <overall-y>, "rootview": <p44lrgraphics-view-config> }

  • x,y: position of this p44feature unit in a longer scroller consisting of multiple p44feature based hardware units. This allows sending the same global scrolling offsets to all units, and each unit interprets it according to its position in the overall installation.
  • if no p44lrgraphics-view-config is specified, the root view will be set to a scroller labelled "DISPSCROLLER" filling the entire LEDarrangement. If a custom view config is passed, it should contain a scroller named "DISPSCROLLER".
  • p44lrgraphics-view-config can be the view config JSON object itself or a resource file name. A relative filename will be searched in the /dispmatrix subdirectory of the app's resource directory.

Start scrolling

{ "feature":"dispmatrix", "cmd":"startscroll", "stepx":<x-step-size>, "stepy": <y-step-size>, "steps": <num-steps>, "interval": <step-interval-seconds>, "roundoffsets": <bool>, "start": <absolute_unix-time-in-seconds> }

  • step sizes can be fractional
  • num-steps can be negative for unlimited scrolling
  • roundoffsets causes the current scroll offsets to be rounded to integer number before starting scroll
  • absolute_unix-time-in-seconds allows strictly synchronized scrolling start over multiple (NTP synchronized!) hardware units. if null is passed, scrolling starts at the next 10-second boundary in absolute unix time.

Stop scrolling

{ "feature":"dispmatrix", "cmd":"stopscroll" }

Fade Alpha

{ "feature":"dispmatrix", "cmd":"fade", "to": <target-alpha>, "t": <fade-time-in-seconds> }

(Re)Configure a view

{ "feature":"dispmatrix", "cmd":"configure", "view": <view-label>, "config": <p44lrgraphics-view-config> }

Set a "scene"

{ "feature":"dispmatrix", "scene":<p44lrgraphics-view-config> }

  • Setting a scene means replacing the "DISPSCROLLER"'s scrolled view by a new view. This special command makes sure changing the scrolled view's works with wraparound scrolling over multiple modules.

Set scroll offsets

{ "feature":"dispmatrix", "offsetx":<offset-x> }

{ "feature":"dispmatrix", "offsetx":<offset-y> }

  • This sets the content's scroll position, relative to the configured installationX/Y offsets

Indicators

Initialisation

{ "cmd":"init", "indicators": { "rootview": <p44lrgraphics-view-config> } }

  • if no p44lrgraphics-view-config is specified, the root view will be set to a stack labelled "INDICATORS" filling the entire LEDarrangement. If a custom view config is passed, it should contain a stack named "INDICATORS".

Show an indicator

{ "feature":"indicators", "cmd":"indicate", "x":<x-start>, "dx":<x-size>, "y":<y-start>, "dy":<y-size>, "effect":"<effect-name-or-viewconfig>", "t":<effect-duration-in-seconds>, "color":"<web-color>" }

  • effect-name-or-viewconfig can be one of the built-in effects (at this time: "plain", "swipe", "pulse", "spot") or configuration of a view (including animations) to be shown at the specified coordinates. The view can be specified as inline JSON or via specifying the resource name of a resource file. A relative filename will be searched in the /indicators subdirectory of the app's resource directory.

RFIDs

Initialisation

{ "cmd":"init", "rfids": { "readers": [<index>, <index>,...], "pollinterval":<pollinterval_seconds>, "sameidtimeout":<re-reporting-timeout> "pauseafterdetect":<poll-pause-after-card-detected> } }

  • index are the physical bus addresses (0..23 in p44rfidctrl and p44rfidhat hardware) to select the reader. Depending on which readers on which cables are in use, this can be a sequence of numbers with or without gaps.
  • pollinterval_seconds is the polling interval for the connected readers, i.e. how often every reader will be checked for the presence of a new RFID tag (default: 0.1 seconds)
  • re-reporting-timeout is the time during which a reader will not report the _same nUID again (default: 3 seconds)
  • poll-pause-after-card-detected is the time polling RFIDs will be paused after detecting a card - mainly to free performance for LED effects, as SPI on RPi seems to block a lot (default: 1 second)

API events

{ "feature":"rfids", "nUID":"<rfid_nUID>", "reader":<rfid-reader-index> }

  • rfid_nUID is the nUID of the RFID tag seen
  • rfid-reader-index is the physical bus address of the reader which has seen the RFID tag

Splitflaps

Initialisation

{ "cmd":"init", "splitflaps": { "modules":[ {"name":"<module_name>","addr":<module_address>,"type":"<hour|minute|40|62>"}, ... ] }}

  • The "modules" array defines the splitflaps to be used.
  • name is a handle for the module to access it with the position command later (see below).
  • module_address is the module address of the splitflap module (for SBB (Swiss Railways) modules, usually written onto a yellow sticker on the module itself, but as the address can be reprogrammed, the sticker might not be correct in all cases).
  • the "type" field specifies the module kind. hour and minute are basically the same as 40 and 62, however the flap indices are made to match the actual numerical display (the flaps are not in strict ascending order in those modules). 40 and 62 are for generic modules with 40 and 62 flaps, resp.

Set splitflap positions

{ "feature":"splitflaps", "cmd":"position", "name":"<module_name>", "value":<flap_number> }

Sets the module that was named module_name at initialisation (see above) to position flap_number, starting at 0 for the first flap (in 42 und 60 type modules, and with hour 0/minute 00 for hour and minute type modules.

Generic Inputs

Initialisation

{ "cmd":"init", "inputs": { "<input_name>":{ "pin":"<pin_spec>", "initially":<initial_bool>, "debouncing":<debounce-in-seconds>, "pollinterval":<pollinterval-in-seconds> } , ... } }

  • input_name is a name which is included in the API events to identify the input.
  • pin_spec is a p44utils DigitalIo pin specification
  • optional initial_bool is the initial value the input is assumed to have (to force/prevent event at init)
  • optional debounce-in-seconds sets debouncing time (default = 80mS)
  • optional pollinterval-in-seconds sets polling interval (default = 250mS). This is only for inputs which do not have system level edge detection.

API events

{ "feature":"inputs", "*input_name*":*input_value* }

  • input_name is a name of the input.
  • input_value is the current value of the input

Supporting p44features

  1. use it!
  2. support development via github sponsors or flattr
  3. Discuss it in the plan44 community forum.
  4. contribute patches, report issues and suggest new functionality on github or in the forum.
  5. Create cool new features!
  6. Buy plan44.ch products - sales revenue is paying the time for contributing to opensource projects :-)

(c) 2013-2022 by Lukas Zeller / plan44.ch