Datatypes and Type Conversions
SHC’s Connectable objects are designed to work with simple (“scalar”) Python types, basic structured types, specifically NamedTuples, and Enums.
Basically, thanks to Python’s dynamic nature, any Python type can be used as a value type by connectable objects.
However, some of SHC’s features work much better with simple types, e.g. the dynamic type checking and automatic type conversions and the builtin JSON serialization (e.g. for the REST API and MQTT
).
Examples for well supported Python builtin types and standard-library types:
bool
int
float
str
datetime.datetime
datetime.date
datetime.time
datetime.timedelta
In addition, SHC specifies some derived types of these builtin types with addtional semantics (see next section) and some NamedTuples for commonly used and interface-specific data structures:
Inherited semantic types in SHC
To make type checking and automatic type conversions more useful, SHC makes use of type inheritance for semantic purposes. This is similar to how the “Newtype” paradigm is used in Haskell or Rust: When a Connectable object’s values have special additional semantics, a derived type is used instead of the plain scalar type to specify these semantics. This allows the type checking to check for mismatched value semantics of connected objects (even with the same scalar type) and to chose the correct type conversion automatically. A good example for this method are the different integer types for 0-100% ranges provided by SHC:
RangeUInt8
is derived from int and its instances shall be values from 0 (0%) to 255 (100%)RangeInt0To100
is derived from int and its instances shall be values from 0 (0%) to 100 (100%)
Obviously, values of these two types are compatible on a syntactic level, but not on a semantic level.
SHC provides default converters for converting both of these types into plain int
, as well as default converters to convert them to RangeFloat1
and into each other (with the appropriate scaling).
List of New Types included with SHC:
Default converters
SHC maintains a global dict of default conversion functions for pairs of types to convert values from the one type into the other type.
These default converters are used by .subscribe()
, .set_provider()
and .connect()
, when convert=True is given.
See Typing of Connectable Objects for more information.
To retrieve a default converter from that global dict, use shc.conversion.get_converter()
.
Reasonable default converters for the scalar builtin Python types and the additional New Types and NamedTuples provided by SHC are already included with SHC.
To add additional default converters, e.g. for custom types to be used with SHC, use shc.conversion.register_converter()
.
JSON conversion
Different modules of SHC require to serialize values into JSON data or deserialize them back into objects of the respective value type.
Similar to the default converters, the shc.conversion
module provides a global uniform and extensible way to do this:
For encoding, the
shc.conversion.SHCJsonEncoder
class can be used as an encoderclass with Python’s builtin JSON module:serialized_value = json.dumps(value, cls=shc.conversion.SHCJsonEncoder)
This also allows to convert lists, dicts, etc. of supported values to the respective JSON representation.
For decoding, use the usual JSON deserialization methods and afterwards apply
shc.conversion.from_json()
to the resulting object to convert it to the expected value type, e.g.:value = shc.conversion.from_json(json.loads(serialized_value), shc.datatypes.RangeFloat1)
The two converters natively support simple builtin types, Enums and NamedTuples by default, as well as any derived types from these (e.g. for semantic derived types).
To add support for further types, shc.conversion.register_json_conversion()
can be used to register the required converter functions.
shc.datatypes
Module Reference
- namedtuple shc.datatypes.RGBUInt8(red: RangeUInt8, green: RangeUInt8, blue: RangeUInt8)
A 24bit color in RGB colorspace, composed of three
RangeUInt8
values red, green and blue- Fields:
red (
RangeUInt8
) – Alias for field number 0green (
RangeUInt8
) – Alias for field number 1blue (
RangeUInt8
) – Alias for field number 2
- namedtuple shc.datatypes.RGBFloat1(red: RangeFloat1, green: RangeFloat1, blue: RangeFloat1)
A floating point RGB color, composed of three
RangeFloat1
values red, green and blue- Fields:
red (
RangeFloat1
) – Alias for field number 0green (
RangeFloat1
) – Alias for field number 1blue (
RangeFloat1
) – Alias for field number 2
- namedtuple shc.datatypes.HSVFloat1(hue: RangeFloat1, saturation: RangeFloat1, value: RangeFloat1)
A floating point color in HSV colorspace, composed of three
RangeFloat1
values hue, saturation and value.- Fields:
hue (
RangeFloat1
) – Alias for field number 0saturation (
RangeFloat1
) – Alias for field number 1value (
RangeFloat1
) – Alias for field number 2
- namedtuple shc.datatypes.RGBWUInt8(rgb: RGBUInt8, white: RangeUInt8)
4-channel RGBW LED color value, composed of a
RGBUInt8
for rgb and aRangeUInt8
for white.- Fields:
rgb (
RGBUInt8
) – Alias for field number 0white (
RangeUInt8
) – Alias for field number 1
- namedtuple shc.datatypes.CCTUInt8(cold: RangeUInt8, warm: RangeUInt8)
A CCT LED brightness value, composed of two
RangeUInt8
values cold and warm- Fields:
cold (
RangeUInt8
) – Alias for field number 0warm (
RangeUInt8
) – Alias for field number 1
- namedtuple shc.datatypes.RGBCCTUInt8(rgb: RGBUInt8, white: CCTUInt8)
5 channel LED color value, composed of a
RGBUInt8
for rgb and aCCTUInt8
for white.
- class shc.datatypes.RangeFloat1(*args, **kwargs)
A range / percentage value, represented as a floating point number from 0.0 (0%) to 1.0 (100%).
- class shc.datatypes.RangeUInt8
A range / percentage value, represented as an 8bit integer number from 0 (0%) to 255 (100%).
- class shc.datatypes.RangeInt0To100
A range / percentage value, represented as an 8bit integer percent number from 0 (0%) to 100 (100%).
- class shc.datatypes.AngleUInt8
An angle, encoded as a 8-bit integer, from 0 (0°) to 255 (360°).
- class shc.datatypes.Balance(x=0, /)
A balance between to extreme positions, e.g. left-right, front-rear, channel 1-channel 2, etc., represented as a floating point number between -1.0 and 1.0. Thus, 0.0 represents the “center”/”balanced”/”normal” value.
-1.0 typically means: - left (audio balance) - front (surround audio balance) - no LFE (surround audio balance)
- class shc.datatypes.AbstractStep
Abstract base class for all difference/step types, that represent a step within an associated range type
- abstract apply_to(value: T) T
Apply this step to a given value of the associated range type
- Parameters:
value – The old value
- Returns:
The new value, when this step is applied to the old value
- class shc.datatypes.FadeStep(x=0, /)
A dimmer or fader change step in the range -1.0 to 1.0. It can be applied to a
RangeFloat1
adding it to the step to the current value and clipping the result to the range 0..1.0.See
shc.misc.FadeStepAdapter
to do this to SHC.- apply_to(value: RangeFloat1) RangeFloat1
Apply this step to a given value of the associated range type
- Parameters:
value – The old value
- Returns:
The new value, when this step is applied to the old value
shc.conversion
Module Reference
- shc.conversion.register_converter(from_type: Type[S], to_type: Type[T], converter: Callable[[S], T]) None
- shc.conversion.get_converter(from_type: Type[S], to_type: Type[T]) Callable[[S], T]
Get the default conversion function for converting values from
from_type
toto_type
.- Parameters:
from_type – The source type
to_type – The target type
- Returns:
A function, which converts a value of type
from_type
toto_type
.- Raises:
TypeError – If no converter is known for this particular type conversion
- shc.conversion.register_json_conversion(type_: Type[T], to_json: Callable[[T], Any], from_json: Callable[[Any], T]) None
- class shc.conversion.SHCJsonEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)
- shc.conversion.from_json(type_: Type[T], value: Any) T