Developer Reference¶
This will give you an overview of all the classes in 102shows.
mqttcontrol
¶
The MQTT controller is the essential idea of 102shows: Starting and controlling lightshows via MQTT without making lightshow development very hard.
The MQTT controller takes care of reading the configuration file and initializing the LED strip with the right driver, providing the MQTT interface for starting and stopping shows (of course) and it ensures that only one lightshow is running at the same time. You can think of it as the “main function” of 102shows that is starting and controlling all things that happen.
-
class
mqttcontrol.
MQTTControl
(config: orderedattrdict.AttrDict)[source]¶ This class provides function to start/stop the shows under lightshows/ according to the commands it receives via MQTT
-
notify_user
(message, qos=0)[source]¶ send to the MQTT notification channel: Node-RED will display a toast notification
Parameters: - message – the text to be displayed
- qos – MQTT parameter
Return type:
-
on_connect
(client, userdata, flags, rc)[source]¶ subscribe to all messages related to this LED installation
-
on_message
(client, userdata, msg)[source]¶ react to a received message and eventually starts/stops a show
-
start_show
(show_name, parameters)[source]¶ looks for a show, checks if it can run and if so, starts it in an own process
Parameters: Return type:
-
drivers
¶
Structure¶
102shows is designed to work with several types of LED strips. Currently, only APA102 (aka Adafruit DotStar) chips are supported but other chipsets will be included in the future.
There is also a Dummy driver included.
It does not control any LED strip. It merely manages similar internal
buffers as a “normal” driver and if drivers.dummy.DummyDriver.show()
is called, it will print the state of all LEDs in the hypothetical strip
to the debug output. This is particular useful for tests on a machine
with no actual LED strip attached.
To be able to effortlessly switch between drivers, there is a common
interface: All drivers should base on the class drivers.LEDStrip
and be located under /path/to/102shows/server/drivers
.
Note
For 102shows to find and use the driver, it must have an entry in both
drivers.__all__
and drivers.__active__.drivers
.
Interface¶
-
class
drivers.
LEDStrip
(num_leds: int, max_clock_speed_hz: int = 4000000, max_global_brightness: float = 1.0)[source]¶ This class provides the general interface for LED drivers that the lightshows use. All LED drivers for 102shows should inherit this class. Mind the following:
- Pixel order is
r,g,b
- Pixel resolution (number of dim-steps per color component) is 8-bit, so minimum brightness is
0
and maximum brightness is255
The constructor stores the given parameters and initializes the color and brightness buffers. Drivers can and should extend this method.
Parameters: -
clear_strip
()[source]¶ Clears the color buffer, then invokes a blackout on the strip by calling
show()
Return type: None
-
close
()[source]¶ An abstract method to be overwritten by the drivers.
It should close the bus connection and clean up any remains.
Return type: None
-
static
color_bytes_to_tuple
()[source]¶ Converts a 3-byte color value (like
FF001A
) into an RGB color tuple (like(255, 0, 26)
).Parameters: rgb_color ( int
) – a 3-byte RGB color value represented as a base-10 integerReturn type: tuple
Returns: color tuple (red, green, blue)
-
static
color_tuple_to_bytes
(green, blue)[source]¶ Converts an RGB color tuple (like
(255, 0, 26)
) into a 3-byte color value (likeFF001A
)Parameters: Return type: Returns: the tuple components joined into a 3-byte value with each byte representing a color component
-
freeze
()[source]¶ Freezes the strip. All state-changing methods (
on_color_change()
andon_brightness_change()
) must not do anything anymore and leave the buffer unchanged.Return type: None
-
get_pixel
(led_num)[source]¶ Returns the pixel at index
led_num
Parameters: led_num ( int
) – the index of the pixel you want to getReturn type: tuple
Returns: (red, green, blue)
as tuple
-
max_refresh_time_sec
= 1¶ The maximum time (in seconds) that a call of
show()
needs to execute. Currently only used inlightshows.templates.base.sleep()
-
on_brightness_change
(led_num)[source]¶ Reacts to a brightness change at
led_num
by modifying the message bufferParameters: led_num ( int
) – number of the LED whose brightness was modifiedReturn type: None
-
on_color_change
(led_num, red, green, blue)[source]¶ Changes the message buffer after a pixel was changed in the global color buffer. To send the buffer to the strip and show the changes, you must invoke
show()
Parameters: Return type:
-
rotate
(positions=1)[source]¶ Treating the internal leds array as a circular buffer, rotate it by the specified number of positions. The number can be negative, which means rotating in the opposite direction.
Parameters: positions ( int
) – the number of steps to rotateReturn type: None
-
set_brightness
(led_num, brightness)[source]¶ Sets the brightness for a single LED in the strip. A global multiplier is applied.
Parameters: Return type:
-
set_global_brightness
(brightness)[source]¶ Sets a global brightness multiplicator which applies to every single LED’s brightness.
Parameters: brightness ( float
) – the global brightness (0.0 - 1.0
) multiplicator to be setReturn type: None
-
set_global_brightness_percent
(brightness)[source]¶ Just like
set_global_brightness()
, but with a 0-100 percent value.Parameters: brightness ( float
) – the global brightness (0.0 - 100.0
) multiplicator to be setReturn type: None
-
set_pixel
(led_num, red, green, blue)[source]¶ The buffer value of pixel
led_num
is set to(red, green, blue)
Parameters: Return type:
-
set_pixel_bytes
(led_num, rgb_color)[source]¶ Changes the pixel
led_num
to the given color in the buffer. To send the buffer to the strip and show the changes, invokeshow()
If you do not know, how the 3-byte
rgb_color
works, just useset_pixel()
.Parameters: Return type:
-
show
()[source]¶ Subclasses should overwrite this method
This method should show the buffered pixels on the strip, e.g. write the message buffer to the port on which the strip is connected.
Return type: None
-
sync_down
()[source]¶ Reads the shared color and brightness buffers and copies them to the local buffers
Return type: None
-
sync_up
()[source]¶ Copies the local color and brightness buffers to the shared buffer so other processes can see the current strip state.
Return type: None
-
synced_red_buffer
= None¶ the individual dim factors for each LED (0-1), EXCLUDING the global dim factor
- Pixel order is
helpers
¶
Overview¶
This module includes several helpful functions for 102shows to use. Any functionality that could be used in multiple parts of the program should be defined here.
- For example:
- checking if color tuples are valid:
helpers.verify.rgb_color_tuple()
- add two color tuples:
helpers.color.add_tuples()
- interpreting an incoming MQTT message:
helpers.mqtt
- parsing the
config.yml
file:helpers.configparser
- checking if color tuples are valid:
The module also includes some functions that are just too generic to include them in the one place where they are used.
- For example:
- getting the 102shows version:
helpers.get_logo()
- getting the colored 102shows logo:
helpers.get_version()
- getting the 102shows version:
-
helpers.
get_logo
(filename='../logo')[source]¶ Returns the colored 102shows logo. It is read from
/path/to/102shows/logo
Parameters: filename ( str
) – You can specify another logo source file, if you want.Return type: str
Returns: The logo as a multiline string. The colors are included as escape characters.
-
helpers.
get_version
(filename='../version')[source]¶ Returns the current 102shows version as a string that is read from a special version file
Parameters: filename ( str
) – Name of the version file. If no name is supplied, the standard file/path/to/102shows/version
will be usedReturn type: str
Returns: version string (as in the file))
color¶
-
class
helpers.color.
SmoothBlend
(strip: drivers.LEDStrip)[source]¶ This class lets the user define a specific state of the strip (
target_colors
) and then smoothly blends the current state over to the set state.-
class
BlendFunctions
[source]¶ Todo
Include blend pictures directly in documentation
An internal class which provides functions to blend between two colors by a parameter fade_progress for
fade_progress == 0
the function should return the start_color forfade_progress == 1
the function should return the end_color-
classmethod
cubic_blend
(start_color, end_color, fade_progress)[source]¶ cubic blend => see https://goo.gl/wZWm07
Return type: tuple
-
classmethod
linear_blend
(start_color, end_color, fade_progress)[source]¶ linear blend => see https://goo.gl/lG8RIW
Return type: tuple
-
classmethod
parabolic_blend
(start_color, end_color, fade_progress)[source]¶ quadratic blend => see https://goo.gl/hzeFb6
Return type: tuple
-
classmethod
-
SmoothBlend.
blend
(time_sec=2, blend_function=<bound method SmoothBlend.BlendFunctions.linear_blend of <class 'helpers.color.SmoothBlend.BlendFunctions'>>)[source]¶ blend the current LED state to the desired state
-
SmoothBlend.
set_color_for_whole_strip
(red, green, blue)[source]¶ set the same color for all LEDs in the strip
-
SmoothBlend.
set_pixel
(led_num, red, green, blue)[source]¶ set the desired state of a given pixel after the blending is finished
-
SmoothBlend.
target_colors
= None¶ an array of float tuples
-
class
-
helpers.color.
add_tuples
(tuple1, tuple2)[source]¶ Add two tuples component-wise
Parameters: Returns: sum
-
helpers.color.
blend_whole_strip_to_color
(strip, color, fadetime_sec=2)[source]¶ this name is pretty self-explanatory ;-)
Parameters: Return type:
-
helpers.color.
grayscale_correction
(lightness, max_in=255.0, max_out=255)[source]¶ Corrects the non-linear human perception of the led brightness according to the CIE 1931 standard. This is commonly mistaken for gamma correction. [1]
CIE 1931 Lightness correction [2]
The human perception of brightness is not linear to the duty cycle of an LED. The relation between the (perceived) lightness \(Y\) and the (technical) lightness \(L^*\) was described by the CIE:
\begin{align} Y & = Y_{max} \cdot g( ( L^* + 16) / 116 ) \quad ,& \quad 0 \le L^* \le 100 \\ \text{with} \quad g(t) & = \begin{cases} 3 \cdot \delta^2 \cdot ( t - \frac{4}{29}) & t \le \delta \\ t^3 & t > \delta \end{cases} \quad ,& \quad \delta = \frac{6}{29} \end{align}For more efficient computation, these two formulas can be simplified to:
\[\begin{split}Y = \begin{cases} L^* / 902.33 & L^* \le 8 \\ ((L^* + 16) / 116)^3 & L^* > 8 \end{cases} \\ \\ 0 \le Y \le 1 \qquad 0 \le L^* \le 100\end{split}\][1] For more information, read here: https://goo.gl/9Ji129 [2] formula from Wikipedia Parameters: Returns: the correct PWM duty cycle for humans to see the desired lightness as integer
configparser¶
-
helpers.configparser.
get_configuration
(default_filename='defaults.yml', user_filename='config.yml')[source]¶ gets the current configuration, as specified by YAML files
Parameters: Return type: AttrDict
Returns: settings tree
-
helpers.configparser.
update_settings_tree
(base, update)[source]¶ For all attributes in
update
override the defaults set inbase
or add them to the tree, if they did not exist inbase
.Parameters: - base (
AttrDict
) – default config tree - update (
AttrDict
) – “patch” for the default config tree
Return type: AttrDict
Returns: the updated tree
- base (
exceptions¶
see Exceptions (#fixme: link)
mqtt¶
A couple of helper functions (big surprise!) for MQTTControl
-
class
helpers.mqtt.
TopicAspect
[source]¶ information you can get out of an MQTT topic (and on which path hierarchy they are)
preprocessors¶
verify¶
Functions that validate input parameters and exceptions, raising InvalidParameters exceptions if the input does not fit the requirements. #fixme: link to exception
-
helpers.verify.
boolean
(candidate, param_name=None)[source]¶ a boolean value: True or False
Parameters: - candidate – the object to be tested
- param_name (
Optional
[str
]) – name of the parameter (to be included in the error message)
-
helpers.verify.
not_negative_integer
(candidate, param_name=None)[source]¶ a not-negative integer => 0,1,2,3,...
Parameters: - candidate – the object to be tested
- param_name (
Optional
[str
]) – name of the parameter (to be included in the error message)
-
helpers.verify.
not_negative_numeric
(candidate, param_name=None)[source]¶ a not-negative number => 0 or above
Parameters: - candidate – the object to be tested
- param_name (
Optional
[str
]) – name of the parameter (to be included in the error message)
-
helpers.verify.
numeric
(candidate, param_name=None, minimum=None, maximum=None)[source]¶ number (between minimum and maximum)
Parameters:
-
helpers.verify.
positive_integer
(candidate, param_name=None)[source]¶ a positive integer => greater than 0 => 1 or above
Parameters: - candidate – the object to be tested
- param_name (
Optional
[str
]) – name of the parameter (to be included in the error message)
-
helpers.verify.
positive_numeric
(candidate, param_name=None)[source]¶ a positive number => greater than 0
Parameters: - candidate – the object to be tested
- param_name (
Optional
[str
]) – name of the parameter (to be included in the error message)
-
helpers.verify.
rgb_color_tuple
(candidate, param_name=None)[source]¶ An RGB color tuple. It must contain three integer components between 0 and 255.
Parameters: - candidate – the object to be tested
- param_name (
Optional
[str
]) – name of the parameter (to be included in the error message)
Tests¶
Todo
write docstring for this module
lightshows
¶
Overview¶
102shows offers a framework for writing and displaying lightshows.
lightshows
includes the code that actually relies on this
and displays animations on an LED strip.
Templates¶
Todo
include link to controller
To make writing lightshows easy and convenient we introduced templates. These provide the interfaces for the controller and generic functionalities.
Basically: The templates are there so that lightshow modules just have to worry about the LED animations, and not about the backgrounds of 102shows
The base template¶
As the name says, this is the most basic template. All lightshows (and all other templates) rely on this template. It offers quite a lot:
- The interface to the controller:
lightshows.base.Lightshow.name()
returns the name of the lightshow
lightshows.base.Lightshow.start()
initializes the show process,- starts the built-in MQTT client and then triggers the start of the animation
lightshows.base.Lightshow.stop()
can be called to gracefully end the showlightshows.base.Lightshow.name()
-
class
lightshows.templates.base.
Lightshow
(strip: drivers.LEDStrip, parameters: dict)[source]¶ This class defines the interfaces and a few helper functions for lightshows. It is highly recommended to use it as your base class when writing your own show.
Parameters: - strip (
LEDStrip
) – Adrivers.LEDStrip
object representing your strip - parameters (
dict
) –A
dict
mapping parameter names (of the lightshow) to the parameter values, for example:parameters = {'example_rgb_color': (255,127,8), 'an_arbitrary_fade_time_sec': 1.5}
-
class
MQTTListener
(lightshow)[source]¶ This class collects the functions that receive incoming MQTT messages and parse them as parameter changes.
-
parse_message
(client, userdata, msg)[source]¶ Function to be executed as
on_message
hook of the Paho MQTT client. If the message commands a brightness or parameter change the corresponding hook (set_brightness()
orset_parameter()
) is called.Todo
- include link to the paho mqtt lib
- explain currently unknown parameters
Parameters: - client – the calling client object
- userdata – no idea what this does. This is a necessary argument but is not handled in any way in the function.
- msg – The object representing the incoming MQTT message
Return type:
-
set_brightness
(brightness)[source]¶ Limits the brightness value to the maximum brightness that is set in the configuration file, then calls the strip driver’s
drivers.LEDStrip.set_global_brightness()
functionParameters: brightness ( float
) – float between 0.0 and 1.0Return type: None
-
start_listening
()[source]¶ If this method is called (e.g. by the show object), incoming MQTT messages will be parsed, given they have the path
$prefix/$sys_name/$show_name/$parameter
$parameter
and the$payload
will be given tolightshow.templates.base.Lightshow.set_parameter()
Return type: None
-
stop_listening
()[source]¶ Ends the connection to the MQTT broker. Messages from the subscribed topics are not parsed anymore.
Return type: None
-
subscribe
(client, userdata, flags, rc)[source]¶ Function to be executed as
on_connect
hook of the Paho MQTT client. It subscribes to the MQTT paths for brightness changes and parameter changes for the show.Todo
- include link to the paho mqtt lib
- explain currently unknown parameters
Parameters: - client – the calling client object
- userdata – no idea what this does. This is a necessary argument but is not handled in any way in the function.
- flags – no idea what this does. This is a necessary argument but is not handled in any way in the function.
- rc – no idea what this does. This is a necessary argument but is not handled in any way in the function.
Return type:
-
-
Lightshow.
apply_parameter_set
(parameters)[source]¶ Applies a set of parameters to the show.
Parameters: parameters ( dict
) – Parameter JSON Object, represented as a Pythondict
Return type: None Returns: True
if successful,False
if not
-
Lightshow.
check_runnable
()[source]¶ Todo
include official exception raise notice
Raise an exception (InvalidStrip, InvalidConf or InvalidParameters) if the show is not runnable
-
Lightshow.
cleanup
()[source]¶ This is called before the show gets terminated. Lightshows can use it to clean up resources before their process is killed.
Return type: None
-
Lightshow.
idle_forever
(delay_sec=-1)[source]¶ Just does nothing and invokes
drivers.LEDStrip.show()
until the end of time (or a call ofstop()
)Parameters: delay_sec ( float
) – Time between two calls ofdrivers.LEDStrip.show()
Return type: None
-
Lightshow.
init_parameters
()[source]¶ Lightshows can inherit this to set their default parameters. This function is called at initialization of a new show object.
Return type: None
-
Lightshow.
logger
= None¶ The logger object this show will use for debug output
-
Lightshow.
mqtt
= None¶ represents the MQTT connection for parsing parameter changes #FIXME: type annotation
-
Lightshow.
p
= None¶ The object that stores all show parameters
-
Lightshow.
register
(parameter_name, default_val, verifier, args=None, kwargs=None, preprocessor=None)[source]¶ MQTT-settable parameters are stored in
lightshows.templates.base.Lightshow.p.value
. Calling this function will register a new parameter and his verifier invalue
andverifier
, so the parameter can be set via MQTT and by the controller.Parameters: - parameter_name (
str
) – name of the parameter. You access the parameter via self.p.value[parameter_name]. - default_val – initializer value of the parameter. Note that this value will not be checked by the verifier function!
- verifier – a function that is called before the parameter is set via MQTT. If it raises an InvalidParameters exception, the new value will not be set. #FIXLINK
- args (
Optional
[list
]) – the verifier function will be called asverifier(new_value, param_name, *args, **kwargs)
- kwargs (
Optional
[dict
]) – the verifier function will be called viaverifier(new_value, param_name, *args, **kwargs)
- preprocessor – before the validation in set_parameter
value = preprocessor(value)
will be called
Return type: - parameter_name (
-
Lightshow.
run
()[source]¶ The “main” function of the show (obviously this must be re-implemented in child classes)
Return type: None
-
Lightshow.
set_parameter
(param_name, value, send_mqtt_update=True)[source]¶ Take a parameter by name and new value and store it to p.value.
Parameters: Return type:
-
Lightshow.
sleep
(time_sec)[source]¶ Does nothing (but refreshing the strip a few times) for
time_sec
secondsParameters: time_sec ( float
) – duration of the breakReturn type: None
-
Lightshow.
start
()[source]¶ invokes the
run()
method and after that synchronizes the shared bufferReturn type: None
-
Lightshow.
stop
(signum=None, frame=None)[source]¶ Todo
include link for SIGINT
This should be called to stop the show with a graceful ending. It guarantees that the last strip state is uploaded to the global inter-process buffer. This method is called when SIGINT is sent to the show process. The arguments have no influence on the function.
Parameters: - signum – The integer-code of the signal sent to the show process. This has no influence on how the function works.
- frame – #fixme
Return type:
-
Lightshow.
strip
= None¶ the object representing the LED strip (driver) #FIXME: type annotation
- strip (
-
class
lightshows.templates.base.
LightshowParameters
[source]¶ A collection of maps for the parameters which store their:
- current values
- preprocessor method references
- verifier method references
-
preprocessor
= None¶ maps the show parameter names to their preprocessor functions
-
value
= None¶ maps the show parameter names to their current values
-
verifier
= None¶ maps the show parameter names to their verifier functions
Exceptions¶
This module defines some exception classes specific to 102shows:
-
exception
helpers.exceptions.
DescriptiveException
(value)[source]¶ This type of exception must contain a value (usually a string) that is used as the string representation of the exception
-
exception
helpers.exceptions.
InvalidConf
(value)[source]¶ Use if something in the configuration will not work for what the user has chosen in the config file.