Neuigkeiten:

Am Sonntag den 8.12.2024 kann es ab ca. 8:00 Uhr zu kurzzeitigen Einschränkungen / Ausfällen bei den Diensten des FHEM Vereines kommen.
Die Server müssen mal gewartet und dabei neu gestartet werden ;)

Hauptmenü

TA-Geräte (UVR16x2/RSM) für Jalousiesteuerung/Sensorik + Zehnder ComfoAir Q600

Begonnen von Maxix2, 09 Februar 2019, 15:37:54

Vorheriges Thema - Nächstes Thema

Maxix2

Moin,

ich will euch mein Projekt bzw. die Haussteuerung vorstellen, primär um andere "Mitstreiter" zu finden die diese Geräte selber verwenden.

Mein FHEM-System besteht aus einem Raspi 2B mit einem PiCAN Duo und einem RTC-Modul. An das CAN-Modul sind einmal das "ComfoNet" der Lüftung und der CAN-Bus unserer TA-Geräte angeschlossen

Die 1. und kleinere Abteilung ist das Empfangen von Sensorik und in Zukunft auch das Steuern der Lüftung. Hierfür habe ich vor kurzem das Repository von Marco Hoyer bzw. das von "djwlindenaar" entdeckt (https://github.com/djwlindenaar/zcan), das darauf ausgelegt war diese Daten in eine InfluxDB zu schieben. Das habe ich angepasst um die Werte in ein lokal betriebenen mosquitto MQTT-Server zu schreiben.
Ein paar MQTT-Devices  für die einzelnen Werte und das Ding läuft (Siehe Bild).

Das 2. Projekt war die Geräte von TA anzubinden, mit einem Fokus auf die Jalousiensteuerung und die Temperatur-Werte etc. in das System zu kriegen.
Hierfür musste ein weiteres Programm geschrieben werden dass mit den Geräten interagiert und auf den MQTT-Server schiebt / liest.
Zusätzlich habe ich mit Packet-Sniffing/Reverse Engineering herausgefunden wie die Jalousien gesteuert werden können bzw. ausgelesen werden.
Ebenfalls kann ich mit dem Programm CAN-Eingänge und Ausgänge auslesen und emulieren. Hierüber kann man dann natürlich absolut alles realisieren.
Das ganze funktioniert ohne ein angeschlossenes CMI wie bei den Modulen von @delmar benötigt.

Damit ich beim Erstellen von den Jalousien im FHEM keinen Muskelkrampf bekomme analysiert das Programm die Geräte und verwendeten Funktionen im Netz und bietet an alle im FHEM anzulegen

Was mir noch fehlt ist dass ich die einzelnen Sensoren im FHEM sinnvoll erstellen kann bzw. die CAN-Ausgänge ändern kann.
Ebenfalls in der Mache ist eine Tablet-UI und unabhängig von FHEM die Möglichkeit die Funktionsdaten einzuspielen

Einige Screenshots sind angehangen wie es zur Zeit aussieht.

Viele Grüße
Maxi

PeMue

Hallo,

welche Geräte von TA hast Du denn? Meines Wissens gibt die Firma die Protokolle ihrer Geräte raus, eine nette Mail reicht  :).

Gruß Peter
RPi3Bv1.2 rpiaddon 1.66 6.0 1xHM-CC-RT-DN 1.4 1xHM-TC-IT-WM 1.1 2xHB-UW-Sen-THPL-O 0.15 1x-I 0.14OTAU  1xCUNO2 1.67 2xEM1000WZ 2xUniroll 1xASH2200 3xHMS100T(F) 1xRFXtrx 90 1xWT440H 3xTFA30.3150 5xFA21
RPi1Bv2 LCDCSM 1.63 5.8 2xMAX HKT 1xMAX RT V200KW1 Heizung Wasser

Maxix2

Hallo Peter,

ich verwende einige UVR16x2 und RSM610's. Keine weiteren Geräte.
Ich habe schon 3 mal bei TA angefragt und jedes mal unterschiedliche Dokumente erhalten.
Die Dokumente sind sehr hilfreich gewesen bei den PDO's (also den CAN-Ein/Ausgängen)
Für den Rest ist das insgesamt nicht sehr hilfreich gewesen, da die einzelnen Objekte bzw. die Schreibparameter nicht dokumentiert sind.
Vieles ist ja auch schon vom CANopen definiert, deshalb ist die Implementation nicht zu aufwendig.

