Skip to content

Commit c8577aa

Browse files
Merge pull request #12 from michaelarnauts/airflow-contraints
Parse airflow constraints
2 parents 2451cf2 + 777c679 commit c8577aa

File tree

5 files changed

+98
-5
lines changed

5 files changed

+98
-5
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ $ python -m aiocomfoconnect set-speed high --host 192.168.1.213
2828

2929
$ python -m aiocomfoconnect show-sensors --host 192.168.1.213
3030
$ python -m aiocomfoconnect show-sensor 276 --host 192.168.1.213
31+
$ python -m aiocomfoconnect show-sensor 276 --host 192.168.1.213 -f
3132

3233
$ python -m aiocomfoconnect get-property --host 192.168.1.213 1 1 8 9 # Unit 0x01, SubUnit 0x01, Property 0x08, Type STRING. See PROTOCOL-RMI.md
3334
```

aiocomfoconnect/__main__.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async def main(args):
4040
await run_show_sensors(args.host, args.uuid)
4141

4242
elif args.action == "show-sensor":
43-
await run_show_sensor(args.host, args.uuid, args.sensor)
43+
await run_show_sensor(args.host, args.uuid, args.sensor, args.follow)
4444

4545
elif args.action == "get-property":
4646
await run_get_property(args.host, args.uuid, args.node_id, args.unit, args.subunit, args.property_id, args.property_type)
@@ -190,7 +190,7 @@ def sensor_callback(sensor, value):
190190
await comfoconnect.disconnect()
191191

192192

193-
async def run_show_sensor(host: str, uuid: str, sensor: int):
193+
async def run_show_sensor(host: str, uuid: str, sensor: int, follow=False):
194194
"""Connect to a bridge."""
195195
result = Future()
196196

@@ -201,7 +201,9 @@ async def run_show_sensor(host: str, uuid: str, sensor: int):
201201

202202
def sensor_callback(sensor_, value):
203203
"""Print sensor update."""
204-
result.set_result(value)
204+
print(value)
205+
if not result.done():
206+
result.set_result(value)
205207

206208
# Connect to the bridge
207209
comfoconnect = ComfoConnect(bridges[0].host, bridges[0].uuid, sensor_callback=sensor_callback)
@@ -219,7 +221,16 @@ def sensor_callback(sensor_, value):
219221
await comfoconnect.register_sensor(SENSORS[sensor])
220222

221223
# Wait for value
222-
print(await result)
224+
await result
225+
226+
# Follow for updates if requested
227+
if follow:
228+
try:
229+
while True:
230+
await asyncio.sleep(1)
231+
232+
except KeyboardInterrupt:
233+
pass
223234

224235
# Disconnect
225236
await comfoconnect.disconnect()
@@ -277,6 +288,7 @@ async def run_get_property(host: str, uuid: str, node_id: int, unit: int, subuni
277288
p_sensor.add_argument("sensor", help="The ID of the sensor", type=int)
278289
p_sensor.add_argument("--host", help="Host address of the bridge")
279290
p_sensor.add_argument("--uuid", help="UUID of this app", default=DEFAULT_UUID)
291+
p_sensor.add_argument("--follow", "-f", help="Follow", default=False, action="store_true")
280292

281293
p_sensor = subparsers.add_parser("get-property", help="show a property value")
282294
p_sensor.add_argument("unit", help="The Unit of the property", type=int)

aiocomfoconnect/sensors.py

+4
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
from dataclasses import dataclass
55
from typing import Callable, Dict
66

7+
from .util import calculate_airflow_constraints
78
from .const import (
89
TYPE_CN_BOOL,
910
TYPE_CN_INT16,
1011
TYPE_CN_UINT8,
1112
TYPE_CN_UINT16,
1213
TYPE_CN_UINT32,
14+
TYPE_CN_INT64,
1315
)
1416

1517
# Sensors
@@ -74,6 +76,7 @@
7476
SENSOR_TEMPERATURE_SUPPLY = 221
7577
SENSOR_UNIT_AIRFLOW = 224
7678
SENSOR_UNIT_TEMPERATURE = 208
79+
SENSOR_AIRFLOW_CONSTRAINTS = 230
7780

7881
UNIT_WATT = "W"
7982
UNIT_KWH = "kWh"
@@ -148,6 +151,7 @@ class Sensor:
148151
SENSOR_FAN_SPEED_MODE_MODULATED: Sensor("Fan Speed (modulated)", None, 226, TYPE_CN_UINT16),
149152
SENSOR_BYPASS_STATE: Sensor("Bypass State", UNIT_PERCENT, 227, TYPE_CN_UINT8),
150153
SENSOR_FROSTPROTECTION_UNBALANCE: Sensor("frostprotection_unbalance", None, 228, TYPE_CN_UINT8),
154+
SENSOR_AIRFLOW_CONSTRAINTS: Sensor("Airflow constraints", None, 230, TYPE_CN_INT64, calculate_airflow_constraints),
151155
SENSOR_TEMPERATURE_EXTRACT: Sensor("Extract Air Temperature", UNIT_CELCIUS, 274, TYPE_CN_INT16, lambda x: x / 10),
152156
SENSOR_TEMPERATURE_EXHAUST: Sensor("Exhaust Air Temperature", UNIT_CELCIUS, 275, TYPE_CN_INT16, lambda x: x / 10),
153157
SENSOR_TEMPERATURE_OUTDOOR: Sensor("Outdoor Air Temperature", UNIT_CELCIUS, 276, TYPE_CN_INT16, lambda x: x / 10),

aiocomfoconnect/util.py

+76
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ def bytearray_to_bits(arr):
1919
return bits
2020

2121

22+
def uint_to_bits(value):
23+
"""Convert an unsigned integer to a list of set bits."""
24+
bits = []
25+
j = 0
26+
for i in range(64):
27+
if value & (1 << i):
28+
bits.append(j)
29+
j += 1
30+
return bits
31+
32+
2233
def version_decode(version):
2334
"""Decode the version number to a string."""
2435
v_1 = (version >> 30) & 3
@@ -46,3 +57,68 @@ def pdo_to_can(pdo, node_id=1):
4657
def can_to_pdo(can, node_id=1):
4758
"""Convert a CAN-ID to a PDO-ID."""
4859
return (int(can, 16) - 0x40 - node_id) >> 14
60+
61+
62+
def calculate_airflow_constraints(value):
63+
"""Calculate the airflow constraints based on the bitshift value."""
64+
bits = uint_to_bits(value)
65+
if 45 not in bits:
66+
return None
67+
68+
constraints = []
69+
if 2 in bits or 3 in bits:
70+
constraints.append("Resistance")
71+
if 4 in bits:
72+
constraints.append("PreheaterNegative")
73+
if 5 in bits or 7 in bits:
74+
constraints.append("NoiseGuard")
75+
if 6 in bits or 8 in bits:
76+
constraints.append("ResistanceGuard")
77+
if 9 in bits:
78+
constraints.append("FrostProtection")
79+
if 10 in bits:
80+
constraints.append("Bypass")
81+
if 12 in bits:
82+
constraints.append("AnalogInput1")
83+
if 13 in bits:
84+
constraints.append("AnalogInput2")
85+
if 14 in bits:
86+
constraints.append("AnalogInput3")
87+
if 15 in bits:
88+
constraints.append("AnalogInput4")
89+
if 16 in bits:
90+
constraints.append("Hood")
91+
if 18 in bits:
92+
constraints.append("AnalogPreset")
93+
if 19 in bits:
94+
constraints.append("ComfoCool")
95+
if 22 in bits:
96+
constraints.append("PreheaterPositive")
97+
if 23 in bits:
98+
constraints.append("RFSensorFlowPreset")
99+
if 24 in bits:
100+
constraints.append("RFSensorFlowProportional")
101+
if 25 in bits:
102+
constraints.append("TemperatureComfort")
103+
if 26 in bits:
104+
constraints.append("HumidityComfort")
105+
if 27 in bits:
106+
constraints.append("HumidityProtection")
107+
if 47 in bits:
108+
constraints.append("CO2ZoneX1")
109+
if 48 in bits:
110+
constraints.append("CO2ZoneX2")
111+
if 49 in bits:
112+
constraints.append("CO2ZoneX3")
113+
if 50 in bits:
114+
constraints.append("CO2ZoneX4")
115+
if 51 in bits:
116+
constraints.append("CO2ZoneX5")
117+
if 52 in bits:
118+
constraints.append("CO2ZoneX6")
119+
if 53 in bits:
120+
constraints.append("CO2ZoneX7")
121+
if 54 in bits:
122+
constraints.append("CO2ZoneX8")
123+
124+
return constraints

docs/PROTOCOL-PDO.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Numbers are stored in little endian format.
8888
| 227 | CN_UINT8 | Bypass state | value in % (100% = fully open) |
8989
| 228 | CN_UINT8 | ?? FrostProtectionUnbalance | 0 |
9090
| 229 | CN_BOOL | | 1 |
91-
| 230 | CN_INT64 | Ventilation Constraints Bitset | |
91+
| 230 | CN_INT64 | Ventilation Constraints Bitset | See calculate_airflow_constraints() |
9292
| 256 | CN_UINT8 | | 1=basic, 2=advanced, 3=installer |
9393
| 257 | CN_UINT8 | | |
9494
| 274 | CN_INT16 | Temperature: Extract Air | value in °C (171 -> 17.1 °C) |

0 commit comments

Comments
 (0)