A lightweight wait light!
NOTE This is the description of the lightwait-stack, the architecture of the lightwait eco-system. For the product "lightwait", see lightwait-go-shell , the reference implemenation of a lightwait-trigger, containing information how to connect to lightwait-arduino, the reference implementation of a lightwait-presenter! (or take a look at the CLI-status notifier section)
- Principles
- Trigger
- Transmitter
- Presenter
- Inter-layer communication protocols
- Known colors
- How to
- All related Repositories
- Acknowledgements
- License of this documentation/specification
The different lightwait programs follow these common principles:
- Splitted in a three layer stack
- CLI based transmitters)
- Pure push based
- Pure color based
- Code duplication over dependencies
- Language-agnostic
- Free
lightwait consists of a three layered stack. Each stack can be implemented by a different program which then connects to its previous or next layer via protocols.
One program implements one or more than one layer, removing the need to a protocol based communication. This also makes the program and its usage less flexible.
The three layers are:
Transmitters should be as simple as possible, so that every trigger written in any programming language or script is able to call a transmtiter.
To achieve this, transmitters are cli-based. So every script or program which is able to spawn a child process and execute a command, is able to start a transmitter.
To establish a protocol which is as simple as possible, the trigger is the only unit initiating updates, there is no way to pull the latest status. Also presenters don't offer a listener/callback/observable to register to.
This has the following consequences:
- The trigger can be implemented stateless
- The presenter most likely can be implemented stateless besides displaying the latest status as color
- If the communication based on a not-reliable protocol (like e.g. UDP), updates might be lost
- If the presenter is switched off and on again, it displays no status until the next update is sent
The only information which is transmitted from the trigger to the presenter (via a transmitter) is a color. Therefore is the trigger the only entity which decides which color should be displayed in which situation. Hence, the trigger is the only place to contain business logic.
- Every presenter is able to work with every trigger (as long as a transmitter which works with the presenter exists)
- Transmitter and presenter are easy to write, as they don't contain business logic. That means they are small and easy to read, and therefore less error-prone.
- Every Presenter should support the full range of 24-Bit RGB colors. (Like in the web,
#000000
(black) to#FFFFFF
(white) and everything in between. This doesn't necessarily mean the presenter has to be able to display every of these colors. It's also applicable to round a color code to the next displayable color. But the presenter has to be robust to accept every color in this range!
Every project implementing a trigger/transmitter/presenter in the lightwait-stack should be independent of other projects. This has the consequence that some lines of code are duplicated several times (e.g. the parsing and translating of colors in transmitters). But to enable users to select every layer of the lightwait-stack independently of other layers and to even allow cross-language selections, small simple and isolated projects are important.
This means to not even create utils projects to reuse common functionalities!
By complying to these principles:
- Splitted in a three layer stack
- CLI based (or integrated as library)
- Code duplication over dependencies
lightwait offers developers to add their missing layer of the stack in the programming language and the technology stack of their desire. Different layers of the stack can be written in different languages and can be changed independently.
... as in free speech!
Every related repository contains code written under a free license. The default should be the GPLv3 (but it's not guaranteed, that all repositories really are released under this license, check the specific repository for details!). And all contributors are encouraged to also release their code under a free license like the GPLv3.
This enables every user to investigate what the code is doing and can adapt or copy it easily.
In addition, this document is also released under a free license, encouraging developers to contribute, use and distribute lightwait.
A trigger calls the connected transmitter to deliver the change to the presenter. It contains all the logic regarding what color corresponds to which status and which colors (and therefore) statuses are available.
This type of trigger was the reason to initially create the lightwait project. It tries to provide a support for developers, who run a long-running task in the shell (like npm start
, gradle build
or mvn clean install
) and wants to do other work while the task is executed. Besides that, they want to be informed, when the task it completed (or in a stable state, when it's a non-terminating task like npm start
).
For that, a CLI-wrapper named lw
is created, which calls the real task. So just launch
lw mvn clean install
lw npm start
lw gradle build
instead, and the status will be passed to the connected lightwait-transmitter, which will forward this to a lightwait-presenter. For more details, take a look at the documentation of the trigger projects.
Currently there are two triggers which implements this logic:
Trigger | programming language | description |
---|---|---|
lightwait-go-shell | go | This project may be compiled to a binary CLI for multiple operation systems and multiple architectures. It may call a lightwait-transmitter by a sub-process, or include lightwait-go as library to already contain the transmitter. |
lightwait-shell | bash/batch | This project contains one bash file for linux/unix/cygwin machines and a batch file for windows machines. They are able to call a lightwait-transmitter as a sub-process. They lack some functionality compared to lightwait-go-shell. |
A lightwait-transmitter receives are color code (which may include a blink code) and sends this information to the presenter. As the presenter may be a different hardware device, the transmitter establishes and handles the communication stream to its presenter. A transmitter may support more than one presenter and therefore more than one communication stream.
The default port for TCP and UDP based connections is: 3030
Use a transmitter of the programming language of your choice as base of your own trigger.
Available transmitters and the presenters they can connect to:
Transmitter | programming language | description |
---|---|---|
lightwait-go | go | Is able to connect to an arduino via serial communication |
lightwait-python | python | Is able to connect to an arduino via serial communication |
lightwait-python-tcp-udp | python | Is able to communicate to presenters via TCP or UDP |
lightwait-node-tcp-udp | JavaScript | Is able to communicate to presenters via TCP or UDP |
lightwait-python-multiplexer | python | Is not a real transmitter, but an entity placed before, to split every received signal to multiple transmitters at the same time |
lightwait-python-jambel | python | Is able to communicate with a jambel device, using python-jambel |
See: lightwait-transmitter-test
A lightwait presenter displays the state set by the trigger using one RGB LED. Supporting multiple LEDs is planned.
A presenter may be a program running locally on the same machine as the trigger and transmitter, or it may be a different hardware device. So the lightwait presenter is in fact one of the following:
- just a program, which can be started locally
- A program which must be running on the additional hardware device, like an arduino or a raspberry pi
- An existing (third party) hardware device, which is able to display a color (like the fast-feedback lights also called "jambel"). So no presenter code exists in this case.
Presenters should be independent of a lightwait-trigger logic, although they might be optimized for specific usecases.
Available presenters:
Presenter | programming language | description |
---|---|---|
lightwait-arduino | C | Code that runs on an arduino to display the received color with a connected RGB LED |
lightwait-gnome-extension | JavaScript for gjs | An extention for the gnome 3 Desktop Environment placing a received color in the gnome panel |
lightwait-python-gtk | python | A GTK3 application displaying the received color in a gtk window |
(jambel) | --- | A hardware device without code written in this project. Can be used to display triafficlight-like colors and can be controled using python-jambel |
lightwait-js-web-extension | JavaScript | A Web-extension supporting Firefox and Chrome displaying the received color in the toolbar |
lightwait-python-pi | python | A presenter using GPIO pins on the Raspberry Pi. Compatible with every Raspberry Pi version! |
Also possible (not not actually planned):
- lightwait-android
- lightwait-ios
This is also called lightwait-tt communication protocol
The way the trigger communicates with the transmitter. Based on the used components, the transmitter should be separate from the trigger or may be combined with the trigger to one program. A separation may be useful, when the presenter should be an external hardware device (like an arduino, when using lightwait-arduino or raspberry pi. An addition to the ISO layer 7 protocol, they also need lower-layer communication. To keep this out of the trigger, which should only contain the business logic of the status (i.e. color) change, an additional transmitter should be used.
If the transmitter is in fact a library, which can be imported and used by a trigger to include the functionality in a combined program, take a look at the readme of this library to see how to use it.
Currently available transmitters which can be used as a library are:
lightwait-transmitters which are CLI based, are scripts or binary programs, which accept the color/blinking code as parameter.
The first parameter should consist the complete color/blinking code. Being of one of the following formats
- A known color, e.g. "yellow"
- A 6-digit hex-code, e.g. "FF0034"
- A 3-digit hex-code, e.g. "F0C" (means "FF00CC" in the 6-digit format, so double every digit)
- One of the three above, prefixed with "b-", e.g. "b-red", "b-F0C" or "b-FF4423"
- (A proposal for a multi-color-blinking status)
In every case, the color-code should be interpreted case-insensitive, although some letters are lowercase and some uppercase, for readability purposes.
Currently available CLI parameter-based transmitters:
- lightwait-go
- lightwait-python
- lightwait-python-jambel
- lightwait-python-tcp-udp
- lightwait-node-tcp-udp
- lightwait-python-multiplexer
This is also called "lightwait-tp communication protocol"
Every Presenter may offer different payload formats, especially when using third party LED devices as lightwait-presenters.
Anyways it exists a recommendation for implementing a lightwait-presenter, which simplifies the interoperability between different transmitters and presenters. It's therefore suggested, that a program which operates as lightwait-transmitter, should implement this communication protocol, even when implementing others in addtion.
This communication protocol is called lightwait-tpp (lightwait-transmitter-presenter-protocol).
Schema: <red>:<green>:<blue>
where every color value is between 0 and 255.
Some examples:
Color | Value |
---|---|
Black | 0:0:0 |
Red | 255:0:0 |
White | 255:255:255 |
Magenta | 255:0:255 |
Schema: b<red>:<green>:<blue>
where every color value is between 0 and 255.
Some examples:
Color | Value |
---|---|
Black | b0:0:0 |
Red | b255:0:0 |
White | b255:255:255 |
Magenta | b255:0:255 |
Schema: b<red>:<green>:<blue>|<red>:<green>:<blue>|...
Some examples:
Color | Value |
---|---|
Red and green | `b255:0:0 |
Red-yellow-green | `b255:0:0 |
This is a non-standardized idea and currently not part of the lightwait-stack.
Currently, these are all known colors, which should be available for the lightwait-tt communication.
Name | Hex-code | lightwait-tp | comment |
---|---|---|---|
red | #FF0000 | 255:0:0 | |
green | #00FF00 | 0:255:0 | |
blue | #0000FF | 0:0:255 | |
yellow | #FFFF00 | 255:255:0 | |
magenta | #FF00FF | 255:0:255 | |
cyan | #00FFFF | 0:255:255 | |
white | #FFFFFF | 255:255:255 | |
black | #000000 | 0:0:0 | |
off | #000000 | 0:0:0 | might also close the connection of the transmitter, check the description |
- Three digit hex codes
- Six digit hex codes
If you want to write your own trigger, there are basically three different possibilities:
First it's important how your trigger should behave. Does it have a "one-time result", or is it an ongoing stream of status information.
- Write a script and use it with lw
- The script should use the exit code to publish succes/failure, if it's a completing task using
lw
- The script should use color texts and print them using
lw --live
- The script should use the exit code to publish succes/failure, if it's a completing task using
- Write a script, which prints the color via
stdout
and use it with lw --live-color - Write your very own trigger, which calls a transmitter
This shouldn't be necessary for most of the usecases, as transmitters could be reused by every trigger. So please first check the Transmitters and the related repositories If you have a communication channel for which no transmitter exists and you have to write one, please contribute this improvement to lightwait!
TODO
If you do wrote your own transmitter, be sure to use the lightwait-transmitter-test.
TODO
Name | type | programming language | description |
---|---|---|---|
lightwait-go-shell | Trigger | go | |
lightwait-shell | Trigger | bash/batch | |
lightwait-go | Transmitter | go | |
lightwait-python | Transmitter | python | |
lightwait-python-tcp-udp | Transmitter | python | |
lightwait-node-tcp-udp | Transmitter | JavaScript | |
lightwait-python-multiplexer | (Meta-) Transmitter | python | |
lightwait-python-jambel | Transmitter | python | Using python-jambel to connect to fast-feedback lights |
lightwait-arduino | Presenter | C | |
lightwait-gnome-extension | Presenter | JavaScript for gjs | |
lightwait-python-gtk | Presenter | python | |
lightwait-js-web-extension | Presenter | JavaScript | Currently only supporting Firefox and Chrome |
lightwait-python-pi | Presenter | python | |
lightwait-go-set | Configuration setter for lightwait-go-shell | go | |
lightwait-transmitter-test | Testsuite for transmitters | python | Testsuites for TCP and UDP transmitters already exist. Easy extendable for other transmitters |
- Thanks to the serial-port-json-server project, for the code for determine the arduino port for the go version!
- Thanks to the system-monitor project, helping me to understand how to write gnome-extensions, by looking at the source!
- Thanks to Max for a printable arduino case design and the catchy slogan! :)
- Thanks to moepi for suggesting to implement it in go and made me to want to learn it! :)
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.