Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
bd1f3bc8c9
|
|||
|
f9df70cf68
|
|||
|
5364b855aa
|
|||
|
3a1841a8a9
|
@@ -18,6 +18,7 @@ from apps.abstraction.vendors import (
|
||||
shelly,
|
||||
tasmota,
|
||||
hottis_pv_modbus,
|
||||
hottis_wago_modbus,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -40,6 +41,7 @@ for vendor_name, vendor_module in [
|
||||
("shelly", shelly),
|
||||
("tasmota", tasmota),
|
||||
("hottis_pv_modbus", hottis_pv_modbus),
|
||||
("hottis_wago_modbus", hottis_wago_modbus),
|
||||
]:
|
||||
for (device_type, direction), handler in vendor_module.HANDLERS.items():
|
||||
key = (device_type, vendor_name, direction)
|
||||
|
||||
39
apps/abstraction/vendors/hottis_pv_modbus.py
vendored
39
apps/abstraction/vendors/hottis_pv_modbus.py
vendored
@@ -23,17 +23,40 @@ def transform_relay_to_vendor(payload: dict[str, Any]) -> str:
|
||||
def transform_relay_to_abstract(payload: str) -> dict[str, Any]:
|
||||
"""Transform Hottis Modbus relay payload to abstract format.
|
||||
|
||||
Hottis Modbus sends JSON like:
|
||||
{"status": "Ok", "timestamp": "...", "state": false, "cnt": 528}
|
||||
Hottis Modbus sends plain text 'on' or 'off'.
|
||||
Example:
|
||||
- Hottis PV Modbus: 'on'
|
||||
- Abstract: {'power': 'on'}
|
||||
"""
|
||||
return {"power": payload.strip()}
|
||||
|
||||
def transform_contact_sensor_to_vendor(payload: dict[str, Any]) -> str:
|
||||
"""Transform abstract contact sensor payload to format.
|
||||
|
||||
Contact sensors are read-only.
|
||||
"""
|
||||
logger.warning("Contact sensors are read-only - SET commands should not be used")
|
||||
return json.dumps(payload)
|
||||
|
||||
|
||||
def transform_contact_sensor_to_abstract(payload: str) -> dict[str, Any]:
|
||||
"""Transform contact sensor payload to abstract format.
|
||||
|
||||
MAX! sends "true"/"false" (string or bool) on STATE topic.
|
||||
|
||||
Transformations:
|
||||
- state: true -> power: 'on'
|
||||
- state: false -> power: 'off'
|
||||
- "true" or True -> "open" (window/door open)
|
||||
- "false" or False -> "closed" (window/door closed)
|
||||
|
||||
Example:
|
||||
- contact sensor: "off"
|
||||
- Abstract: {"contact": "open"}
|
||||
"""
|
||||
data = json.loads(payload)
|
||||
state = data.get("state", False)
|
||||
power = "on" if bool(state) else "off"
|
||||
return {"power": power}
|
||||
contact_value = payload.strip().lower() == "off"
|
||||
return {
|
||||
"contact": "open" if contact_value else "closed"
|
||||
}
|
||||
|
||||
|
||||
|
||||
def transform_three_phase_powermeter_to_vendor(payload: dict[str, Any]) -> str:
|
||||
|
||||
58
apps/abstraction/vendors/hottis_wago_modbus.py
vendored
Normal file
58
apps/abstraction/vendors/hottis_wago_modbus.py
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
"""Hottis Wago Modbus vendor transformations."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def transform_relay_to_vendor(payload: dict[str, Any]) -> str:
|
||||
"""Transform abstract relay payload to Hottis Wago Modbus format.
|
||||
|
||||
Hottis Wago Modbus expects plain text 'true' or 'false' (not JSON).
|
||||
|
||||
Example:
|
||||
- Abstract: {'power': 'on'}
|
||||
- Hottis Wago Modbus: 'true' or 'false'
|
||||
"""
|
||||
power = payload.get("power", "off")
|
||||
|
||||
# Map abstract "on"/"off" to vendor "true"/"false"
|
||||
if isinstance(power, str):
|
||||
power_lower = power.lower()
|
||||
if power_lower in {"on", "true", "1"}:
|
||||
return "true"
|
||||
if power_lower in {"off", "false", "0"}:
|
||||
return "false"
|
||||
|
||||
# Fallback: any truthy value -> "true", else "false"
|
||||
return "true" if power else "false"
|
||||
|
||||
|
||||
def transform_relay_to_abstract(payload: str) -> dict[str, Any]:
|
||||
"""Transform Hottis Wago Modbus relay payload to abstract format.
|
||||
|
||||
Hottis Wago Modbus sends plain text 'true' or 'false'.
|
||||
|
||||
Example:
|
||||
- Hottis Wago Modbus: 'true'
|
||||
- Abstract: {'power': 'on'}
|
||||
"""
|
||||
value = payload.strip().lower()
|
||||
|
||||
if value == "true":
|
||||
power = "on"
|
||||
elif value == "false":
|
||||
power = "off"
|
||||
else:
|
||||
# Fallback for unexpected values: keep as-is
|
||||
logger.warning("Unexpected relay payload from Hottis Wago Modbus: %r", payload)
|
||||
power = value
|
||||
|
||||
return {"power": power}
|
||||
|
||||
|
||||
# Registry of handlers for this vendor
|
||||
HANDLERS = {
|
||||
("relay", "to_vendor"): transform_relay_to_vendor,
|
||||
("relay", "to_abstract"): transform_relay_to_abstract,
|
||||
}
|
||||
@@ -860,7 +860,6 @@ devices:
|
||||
topics:
|
||||
set: "IoT/Car/Control"
|
||||
state: "IoT/Car/Control/State"
|
||||
|
||||
- device_id: powermeter_caroutlet
|
||||
name: Car Outlet
|
||||
type: three_phase_powermeter
|
||||
@@ -868,6 +867,13 @@ devices:
|
||||
technology: hottis_pv_modbus
|
||||
topics:
|
||||
state: "IoT/Car/Values"
|
||||
- device_id: sensor_caroutlet
|
||||
name: Car Outlet
|
||||
type: contact
|
||||
cap_version: contact_sensor@1.0.0
|
||||
technology: hottis_pv_modbus
|
||||
topics:
|
||||
state: IoT/Car/Feedback/State
|
||||
|
||||
- device_id: schranklicht_flur_vor_kueche
|
||||
name: Schranklicht Flur vor Küche
|
||||
|
||||
@@ -321,5 +321,9 @@ rooms:
|
||||
title: Ladestrom
|
||||
icon: 📊
|
||||
rank: 320
|
||||
- device_id: sensor_caroutlet
|
||||
title: Ladestrom
|
||||
icon: 🪟
|
||||
rank: 330
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user