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)
