uun_windsurfguru.modules package
Submodules
uun_windsurfguru.modules.WindSurfGuru module
- class uun_windsurfguru.modules.WindSurfGuru.Overlay(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
IntEnumOverlays of LED strip for different functionalities.
- METER = 1
basic functionality
- SPECIAL = 2
abnormal behaivour -
SpecialState
- class uun_windsurfguru.modules.WindSurfGuru.SpecialState(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
EnumSpecial states of the LED strip signaling some abormality.
- BLANK = 'blank'
- ERROR = 'error'
- NO_CONNECTION = 'noConnection'
- class uun_windsurfguru.modules.WindSurfGuru.WindSurfGuru(config: dict, get_uucmd, device: LedDev = None)
Bases:
ModuleModule for visualization of wind speeds on a LED strip.
The method
on_tick()is repeatedly executed by the :pkg:uun-iot library. The method gets data from uuCmdweatherConditions/getLast. If it successfuly retrieved the weather data, it will attempt to display them on the strip. If there was an error (internet connection error or any other code-related Exception), go into special state and display the error on the LED strip.The display of error, or the actual wind speed data on the strip is exweather data, it will attempt to display them on the strip. If there was an error (internet connection error or any other code-related Exception), go into special state and display the error on the LED strip.
The LED strip device can be realized by various physical hardwares. Examples are:
a simple array of one-colored LEDs controled over GPIO,
the same array but with a I2C controller, or
an individually color-controllable LED strip such as Neopixel driven by an external library.
For each of these examples, there is a corresponding
uun_iot_libledstrip.devices.LedDevdriver – calledGPIODev,I2CDevandNeopixelDev, respectively. All of these drivers inherit from the LedDev interface and are thus interchangeable. Of course, the simple one-colored LED strip cannot have different colours, but the driver behaves like they can – this is done for interchangeability of the underlying code. The code should not depend on the current realization of the hardware LED strip backend. The LED strip type can be chosen in configuration.The display of an error, or the actual wind speed data on the strip, is exclusive – meaning that only the error, or the data can be displayed at the same time. For this reason, there is a
uun_iot_libledstrip.StripOverlayBundlewhich provides exactly this exclusive access to the underlying hardware device.On module initialization, two
uun_iot_libledstrip.LedStrip-s are created. One responsible for the error display and the seconduun_iot_libledstrip.MeterStrip, inheriting from class LedStrip, responsible for linear display of the wind speed on the strip. The StripOverlayBundle can then change in between the two by clearing the old one and activating the new one. This ensures exclusivity.A LedStrip instance is created using a LedDev driver and a list or a dictionary of
uun_iot_libledstrip.LedStripSegments-s. Each of the segments has a fixed LED position span (for example from 2nd to 5th LED) and the segments act as basic building blocks. Each of the segments can be lit with a solid color or can blink with given color and with given period. This display action can be encapsulated in auun_iot_libledstrip.Actionobject, which is a “container” for these two kinds of visualization. Action can be stored in a segment and then activated later, activating the saved display action (blinking/solid color).A
uun_iot_libledstrip.MeterStripbases on LedStrip and is composed ofuun_iot_libledstrip.MeterStripSegment-s which base on LedStripSegment. Each MeterStripSegment is given a LedDev, array of led IDs and two crucial values:value_minandvalue_max. As the name MeterStripSegment suggests, the segment is supposed to measure some quantity. The segment linearly interpolates between tuning on no LEDs and turning on all of the allocated LEDs in the segment, based onvalue. The ratio of turned on LEDs is computed simply asvalue/(value_max-value_min)and the LEDs turn on up from lowest to highest IDs (or positions). This is done by virually decreasing the number of LEDs in a segment. If the value is less than value_min, all LEDs are off and if above value_max, all LEDs are on. Thevaluecan be set using auun_iot_libledstrip.MeterStripSegment.set_value().Additionaly, a MeterStripSegment can be initialized with an optional hook function. The hook function is called at the end of
uun_iot_libledstrip.MeterStripSegment.set_value()and is given current value together with some MeterStripSegment properties. The function should return an Action, which will be stored into the segment and can be activated later. This can be used to dynamically change stored Action for the MeterStripSegment based on current value given inset_value().The MeterStrip has a method with the same name
set_value()which calls set_value on each of its segments and additionaly activates their action.The following example illustrates this behaviour:
def hook(value, leds, action): if value > 100: action = Action(ActionType.SOLID, color=(255,0,0)) else: action = Action(ActionType.SOLID, color=(0,255,0)) return leds, action segment = MeterStripSegment( device, autoshow=True, leds=[0,1,2,3,4], value_min=5, value_max=200, hook_set_value=hook ) # definition of MeterStrip strip containing the segment strip = MeterStrip(device,[segment]) strip.set_value(200) strip.set_value(50)
>>> # the whole segment is lit red (255, 0, 0) >>> # some LEDs in the segment are lit green (0, 255, 0)
This hook behaviour is used to set special actions if the wind speed is less than 15 knt or more than 30 knt for the first and the last segments. The whole process can be directly controlled from the configuration file.
In the configuration file, there are the definitions of the segments. Each segment contains a default action in keys
color, action, interval. The LED positions are in thesettingssubkey together with definitions for minimal and maximal wind values for the given segment. The segment may have defined aspecialActionkey. The key contains information about the associated Action together with aconditionkey. The key indicates, when to activate the special action using the hook MeterStripSegment functionality.Possible values of configuration
<severity>/specialAction/conditionare the following:Each condition translates to one of:
ifWindBelow:
wind < windMin,ifWindBetween:
windMin <= wind <= windMax,ifWindGreater:
windMax < wind,
where wind is the value of wind at the time of calling
self._meter_strip.set_value(). If the wind conditions above are satisfied, apply the special action to the segment. Otherwise apply normal action.Example of configuration file:
{ "oidcGrantToken": { "gateway": "uuidentity.plus4u.net", "uuAppName": "uu-oidc-maing02", "awid": "xxx", "uuCmd": "oidc/grantToken", "tokenPath": "./oidc-token" }, "uuThing": { "accessCode1": "xxx", "accessCode2": "xxx" }, "uuApp": { "gateway": "uuapp.plus4u.net", "uuAppName": "ucl-weatherstation-maing01", "awid": "xxx", "uuCmdList": { "weatherConditionsGetLast": "weatherConditions/getLast" } }, "gateway": { "moduleTimers": { "windSurfGuru": 120 }, "windSurfGuru": { "weatherStationCode": "MELTEMI", "ledStrip": { "device": "virtual", "pixels": 16, "pin": "D10" }, "state": { "noConnection": { "color": "#ff0000", "action": "blink", "interval": 0.2 }, "blank": { "color": "#000000", "action": "solid", "interval": null }, "error": { "color": "#ff0000", "action": "blink", "interval": 0.2 } }, "severity": { "low": { "color": "#0000ff", "action": "solid", "interval": null, "specialAction": { "condition": "ifWindBetween", "color": "#0000ff", "action": "blink", "interval": 0.2 }, "settings": { "windMin": 0, "windMax": 14, "ledMinPosition": 0, "ledMaxPosition": 0 } }, "light": { "color": "#0000ff", "action": "solid", "interval": null, "settings": { "windMin": 16, "windMax": 18, "ledMinPosition": 1, "ledMaxPosition": 3 } }, "optimal": { "color": "#00ff00", "action": "solid", "interval": null, "settings": { "windMin": 19, "windMax": 22, "ledMinPosition": 4, "ledMaxPosition": 7 } }, "heavy": { "color": "#ff8000", "action": "solid", "interval": null, "settings": { "windMin": 23, "windMax": 26, "ledMinPosition": 8, "ledMaxPosition": 11 } }, "extreme": { "color": "#ff0000", "action": "solid", "interval": null, "specialAction": { "condition": "ifWindGreater", "color": "#ff0000", "action": "blink", "interval": 0.2 }, "settings": { "windMin": 27, "windMax": 30, "ledMinPosition": 12, "ledMaxPosition": 15 } } } } } }
- Parameters:
config – gateway configuration
get_uucmd – uucmd for getting new weather conditions, uucmd(weatherstation_code) ->
requests.Responsedevice – optional external
uun_iot_libledstrip.LedDev
- Raises:
ValueError – if
devicewas specified and is not an instance ofLedDev
- _abc_impl = <_abc._abc_data object>
- _create_action_from_config(centry: dict) Action
Create
Actionobject from configuration dictionary with keys{"action": ..., "color": ..., "interval": ...}.- Parameters:
centry – configuration dictionary. Key
actioncan besolidorblink,coloris in hex format andintervalis in seconds.- Returns:
Actionobject constructed fromcentry- Return type:
Action
- _device: LedDev
- _init_hw() LedDev
Initialize underlying LED strip. Look at configuration
ledStrip/deviceto determine what type of LED strip to use. Also readledStrip/pixelsto determine number of pixels to use. Somedevicesmight use theledStrip/pinsetting (such as neopixel). The numbering of pin depends on useddevice.ledStrip/device: neopixel, i2c, virtual (virtual is default, if none of the before were found)
- _init_meter_segments() Dict[Any, MeterStripSegment]
Each
severitykey in configuration corresponds to one LED segment.For severities which have special action
specialActionandspecialAction/conditionconfigured, addhook_set_valuehook to the severity segment. Seeuun_iot_libledstrip.MeterStripSegmentfor more information about hooks.Possible values of configuration
<severity>/specialAction/conditionare the following. Each condition translates to one of:ifWindBelow:
wind < windMin,ifWindBetween:
windMin <= wind <= windMax,ifWindGreater:
windMax < wind,
where wind is the value of wind at the time of calling
self._meter_strip.set_value(). If the wind conditions above are satisfied, apply the special action to the segment. Otherwise apply normal action.
- _init_state_segments() Dict[Any, LedStripSegment]
Special states have a single common segment stretching over the whole strip with variable actions depending on state (see
_set_special_state()).
- _meter_segments: Dict[any, MeterStripSegment]
- _sbundle: StripOverlayBundle
bundle a MeterStrip for normal usage and a general LedStrip for special state display
- _set_special_state(state: SpecialState) None
Set application special state.
Display a
SpecialStateon the LED strip (currently whole strip, see_init_state_segments()), action for the strip/segments are taken from configuration.- Parameters:
state –
SpecialStatestate to display
- _wind_knt_min: float
- evaluate_conditions(wind_speed_kph: float) None
Process wind speed and display it on a LED strip accordingly.
- Parameters:
wind_speed_kph – wind speed in km/h
- on_tick() None
Method to be called on each timer hit.
Receive information about weather from uuApp and call
evaluate_conditions()to display the wind speed on the strip.When ConnectionError occurs (when getting weather conditions), set special state to
SpecialState.NO_CONNECTIONusing_set_special_state(). When any other exception occurs, set state toSpecialState.ERRORby same procedure.
Module contents
- uun_windsurfguru.modules.init(config, uuclient: UuAppClient)