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:
  1.  red (RangeUInt8) – Alias for field number 0

  2.  green (RangeUInt8) – Alias for field number 1

  3.  blue (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:
  1.  red (RangeFloat1) – Alias for field number 0

  2.  green (RangeFloat1) – Alias for field number 1

  3.  blue (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:
  1.  hue (RangeFloat1) – Alias for field number 0

  2.  saturation (RangeFloat1) – Alias for field number 1

  3.  value (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 a RangeUInt8 for white.

Fields:
  1.  rgb (RGBUInt8) – Alias for field number 0

  2.  white (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:
  1.  cold (RangeUInt8) – Alias for field number 0

  2.  warm (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 a CCTUInt8 for white.

Fields:
  1.  rgb (RGBUInt8) – Alias for field number 0

  2.  white (CCTUInt8) – Alias for field number 1

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 to to_type.

Parameters:
  • from_type – The source type

  • to_type – The target type

Returns:

A function, which converts a value of type from_type to to_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