Grüße Maxi

tjareson

Hallo,
das Thema ist hier zwar schon etwas älter, aber vielleicht kann mir jemand weiterhelfen.
Ich habe gerade "zusammen mit chatGPT" angefangen, die Daten auf dem CAN Bus der UVR16x2 etwas zu analysieren. Wenn ich das richtig verstehe, setzt fhem nämlich auch das CMI voraus. Da ich aber eigentlich nur 3 Temperaturen abfragen und 3 digital Eingänge über CAN setzen möchte, ist mir das zu teuer und ich will die Lösung möglichst schlank halten.

Ich kann Temperaturen und Schaltzustände aus meiner UVR16x2 rausbekommen - nur schreiben funktioniert irgendwie nicht, egal was ich der UVR sende. Die Lösung von Maxix2 liest sich irgendwie so, als ob das trotzdem ginge ohne CMI?

Maxix2

Genau, die (beiden?) Module die im offiziellen Repository sind benötigen beide das CMI. Wir wollten das uns auch nicht anschaffen, sondern sind eine Eigenlösung gefahren.
Beide Lösungen haben aber gemeinsam, dass ein Zugriff auf den CAN-Bus benötigt wird.
Zuerst habe ich versucht, das ganze als Modul in FHEM einzubauen. Hier ist der originale Post wo auch das Modul in seiner letzten Version verlinkt ist: https://forum.fhem.de/index.php?topic=99821.msg932115#msg932115
Das sollte für deinen Zweck eigentlich auch reichen. Die digitalen Ausgänge müssen in der UVR als CAN-Eingang angelegt werden und entsprechend im Modul konfiguriert werden.

tjareson

#5
Hi,

Zitat von: Maxix2 am 31 Dezember 2023, 14:55:01Hier ist der originale Post wo auch das Modul in seiner letzten Version verlinkt ist: https://forum.fhem.de/index.php?topic=99821.msg932115#msg932115

Danke, den Eintrag habe ich auch schon gesehen und versucht zu berücksichtigen.
Ich habe ein python script zum empfangen (funtioniert) und senden (funktioniert nicht) von Werten an die UVR gebaut.
Bei letzterem fehlt mir irgendwas. Vermutlich baue ich die Arbitration ID aus Node-ID und Funktions-Code nicht richtig zusammen oder der UVR fehlt sonst noch irgendwas.

Anbei mal beide Scripte - ich versuche das komplett schmalspur zu machen, also direktes Auswerten der CAN-Rohdaten, die die UVR16x2 sendet. Leider klappt das beim Senden an die UVR nicht. Ich sehe die Werte auf dem CAN Bus in der UVR einfach nicht. Sobald ich auf einem CAN-Eingangskanal eine Node-ID auswähle, zeigt mir die UVR schon einen Fehler.
Da bei mir die Einzelraum-Heizungsanforderung auf NodeRed basiert, muss ich das dann ohnehin nochmal Richtung MQTT umbauen.

UVR-Read:
import can

def decode_temperature(data):
    """Decode temperature from CAN data assuming 2 bytes per reading."""
    temp_raw = int.from_bytes(data, byteorder='little', signed=True)
    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 extract_node_id(arbitration_id):
    """Extract node ID from arbitration ID."""
    return arbitration_id & 0x7F

def extract_function_code(arbitration_id):
    """Extract function code from arbitration ID."""
    return arbitration_id >> 7

