UNPKG

homebridge-smartsystem

Version:

SmartServer (Proxy Websockets to TCP sockets, Smappee MQTT, Duotecno IP Nodes, Homekit interface)

227 lines (189 loc) 6.98 kB
// P1 implementation // Johan Coppieters, Jul 2022. // import { System } from "../duotecno/system"; import { P1Config } from "../duotecno/types"; import { err, log } from "../duotecno/logger"; import { PowerBase } from "./powerbase"; import { debug } from "../duotecno/logger"; import { get } from "../duotecno/api"; /* http://192.168.0.214/api/v1/data { "smr_version":50, "meter_model":"Fluvius 253769484_A", "wifi_ssid":"Tele Coppieters", "wifi_strength":32, "total_power_import_t1_kwh":10247.015, "total_power_import_t2_kwh":18548.61, "total_power_export_t1_kwh":5890.344, "total_power_export_t2_kwh":2191.808, "active_power_w":461, "active_power_l1_w":400, "active_power_l2_w":0, "active_power_l3_w":60, "total_gas_m3":null, "gas_timestamp":null} } * https://jensd.be/1205/linux/data-lezen-van-de-belgische-digitale-meter-met-de-p1-poort * http://192.168.0.214/api/v1/telegram /FLU5\253769484_A 0-0:96.1.4(50216) 0-0:96.1.1(3153414733313030303539333731) 0-0:1.0.0(220720162529S) 1-0:1.8.1(010246.991*kWh) 1-0:1.8.2(018548.610*kWh) 1-0:2.8.1(005890.344*kWh) 1-0:2.8.2(002191.808*kWh) 0-0:96.14.0(0001) 1-0:1.7.0(00.489*kW) 1-0:2.7.0(00.000*kW) 1-0:21.7.0(00.405*kW) 1-0:41.7.0(00.000*kW) 1-0:61.7.0(00.084*kW) 1-0:22.7.0(00.000*kW) 1-0:42.7.0(00.000*kW) 1-0:62.7.0(00.000*kW) 1-0:32.7.0(233.8*V) 1-0:52.7.0(000.0*V) 1-0:72.7.0(234.4*V) 1-0:31.7.0(002.11*A) 1-0:51.7.0(001.10*A) 1-0:71.7.0(001.92*A) 0-0:96.3.10(1) 0-0:17.0.0(999.9*kW) 1-0:31.4.0(999*A) 0-0:96.13.0() !56E6 fetchData => { 1.7.0:{value: 0.469, unit: 'kW'} 1.8.1:{value: 10247.463, unit: 'kWh'} 1.8.2:{value: 18548.61, unit: 'kWh'} 2.7.0:{value: 0, unit: 'kW'} 2.8.1:{value: 5890.344, unit: 'kWh'} 2.8.2:{value: 2191.808, unit: 'kWh'} 21.7.0:{value: 0.432, unit: 'kW'} 22.7.0:{value: 0, unit: 'kW'} 31.4.0:{value: 999, unit: 'A'} 31.7.0:{value: 2.14, unit: 'A'} 32.7.0:{value: 233.7, unit: 'V'} 41.7.0:{value: 0, unit: 'kW'} 42.7.0:{value: 0, unit: 'kW'} 51.7.0:{value: 1.03, unit: 'A'} 52.7.0:{value: 0, unit: 'V'} 61.7.0:{value: 0.036, unit: 'kW'} 62.7.0:{value: 0, unit: 'kW'} 71.7.0:{value: 1.93, unit: 'A'} 72.7.0:{value: 233.5, unit: 'V'} } */ interface P1Data { [key: string]: {value: number; unit: string} } export class P1 extends PowerBase { config: P1Config; // redefine timer: NodeJS.Timer; constructor(system: System) { super("p1", system); // readconfig and init are called by super } // // return data for ejs pages // // async getData(context: Context, message: String): Promise<any> { // // nothing special... for now // return super.getData(context, message); // } // // config mgt // // async updateConfig(config: any) { // // nothing special... for now // return super.updateConfig(config); // } async subscribe() { const kInterval = 5; log("p1", "connecting to P1: " + this.config.address); if (this.config.address) { this.timer = setInterval(async () => { this.realtimeCounter += kInterval; // fetch data const message = await this.fetchData(); if (message) this.consume(message); // call process/bindings/rules this.applyBindings(); this.applyRules(); }, kInterval * 1000); } } async unsubscribe() { if (this.timer) { clearInterval(this.timer); this.timer = null; } } async fetchData(): Promise<P1Data> { try { debug("p1", "fetching from " + this.config.address + "/api/v1/telegram"); const res = await get(this.config.address, 80, "/api/v1/telegram", undefined); debug("p1", "received: " + res); const result: P1Data = {}; res.split("\r\n").filter(l => (l[0] === '1')).map(L => { // 0-0:1.0.0(220720172521S) // 1-0:62.7.0(00.135*kW) const S = L.split(":")[1]; // remove preamble 1-0 if (!S) return undefined; // no key-value -> remove const V = S.split("("); // split "key(value" const key = V[0]; if (V.length < 2) return undefined; // no value -> remove const value = V[1].substring(0, V[1].length - 1); // remove last ")" const VU = value.split("*"); // split "value*unit" return { key, value: VU[0], unit: VU[1]}; }).forEach(R => result[R.key] = {value: parseFloat(R.value), unit: R.unit} ); return result; } catch(error) { err("p1", "error fetching data: " + JSON.stringify(error)); return null; } } consume(data: P1Data) { if (! data['32.7.0']) return; this.channels = { 0: { name: "Zonnepanelen L1", type: "CT", flow: "PRODUCTION", voltage: data['32.7.0']?.value, power: data['22.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 0, current: 0, apparentPower: 0, cosPhi: 0, formula: ""}, 1: { name: "Zonnepanelen L2", type: "CT", flow: "PRODUCTION", voltage: data['52.7.0']?.value, power: data['42.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 1, current: 0, apparentPower: 0, cosPhi: 0, formula: ""}, 2: { name: "Zonnepanelen L3", type: "CT", flow: "PRODUCTION", voltage: data['72.7.0']?.value, power: data['62.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 2, current: 0, apparentPower: 0, cosPhi: 0, formula: ""}, 3: { name: "Grid L1", type: "CT", flow: "CONSUMPTION", voltage: data['32.7.0']?.value, power: data['21.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 0, current: data['31.7.0']?.value, apparentPower: 0, cosPhi: 0, formula: ""}, 4: { name: "Grid L2", type: "CT", flow: "CONSUMPTION", voltage: data['52.7.0']?.value, power: data['41.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 1, current: data['51.7.0']?.value, apparentPower: 0, cosPhi: 0, formula: ""}, 5: { name: "Grid L3", type: "CT", flow: "CONSUMPTION", voltage: data['72.7.0']?.value, power: data['61.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 2, current: data['71.7.0']?.value, apparentPower: 0, cosPhi: 0, formula: ""} }; // console.log(data); this.voltages = [data['32.7.0']?.value, data['52.7.0']?.value, data['72.7.0']?.value]; this.realtime = { totalPower: data['1.7.0']?.value * 1000, totalReactivePower: data['2.7.0']?.value * 1000, totalExportEnergy: data['2.8.1']?.value + data['2.8.2']?.value, totalImportEnergy: data['1.8.1']?.value + data['1.8.2']?.value, monitorStatus: 0, utcTimeStamp: new Date().getTime() }; this.production = this.realtime.totalPower; this.consumption = this.realtime.totalReactivePower; } }