Add extended color light
This commit is contained in:
parent
572c7a7fb7
commit
0a8b706903
15 changed files with 504 additions and 21 deletions
|
|
@ -3,6 +3,7 @@ import enum
|
|||
from circuitmatter.data_model import (
|
||||
Cluster,
|
||||
Enum8,
|
||||
Map16,
|
||||
NumberAttribute,
|
||||
OctetStringAttribute,
|
||||
BoolAttribute,
|
||||
|
|
@ -13,6 +14,14 @@ from circuitmatter.data_model import (
|
|||
from circuitmatter import tlv
|
||||
|
||||
|
||||
class ThreadCapabilitiesBitmap(Map16):
|
||||
IS_BORDER_ROUTER_CAPABLE = 1 << 0
|
||||
IS_ROUTER_CAPABLE = 1 << 1
|
||||
IS_SLEEPY_END_DEVICE_CAPABLE = 1 << 2
|
||||
IS_FULL_THREAD_DEVICE = 1 << 3
|
||||
IS_SYNCHRONIZED_SLEEPY_END_DEVICE_CAPABLE = 1 << 4
|
||||
|
||||
|
||||
class NetworkCommissioningCluster(Cluster):
|
||||
CLUSTER_ID = 0x0031
|
||||
|
||||
|
|
@ -101,7 +110,10 @@ class NetworkCommissioningCluster(Cluster):
|
|||
8, WifiBandEnum, feature=FeatureBitmap.WIFI_NETWORK_INTERFACE, F_fixed=True
|
||||
)
|
||||
supported_thread_features = BitmapAttribute(
|
||||
9, feature=FeatureBitmap.THREAD_NETWORK_INTERFACE, F_fixed=True
|
||||
9,
|
||||
ThreadCapabilitiesBitmap,
|
||||
feature=FeatureBitmap.THREAD_NETWORK_INTERFACE,
|
||||
F_fixed=True,
|
||||
)
|
||||
thread_version = NumberAttribute(
|
||||
10,
|
||||
|
|
|
|||
92
circuitmatter/clusters/general/level_control.py
Normal file
92
circuitmatter/clusters/general/level_control.py
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import enum
|
||||
|
||||
from circuitmatter import data_model
|
||||
from circuitmatter import tlv
|
||||
|
||||
|
||||
class FeatureBitmap(enum.IntFlag):
|
||||
ON_OFF = 1 << 0
|
||||
LIGHTING = 1 << 1
|
||||
FREQUENCY = 1 << 2
|
||||
|
||||
|
||||
class OptionsBitmap(data_model.Map8):
|
||||
ExecuteIfOff = 0
|
||||
CoupleColorTempToLevel = 1
|
||||
|
||||
|
||||
class MoveModeEnum(data_model.Enum8):
|
||||
UP = 0
|
||||
DOWN = 1
|
||||
|
||||
|
||||
class StepModeEnum(data_model.Enum8):
|
||||
UP = 0
|
||||
DOWN = 1
|
||||
|
||||
|
||||
class LevelControl(data_model.Cluster):
|
||||
CLUSTER_ID = 0x0008
|
||||
|
||||
CurrentLevel = data_model.NumberAttribute(
|
||||
0x0000, signed=False, bits=8, N_nonvolatile=True, X_nullable=True
|
||||
)
|
||||
RemainingTime = data_model.NumberAttribute(
|
||||
0x0001, signed=False, bits=16, default=0, feature=FeatureBitmap.LIGHTING
|
||||
)
|
||||
MinLevel = data_model.NumberAttribute(
|
||||
0x0002,
|
||||
signed=False,
|
||||
bits=8,
|
||||
default=lambda features: 1 if features & FeatureBitmap.LIGHTING else 0,
|
||||
)
|
||||
MaxLevel = data_model.NumberAttribute(0x0003, signed=False, bits=8, default=254)
|
||||
OnLevel = data_model.NumberAttribute(0x0011, signed=False, bits=8, X_nullable=True)
|
||||
Options = data_model.BitmapAttribute(0x000F, OptionsBitmap, default=0)
|
||||
StartUpCurrentLevel = data_model.NumberAttribute(
|
||||
0x4000,
|
||||
signed=False,
|
||||
bits=8,
|
||||
X_nullable=True,
|
||||
N_nonvolatile=True,
|
||||
feature=FeatureBitmap.LIGHTING,
|
||||
)
|
||||
|
||||
class MoveToLevel(tlv.Structure):
|
||||
Level = tlv.IntMember(0, signed=False, octets=1)
|
||||
TransitionTime = tlv.IntMember(1, signed=False, octets=2, nullable=True)
|
||||
OptionsMask = tlv.BitmapMember(2, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
|
||||
move_to_level = data_model.Command(0x00, MoveToLevel)
|
||||
|
||||
class Move(tlv.Structure):
|
||||
MoveMode = tlv.EnumMember(0, MoveModeEnum)
|
||||
Rate = tlv.IntMember(1, signed=True, octets=1, nullable=True)
|
||||
OptionsMask = tlv.BitmapMember(2, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
|
||||
move = data_model.Command(0x01, Move)
|
||||
|
||||
class Step(tlv.Structure):
|
||||
StepMode = tlv.EnumMember(0, StepModeEnum)
|
||||
StepSize = tlv.IntMember(1, signed=True, octets=1)
|
||||
TransitionTime = tlv.IntMember(2, signed=False, octets=2, nullable=True)
|
||||
OptionsMask = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(4, OptionsBitmap, default=0)
|
||||
|
||||
step = data_model.Command(0x02, Step)
|
||||
|
||||
class Stop(tlv.Structure):
|
||||
OptionsMask = tlv.BitmapMember(0, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(1, OptionsBitmap, default=0)
|
||||
|
||||
stop = data_model.Command(0x03, Stop)
|
||||
|
||||
move_to_level_with_on_off = data_model.Command(0x04, MoveToLevel)
|
||||
|
||||
move_with_on_off = data_model.Command(0x05, Move)
|
||||
|
||||
step_with_on_off = data_model.Command(0x06, Step)
|
||||
|
||||
stop_with_on_off = data_model.Command(0x07, Stop)
|
||||
|
|
@ -1,7 +1,15 @@
|
|||
import enum
|
||||
|
||||
from circuitmatter import data_model
|
||||
from circuitmatter import tlv
|
||||
|
||||
|
||||
class FeatureBitmap(enum.IntFlag):
|
||||
LIGHTING = 1 << 0
|
||||
DEAD_FRONT_BEHAVIOR = 1 << 1
|
||||
OFF_ONLY = 1 << 2
|
||||
|
||||
|
||||
class StartUpOnOffEnum(data_model.Enum8):
|
||||
OFF = 0
|
||||
ON = 1
|
||||
|
|
@ -12,11 +20,21 @@ class OnOff(data_model.Cluster):
|
|||
CLUSTER_ID = 0x0006
|
||||
|
||||
OnOff = data_model.BoolAttribute(0x0000, default=False, N_nonvolatile=True)
|
||||
GlobalSceneControl = data_model.BoolAttribute(0x4000, default=True)
|
||||
OnTime = data_model.NumberAttribute(0x4001, signed=False, bits=16, default=0)
|
||||
OffWaitTime = data_model.NumberAttribute(0x4002, signed=False, bits=16, default=0)
|
||||
GlobalSceneControl = data_model.BoolAttribute(
|
||||
0x4000, default=True, feature=FeatureBitmap.LIGHTING
|
||||
)
|
||||
OnTime = data_model.NumberAttribute(
|
||||
0x4001, signed=False, bits=16, default=0, feature=FeatureBitmap.LIGHTING
|
||||
)
|
||||
OffWaitTime = data_model.NumberAttribute(
|
||||
0x4002, signed=False, bits=16, default=0, feature=FeatureBitmap.LIGHTING
|
||||
)
|
||||
StartUpOnOff = data_model.EnumAttribute(
|
||||
0x4003, StartUpOnOffEnum, N_nonvolatile=True, X_nullable=True
|
||||
0x4003,
|
||||
StartUpOnOffEnum,
|
||||
N_nonvolatile=True,
|
||||
X_nullable=True,
|
||||
feature=FeatureBitmap.LIGHTING,
|
||||
)
|
||||
|
||||
off = data_model.Command(0x00, None)
|
||||
|
|
|
|||
0
circuitmatter/clusters/lighting/__init__.py
Normal file
0
circuitmatter/clusters/lighting/__init__.py
Normal file
122
circuitmatter/clusters/lighting/color_control.py
Normal file
122
circuitmatter/clusters/lighting/color_control.py
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
import enum
|
||||
|
||||
from circuitmatter import data_model, tlv
|
||||
|
||||
|
||||
class FeatureBitmap(enum.IntFlag):
|
||||
HUE_SATURATION = 1 << 0
|
||||
ENHANCED_HUE = 1 << 1
|
||||
COLOR_LOOP = 1 << 2
|
||||
XY = 1 << 3
|
||||
COLOR_TEMPERATURE = 1 << 4
|
||||
|
||||
|
||||
class OptionsBitmap(data_model.Map8):
|
||||
EXECUTE_IF_OFF = 1 << 0
|
||||
|
||||
|
||||
class Direction(data_model.Enum8):
|
||||
SHORTEST_DISTANCE = 0
|
||||
LONGEST_DISTANCE = 1
|
||||
UP = 2
|
||||
DOWN = 3
|
||||
|
||||
|
||||
class MoveMode(data_model.Enum8):
|
||||
STOP = 0
|
||||
UP = 1
|
||||
DOWN = 3
|
||||
|
||||
|
||||
class StepMode(data_model.Enum8):
|
||||
UP = 1
|
||||
DOWN = 3
|
||||
|
||||
|
||||
class ColorMode(data_model.Enum8):
|
||||
HUE_SATURATION = 0
|
||||
XY = 1
|
||||
COLOR_TEMPERATURE = 2
|
||||
|
||||
|
||||
class ColorControl(data_model.Cluster):
|
||||
CLUSTER_ID = 0x0300
|
||||
REVISION = 6
|
||||
|
||||
CurrentHue = data_model.NumberAttribute(0x0000, signed=False, bits=8, default=0)
|
||||
CurrentSaturation = data_model.NumberAttribute(
|
||||
0x0001, signed=False, bits=8, default=0
|
||||
)
|
||||
RemainingTime = data_model.NumberAttribute(0x0002, signed=False, bits=16, default=0)
|
||||
CurrentX = data_model.NumberAttribute(0x0003, signed=False, bits=16, default=0)
|
||||
CurrentY = data_model.NumberAttribute(0x0004, signed=False, bits=16, default=0)
|
||||
DriftCompensation = data_model.NumberAttribute(
|
||||
0x0005, signed=False, bits=8, default=0
|
||||
)
|
||||
CompensationText = data_model.UTF8StringAttribute(0x0006, default="")
|
||||
ColorTemperature = data_model.NumberAttribute(
|
||||
0x0007, signed=False, bits=16, default=0
|
||||
)
|
||||
ColorMode = data_model.EnumAttribute(0x0008, data_model.Enum8, default=0)
|
||||
Options = data_model.BitmapAttribute(0x000F, OptionsBitmap, default=0)
|
||||
ColorCapabilities = data_model.BitmapAttribute(0x400A, FeatureBitmap, default=0)
|
||||
|
||||
class MoveToHue(tlv.Structure):
|
||||
Hue = tlv.IntMember(0, signed=False, octets=1, maximum=254)
|
||||
Direction = tlv.EnumMember(1, Direction)
|
||||
TransitionTime = tlv.IntMember(2, signed=False, octets=2, nullable=True)
|
||||
OptionsMask = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(4, OptionsBitmap, default=0)
|
||||
|
||||
move_to_hue = data_model.Command(0x00, MoveToHue)
|
||||
|
||||
class MoveHue(tlv.Structure):
|
||||
MoveMode = tlv.EnumMember(0, Direction)
|
||||
Rate = tlv.IntMember(1, signed=True, octets=1, nullable=True)
|
||||
OptionsMask = tlv.BitmapMember(2, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
|
||||
move_hue = data_model.Command(0x01, MoveHue)
|
||||
|
||||
class StepHue(tlv.Structure):
|
||||
StepMode = tlv.EnumMember(0, StepMode)
|
||||
StepSize = tlv.IntMember(1, signed=True, octets=1)
|
||||
TransitionTime = tlv.IntMember(2, signed=False, octets=1)
|
||||
OptionsMask = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(4, OptionsBitmap, default=0)
|
||||
|
||||
step_hue = data_model.Command(0x02, StepHue)
|
||||
|
||||
class MoveToSaturation(tlv.Structure):
|
||||
Saturation = tlv.IntMember(0, signed=False, octets=1)
|
||||
TransitionTime = tlv.IntMember(1, signed=False, octets=2)
|
||||
OptionsMask = tlv.BitmapMember(2, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
|
||||
move_to_saturation = data_model.Command(0x03, MoveToSaturation)
|
||||
|
||||
class MoveSaturation(tlv.Structure):
|
||||
MoveMode = tlv.EnumMember(0, MoveMode)
|
||||
Rate = tlv.IntMember(1, signed=True, octets=1, nullable=True)
|
||||
OptionsMask = tlv.BitmapMember(2, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
|
||||
move_saturation = data_model.Command(0x04, MoveSaturation)
|
||||
|
||||
class StepSaturation(tlv.Structure):
|
||||
StepMode = tlv.EnumMember(0, StepMode)
|
||||
StepSize = tlv.IntMember(1, signed=True, octets=1)
|
||||
TransitionTime = tlv.IntMember(2, signed=False, octets=2, nullable=True)
|
||||
OptionsMask = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(4, OptionsBitmap, default=0)
|
||||
|
||||
step_saturation = data_model.Command(0x05, StepSaturation)
|
||||
|
||||
class MoveToHueAndSaturation(tlv.Structure):
|
||||
Hue = tlv.IntMember(0, signed=False, octets=1)
|
||||
Saturation = tlv.IntMember(1, signed=False, octets=1)
|
||||
TransitionTime = tlv.IntMember(2, signed=False, octets=2, nullable=True)
|
||||
OptionsMask = tlv.BitmapMember(3, OptionsBitmap, default=0)
|
||||
OptionsOverride = tlv.BitmapMember(4, OptionsBitmap, default=0)
|
||||
|
||||
move_to_hue_and_saturation = data_model.Command(0x06, MoveToHueAndSaturation)
|
||||
|
|
@ -21,6 +21,14 @@ class Enum16(enum.IntEnum):
|
|||
pass
|
||||
|
||||
|
||||
class Map8(enum.IntFlag):
|
||||
pass
|
||||
|
||||
|
||||
class Map16(enum.IntFlag):
|
||||
pass
|
||||
|
||||
|
||||
class Uint16(tlv.IntMember):
|
||||
def __init__(self, _id=None, minimum=0, **kwargs):
|
||||
super().__init__(_id, signed=False, octets=2, minimum=minimum, **kwargs)
|
||||
|
|
@ -88,6 +96,8 @@ class Attribute:
|
|||
def __get__(self, instance, cls):
|
||||
v = instance._attribute_values.get(self.id, None)
|
||||
if v is None:
|
||||
if callable(self.default):
|
||||
return self.default(instance.feature_map)
|
||||
return self.default
|
||||
return v
|
||||
|
||||
|
|
@ -270,8 +280,11 @@ class UTF8StringAttribute(Attribute):
|
|||
return self.member.encode(value)
|
||||
|
||||
|
||||
class BitmapAttribute(Attribute):
|
||||
pass
|
||||
class BitmapAttribute(NumberAttribute):
|
||||
def __init__(self, _id, enum_type, **kwargs):
|
||||
self.enum_type = enum_type
|
||||
bits = 8 if issubclass(enum_type, Map8) else 16
|
||||
super().__init__(_id, signed=False, bits=bits, **kwargs)
|
||||
|
||||
|
||||
class Command:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,24 @@
|
|||
from .dimmable import DimmableLight
|
||||
|
||||
from circuitmatter.clusters.lighting import color_control
|
||||
|
||||
|
||||
class ColorTemperatureLight(DimmableLight):
|
||||
DEVICE_TYPE_ID = 0x010C
|
||||
REVISION = 4
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
|
||||
self._color_control = color_control.ColorControl()
|
||||
self._color_control.feature_map |= color_control.FeatureBitmap.COLOR_TEMPERATURE
|
||||
|
||||
self.servers.append(self._color_control)
|
||||
|
||||
@property
|
||||
def color_rgb(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@color_rgb.setter
|
||||
def color_rgb(self, value):
|
||||
raise NotImplementedError()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,35 @@
|
|||
from .on_off import OnOffLight
|
||||
|
||||
from circuitmatter.clusters.general import level_control
|
||||
|
||||
|
||||
class DimmableLight(OnOffLight):
|
||||
DEVICE_TYPE_ID = 0x0101
|
||||
REVISION = 3
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
|
||||
self._level_control = level_control.LevelControl()
|
||||
self._level_control.feature_map |= level_control.FeatureBitmap.LIGHTING
|
||||
self._level_control.min_level = 1
|
||||
self._level_control.max_level = 254
|
||||
self.servers.append(self._level_control)
|
||||
|
||||
self._level_control.move_to_level_with_on_off = self._move_to_level_with_on_off
|
||||
|
||||
def _move_to_level_with_on_off(self, session, value):
|
||||
try:
|
||||
self.brightness = value.Level / self._level_control.max_level
|
||||
except Exception as e:
|
||||
print(f"Error setting brightness: {e}")
|
||||
return
|
||||
self._level_control.CurrentLevel = value.Level
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
return self._level_control.CurrentLevel / self._level_control.max_level
|
||||
|
||||
@brightness.setter
|
||||
def brightness(self, value):
|
||||
raise NotImplementedError()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,37 @@
|
|||
import colorsys
|
||||
|
||||
from .color_temperature import ColorTemperatureLight
|
||||
|
||||
|
||||
from circuitmatter.clusters.lighting import color_control
|
||||
|
||||
|
||||
class ExtendedColorLight(ColorTemperatureLight):
|
||||
DEVICE_TYPE_ID = 0x010D
|
||||
REVISION = 4
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
|
||||
self._color_control.feature_map |= (
|
||||
color_control.FeatureBitmap.HUE_SATURATION
|
||||
| color_control.FeatureBitmap.ENHANCED_HUE
|
||||
| color_control.FeatureBitmap.COLOR_LOOP
|
||||
| color_control.FeatureBitmap.XY
|
||||
)
|
||||
|
||||
self._color_control.move_to_hue_and_saturation = (
|
||||
self._move_to_hue_and_saturation
|
||||
)
|
||||
|
||||
def _move_to_hue_and_saturation(self, session, value):
|
||||
try:
|
||||
r, g, b = colorsys.hsv_to_rgb(value.Hue / 254, value.Saturation / 254, 1)
|
||||
self.color_rgb = int(r * 255) << 16 | int(g * 255) << 8 | int(b * 255)
|
||||
except Exception as e:
|
||||
print(f"Error setting color: {e}")
|
||||
return
|
||||
|
||||
self._color_control.ColorMode = color_control.ColorMode.HUE_SATURATION
|
||||
self._color_control.CurrentHue = value.Hue
|
||||
self._color_control.CurrentSaturation = value.Saturation
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from circuitmatter.clusters.general.identify import Identify
|
||||
from circuitmatter.clusters.general.on_off import OnOff
|
||||
from circuitmatter.clusters.general import on_off
|
||||
|
||||
from .. import simple_device
|
||||
|
||||
|
|
@ -14,15 +14,30 @@ class OnOffLight(simple_device.SimpleDevice):
|
|||
self._identify = Identify()
|
||||
self.servers.append(self._identify)
|
||||
|
||||
self._on_off = OnOff()
|
||||
self._on_off.on = self.on
|
||||
self._on_off.off = self.off
|
||||
self._on_off = on_off.OnOff()
|
||||
self._on_off.on = self._on
|
||||
self._on_off.off = self._off
|
||||
self._on_off.feature_map |= on_off.FeatureBitmap.LIGHTING
|
||||
self.servers.append(self._on_off)
|
||||
|
||||
def on(self, session):
|
||||
print("on!")
|
||||
def _on(self, session):
|
||||
try:
|
||||
self.on()
|
||||
except Exception as e:
|
||||
print(f"Error turning on light: {e}")
|
||||
return
|
||||
self._on_off.on_off = True
|
||||
|
||||
def off(self, session):
|
||||
print("off!")
|
||||
def _off(self, session):
|
||||
try:
|
||||
self.off()
|
||||
except Exception as e:
|
||||
print(f"Error turning off light: {e}")
|
||||
return
|
||||
self._on_off.on_off = False
|
||||
|
||||
def on(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def off(self):
|
||||
raise NotImplementedError()
|
||||
|
|
|
|||
|
|
@ -6,10 +6,15 @@ class SimpleDevice:
|
|||
self.name = name
|
||||
self.servers = []
|
||||
self.descriptor = descriptor.DescriptorCluster()
|
||||
device_type = descriptor.DescriptorCluster.DeviceTypeStruct()
|
||||
device_type.DeviceType = self.DEVICE_TYPE_ID
|
||||
device_type.Revision = self.REVISION
|
||||
self.descriptor.DeviceTypeList = [device_type]
|
||||
device_types = []
|
||||
for superclass in type(self).__mro__:
|
||||
if not hasattr(superclass, "DEVICE_TYPE_ID"):
|
||||
continue
|
||||
device_type = descriptor.DescriptorCluster.DeviceTypeStruct()
|
||||
device_type.DeviceType = superclass.DEVICE_TYPE_ID
|
||||
device_type.Revision = superclass.REVISION
|
||||
device_types.append(device_type)
|
||||
self.descriptor.DeviceTypeList = device_types
|
||||
self.descriptor.PartsList = []
|
||||
self.descriptor.ServerList = []
|
||||
self.descriptor.ClientList = []
|
||||
|
|
|
|||
|
|
@ -579,6 +579,11 @@ class EnumMember(IntMember):
|
|||
return self.enum_class(value).name
|
||||
|
||||
|
||||
class BitmapMember(EnumMember):
|
||||
def print(self, value):
|
||||
return repr(self.enum_class(value))
|
||||
|
||||
|
||||
class FloatMember(NumberMember[float, _OPT, _NULLABLE]):
|
||||
def __init__(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ class LED(on_off.OnOffLight):
|
|||
self._led = led
|
||||
self._led.direction = digitalio.Direction.OUTPUT
|
||||
|
||||
def on(self, session):
|
||||
def on(self):
|
||||
self._led.value = True
|
||||
|
||||
def off(self, session):
|
||||
def off(self):
|
||||
self._led.value = False
|
||||
|
||||
|
||||
|
|
|
|||
91
examples/replay_rgb_light.py
Normal file
91
examples/replay_rgb_light.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
"""Pure Python implementation of the Matter IOT protocol."""
|
||||
|
||||
import json
|
||||
import pathlib
|
||||
import socket
|
||||
import time
|
||||
|
||||
import circuitmatter as cm
|
||||
|
||||
from circuitmatter.device_types.lighting import extended_color
|
||||
|
||||
from circuitmatter.utility import random
|
||||
from circuitmatter.utility.recording import RecordingSocketPool, RecordingRandom
|
||||
from circuitmatter.utility.replay import ReplaySocketPool, ReplayRandom
|
||||
|
||||
from circuitmatter.utility.mdns import DummyMDNS
|
||||
from circuitmatter.utility.mdns.avahi import Avahi
|
||||
|
||||
|
||||
class NeoPixel(extended_color.ExtendedColorLight):
|
||||
@property
|
||||
def color_rgb(self):
|
||||
return self._color
|
||||
|
||||
@color_rgb.setter
|
||||
def color_rgb(self, value):
|
||||
self._color = value
|
||||
print(f"new color 0x{value:06x}")
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
return self._brightness
|
||||
|
||||
@brightness.setter
|
||||
def brightness(self, value):
|
||||
self._brightness = value
|
||||
print(f"new brightness {value}")
|
||||
|
||||
def on(self):
|
||||
print("on!")
|
||||
|
||||
def off(self):
|
||||
print("off!")
|
||||
|
||||
|
||||
def run(replay_file=None):
|
||||
device_state = pathlib.Path("live-rgb-device-state.json")
|
||||
if replay_file:
|
||||
replay_lines = []
|
||||
with open(replay_file, "r") as f:
|
||||
device_state_fn = f.readline().strip()
|
||||
for line in f:
|
||||
replay_lines.append(json.loads(line))
|
||||
socketpool = ReplaySocketPool(replay_lines)
|
||||
mdns_server = DummyMDNS()
|
||||
random_source = ReplayRandom(replay_lines)
|
||||
# Reset device state to before the captured run
|
||||
if device_state_fn == "none":
|
||||
device_state.unlink(missing_ok=True)
|
||||
else:
|
||||
device_state.write_text(pathlib.Path(device_state_fn).read_text())
|
||||
else:
|
||||
timestamp = time.strftime("%Y%m%d-%H%M%S")
|
||||
record_file = open(f"test_data/recorded_packets-{timestamp}.jsonl", "w")
|
||||
device_state_fn = f"test_data/device_state-{timestamp}.json"
|
||||
replay_device_state = pathlib.Path(device_state_fn)
|
||||
if device_state.exists():
|
||||
record_file.write(f"{device_state_fn}\n")
|
||||
# Save device state before we run so replays can use it.
|
||||
replay_device_state.write_text(device_state.read_text())
|
||||
else:
|
||||
# No starting state.
|
||||
record_file.write("none\n")
|
||||
socketpool = RecordingSocketPool(record_file, socket)
|
||||
mdns_server = Avahi()
|
||||
random_source = RecordingRandom(record_file, random)
|
||||
|
||||
matter = cm.CircuitMatter(socketpool, mdns_server, random_source, device_state)
|
||||
led = NeoPixel("neopixel1")
|
||||
matter.add_device(led)
|
||||
while True:
|
||||
matter.process_packets()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
replay_file = None
|
||||
if len(sys.argv) > 1:
|
||||
replay_file = sys.argv[1]
|
||||
run(replay_file=replay_file)
|
||||
29
examples/two_onoff_led.py
Normal file
29
examples/two_onoff_led.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
"""Simple LED on and off as a light."""
|
||||
|
||||
import circuitmatter as cm
|
||||
from circuitmatter.device_types.lighting import on_off
|
||||
|
||||
import digitalio
|
||||
import board
|
||||
|
||||
|
||||
class LED(on_off.OnOffLight):
|
||||
def __init__(self, name, led):
|
||||
super().__init__(name)
|
||||
self._led = led
|
||||
self._led.direction = digitalio.Direction.OUTPUT
|
||||
|
||||
def on(self):
|
||||
self._led.value = True
|
||||
|
||||
def off(self):
|
||||
self._led.value = False
|
||||
|
||||
|
||||
matter = cm.CircuitMatter()
|
||||
led = LED("led1", digitalio.DigitalInOut(board.D19))
|
||||
matter.add_device(led)
|
||||
led = LED("led2", digitalio.DigitalInOut(board.D20))
|
||||
matter.add_device(led)
|
||||
while True:
|
||||
matter.process_packets()
|
||||
Loading…
Reference in a new issue