def main():
    analog_temp_ids = [513, 769]  # Each ID corresponds to a block of 8 channels
    digital_ids = [385]
    last_digital_states = [None] * 32  # Initialize with None to track changes

    bus = can.interface.Bus(bustype='slcan', channel='/dev/ttyACM0', bitrate=50000)

    try:
        print("Listening for CAN messages...")
        while True:
            message = bus.recv()

            if message is not None:
                node_id = extract_node_id(message.arbitration_id)
                function_code = extract_function_code(message.arbitration_id)
                byte_values = [f"{b:02x}" for b in message.data]  # Convert each byte to hex string
                print(f"Raw Message: ID: {message.arbitration_id} (Node ID: {node_id}, Function Code: {function_code}), Data: {byte_values}")

                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), 2):
                        temp = decode_temperature(message.data[i:i+2])
                        if temp != 0:  # Assuming 0 is not a valid temperature
                            channel = base_channel_offset + (i // 2) + 1
                            print(f"Analog Channel {channel}: {temp}°C")
               
                elif message.arbitration_id in digital_ids:
                    states = decode_digital(message.data)
                    for i, state in enumerate(states):
                        if last_digital_states[i] is not None and state != last_digital_states[i]:
                            print(f"Digital Channel {i + 1}: {'ON' if state else 'OFF'}")
                        last_digital_states[i] = state

    except KeyboardInterrupt:
        print("Interrupted, closing connection.")
        bus.shutdown()

if __name__ == "__main__":
    main()

Und hier mein Versuch, Daten an die UVR zu senden, auch nahe Bodenblech, da ich eigentlich im Endeffekt nur 2-3 Temperaturen und 2-3 Digitaleingänge ansteuern will.

import can
import struct
import time

def create_analog_message(channel, temperature, node_id=2):
    """Create a CAN message for an analog channel with a given temperature."""
    offset = 0x200 + ((channel - 1) // 4) * 0x80
    arbitration_id = offset + node_id
    data = bytearray(8)
    channel_index = (channel - 1) % 4
    temp_raw = int(temperature * 10)  # Convert temperature to tenths of degrees
    temp_bytes = struct.pack("<h", temp_raw)  # Pack as 16-bit signed
    temp_unsigned = struct.unpack("<H", temp_bytes)[0]  # Unpack as 16-bit unsigned
    data[channel_index * 2:channel_index * 2 + 2] = struct.pack("<H", temp_unsigned)
    return can.Message(arbitration_id=arbitration_id, data=data)

def create_digital_message(channel, state, node_id=2):
    """Create a CAN message for a digital channel with a given state."""
    arbitration_id = 0x180 + node_id
    data = bytearray(8)
    if state:
        data[(channel - 1) // 8] |= 1 << ((channel - 1) % 8)
    return can.Message(arbitration_id=arbitration_id, data=data)

def main():
    bus = can.interface.Bus(bustype='slcan', channel='/dev/ttyACM0', bitrate=50000)
    node_id = 2

    digital_states = {1: True, 2: False}  # Example states
    analog_values = {0: [25.5, 22.0], 1: [23.5, 24.0]}  # Grouped analog values

    try:
        while True:
            # Send digital message
            digital_message = create_digital_message(1, digital_states[1], node_id)
            bus.send(digital_message)
            print(f"Sent Digital Message: Data: {digital_message.data}")

            # Send analog messages
            for group, values in analog_values.items():
                analog_message = create_analog_message(group + 1, values[group], node_id)
                bus.send(analog_message)
                print(f"Sent Analog Message for Group {group + 1}: Data: {analog_message.data}")

            time.sleep(60)  # Repeat every minute

    except KeyboardInterrupt:
        print("Interrupted, closing connection.")
        bus.shutdown()

if __name__ == "__main__":
    main()

Ich nutze übrigens den USBtin Adapter zur Hardwareanbindung.

tjareson

Ich habe das jetzt nochmal mit dem fhem modul von dem Link ausprobiert. (98_UVR16x2.pm)
Wenn ich versuche, eine UVR zu definieren mit
define UVR UVR16x2 slcan0 1
hängt sich mein fhem auf bis ich das script neu starte. Übersehe ich irgendetwas?
Die Anbindung des CAN-Adapters mache ich wie folgt:
modprobe can
modprobe can-raw
modprobe slcan
slcan_attach -f -s2 -o /dev/ttyACM0
slcand ttyACM0 slcan0
ifconfig slcan0 up


candump slcan0 funktioniert auch. Nur die UVR in fhem anzulegen funktioniert nicht.

tjareson

So, habe es jetzt doch per Javascript direkt in NodeRed hinbekommen, Thema hat sich damit für fhem erstmal erledigt.