def RangeValidator(subcon, *, min_value=None, max_value=None): def validate_range(obj, ctx): if min_value is not None and obj < min_value: return False if max_value is not None and obj > max_value: return False return True return ExprValidator(subcon, validate_range)
from construct import (Int8ul, Int16ul, Int16ub, Default, Enum, Struct, Switch, GreedyRange, Padding, Default, ExprValidator, obj_, this) from .util import EnumAdapter, Opcode FaultTest = Struct( "test_id" / Int8ul, "company_id" / Int16ul, ) FaultStatus = Struct("test_id" / Int8ul, "company_id" / Int16ul, "fault_array" / Default(GreedyRange(Int8ul), [])) FastPeriodDivisor = Struct("fast_period_divisor" / ExprValidator(Int8ul, obj_ <= 15)) Attention = Struct("attention" / Int8ul) CompanyId = Struct("company_id" / Int16ul) HealthCurrentStatus = FaultStatus HealthFaultGet = CompanyId HealthFaultClear = CompanyId HealthFaultTest = FaultTest HealthFaultStatus = FaultStatus
def AddressTypeValidator(subcons, *allowed_types): return ExprValidator( subcons, lambda obj, ctx: get_address_type(obj) in allowed_types)
def AddressTypeValidator(subcons, *allowed_types): return ExprValidator( subcons, lambda obj, ctx: get_address_type(obj) in allowed_types) # fmt: off UnassignedAddress = AddressTypeValidator(Int16ul, AddressType.UNASSIGNED) UnicastAddress = AddressTypeValidator(Int16ul, AddressType.UNICAST) # TODO Fixed Groups? GroupAddress = AddressTypeValidator(Int16ul, AddressType.GROUP) VirtualLabel = AddressTypeValidator(Int16ul, AddressType.VIRTUAL) NotVirtualLabel = ExprValidator( Int16ul, lambda obj, ctx: get_address_type(obj) != AddressType.VIRTUAL) SubscriptionAddress = ExprValidator( Int16ul, lambda obj, ctx: get_address_type(obj) not in [ AddressType.UNASSIGNED, AddressType.UNICAST, AddressType.ALL_NODES, AddressType.VIRTUAL ]) StatusSubscriptionAddress = ExprValidator( Int16ul, lambda obj, ctx: get_address_type(obj) not in [AddressType.UNICAST, AddressType.ALL_NODES]) UnicastUnassignedAddress = AddressTypeValidator( Int16ul, AddressType.UNICAST, AddressType.UNASSIGNED,
SCENE_STORE_UNACKNOWLEDGED = 0x8247 SCENE_DELETE = 0x829E SCENE_DELETE_UNACKNOWLEDGED = 0x829F class SceneStatusCode(IntEnum): SUCCESS = 0x00 SCENE_REGISTER_FULL = 0x01 SCENE_NOT_FOUND = 0x02 # fmt: off SceneGet = Struct() SceneRecallMinimal = Struct( "scene_number" / ExprValidator(Int16ul, obj_ > 0), "tid" / Int8ul, ) SceneRecallWithTransition = Struct( "scene_number" / ExprValidator(Int16ul, obj_ > 0), "tid" / Int8ul, "transition_time" / TransitionTimeAdapter(TransitionTime, allow_unknown=False), "delay" / Delay(Int8ul), ) SceneRecall = Select( SceneRecallWithTransition, SceneRecallMinimal )
NOTE: This is a hack. Do not use unless you absolutely have to. """ bit_struct = BitStruct(*args) if reversed: bit_struct = Reversed(bit_struct) bit_struct.__construct_doc__ = Embedded(Struct(*args)) return (name / Rebuild(bit_struct, dict), ) + \ tuple(i.name / Computed(this[name][i.name]) for i in args if i.name is not None) Opcode = Select( ExprValidator(Int8ub, (obj_ != 0x7F) and (obj_ >> 7 == 0)), ExprValidator(Int16ub, (obj_ >> 14 == 2)), ExprValidator(Int24ub, (obj_ >> 22 == 3)), ) class DefaultCountValidator(Adapter): def __init__(self, subcon, rounding=None, resolution=1.0): super().__init__(subcon) self.rounding = rounding self.resolution = resolution def _decode(self, obj, content, path): if obj == (256**self.subcon.length) - 1: return None else: