Benutzer-Werkzeuge

Webseiten-Werkzeuge


wp:vitocal_250a_datenerfassung

Vitocal 250A Datenerfassung UDS/CanBus

Alle Angaben ohne Gewähr und jeglicher Nachbau auf eigene Verantwortung des Lesers.

Die Daten meiner Wärmepumpe erfasse ich mit einem RasPi 3B über UDS/CanBus mit einem umgebauten und über SPI an den RasPi angeschlossenen MCP2515-Modul. Der Umbau besteht aus einem 3V3-Linearregler für die Versorgung des MCP2515-IC. Dabei wird der Transceiver (ich habe den TJA1050 durch einen TJA1051T ersetzt) weiterhin mit 5V versorgt, die der MCP2515 aber vom RasPi fernhält. Ich habe nur CANH und CANL verbunden. Der RasPi ist zudem an keiner Stelle hart mit N oder PE verbunden, auch nicht über die Schirmung seines LAN-Kabels, sondern nur indirekt über den kleinen Y-Kondensator seines Netzteils kapazitiv an ein Potential gekoppelt.

Zur Abfrage der Daten benutze ich Open3E. Ich arbeite mit meinem eigenen Fork auf dem develop-Branch, um meine Änderungen dem offiziellen Repo als Pull-Requests zur Verfügung stellen zu können. Zur Zeit hinkt mein Repo dem offiziellen allerdings ein wenig hinterher.

Mein Abfrageskript ist ziemlich simpel. Ich erfrage alle zehn Sekunden eine kleine Untermenge aller verfügbaren Daten, und stündlich den kompletten verfügbaren Datensatz, und leite diese an meinen MQTT-Broker weiter.

#!/home/vito/vitocal-dev/.venv/bin/python
import time
import json
import paho.mqtt.client as mqtt
import open3e.Open3Eclass
import datetime
 
mc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
mc.connect("192.168.9.1")
mc.loop_start()
 
can = 'can0'
ecutx = 0x680
devfile = 'Open3Edatapoints_680.py'
topic = 'vito/vcal'
fastdids = [268,269,271,274,282,286,318,320,321,322,324,325,354,355,381,388,389,390,391,402,476, \
        543,548,565,988, \
        1043,1190,1211,1240,1391,1396,1416,1644,1769,1770,1771,1772,1773,1774,1775,1776,1799,1842, \
        2256,2259,2333,2334,2346,2351,2369,2370,2457,2486,2487,2488,2494,2495,2496, \
        2517,2526,2569,2580,2629,2735,2791,2793,2852,2934, \
        3016,3190]
dictignores = {
        'Minimum','Maximum','Average','DampedMin','DampedMax','DampedAverage',
        'Unknown','Unknown1','Unknown2','Unknown3',
        (402,0),(402,1),(402,4),
        (548,1),(548,2),(548,3),(548,4),(548,5),
        (565,1),(565,2),(565,3),(565,4),(565,5),
        (1211,1),(1211,2),(1211,3),(1211,4),(1211,5),
        (1391,1),(1391,2),(1391,3),(1391,4),(1391,5),
        (1396,1),
        (2517,1),(2517,2),(2517,3),(2517,4),(2517,5),
        (2526,1),(2526,2),(2526,3),(2526,4),(2526,5),
}
 
 
def retrieve(ecu,dids,enterdict):
    dval = {}
    t0 = time.time()
    response = ecu.uds_client.read_data_by_identifier(dids)
    td = time.time()-t0
    #print (td)
    for did in dids:
        value = response.service_data.values[did]
        idstr = ecu.dataIdentifiers[did].id
        if enterdict and isinstance(value,dict):
            idx = -1
            for key in value:
                idx += 1
                if key in dictignores or (did,idx) in dictignores: continue
                dnam = '%04d.%d'%(did,idx)
                dtxt = '%s%s'%(idstr,key if key!='Actual' else '')
                dkey = '%s %s'%(dnam,dtxt)
                val = value[key]
                if did==1416: val = val['ID']
                dval[dkey] = val
        else:
            dnam = '%04d'%did
            dtxt = idstr
            dkey = '%s %s'%(dnam,dtxt)
            dval[dkey] = value
    return dval
 
def publish(topic,dval):
    #print(dval)
    jo = json.dumps(dval)
    #print(topic+': '+jo)
    mc.publish(topic,jo)
 
ecu = open3e.Open3Eclass.O3Eclass(ecutx=ecutx, can=can, dev=devfile)
open3e.Open3Ecodecs.flag_rawmode = False
fulldids = sorted(ecu.dataIdentifiers.keys())
 
hourlastfull = fullidx = None
cycle = 0
last = time.time()
while True:
    cycle += 1
    dval = retrieve(ecu,fastdids[:len(fastdids)//2],True)
    dval.update(retrieve(ecu,fastdids[len(fastdids)//2:],True))
    publish(topic,dval)
    hournow = datetime.datetime.today().hour
    if hournow!=hourlastfull and fullidx is None:
        fulldval = {}
        fullidx = 0
    while True:
        now = time.time()
        if now-last>=10:
            last = now
            break
        if fullidx is not None:
            if fullidx>=len(fulldids):
                publish(topic+'-full',fulldval)
                hourlastfull = hournow
                fullidx = None
            else:
                dval = retrieve(ecu,fulldids[fullidx:fullidx+1],False)
                fulldval.update(dval)
                fullidx += 1
        else:
            time.sleep(1.0)
wp/vitocal_250a_datenerfassung.txt · Zuletzt geändert: von sebastian