MAX transformation added

This commit is contained in:
2025-11-10 16:11:28 +01:00
parent a49d56df60
commit b57ddb1589
3 changed files with 346 additions and 15 deletions

View File

@@ -173,7 +173,12 @@ async def handle_abstract_set(
# Transform abstract payload to vendor-specific format
vendor_payload = transform_abstract_to_vendor(device_type, device_technology, abstract_payload)
vendor_message = json.dumps(vendor_payload)
# For MAX! thermostats, vendor_payload is a plain string (integer temperature)
# For other devices, it's a dict that needs JSON encoding
if device_technology == "max" and device_type == "thermostat":
vendor_message = vendor_payload # Already a string
else:
vendor_message = json.dumps(vendor_payload)
logger.info(f"→ vendor SET {device_id}: {vendor_topic}{vendor_message}")
await mqtt_client.publish(vendor_topic, vendor_message, qos=1)
@@ -294,11 +299,30 @@ async def mqtt_worker(config: dict[str, Any], redis_client: aioredis.Redis) -> N
topic = str(message.topic)
payload_str = message.payload.decode()
try:
payload = json.loads(payload_str)
except json.JSONDecodeError:
logger.warning(f"Invalid JSON on {topic}: {payload_str}")
continue
# Determine if message is from a MAX! device (requires plain text handling)
is_max_device = False
max_device_id = None
max_device_type = None
# Check if topic matches any MAX! device state topic
for device_id, device in devices.items():
if device.get("technology") == "max" and topic == device["topics"]["state"]:
is_max_device = True
max_device_id = device_id
max_device_type = device["type"]
break
# Parse payload based on device technology
if is_max_device:
# MAX! sends plain integer/string, not JSON
payload = payload_str.strip()
else:
# All other technologies use JSON
try:
payload = json.loads(payload_str)
except json.JSONDecodeError:
logger.warning(f"Invalid JSON on {topic}: {payload_str}")
continue
# Check if this is an abstract SET message
if topic.startswith("home/") and topic.endswith("/set"):
@@ -318,15 +342,24 @@ async def mqtt_worker(config: dict[str, Any], redis_client: aioredis.Redis) -> N
# Check if this is a vendor STATE message
else:
# Find device by vendor state topic
for device_id, device in devices.items():
if topic == device["topics"]["state"]:
device_technology = device.get("technology", "unknown")
await handle_vendor_state(
client, redis_client, device_id, device["type"],
device_technology, payload, redis_channel
)
break
# For MAX! devices, we already identified them above
if is_max_device:
device = devices[max_device_id]
device_technology = device.get("technology", "unknown")
await handle_vendor_state(
client, redis_client, max_device_id, max_device_type,
device_technology, payload, redis_channel
)
else:
# Find device by vendor state topic for other technologies
for device_id, device in devices.items():
if topic == device["topics"]["state"]:
device_technology = device.get("technology", "unknown")
await handle_vendor_state(
client, redis_client, device_id, device["type"],
device_technology, payload, redis_channel
)
break
except asyncio.CancelledError:
logger.info("MQTT worker cancelled")