268 lines
9.0 KiB
Python
Executable File
268 lines
9.0 KiB
Python
Executable File
# =============================================================================
|
|
# DISCLAIMER
|
|
# -----------------------------------------------------------------------------
|
|
# This script is provided as-is and is **not** part of any official Acroname
|
|
# API or SDK. It is for illustrative or utility purposes only.
|
|
#
|
|
# There are no guarantees of correctness, compatibility, or ongoing support.
|
|
# This code may change at any time without notice.
|
|
#
|
|
# Use at your own risk.
|
|
# =============================================================================
|
|
|
|
class PDMessageHeader:
|
|
def __init__(self, msgHeaderVal=0):
|
|
# Initialize with the full 16-bit message header value
|
|
self.msgHeaderVal = msgHeaderVal
|
|
|
|
@property
|
|
def messageType(self):
|
|
# Extract the 5-bit message type (bits 0-4)
|
|
return self.msgHeaderVal & 0x1F
|
|
|
|
@messageType.setter
|
|
def messageType(self, value):
|
|
# Set the 5-bit message type (bits 0-4)
|
|
self.msgHeaderVal = (self.msgHeaderVal & ~0x1F) | (value & 0x1F)
|
|
|
|
@property
|
|
def portDataRole(self):
|
|
# Extract the 1-bit port data role (bit 5)
|
|
return (self.msgHeaderVal >> 5) & 0x01
|
|
|
|
@portDataRole.setter
|
|
def portDataRole(self, value):
|
|
# Set the 1-bit port data role (bit 5)
|
|
self.msgHeaderVal = (self.msgHeaderVal & ~(0x01 << 5)) | ((value & 0x01) << 5)
|
|
|
|
@property
|
|
def specRevision(self):
|
|
# Extract the 2-bit spec revision (bits 6-7)
|
|
return (self.msgHeaderVal >> 6) & 0x03
|
|
|
|
@specRevision.setter
|
|
def specRevision(self, value):
|
|
# Set the 2-bit spec revision (bits 6-7)
|
|
self.msgHeaderVal = (self.msgHeaderVal & ~(0x03 << 6)) | ((value & 0x03) << 6)
|
|
|
|
@property
|
|
def portPowerRoleOrCablePlug(self):
|
|
# Extract the 1-bit port power role or cable plug (bit 8)
|
|
return (self.msgHeaderVal >> 8) & 0x01
|
|
|
|
@portPowerRoleOrCablePlug.setter
|
|
def portPowerRoleOrCablePlug(self, value):
|
|
# Set the 1-bit port power role or cable plug (bit 8)
|
|
self.msgHeaderVal = (self.msgHeaderVal & ~(0x01 << 8)) | ((value & 0x01) << 8)
|
|
|
|
@property
|
|
def messageID(self):
|
|
# Extract the 3-bit message ID (bits 9-11)
|
|
return (self.msgHeaderVal >> 9) & 0x07
|
|
|
|
@messageID.setter
|
|
def messageID(self, value):
|
|
# Set the 3-bit message ID (bits 9-11)
|
|
self.msgHeaderVal = (self.msgHeaderVal & ~(0x07 << 9)) | ((value & 0x07) << 9)
|
|
|
|
@property
|
|
def numOfDataObjs(self):
|
|
# Extract the 3-bit number of data objects (bits 12-14)
|
|
return (self.msgHeaderVal >> 12) & 0x07
|
|
|
|
@numOfDataObjs.setter
|
|
def numOfDataObjs(self, value):
|
|
# Set the 3-bit number of data objects (bits 12-14)
|
|
self.msgHeaderVal = (self.msgHeaderVal & ~(0x07 << 12)) | ((value & 0x07) << 12)
|
|
|
|
@property
|
|
def extended(self):
|
|
# Extract the 1-bit extended flag (bit 15)
|
|
return (self.msgHeaderVal >> 15) & 0x01
|
|
|
|
@extended.setter
|
|
def extended(self, value):
|
|
# Set the 1-bit extended flag (bit 15)
|
|
self.msgHeaderVal = (self.msgHeaderVal & ~(0x01 << 15)) | ((value & 0x01) << 15)
|
|
|
|
def __repr__(self):
|
|
return (f"PDMessageHeader(messageType={self.messageType}, portDataRole={self.portDataRole}, "
|
|
f"specRevision={self.specRevision}, portPowerRoleOrCablePlug={self.portPowerRoleOrCablePlug}, "
|
|
f"messageID={self.messageID}, numOfDataObjs={self.numOfDataObjs}, extended={self.extended})")
|
|
|
|
|
|
class PDExtendedMessageHeader:
|
|
def __init__(self, extendedMsgHeaderVal=0):
|
|
# Initialize with the full 16-bit extended message header value
|
|
self.extendedMsgHeaderVal = extendedMsgHeaderVal
|
|
|
|
@property
|
|
def dataSize(self):
|
|
# Extract the 9-bit data size (bits 0-8)
|
|
return self.extendedMsgHeaderVal & 0x1FF
|
|
|
|
@dataSize.setter
|
|
def dataSize(self, value):
|
|
# Set the 9-bit data size (bits 0-8)
|
|
self.extendedMsgHeaderVal = (self.extendedMsgHeaderVal & ~0x1FF) | (value & 0x1FF)
|
|
|
|
@property
|
|
def reserved(self):
|
|
# Extract the 1-bit reserved (bit 9)
|
|
return (self.extendedMsgHeaderVal >> 9) & 0x01
|
|
|
|
@reserved.setter
|
|
def reserved(self, value):
|
|
# Set the 1-bit reserved (bit 9)
|
|
self.extendedMsgHeaderVal = (self.extendedMsgHeaderVal & ~(0x01 << 9)) | ((value & 0x01) << 9)
|
|
|
|
@property
|
|
def requestChunk(self):
|
|
# Extract the 1-bit request chunk (bit 10)
|
|
return (self.extendedMsgHeaderVal >> 10) & 0x01
|
|
|
|
@requestChunk.setter
|
|
def requestChunk(self, value):
|
|
# Set the 1-bit request chunk (bit 10)
|
|
self.extendedMsgHeaderVal = (self.extendedMsgHeaderVal & ~(0x01 << 10)) | ((value & 0x01) << 10)
|
|
|
|
@property
|
|
def chunkNumber(self):
|
|
# Extract the 4-bit chunk number (bits 11-14)
|
|
return (self.extendedMsgHeaderVal >> 11) & 0x0F
|
|
|
|
@chunkNumber.setter
|
|
def chunkNumber(self, value):
|
|
# Set the 4-bit chunk number (bits 11-14)
|
|
self.extendedMsgHeaderVal = (self.extendedMsgHeaderVal & ~(0x0F << 11)) | ((value & 0x0F) << 11)
|
|
|
|
@property
|
|
def chunked(self):
|
|
# Extract the 1-bit chunked flag (bit 15)
|
|
return (self.extendedMsgHeaderVal >> 15) & 0x01
|
|
|
|
@chunked.setter
|
|
def chunked(self, value):
|
|
# Set the 1-bit chunked flag (bit 15)
|
|
self.extendedMsgHeaderVal = (self.extendedMsgHeaderVal & ~(0x01 << 15)) | ((value & 0x01) << 15)
|
|
|
|
def __repr__(self):
|
|
return (f"PDExtendedMessageHeader(dataSize={self.dataSize}, reserved={self.reserved}, "
|
|
f"requestChunk={self.requestChunk}, chunkNumber={self.chunkNumber}, chunked={self.chunked})")
|
|
|
|
|
|
class BatteryInfoBitFields:
|
|
def __init__(self):
|
|
self._invalidBatteryRef = 0
|
|
self._batteryIsPresent = 0
|
|
self._batteryChargingStatus = 0
|
|
self._reserved = 0
|
|
|
|
# Getters and setters for the bitfields
|
|
@property
|
|
def invalid_battery_ref(self):
|
|
return self._invalidBatteryRef
|
|
|
|
@invalid_battery_ref.setter
|
|
def invalid_battery_ref(self, value):
|
|
if value in [0, 1]:
|
|
self._invalidBatteryRef = value
|
|
else:
|
|
raise ValueError("Invalid Battery Reference must be 0 or 1.")
|
|
|
|
@property
|
|
def battery_is_present(self):
|
|
return self._batteryIsPresent
|
|
|
|
@battery_is_present.setter
|
|
def battery_is_present(self, value):
|
|
if value in [0, 1]:
|
|
self._batteryIsPresent = value
|
|
else:
|
|
raise ValueError("Battery Is Present must be 0 or 1.")
|
|
|
|
@property
|
|
def battery_charging_status(self):
|
|
return self._batteryChargingStatus
|
|
|
|
@battery_charging_status.setter
|
|
def battery_charging_status(self, value):
|
|
if 0 <= value <= 3:
|
|
self._batteryChargingStatus = value
|
|
else:
|
|
raise ValueError("Battery Charging Status must be between 0 and 3.")
|
|
|
|
@property
|
|
def reserved(self):
|
|
return self._reserved
|
|
|
|
@reserved.setter
|
|
def reserved(self, value):
|
|
if 0 <= value <= 15:
|
|
self._reserved = value
|
|
else:
|
|
raise ValueError("Reserved (bitfields) must be between 0 and 15.")
|
|
|
|
|
|
class PDBatteryStatusDataObject:
|
|
def __init__(self):
|
|
self._reserved = 0
|
|
self._batteryInfoBitFields = BatteryInfoBitFields()
|
|
self._batteryPC = 0
|
|
|
|
# Getters and setters for the fields
|
|
@property
|
|
def reserved(self):
|
|
return self._reserved
|
|
|
|
@reserved.setter
|
|
def reserved(self, value):
|
|
if 0 <= value <= 255: # 8-bit value
|
|
self._reserved = value
|
|
else:
|
|
raise ValueError("Reserved must be between 0 and 255.")
|
|
|
|
@property
|
|
def battery_info_bit_fields(self):
|
|
return self._batteryInfoBitFields
|
|
|
|
@property
|
|
def battery_pc(self):
|
|
return self._batteryPC
|
|
|
|
@battery_pc.setter
|
|
def battery_pc(self, value):
|
|
if 0 <= value <= 65535: # 16-bit value
|
|
self._batteryPC = value
|
|
else:
|
|
raise ValueError("Battery PC must be between 0 and 65535.")
|
|
|
|
def __str__(self):
|
|
return (f"Reserved (8-bit): {self._reserved}\n"
|
|
f"Invalid Battery Ref: {self._batteryInfoBitFields.invalid_battery_ref}\n"
|
|
f"Battery Is Present: {self._batteryInfoBitFields.battery_is_present}\n"
|
|
f"Battery Charging Status: {self._batteryInfoBitFields.battery_charging_status}\n"
|
|
f"Reserved (bitfields, 4-bit): {self._batteryInfoBitFields.reserved}\n"
|
|
f"Battery PC: {self._batteryPC}")
|
|
|
|
|
|
# Function to decode rule into PDBatteryStatusDataObject
|
|
def rule_to_battery_status_data_object(rule):
|
|
bsdo_rule = PDBatteryStatusDataObject()
|
|
|
|
# Decode the 8-bit reserved field
|
|
bsdo_rule.reserved = (rule >> 0) & 0xFF
|
|
|
|
# Decode the bitfields from the byte at bit 8
|
|
bsdo_rule.battery_info_bit_fields.invalid_battery_ref = (rule >> 8) & 0x1
|
|
bsdo_rule.battery_info_bit_fields.battery_is_present = (rule >> 9) & 0x1
|
|
bsdo_rule.battery_info_bit_fields.battery_charging_status = (rule >> 10) & 0x3
|
|
bsdo_rule.battery_info_bit_fields.reserved = (rule >> 12) & 0xF
|
|
|
|
# Decode the 16-bit batteryPC field
|
|
bsdo_rule.battery_pc = (rule >> 16) & 0xFFFF
|
|
|
|
return bsdo_rule
|
|
|
|
|