Hoffe, das ist nicht zu softwarelastig, aber irgendwie finde ich ansonsten auch nicht viel im Netz dazu. Die fhem-Lösung erfordert auch das CMI, sofern ich das richtig verstanden habe. Das ist mir allein dazu aber zu teuer.
Ich habe mich mal gestern abend zusammen mit chatGPT etwas an die Analyse von dem CAN Bus der UVR gemacht und bin dabei in recht kurzer Zeit ein Stück weiter gekommen.
Ich nutze übrigens den CAN-Adapter USBtin. Der ist relativ teuer, aber irgendwie scheint das die "amtliche Version" zu sein und es gibt auch ein bißchen Software dazu.
Meine UVR (derzeit übrigens noch nicht verbaut) läuft als Node 1, mit 50.000 baud auf'm bus.
Ich habe 2 PT1000 (an Eingang 1 und 2) und 2 Relais definiert (Ausgang 1 und 5).
Dann habe ich auf dem CAN-Bus der UVR testweise bei den Analogausgängen den Kanal 1 mit dem ersten Temperatursensor und den Kanal 9 mit dem zweiten Temperatursensor belegt.
Bei den digitalen Ausgängen habe ich ein Relais auf Kanal 1 und das zweite auf Kanal 17 gelegt.
Daraufhin sendet die UVR schon mal 3 zusätzliche IDs: 513 und 769 (darin stehen die Temperaturen für Tempsensor 1 und 2 auf den Kanälen 1 und 9) In der payload stehen jeweils 4 bytes für die Temperatur als Zehntelgrad.
Code: Alles auswählen
Raw Message: ID: 449, Data: bytearray(b'\x01\x06++++++')
Raw Message: ID: 513, Data: bytearray(b'\xf0\x00\x00\x00\x00\x00\x00\x00')
Analog Channel 1: 24.0°C
Raw Message: ID: 1793, Data: bytearray(b'\x05')
Raw Message: ID: 1793, Data: bytearray(b'\x05\x87\x01\x00\x9d\x9b\x9d\x91')
Raw Message: ID: 449, Data: bytearray(b'\x01\x08++++++')
Raw Message: ID: 769, Data: bytearray(b'\xe5\x00\x00\x00\x00\x00\x00\x00')
Analog Channel 9: 22.9°C
Code: Alles auswählen
Raw Message: ID: 385, Data: bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00')
Digital Channel 1: ON
Raw Message: ID: 1793, Data: bytearray(b'\x05')
Raw Message: ID: 1793, Data: bytearray(b'\x05\x87\x01\x00\x9d\x9b\x9d\x91')
Raw Message: ID: 1793, Data: bytearray(b'\x05')
Raw Message: ID: 1793, Data: bytearray(b'\x05\x87\x01\x00\x9d\x9b\x9d\x91')
Raw Message: ID: 449, Data: bytearray(b'\x01\x00\x01\x00\x00\x00\x00\x00')
Raw Message: ID: 385, Data: bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
Digital Channel 1: OFF
Raw Message: ID: 385, Data: bytearray(b'\x00\x00\x01\x00\x00\x00\x00\x00')
Digital Channel 17: ON
Raw Message: ID: 1793, Data: bytearray(b'\x05')
Raw Message: ID: 1793, Data: bytearray(b'\x05\x87\x01\x00\x9d\x9b\x9d\x91')
Raw Message: ID: 449, Data: bytearray(b'\x01\x01\x00\x00\x01\x00\x00\x00')
Raw Message: ID: 385, Data: bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
Digital Channel 17: OFF
Ich habe chatGPT dann gebeten, mir das Python script so zu schreiben, dass ich die CAN-Bus IDs für analoge und digitale Werte festlegen kann. Vermutlich kann man das auch direkt an der Payload der ID 449 erkennen, aber da habe ich bisher nichts schlüssiges erkennen können. Das Script hat auch noch den Fehler, das nur Temperaturen ungleich 0 gültig sind, das muss ich noch ändern. Ungültige Werte sind da glaube ich 9999 oder sowas.
Das python script anbei. Falls das mal jemand mit seiner UVR ausprobieren und mitteilen kann, was da für IDs gesendet werden, wäre das ganz aufschlussreich.
Code: Alles auswählen
import can
def decode_temperature(data):
"""Decode temperature from CAN data."""
temp_raw = int.from_bytes(data, byteorder='little')
return temp_raw / 10
def decode_digital(data):
"""Decode digital data from CAN data."""
states = []
for byte in data[:4]: # Limit to the first 4 bytes (32 channels)
for bit in range(8):
states.append(bool(byte & (1 << bit)))
return states
def main():
# Configurable section for analog temperature data IDs
analog_temp_ids = [513, 769] # Each ID corresponds to a block of 8 channels
# Configurable section for digital data IDs
digital_ids = [385]
# Initial states for digital channels
last_digital_states = [False] * 32
# Configure the connection to the CAN interface
bus = can.interface.Bus(bustype='slcan', channel='/dev/ttyACM0', bitrate=50000)
try:
print("Listening for CAN messages...")
while True:
message = bus.recv() # Block and wait for a message
if message is not None:
print(f"Raw Message: ID: {message.arbitration_id}, Data: {message.data}")
# Handle analog temperature data
if message.arbitration_id in analog_temp_ids:
base_channel_offset = 8 * analog_temp_ids.index(message.arbitration_id)
for i in range(0, len(message.data), 4):
temp = decode_temperature(message.data[i:i+4])
if temp != 0: # Assuming 0 is not a valid temperature
channel = base_channel_offset + (i // 4) + 1
print(f"Analog Channel {channel}: {temp}°C")
# Handle digital data
elif message.arbitration_id in digital_ids:
states = decode_digital(message.data)
for i, state in enumerate(states):
if i < len(last_digital_states):
if state != last_digital_states[i]:
last_digital_states[i] = state
print(f"Digital Channel {i + 1}: {'ON' if state else 'OFF'}")
except KeyboardInterrupt:
print("Interrupted, closing connection.")
bus.shutdown()
if __name__ == "__main__":
main()
Noch ein Nachtrag: es hat sich herausgestellt, dass es bei Änderungen der CAN-Bus Ausgänge es sinnvoll sein kann, dass man die UVR danach neu startet. Zumindest wenn ich Ausgänge am CAN-Bus wieder auf unbenutzt stelle, sendet die UVR danach ab und an Datenmüll auf dem CAN. Nach Neustart ist dann aber alles wieder entsprechend der Config.