[
  {"id":"mhb-universal-tab","type":"tab","label":"MHB Cerbo automatisch","disabled":false,"info":"Universele MHB-flow. Meldt zichzelf aan met het lokale VRM Portal-ID. Opdrachten worden pas na koppeling in MHB Beheer vrijgegeven."},
  {"id":"mhb-universal-note","type":"comment","z":"mhb-universal-tab","name":"Universeel · automatische VRM-herkenning · eerst koppelen in MHB Beheer","info":"Geen klantgegevens of sleutel invullen. De unieke apparaatidentiteit wordt lokaal onder /data/home/nodered/.node-red bewaard.","x":470,"y":40,"wires":[]},
  {"id":"mhb-universal-poll","type":"inject","z":"mhb-universal-tab","name":"Iedere 2 seconden","props":[{"p":"payload"}],"repeat":"2","once":true,"onceDelay":1,"payload":"","payloadType":"date","x":150,"y":100,"wires":[["mhb-universal-config"]]},
  {"id":"mhb-universal-config","type":"function","z":"mhb-universal-tab","name":"Beveiligde opdrachtverbinding","func":"const PORTAL_ID=flow.get('mhb_portal_id'),TOKEN=flow.get('mhb_token');\nif(!PORTAL_ID||!TOKEN){node.status({fill:'yellow',shape:'ring',text:'wacht op koppeling'});return null;}\nmsg.method='GET';\nmsg.url='https://mhbbeheer.site/api/cerbo-node-red/'+PORTAL_ID+'/commands/next';\nmsg.headers={'X-MHB-Cerbo-Token':TOKEN};\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":425,"y":100,"wires":[["mhb-universal-http-get"]]},
  {"id":"mhb-universal-http-get","type":"http request","z":"mhb-universal-tab","name":"Opdracht ophalen","method":"use","ret":"obj","paytoqs":"ignore","url":"","persist":false,"insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":680,"y":100,"wires":[["mhb-universal-dispatch"]]},
  {"id":"mhb-universal-dispatch","type":"function","z":"mhb-universal-tab","name":"Veilige Cerbo-opdracht","func":"const job=(msg.payload||{}).job;if(!job)return [null,null,null,null];\nconst p=job.payload||{};\nif(job.type==='dvcc'){const c=p.current_enabled?Number(p.charge_current):-1,v=p.voltage_enabled?Number(p.charge_voltage):0;if((c!==-1&&(c<1||c>200))||(v!==0&&(v<40||v>64))){node.error('DVCC buiten veilige grens',msg);return [null,null,null,null];}flow.set('mhb_pending',{id:job.id,type:'dvcc',current:c,voltage:v});return [{payload:c},{payload:v},null,{payload:job.id}];}\nif(job.type==='power'||job.type==='reset'){const portal=flow.get('mhb_detected_portal'),instance=flow.get('mhb_vebus_instance');if(!portal||instance===undefined||instance===null){node.error('VE.Bus-apparaat nog niet automatisch herkend',msg);return [null,null,null,null];}const command=p.command||p.requested_state;let path,value,expected;if(command==='power_on'){path='Mode';value=3;expected=3;}else if(command==='power_off'){path='Mode';value=4;expected=4;}else if(command==='alarm_reset'){path='SystemReset';value=1;}else{node.error('Opdracht niet toegestaan',msg);return [null,null,null,null];}flow.set('mhb_pending',{id:job.id,type:job.type,command:command,expected_mode:expected});return [null,null,{topic:'W/'+portal+'/vebus/'+instance+'/'+path,payload:JSON.stringify({value:value}),qos:0,retain:false},{payload:job.id}];}\nnode.error('Opdrachttype niet toegestaan',msg);return [null,null,null,null];","outputs":4,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":935,"y":100,"wires":[["mhb-universal-out-current"],["mhb-universal-out-voltage"],["mhb-mqtt-command"],["mhb-universal-delay"]]},
  {"id":"mhb-universal-out-current","type":"victron-output-ess","z":"mhb-universal-tab","service":"com.victronenergy.settings","path":"/Settings/SystemSetup/MaxChargeCurrent","serviceObj":{"service":"com.victronenergy.settings","name":"Settings"},"pathObj":{"path":"/Settings/SystemSetup/MaxChargeCurrent","type":"float","name":"DVCC Charge current limit (A)","mode":"both"},"initial":"","name":"Schrijf DVCC-laadstroom","x":1240,"y":75,"wires":[]},
  {"id":"mhb-universal-out-voltage","type":"victron-output-ess","z":"mhb-universal-tab","service":"com.victronenergy.settings","path":"/Settings/SystemSetup/MaxChargeVoltage","serviceObj":{"service":"com.victronenergy.settings","name":"Settings"},"pathObj":{"path":"/Settings/SystemSetup/MaxChargeVoltage","type":"float","name":"DVCC Maximum charge voltage (V)","mode":"both"},"initial":"","name":"Schrijf DVCC-laadspanning","x":1245,"y":125,"wires":[]},
  {"id":"mhb-universal-read-current","type":"victron-input-ess","z":"mhb-universal-tab","service":"com.victronenergy.settings","path":"/Settings/SystemSetup/MaxChargeCurrent","serviceObj":{"service":"com.victronenergy.settings","name":"Settings"},"pathObj":{"path":"/Settings/SystemSetup/MaxChargeCurrent","type":"float","name":"DVCC Charge current limit (A)","mode":"both"},"name":"Werkelijke laadstroom","onlyChanges":true,"roundValues":"2","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":180,"y":230,"wires":[["mhb-universal-store-current"]]},
  {"id":"mhb-universal-store-current","type":"function","z":"mhb-universal-tab","name":"Onthoud stroom","func":"flow.set('mhb_actual_current',Number(msg.payload));return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":230,"wires":[["mhb-universal-debug"]]},
  {"id":"mhb-universal-read-voltage","type":"victron-input-ess","z":"mhb-universal-tab","service":"com.victronenergy.settings","path":"/Settings/SystemSetup/MaxChargeVoltage","serviceObj":{"service":"com.victronenergy.settings","name":"Settings"},"pathObj":{"path":"/Settings/SystemSetup/MaxChargeVoltage","type":"float","name":"DVCC Maximum charge voltage (V)","mode":"both"},"name":"Werkelijke laadspanning","onlyChanges":true,"roundValues":"2","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":185,"y":280,"wires":[["mhb-universal-store-voltage"]]},
  {"id":"mhb-universal-store-voltage","type":"function","z":"mhb-universal-tab","name":"Onthoud spanning","func":"flow.set('mhb_actual_voltage',Number(msg.payload));return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":445,"y":280,"wires":[["mhb-universal-debug"]]},
  {"id":"mhb-universal-debug","type":"debug","z":"mhb-universal-tab","name":"Werkelijke lokale waarde","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":700,"y":255,"wires":[]},
  {"id":"mhb-universal-delay","type":"delay","z":"mhb-universal-tab","name":"Wacht op lokale bevestiging","pauseType":"delay","timeout":"4","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":980,"y":180,"wires":[["mhb-universal-complete"]]},
  {"id":"mhb-universal-complete","type":"function","z":"mhb-universal-tab","name":"Bevestig werkelijke waarden","func":"const p=flow.get('mhb_pending'),portal=flow.get('mhb_portal_id'),token=flow.get('mhb_token');if(!p||!portal||!token)return null;let ok=false,result={},error=null;if(p.type==='dvcc'){const c=flow.get('mhb_actual_current'),v=flow.get('mhb_actual_voltage');ok=Number.isFinite(c)&&Number.isFinite(v)&&Math.abs(c-p.current)<0.05&&Math.abs(v-p.voltage)<0.05;result={charge_current:c,charge_voltage:v,confirmed_locally:ok};error=ok?null:'lokale_waarde_niet_bevestigd';}else if(p.type==='power'){const mode=Number(flow.get('mhb_actual_mode'));ok=mode===p.expected_mode;result={mode:mode,expected_mode:p.expected_mode,confirmed_locally:ok};error=ok?null:'vebus_mode_niet_bevestigd';}else if(p.type==='reset'){ok=true;result={reset_sent:true,vebus_instance:flow.get('mhb_vebus_instance')};}msg.method='POST';msg.url='https://mhbbeheer.site/api/cerbo-node-red/'+portal+'/commands/'+p.id+'/complete';msg.headers={'X-MHB-Cerbo-Token':token,'Content-Type':'application/json'};msg.payload={ok:ok,result:result,error:error};return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1245,"y":180,"wires":[["mhb-universal-http-complete"]]},
  {"id":"mhb-universal-http-complete","type":"http request","z":"mhb-universal-tab","name":"Resultaat naar MHB","method":"use","ret":"obj","paytoqs":"ignore","url":"","persist":false,"insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1480,"y":180,"wires":[["mhb-universal-result"]]},
  {"id":"mhb-universal-result","type":"debug","z":"mhb-universal-tab","name":"MHB-resultaat","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1705,"y":180,"wires":[]},
  {"id":"mhb-live-soc","type":"victron-input-system","z":"mhb-universal-tab","service":"com.victronenergy.system/0","path":"/Dc/Battery/Soc","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system","communityTag":"system"},"pathObj":{"path":"/Dc/Battery/Soc","type":"float","name":"Battery State of Charge (%)"},"name":"battery_soc","onlyChanges":true,"roundValues":"1","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":135,"y":360,"wires":[["mhb-live-store"]]},
  {"id":"mhb-live-bv","type":"victron-input-system","z":"mhb-universal-tab","service":"com.victronenergy.system/0","path":"/Dc/Battery/Voltage","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system","communityTag":"system"},"pathObj":{"path":"/Dc/Battery/Voltage","type":"float","name":"Battery voltage (V)"},"name":"battery_voltage","onlyChanges":true,"roundValues":"2","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":145,"y":400,"wires":[["mhb-live-store"]]},
  {"id":"mhb-live-bi","type":"victron-input-system","z":"mhb-universal-tab","service":"com.victronenergy.system/0","path":"/Dc/Battery/Current","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system","communityTag":"system"},"pathObj":{"path":"/Dc/Battery/Current","type":"float","name":"Battery current (A)"},"name":"battery_current","onlyChanges":true,"roundValues":"1","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":145,"y":440,"wires":[["mhb-live-store"]]},
  {"id":"mhb-live-bp","type":"victron-input-system","z":"mhb-universal-tab","service":"com.victronenergy.system/0","path":"/Dc/Battery/Power","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system","communityTag":"system"},"pathObj":{"path":"/Dc/Battery/Power","type":"float","name":"Battery Power (W)"},"name":"battery_power","onlyChanges":true,"roundValues":"0","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":140,"y":480,"wires":[["mhb-live-store"]]},
  {"id":"mhb-live-bt","type":"victron-input-system","z":"mhb-universal-tab","service":"com.victronenergy.system/0","path":"/Dc/Battery/Temperature","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system","communityTag":"system"},"pathObj":{"path":"/Dc/Battery/Temperature","type":"float","name":"Battery temperature (°C)"},"name":"battery_temperature","onlyChanges":true,"roundValues":"1","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":155,"y":520,"wires":[["mhb-live-store"]]},
  {"id":"mhb-live-pv","type":"victron-input-system","z":"mhb-universal-tab","service":"com.victronenergy.system/0","path":"/Dc/Pv/Power","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system","communityTag":"system"},"pathObj":{"path":"/Dc/Pv/Power","type":"float","name":"MPPTs - power (W)"},"name":"pv_power","onlyChanges":true,"roundValues":"0","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":125,"y":560,"wires":[["mhb-live-store"]]},
  {"id":"mhb-live-grid","type":"victron-input-system","z":"mhb-universal-tab","service":"com.victronenergy.system/0","path":"/Ac/Grid/L1/Power","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system","communityTag":"system"},"pathObj":{"path":"/Ac/Grid/L1/Power","type":"float","name":"Grid L1 (W)"},"name":"grid_power","onlyChanges":true,"roundValues":"0","rateLimit":0,"conditionalMode":false,"outputOnChange":false,"debounce":0,"x":130,"y":600,"wires":[["mhb-live-store"]]},
  {"id":"mhb-live-store","type":"function","z":"mhb-universal-tab","name":"Live Cerbo-data onthouden","func":"const names=['battery_soc','battery_voltage','battery_current','battery_power','battery_temperature','pv_power','grid_power'];\nconst source=String(msg.topic||'');\nif(names.includes(source)) flow.set('mhb_live_'+source,msg.payload);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":540,"wires":[]},
  {"id":"mhb-universal-heartbeat","type":"inject","z":"mhb-universal-tab","name":"Status iedere 3 seconden","props":[{"p":"payload"}],"repeat":"3","once":true,"onceDelay":3,"payload":"","payloadType":"date","x":185,"y":800,"wires":[["mhb-universal-heartbeat-build"]]},
  {"id":"mhb-universal-heartbeat-build","type":"function","z":"mhb-universal-tab","name":"Status maken","func":"const portal=flow.get('mhb_portal_id'),token=flow.get('mhb_token');if(!portal||!token)return null;msg.method='POST';msg.url='https://mhbbeheer.site/api/cerbo-node-red/'+portal+'/heartbeat';msg.headers={'X-MHB-Cerbo-Token':token,'Content-Type':'application/json'};msg.payload={charge_current:flow.get('mhb_actual_current'),charge_voltage:flow.get('mhb_actual_voltage'),battery_soc:flow.get('mhb_live_battery_soc'),battery_voltage:flow.get('mhb_live_battery_voltage'),battery_current:flow.get('mhb_live_battery_current'),battery_power:flow.get('mhb_live_battery_power'),battery_temperature:flow.get('mhb_live_battery_temperature'),pv_power:flow.get('mhb_live_pv_power'),grid_power:flow.get('mhb_live_grid_power'),system_state:flow.get('mhb_live_system_state'),charge_disabled:flow.get('mhb_live_charge_disabled'),discharge_disabled:flow.get('mhb_live_discharge_disabled')};return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":435,"y":800,"wires":[["mhb-universal-heartbeat-http"]]},
  {"id":"mhb-universal-heartbeat-http","type":"http request","z":"mhb-universal-tab","name":"Cerbo-status naar MHB","method":"use","ret":"obj","paytoqs":"ignore","url":"","persist":false,"insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":690,"y":370,"wires":[]},
  {"id":"mhb-portal-input","type":"victron-input-system","z":"mhb-universal-tab","service":"com.victronenergy.system/0","path":"/Serial","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system","communityTag":"system"},"pathObj":{"path":"/Serial","type":"string","name":"Serial (System)"},"name":"VRM Portal-ID automatisch","onlyChanges":true,"roundValues":"no","rateLimit":0,"x":180,"y":900,"wires":[["mhb-portal-store"]]},
  {"id":"mhb-portal-store","type":"function","z":"mhb-universal-tab","name":"VRM-ID onthouden","func":"const portal=String(msg.payload||'').trim();if(portal){flow.set('mhb_detected_portal',portal);msg.payload=Date.now();return msg;}return null;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":445,"y":900,"wires":[["mhb-enroll-build"]]},
  {"id":"mhb-identity-start","type":"inject","z":"mhb-universal-tab","name":"Identiteit laden bij start","props":[{"p":"payload"}],"once":true,"onceDelay":1,"payload":"","payloadType":"date","x":190,"y":950,"wires":[["mhb-identity-file"]]},
  {"id":"mhb-identity-file","type":"file in","z":"mhb-universal-tab","name":"Lokale MHB-identiteit","filename":"/data/home/nodered/.node-red/mhb-device.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":450,"y":950,"wires":[["mhb-identity-parse"]]},
  {"id":"mhb-identity-parse","type":"function","z":"mhb-universal-tab","name":"Identiteit controleren","func":"try{const v=typeof msg.payload==='string'?JSON.parse(msg.payload):msg.payload;if(v&&String(v.device_id||'').length>=16&&String(v.device_secret||'').length>=32){flow.set('mhb_device_id',v.device_id);flow.set('mhb_device_secret',v.device_secret);msg.payload=Date.now();return msg;}}catch(e){}node.error('MHB-identiteit ontbreekt of is ongeldig',msg);return null;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":950,"wires":[["mhb-enroll-build"]]},
  {"id":"mhb-identity-catch","type":"catch","z":"mhb-universal-tab","name":"Nieuwe identiteit nodig","scope":["mhb-identity-file","mhb-identity-parse"],"uncaught":false,"x":190,"y":1000,"wires":[["mhb-identity-generate"]]},
  {"id":"mhb-identity-generate","type":"function","z":"mhb-universal-tab","name":"Unieke identiteit maken","func":"const chars='ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789';const random=n=>Array.from({length:n},()=>chars[Math.floor(Math.random()*chars.length)]).join('');const value={device_id:'cerbo_'+random(24),device_secret:random(64)};flow.set('mhb_device_id',value.device_id);flow.set('mhb_device_secret',value.device_secret);return [{payload:Date.now()},{payload:JSON.stringify(value),filename:'/data/home/nodered/.node-red/mhb-device.json'}];","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":1000,"wires":[["mhb-enroll-build"],["mhb-identity-save"]]},
  {"id":"mhb-identity-save","type":"file","z":"mhb-universal-tab","name":"Identiteit veilig bewaren","filename":"/data/home/nodered/.node-red/mhb-device.json","filenameType":"str","appendNewline":false,"createDir":true,"overwriteFile":"true","encoding":"none","x":750,"y":1020,"wires":[[]]},
  {"id":"mhb-enroll-timer","type":"inject","z":"mhb-universal-tab","name":"Aanmelden iedere 15 seconden","props":[{"p":"payload"}],"repeat":"15","once":true,"onceDelay":4,"payload":"","payloadType":"date","x":205,"y":1070,"wires":[["mhb-enroll-build"]]},
  {"id":"mhb-enroll-build","type":"function","z":"mhb-universal-tab","name":"Aanmelding maken","func":"const portal=flow.get('mhb_detected_portal'),deviceId=flow.get('mhb_device_id'),secret=flow.get('mhb_device_secret');if(!portal||!deviceId||!secret){node.status({fill:'yellow',shape:'ring',text:'identiteit/VRM-ID laden'});return null;}msg.method='POST';msg.url='https://mhbbeheer.site/api/cerbo-node-red/enroll/register';msg.headers={'Content-Type':'application/json'};msg.payload={portal_id:portal,device_id:deviceId,device_secret:secret,device_name:'Cerbo GX',node_red_version:'1.6.56',metadata:{flow_version:'4'}};return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":465,"y":1070,"wires":[["mhb-enroll-http"]]},
  {"id":"mhb-enroll-http","type":"http request","z":"mhb-universal-tab","name":"Melden bij MHB Beheer","method":"use","ret":"obj","paytoqs":"ignore","url":"","persist":false,"insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":720,"y":1070,"wires":[["mhb-enroll-result"]]},
  {"id":"mhb-enroll-result","type":"function","z":"mhb-universal-tab","name":"Koppeling activeren","func":"const r=msg.payload||{};if(!r.ok){node.status({fill:'red',shape:'ring',text:'aanmelding mislukt'});return null;}if(r.linked){flow.set('mhb_portal_id',r.portal_id);flow.set('mhb_token',flow.get('mhb_device_secret'));node.status({fill:'green',shape:'dot',text:'gekoppeld · '+r.portal_id});}else{flow.set('mhb_portal_id',null);flow.set('mhb_token',null);node.status({fill:'yellow',shape:'ring',text:r.suggestion?'gevonden · koppelen in MHB':'wacht op VRM-import'});}return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":1070,"wires":[]},
  {"id":"mhb-mqtt-vebus-discovery","type":"mqtt in","z":"mhb-universal-tab","name":"VE.Bus automatisch herkennen","topic":"N/+/vebus/+/DeviceInstance","qos":"0","datatype":"auto-detect","broker":"mhb-local-mqtt","nl":false,"rap":true,"rh":0,"inputs":0,"x":195,"y":1140,"wires":[["mhb-mqtt-vebus-store"]]},
  {"id":"mhb-mqtt-vebus-store","type":"function","z":"mhb-universal-tab","name":"VE.Bus nummer onthouden","func":"const parts=String(msg.topic||'').split('/');if(parts.length>=5){const portal=parts[1],instance=parts[3];if(portal===String(flow.get('mhb_detected_portal')||'')){flow.set('mhb_vebus_instance',instance);node.status({fill:'green',shape:'dot',text:'VE.Bus '+instance});}}return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":485,"y":1140,"wires":[]},
  {"id":"mhb-mqtt-mode-input","type":"mqtt in","z":"mhb-universal-tab","name":"Werkelijke VE.Bus-modus","topic":"N/+/vebus/+/Mode","qos":"0","datatype":"auto-detect","broker":"mhb-local-mqtt","nl":false,"rap":true,"rh":0,"inputs":0,"x":190,"y":1190,"wires":[["mhb-mqtt-mode-store"]]},
  {"id":"mhb-mqtt-mode-store","type":"function","z":"mhb-universal-tab","name":"Modus bevestigen","func":"try{const value=typeof msg.payload==='string'?JSON.parse(msg.payload).value:msg.payload.value;flow.set('mhb_actual_mode',Number(value));node.status({fill:'green',shape:'dot',text:'modus '+value});}catch(e){}return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":1190,"wires":[]},
  {"id":"mhb-mqtt-keepalive-timer","type":"inject","z":"mhb-universal-tab","name":"VE.Bus verversen","props":[{"p":"payload"}],"repeat":"30","once":true,"onceDelay":6,"payload":"","payloadType":"str","x":180,"y":1240,"wires":[["mhb-mqtt-keepalive-build"]]},
  {"id":"mhb-mqtt-keepalive-build","type":"function","z":"mhb-universal-tab","name":"Lokale gegevens opvragen","func":"const portal=flow.get('mhb_detected_portal');if(!portal)return null;msg.topic='R/'+portal+'/keepalive';msg.payload='';return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":1240,"wires":[["mhb-mqtt-command"]]},
  {"id":"mhb-mqtt-command","type":"mqtt out","z":"mhb-universal-tab","name":"Veilige lokale VE.Bus-opdracht","topic":"","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"mhb-local-mqtt","x":780,"y":1215,"wires":[]},
  {"id":"mhb-local-mqtt","type":"mqtt-broker","name":"Lokale Cerbo MQTT","broker":"127.0.0.1","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{}},
  {"id":"victron-client-id","type":"victron-client","name":"Victron Energy Client","showValues":true,"contextStore":true,"enablePolling":false}
]
