UmberHubManager/api/examples/python/utilities/powerdelivery/pd_defs.py

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