From c2524eb4fd2ec7eb0a03b43446a0a322874993a9 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 4 Jan 2024 16:15:26 +0100 Subject: [PATCH] Changed stateOfCapacity to stateOfCharge, added docs page --- README.md | 11 ++++------- build/lib/states.js | 2 +- build/lib/states.js.map | 4 ++-- docs/README.md | 6 ++++++ docs/configuration.md | 11 +++++++++++ docs/images/admin-config.png | Bin 0 -> 28268 bytes docs/migration.md | 33 +++++++++++++++++++++++++++++++++ src/lib/states.ts | 2 +- 8 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/configuration.md create mode 100644 docs/images/admin-config.png create mode 100644 docs/migration.md diff --git a/README.md b/README.md index c0a13e7..2847ff7 100644 --- a/README.md +++ b/README.md @@ -21,17 +21,14 @@ Read data from Huawei SUN2000 inverter and LUNA2000 Storage using Modbus TCP. Huawei products page: [solar.huawei.com](https://solar.huawei.com/at/professionals/all-products) -## Settings - -* `address`: Inverters IP address -* `port`: Inverter modbus port (default: 502) -* `modbusUnitId`: Modbus unit id (default: 1) -* `updateIntervalHigh`: Fast update interval (default: 5 sec) -* `updateIntervalLow`: Slower update interval (default: 20 sec) +## Documentation +see the [documentation page](./docs/README.md) ## Changelog ### **WORK IN PROGRESS** +* [#26](https://github.com/daolis/ioBroker.sun2000-modbus/issues/26) Renamed stateOfCapacity to stateOfCharge\ + Migration of historical data: see [Migration of historical data (on state name change)](docs/migration.md) ### 0.0.2 (2024-01-08) diff --git a/build/lib/states.js b/build/lib/states.js index a307a7a..fa3e8c8 100644 --- a/build/lib/states.js +++ b/build/lib/states.js @@ -122,7 +122,7 @@ class InverterStates { }, { interval: 0 /* HIGH */, - state: { id: "storage.stateOfCapacity", name: "State of capacity", type: "number", unit: "%", role: "value.battery", desc: "SOC" }, + state: { id: "storage.stateOfCharge", name: "State of charge", type: "number", unit: "%", role: "value.battery", desc: "SOC" }, register: { reg: 37760, type: import_modbus_types.ModbusDatatype.uint16, length: 1, gain: 10 } }, { diff --git a/build/lib/states.js.map b/build/lib/states.js.map index d12661a..52c4d52 100644 --- a/build/lib/states.js.map +++ b/build/lib/states.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../src/lib/states.ts"], - "sourcesContent": ["import {ModbusDatatype} from './modbus/modbus_types';\nimport {InverterStatus, MeterStatus, StorageStatus} from './state_enums';\nimport {AdapterInstance} from '@iobroker/adapter-core';\nimport {ModbusDevice} from './modbus/modbus_device';\n\ntype MapperFn = (value: any) => Promise\ntype PostUpdateHookFn = (adapter: AdapterInstance, value: any) => Promise>\ntype PostFetchUpdateHookFn = (adapter: AdapterInstance, toUpdate: Map) => Map\n\ninterface DataField {\n interval?: UpdateIntervalID;\n state: State;\n register: ModbusRegister;\n mapper?: MapperFn;\n postUpdateHook?: PostUpdateHookFn;\n}\n\ninterface StateToUpdate {\n id: string;\n value: any;\n postUpdateHook?: PostUpdateHookFn;\n}\n\ninterface State {\n id: string;\n name: string;\n type: ioBroker.CommonType;\n role: string;\n unit?: string;\n desc?: string;\n}\n\ninterface ModbusRegister {\n reg: number;\n type: ModbusDatatype;\n length: number;\n gain?: number;\n}\n\nexport enum UpdateIntervalID {\n HIGH,\n LOW\n}\n\ninterface UpdateIntervals {\n intervals: number[];\n}\n\ninterface PostFetchUpdateHook {\n interval: UpdateIntervalID;\n hookFn: PostFetchUpdateHookFn;\n}\n\nexport class InverterStates {\n\n private updateIntervals: UpdateIntervals\n private readonly dataFields: DataField[];\n private readonly postFetchUpdateHooks: PostFetchUpdateHook[];\n // private changingFields: DataField[];\n\n constructor(updateIntervals: UpdateIntervals) {\n this.updateIntervals = updateIntervals;\n this.dataFields = [\n // initial fields (no interval set) - no repetitive update\n {\n state: {id: 'info.model', name: 'Model', type: 'string', role: 'info.name'},\n register: {reg: 30000, type: ModbusDatatype.string, length: 15}\n },\n {\n state: {id: 'info.modelID', name: 'Model ID', type: 'number', role: 'info.hardware'},\n register: {reg: 30070, type: ModbusDatatype.uint16, length: 1}\n },\n {\n state: {id: 'info.serialNumber', name: 'Serial number', type: 'string', role: 'info.serial'},\n register: {reg: 30015, type: ModbusDatatype.string, length: 10}\n },\n {\n state: {id: 'info.ratedPower', name: 'Rated power', type: 'number', unit: 'W', role: 'value.power'},\n register: {reg: 30073, type: ModbusDatatype.int32, length: 2}\n },\n {\n state: {id: 'info.numberMPPTrackers', name: 'Number of MPP trackers', type: 'number', unit: '', role: 'value'},\n register: {reg: 30072, type: ModbusDatatype.uint16, length: 1, gain: 1}\n },\n\n // ####################################################################################################################################\n // inverter\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'activePower', name: 'Active power', type: 'number', unit: 'W', role: 'value.power.active', desc: 'Power currently used'},\n register: {reg: 32080, type: ModbusDatatype.int32, length: 2}\n },\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'inputPower', name: 'Input power', type: 'number', unit: 'W', role: 'value.power.produced', desc: 'Power from PV'},\n register: {reg: 32064, type: ModbusDatatype.int32, length: 2}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'peakActivePowerCurrenDay', name: 'Peak active power of current day', type: 'number', unit: 'W', role: 'value.power'},\n register: {reg: 32078, type: ModbusDatatype.int32, length: 2}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'efficiency', name: 'Efficiency', type: 'number', unit: '%', role: 'value'},\n register: {reg: 32086, type: ModbusDatatype.uint16, length: 1, gain: 100}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'internalTemperature', name: 'Internal temperature', type: 'number', unit: '\u00B0C', role: 'value.temperature'},\n register: {reg: 32087, type: ModbusDatatype.int16, length: 1, gain: 10}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'deviceStatus', name: 'Device status', type: 'string', unit: '', role: 'info.status'},\n register: {reg: 32089, type: ModbusDatatype.uint16, length: 1},\n mapper: value => Promise.resolve(InverterStatus[value])\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'accumulatedEnergyYield', name: 'Accumulated energy yield', type: 'number', unit: 'kWh', role: 'value.energy.produced'},\n register: {reg: 32106, type: ModbusDatatype.uint32, length: 2, gain: 100},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'dailyEnergyYield', name: 'Daily energy yield', type: 'number', unit: 'kWh', role: 'value.energy'},\n register: {reg: 32114, type: ModbusDatatype.uint32, length: 2, gain: 100}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'PV1Voltage', name: 'PV1 voltage', type: 'number', unit: 'V', role: 'value.voltage'},\n register: {reg: 32016, type: ModbusDatatype.int16, length: 1, gain: 10}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'PV1Current', name: 'PV1 current', type: 'number', unit: 'A', role: 'value.current'},\n register: {reg: 32017, type: ModbusDatatype.int16, length: 1, gain: 100}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'PV2Voltage', name: 'PV2 voltage', type: 'number', unit: 'V', role: 'value.voltage'},\n register: {reg: 32018, type: ModbusDatatype.int16, length: 1, gain: 10}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'PV2Current', name: 'PV2 current', type: 'number', unit: 'A', role: 'value.current'},\n register: {reg: 32019, type: ModbusDatatype.int16, length: 1, gain: 100}\n },\n\n // ####################################################################################################################################\n // storage\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'storage.runningState', name: 'Running state', type: 'string', role: 'info.status'},\n register: {reg: 37762, type: ModbusDatatype.uint16, length: 1},\n mapper: value => Promise.resolve(StorageStatus[value])\n },\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'storage.stateOfCapacity', name: 'State of capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'SOC'},\n register: {reg: 37760, type: ModbusDatatype.uint16, length: 1, gain: 10}\n },\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'storage.chargeDischargePower', name: 'Charge/Discharge power', desc: '(>0 charging, <0 discharging)', type: 'number', unit: 'W', role: 'value.power'},\n register: {reg: 37765, type: ModbusDatatype.int32, length: 2},\n postUpdateHook: async (adapter, value): Promise> => {\n return Promise.resolve(new Map([\n ['storage.chargePower', {id: 'storage.chargePower', value: Math.max(0, value)}],\n ['storage.dischargePower', {id: 'storage.dischargePower', value: Math.abs(Math.min(0, value))}]\n ]));\n }\n },\n {\n interval: UpdateIntervalID.LOW,\n state: { id: 'storage.CurrentDayChargeCapacity', name: 'CurrentDayChargeCapacity', type: 'number', unit: 'kWh', role: 'value.energy', desc: 'TBD' },\n register: { reg: 37015, type: ModbusDatatype.uint32, length: 2, gain: 100 }\n },\n {\n interval: UpdateIntervalID.LOW,\n state: { id: 'storage.CurrentDayDischargeCapacity', name: 'CurrentDayDischargeCapacity', type: 'number', unit: 'kWh', role: 'value.energy', desc: 'TBD' },\n register: { reg: 37786, type: ModbusDatatype.uint32, length: 2, gain: 100 }\n },\n\n // ####################################################################################################################################\n // grid (meter)\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.meterStatus', name: 'Meter status', type: 'string', role: 'info.status'},\n register: {reg: 37100, type: ModbusDatatype.uint16, length: 1},\n mapper: value => Promise.resolve(MeterStatus[value])\n },\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'grid.activePower', name: 'Active power', type: 'number', role: 'value.power.active', unit: 'W', desc: '(>0 feed-in to the power grid, <0: supply from the power grid)'},\n register: {reg: 37113, type: ModbusDatatype.int32, length: 2},\n postUpdateHook: async (adapter, value): Promise> => {\n return Promise.resolve(new Map([\n ['grid.feedIn', {id: 'grid.feedIn', value: Math.max(0, value)}],\n ['grid.supplyFrom', {id: 'grid.supplyFrom', value: Math.abs(Math.min(0, value))}]\n ]));\n }\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.reactivePower', name: 'Reactive power', type: 'number', role: 'value.power.reactive', unit: 'W'},\n register: {reg: 37115, type: ModbusDatatype.int32, length: 2},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.powerFactor', name: 'Power factor', type: 'number', role: 'value', unit: ''},\n register: {reg: 37117, type: ModbusDatatype.int16, length: 1, gain: 1000},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.gridFrequency', name: 'Grid frequency', type: 'number', role: 'value.frequency', unit: 'Hz'},\n register: {reg: 37118, type: ModbusDatatype.int16, length: 1, gain: 100},\n },\n\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase1Voltage', name: 'Phase 1 voltage', type: 'number', role: 'value.voltage', unit: 'V', desc: 'also L1, or R voltage'},\n register: {reg: 37101, type: ModbusDatatype.int32, length: 2, gain: 10},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase2Voltage', name: 'Phase 2 voltage', type: 'number', role: 'value.voltage', unit: 'V', desc: 'also L2, or S voltage'},\n register: {reg: 37103, type: ModbusDatatype.int32, length: 2, gain: 10},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase3Voltage', name: 'Phase 3 voltage', type: 'number', role: 'value.voltage', unit: 'V', desc: 'also L3, or T voltage'},\n register: {reg: 37105, type: ModbusDatatype.int32, length: 2, gain: 10},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase1Current', name: 'Phase 1 current', type: 'number', role: 'value.current', unit: 'A'},\n register: {reg: 37107, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase2Current', name: 'Phase 2 current', type: 'number', role: 'value.current', unit: 'A'},\n register: {reg: 37109, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase3Current', name: 'Phase 3 current', type: 'number', role: 'value.current', unit: 'A'},\n register: {reg: 37111, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.positiveActivePower', name: 'Positive active power', type: 'number', role: 'value.power.active', unit: 'kWh', desc: 'Electricity fed by the inverter to the power grid.'},\n register: {reg: 37119, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.reverseActivePower', name: 'Reverse active power', type: 'number', role: 'value.power.active', unit: 'kWh', desc: 'Power supplied from the power grid.'},\n register: {reg: 37121, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n ];\n this.postFetchUpdateHooks = [\n {\n interval: UpdateIntervalID.HIGH,\n hookFn: (adapter: AdapterInstance, toUpdate: Map) => {\n const powerGridActive = toUpdate.get('grid.activePower');\n const powerActiveInverter = toUpdate.get('activePower');\n const totalPowerUse = powerActiveInverter?.value - powerGridActive?.value;\n adapter.log.silly(`PostFetchHook: calculate totalPowerUse ${powerGridActive?.value}, ${powerActiveInverter?.value}, ${totalPowerUse}`);\n const result = new Map();\n if (totalPowerUse) {\n result.set('totalPowerUse', {id: 'totalPowerUse', value: totalPowerUse})\n }\n return result;\n }\n }\n ];\n }\n\n public async createStates(adapter: AdapterInstance): Promise {\n for (const field of this.dataFields) {\n const state = field.state\n adapter.extendObject(state.id, {\n type: 'state',\n common: {\n name: state.name,\n type: state.type,\n role: state.role,\n unit: state.unit,\n desc: state.desc,\n read: true,\n write: false\n },\n native: {},\n });\n }\n }\n\n\n public async updateStates(adapter: AdapterInstance, device: ModbusDevice, interval?: UpdateIntervalID): Promise {\n let toUpdate = new Map;\n for (const field of this.dataFields) {\n if (field.interval != interval) {\n continue;\n }\n try {\n let value = await device.readModbusHR(field.register.reg, field.register.type, field.register.length);\n\n if (field.register.gain) {\n value /= field.register.gain;\n }\n if (field.mapper) {\n value = await field.mapper(value);\n }\n toUpdate.set(field.state.id, {id: field.state.id, value: value})\n if (field.postUpdateHook) {\n const hookUpdates = await field.postUpdateHook(adapter, value);\n for (const entry of hookUpdates.entries()) {\n toUpdate.set(entry[0], entry[1]);\n }\n }\n } catch (e) {\n adapter.log.warn(`Error while reading from ${device.getIpAddress()}: [${field.register.reg}|${field.register.length}] '' with : ${e}`);\n break;\n }\n }\n\n toUpdate = this.runPostFetchHooks(adapter, toUpdate, interval);\n\n return this.updateAdapterStates(adapter, toUpdate);\n }\n\n public runPostFetchHooks(adapter: AdapterInstance, toUpdate: Map, interval: UpdateIntervalID | undefined): Map {\n for (const postFetchHook of this.postFetchUpdateHooks) {\n if (postFetchHook.interval == interval) {\n const hookUpdates = postFetchHook.hookFn(adapter, toUpdate);\n for (const entry of hookUpdates.entries()) {\n toUpdate.set(entry[0], entry[1]);\n }\n }\n }\n return toUpdate;\n }\n\n public async updateAdapterStates(adapter: AdapterInstance, toUpdate: Map): Promise {\n for(const updateEntry of toUpdate.values()) {\n if (updateEntry.value !== null) {\n await adapter.setStateAsync(updateEntry.id, {val: updateEntry.value, ack: true});\n if (updateEntry.postUpdateHook) {\n await updateEntry.postUpdateHook(adapter, updateEntry.value);\n }\n adapter.log.silly(`Fetched value ${updateEntry.id}, val=[${updateEntry.value}]`);\n }\n }\n return Promise.resolve(toUpdate.size);\n }\n}\n"], - "mappings": "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", + "sourcesContent": ["import {ModbusDatatype} from './modbus/modbus_types';\nimport {InverterStatus, MeterStatus, StorageStatus} from './state_enums';\nimport {AdapterInstance} from '@iobroker/adapter-core';\nimport {ModbusDevice} from './modbus/modbus_device';\n\ntype MapperFn = (value: any) => Promise\ntype PostUpdateHookFn = (adapter: AdapterInstance, value: any) => Promise>\ntype PostFetchUpdateHookFn = (adapter: AdapterInstance, toUpdate: Map) => Map\n\ninterface DataField {\n interval?: UpdateIntervalID;\n state: State;\n register: ModbusRegister;\n mapper?: MapperFn;\n postUpdateHook?: PostUpdateHookFn;\n}\n\ninterface StateToUpdate {\n id: string;\n value: any;\n postUpdateHook?: PostUpdateHookFn;\n}\n\ninterface State {\n id: string;\n name: string;\n type: ioBroker.CommonType;\n role: string;\n unit?: string;\n desc?: string;\n}\n\ninterface ModbusRegister {\n reg: number;\n type: ModbusDatatype;\n length: number;\n gain?: number;\n}\n\nexport enum UpdateIntervalID {\n HIGH,\n LOW\n}\n\ninterface UpdateIntervals {\n intervals: number[];\n}\n\ninterface PostFetchUpdateHook {\n interval: UpdateIntervalID;\n hookFn: PostFetchUpdateHookFn;\n}\n\nexport class InverterStates {\n\n private updateIntervals: UpdateIntervals\n private readonly dataFields: DataField[];\n private readonly postFetchUpdateHooks: PostFetchUpdateHook[];\n // private changingFields: DataField[];\n\n constructor(updateIntervals: UpdateIntervals) {\n this.updateIntervals = updateIntervals;\n this.dataFields = [\n // initial fields (no interval set) - no repetitive update\n {\n state: {id: 'info.model', name: 'Model', type: 'string', role: 'info.name'},\n register: {reg: 30000, type: ModbusDatatype.string, length: 15}\n },\n {\n state: {id: 'info.modelID', name: 'Model ID', type: 'number', role: 'info.hardware'},\n register: {reg: 30070, type: ModbusDatatype.uint16, length: 1}\n },\n {\n state: {id: 'info.serialNumber', name: 'Serial number', type: 'string', role: 'info.serial'},\n register: {reg: 30015, type: ModbusDatatype.string, length: 10}\n },\n {\n state: {id: 'info.ratedPower', name: 'Rated power', type: 'number', unit: 'W', role: 'value.power'},\n register: {reg: 30073, type: ModbusDatatype.int32, length: 2}\n },\n {\n state: {id: 'info.numberMPPTrackers', name: 'Number of MPP trackers', type: 'number', unit: '', role: 'value'},\n register: {reg: 30072, type: ModbusDatatype.uint16, length: 1, gain: 1}\n },\n\n // ####################################################################################################################################\n // inverter\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'activePower', name: 'Active power', type: 'number', unit: 'W', role: 'value.power.active', desc: 'Power currently used'},\n register: {reg: 32080, type: ModbusDatatype.int32, length: 2}\n },\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'inputPower', name: 'Input power', type: 'number', unit: 'W', role: 'value.power.produced', desc: 'Power from PV'},\n register: {reg: 32064, type: ModbusDatatype.int32, length: 2}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'peakActivePowerCurrenDay', name: 'Peak active power of current day', type: 'number', unit: 'W', role: 'value.power'},\n register: {reg: 32078, type: ModbusDatatype.int32, length: 2}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'efficiency', name: 'Efficiency', type: 'number', unit: '%', role: 'value'},\n register: {reg: 32086, type: ModbusDatatype.uint16, length: 1, gain: 100}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'internalTemperature', name: 'Internal temperature', type: 'number', unit: '\u00B0C', role: 'value.temperature'},\n register: {reg: 32087, type: ModbusDatatype.int16, length: 1, gain: 10}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'deviceStatus', name: 'Device status', type: 'string', unit: '', role: 'info.status'},\n register: {reg: 32089, type: ModbusDatatype.uint16, length: 1},\n mapper: value => Promise.resolve(InverterStatus[value])\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'accumulatedEnergyYield', name: 'Accumulated energy yield', type: 'number', unit: 'kWh', role: 'value.energy.produced'},\n register: {reg: 32106, type: ModbusDatatype.uint32, length: 2, gain: 100},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'dailyEnergyYield', name: 'Daily energy yield', type: 'number', unit: 'kWh', role: 'value.energy'},\n register: {reg: 32114, type: ModbusDatatype.uint32, length: 2, gain: 100}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'PV1Voltage', name: 'PV1 voltage', type: 'number', unit: 'V', role: 'value.voltage'},\n register: {reg: 32016, type: ModbusDatatype.int16, length: 1, gain: 10}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'PV1Current', name: 'PV1 current', type: 'number', unit: 'A', role: 'value.current'},\n register: {reg: 32017, type: ModbusDatatype.int16, length: 1, gain: 100}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'PV2Voltage', name: 'PV2 voltage', type: 'number', unit: 'V', role: 'value.voltage'},\n register: {reg: 32018, type: ModbusDatatype.int16, length: 1, gain: 10}\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'PV2Current', name: 'PV2 current', type: 'number', unit: 'A', role: 'value.current'},\n register: {reg: 32019, type: ModbusDatatype.int16, length: 1, gain: 100}\n },\n\n // ####################################################################################################################################\n // storage\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'storage.runningState', name: 'Running state', type: 'string', role: 'info.status'},\n register: {reg: 37762, type: ModbusDatatype.uint16, length: 1},\n mapper: value => Promise.resolve(StorageStatus[value])\n },\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'storage.stateOfCharge', name: 'State of charge', type: 'number', unit: '%', role: 'value.battery', desc: 'SOC'},\n register: {reg: 37760, type: ModbusDatatype.uint16, length: 1, gain: 10}\n },\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'storage.chargeDischargePower', name: 'Charge/Discharge power', desc: '(>0 charging, <0 discharging)', type: 'number', unit: 'W', role: 'value.power'},\n register: {reg: 37765, type: ModbusDatatype.int32, length: 2},\n postUpdateHook: async (adapter, value): Promise> => {\n return Promise.resolve(new Map([\n ['storage.chargePower', {id: 'storage.chargePower', value: Math.max(0, value)}],\n ['storage.dischargePower', {id: 'storage.dischargePower', value: Math.abs(Math.min(0, value))}]\n ]));\n }\n },\n {\n interval: UpdateIntervalID.LOW,\n state: { id: 'storage.CurrentDayChargeCapacity', name: 'CurrentDayChargeCapacity', type: 'number', unit: 'kWh', role: 'value.energy', desc: 'TBD' },\n register: { reg: 37015, type: ModbusDatatype.uint32, length: 2, gain: 100 }\n },\n {\n interval: UpdateIntervalID.LOW,\n state: { id: 'storage.CurrentDayDischargeCapacity', name: 'CurrentDayDischargeCapacity', type: 'number', unit: 'kWh', role: 'value.energy', desc: 'TBD' },\n register: { reg: 37786, type: ModbusDatatype.uint32, length: 2, gain: 100 }\n },\n\n // ####################################################################################################################################\n // grid (meter)\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.meterStatus', name: 'Meter status', type: 'string', role: 'info.status'},\n register: {reg: 37100, type: ModbusDatatype.uint16, length: 1},\n mapper: value => Promise.resolve(MeterStatus[value])\n },\n {\n interval: UpdateIntervalID.HIGH,\n state: {id: 'grid.activePower', name: 'Active power', type: 'number', role: 'value.power.active', unit: 'W', desc: '(>0 feed-in to the power grid, <0: supply from the power grid)'},\n register: {reg: 37113, type: ModbusDatatype.int32, length: 2},\n postUpdateHook: async (adapter, value): Promise> => {\n return Promise.resolve(new Map([\n ['grid.feedIn', {id: 'grid.feedIn', value: Math.max(0, value)}],\n ['grid.supplyFrom', {id: 'grid.supplyFrom', value: Math.abs(Math.min(0, value))}]\n ]));\n }\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.reactivePower', name: 'Reactive power', type: 'number', role: 'value.power.reactive', unit: 'W'},\n register: {reg: 37115, type: ModbusDatatype.int32, length: 2},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.powerFactor', name: 'Power factor', type: 'number', role: 'value', unit: ''},\n register: {reg: 37117, type: ModbusDatatype.int16, length: 1, gain: 1000},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.gridFrequency', name: 'Grid frequency', type: 'number', role: 'value.frequency', unit: 'Hz'},\n register: {reg: 37118, type: ModbusDatatype.int16, length: 1, gain: 100},\n },\n\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase1Voltage', name: 'Phase 1 voltage', type: 'number', role: 'value.voltage', unit: 'V', desc: 'also L1, or R voltage'},\n register: {reg: 37101, type: ModbusDatatype.int32, length: 2, gain: 10},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase2Voltage', name: 'Phase 2 voltage', type: 'number', role: 'value.voltage', unit: 'V', desc: 'also L2, or S voltage'},\n register: {reg: 37103, type: ModbusDatatype.int32, length: 2, gain: 10},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase3Voltage', name: 'Phase 3 voltage', type: 'number', role: 'value.voltage', unit: 'V', desc: 'also L3, or T voltage'},\n register: {reg: 37105, type: ModbusDatatype.int32, length: 2, gain: 10},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase1Current', name: 'Phase 1 current', type: 'number', role: 'value.current', unit: 'A'},\n register: {reg: 37107, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase2Current', name: 'Phase 2 current', type: 'number', role: 'value.current', unit: 'A'},\n register: {reg: 37109, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.phase3Current', name: 'Phase 3 current', type: 'number', role: 'value.current', unit: 'A'},\n register: {reg: 37111, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.positiveActivePower', name: 'Positive active power', type: 'number', role: 'value.power.active', unit: 'kWh', desc: 'Electricity fed by the inverter to the power grid.'},\n register: {reg: 37119, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n {\n interval: UpdateIntervalID.LOW,\n state: {id: 'grid.reverseActivePower', name: 'Reverse active power', type: 'number', role: 'value.power.active', unit: 'kWh', desc: 'Power supplied from the power grid.'},\n register: {reg: 37121, type: ModbusDatatype.int32, length: 2, gain: 100},\n },\n ];\n this.postFetchUpdateHooks = [\n {\n interval: UpdateIntervalID.HIGH,\n hookFn: (adapter: AdapterInstance, toUpdate: Map) => {\n const powerGridActive = toUpdate.get('grid.activePower');\n const powerActiveInverter = toUpdate.get('activePower');\n const totalPowerUse = powerActiveInverter?.value - powerGridActive?.value;\n adapter.log.silly(`PostFetchHook: calculate totalPowerUse ${powerGridActive?.value}, ${powerActiveInverter?.value}, ${totalPowerUse}`);\n const result = new Map();\n if (totalPowerUse) {\n result.set('totalPowerUse', {id: 'totalPowerUse', value: totalPowerUse})\n }\n return result;\n }\n }\n ];\n }\n\n public async createStates(adapter: AdapterInstance): Promise {\n for (const field of this.dataFields) {\n const state = field.state\n adapter.extendObject(state.id, {\n type: 'state',\n common: {\n name: state.name,\n type: state.type,\n role: state.role,\n unit: state.unit,\n desc: state.desc,\n read: true,\n write: false\n },\n native: {},\n });\n }\n }\n\n\n public async updateStates(adapter: AdapterInstance, device: ModbusDevice, interval?: UpdateIntervalID): Promise {\n let toUpdate = new Map;\n for (const field of this.dataFields) {\n if (field.interval != interval) {\n continue;\n }\n try {\n let value = await device.readModbusHR(field.register.reg, field.register.type, field.register.length);\n\n if (field.register.gain) {\n value /= field.register.gain;\n }\n if (field.mapper) {\n value = await field.mapper(value);\n }\n toUpdate.set(field.state.id, {id: field.state.id, value: value})\n if (field.postUpdateHook) {\n const hookUpdates = await field.postUpdateHook(adapter, value);\n for (const entry of hookUpdates.entries()) {\n toUpdate.set(entry[0], entry[1]);\n }\n }\n } catch (e) {\n adapter.log.warn(`Error while reading from ${device.getIpAddress()}: [${field.register.reg}|${field.register.length}] '' with : ${e}`);\n break;\n }\n }\n\n toUpdate = this.runPostFetchHooks(adapter, toUpdate, interval);\n\n return this.updateAdapterStates(adapter, toUpdate);\n }\n\n public runPostFetchHooks(adapter: AdapterInstance, toUpdate: Map, interval: UpdateIntervalID | undefined): Map {\n for (const postFetchHook of this.postFetchUpdateHooks) {\n if (postFetchHook.interval == interval) {\n const hookUpdates = postFetchHook.hookFn(adapter, toUpdate);\n for (const entry of hookUpdates.entries()) {\n toUpdate.set(entry[0], entry[1]);\n }\n }\n }\n return toUpdate;\n }\n\n public async updateAdapterStates(adapter: AdapterInstance, toUpdate: Map): Promise {\n for(const updateEntry of toUpdate.values()) {\n if (updateEntry.value !== null) {\n await adapter.setStateAsync(updateEntry.id, {val: updateEntry.value, ack: true});\n if (updateEntry.postUpdateHook) {\n await updateEntry.postUpdateHook(adapter, updateEntry.value);\n }\n adapter.log.silly(`Fetched value ${updateEntry.id}, val=[${updateEntry.value}]`);\n }\n }\n return Promise.resolve(toUpdate.size);\n }\n}\n"], + "mappings": "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", "names": ["UpdateIntervalID"] } diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..e7905bc --- /dev/null +++ b/docs/README.md @@ -0,0 +1,6 @@ +# ioBroker SUN2000 Documentation + +* [Configuration](./configuration.md) +* [Migration of historical data](./migration.md) + +WIP diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..bac6137 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,11 @@ +# Configuration + +![Admin config](./images/admin-config.png) + +1. Inverter IP address + (IP of the Dongle connected to the inverter) +2. Modbus Port +3. Modbus UnitID +4. Faster update interval in seconds +5. Slower update interval in seconds + diff --git a/docs/images/admin-config.png b/docs/images/admin-config.png new file mode 100644 index 0000000000000000000000000000000000000000..2a4b6e2afc21995a2677fe0def593de8b8477d45 GIT binary patch literal 28268 zcmc$`bx>Pf8!y_HQlXT#NP%F*-GfU?aSiTPf;6~Opg^H56iT4DLve@V?hxF9dvOg= z+_{_g{l0VWoipdm+?g|T|4Op=UTf|3JZt?P`>g~jD@i}c0%6^|ckj8ZjD+gFdl>BZ z?%nTx@&LGk(H}N^@18BUtb~~QN5h@D7wUKxjS%nYOA(C_{cGKhA6-;$j9DCCrT(cj zsk25;&uA9^FnnfJfri#kelk!~*zPHPL~{F^yyc+tk*1~OeFEj-AW0RBg9V7nLkUTi zcRw_K;zr7qa5h<(hf~Hqy^W-Kw@`d2kZj6zsPIneU@eY*Q2QfovUI9413uQbcX9bF zY=-sP`ud46F>VJd-OHV!>qCuW4%on}-U~)9^+Yk#{7e$@j5aN8ZEbxpO`QDc?heO; zAJfy*`C7%AnwrruF-En{n^cPT@9xmO|J(KgGF$7iz1E+=XFHpdn_Ht)_vqhS!?UxW z)(4U(e6GUUOZVW<@2(m%y_U-?t*EHT%v_ys@a*>o-}Uo(So=!B^KBi}3ghk}wUUjU zot+_%oJ^A8C%aO2mpIVU6nz3wF7Le0zFuu~*V`$r`8aL$`9^%x$;JvzWD}-i?}{cQ4UZv>jQPaOe#INg z!q^v0NZy-%BO(=@+84O54H@MjhdSW9d=sFDMp#R{!+okiBWcj!aeQ&S4XC`@{cz1~!Ana^ z%k76I6h@z8R`jy@%okbHVhH(cEy+ud<{K@TpVX`-8hN=+bb6=jsek7l1{_AO_YEHk&q-LB*>ambqB7{(|L2&1l2G# zvtPtMg`Yc5yf30{HsuOO%XCrKy@3~GW%=)v|NhN!{9%_O4EgWA6oHx5f}=ecgdmXH zrH&so%U7s^WGz!xPDcKQ`)r?ulSCGqXJQr6t^0Q<$Q-Tc1^5IOaP{!Dy$~9wzlqs86U5!s~daYbca#i^&W9T z`5C`JFt4r&9dfO6BP4e=`21hI=?MlD z|N7RYr{&9IXtJ;lFl$4@fxi1QLqqnLCpNgr&KSfavPfiUa@g4P2L*g;#Lp~1Nu7I5 zx5?#31_p)73|LrLrDbJ!r{wScE8K#pZj|=>*#VKqIHX-(sMr-70c3s zY;lc6+_pcj4@fRGt?~QS>_9=f#CB^lTK>I%+2~bmkMnC=d54cqzFtIiG@fapUsSvg zzEoz}eJ}HI+GQY|SmecNBNLV$#CFw==+$HO>5*=M&5E$*x_pwp{6QzVayTvk@ls1{ zXu6eo9I#kfq`B+V$v(B2dTGc(5FrY`@f(iFozqb|DNC;M?$MkV9DLUysWUT;lfaUg z=KeHbM`V-Q0?$qnFS;{(k(c|E^rQfGl@rM(-iM~GA?JBP2K+5PLty!q$kvUFjD%7^ z4As>$lo|5!@&Eu+(b77-K3(8mXP(-oE{Tye;nEq*`9U=dd`ly8(xE~9Db%Zyxin>` zL9DK>dL8!jm6l`pe54zR?UZ)%4|O3TJ4#T1l_o7GSqDsE);iOEHi?-a^G6&eeg=;# zD(X>#Y%GMV3)-HX3XI?QjvFRNFIxv7oJbDCb}1vbFQWJMODfyQt_(jV>00pXbdKA# zf*RiPicnoiKF(ugF0NTNOcCm7c|WN=^Qw%uZu?PbHNFs3t8~^8YiiDqFk87Q0IIWf zfc>b{f*n!AZe%QZy)q}&uWu|evJfQP;84WQrX>A_TV63HDXErH{`Z>I#L&a4@6Lmh z4+gMCDwEdi0LS2$LL~C$ZDxsSIMUJ45$oBrINvKC9v)Na+BulQ8<=1>kpkDU@e<(= zorpk_jIcYK4wgX?!JA4;4`yqeXb@xqj$boMEXwTqt}!w=8^FAQ3CJLkaWwv?_@&0A zs&l*FmDvih@66b@Lu+fbg*Bf^hlRS&2;fXla-t(LX&z#qzQn5Jln?9SE znR!sT9<8v;2;eGpw;0GkBF=>u23Gs(mgVMwQ63A zmDKCotXGO-i4BasP7rhX(^Lq>m7hW5*@oavB~&v4a@k`(@R-JP>Ixn>*Q(rUmXP>u zX6Lrl^~wj{8rK%EJ;&z-yWG8LQ_gc ziJ#vC!243F^}fCUyuUaw(mAxmH&{$l$azEgkplhLq^0@E!UA4U+;H(YeIA+I%8VXeH#z|@1<(9kXKG~mojFUzEsfqD z_$!NB&*PTyTfqvIX?MhO^E14PkR}rF{4Vf@uVd=^6 zP>sj(^z+pzu{oT)m2F0$@s+F{i|Cs4ME!u7+7J%mU3#CboiAW-De}onalCBgVKT>zI9dgN1nA;`ZGACQdG|$~-Y; zu68MxS#r5Pha${ee{{We@yonWg&%u`U&G!8pQsa}&oy?DqtDe>Uh7ubu6SwW&nsa2 z3t&F;xbbbz5b8JL@CYK|`Pn<~G#dQ2ZgtZDvch__?RdLG+aMJ?(NQmzcX3dg<#iEv z%2B}^-&)*rQkd?G zBa&UnG`iW>;yr9lA(g1We z<(^_0TZdWASl4bW4O#&Iz|6qN3MvBhmpc0gg;SC?QEv_prGB#j6A+~?^F0k3w8 z++-JH(?Dup?d^_QC6erTc>Z{<&gSy_?`_fdj2Dmi!fsmjNtp1mIa}h3dFG6LbcAdY z^iNYaOUnkBVX_jix}Gi@?`PsQxC7IyFX2X)s#Sw8?6uy;aFeaCYesp2g zJQE}1`?~h{4W~$Jkky9|Z`ggy?fk&JJrMiILe}H=d)xt6wb|TXv-|0Hveg^6XO8yC z=$kl;AFGNxCFZ0GM2jw}9<{ILbu9dI@tt?IE z37E2sol6XyhT8T^Cu#kuW~4E!MjXX+PtPH6_;Au6s5&nh7xgBL;t`o|3tU8Dj+b2( zZcs{7FPKBQSD&q&>!>nUBRtGnswdVtz62DQ+a&i~?~fEF8)+@*hI}tgfLKYUV{%k5BD^bzm73kUu?!%0d-=(pt5WKgeDmd z1&?oUb7`Nm-KSIC)Z=MlXk4oOPO(_*%!uQT?HUB)zh*A-S$=R46-?}>&ed4NH)~M%&c3L z`|-zFqA29X!j7FJ{MK@iurGT+(K$(G8ecU2(;N5iS-%_b`-+bpY?mQppRf)F)f>xy zlE)lMsZSVN>YUK{FqOL`{rLsi%GvnCXnIK?tjR`8QB|8nMNavwOZw8jDw8d2`o&xq zKS{U@@?7ajdi2L97`X$XjJ^@PAGE&9yT!^Le+u@7awoRFJq7?QcU3eg7aWP)7`19p z5CRFZC4u(A`TIcvV6%QDvB^|& z53#Io%1NIz4ep;_9Syb_m1jfuIa8{=psXy)*UN6uW9q`w6i+)(-DS6_l6a$>ekyI4;?kIMX3*nQ&Z$@{_ zdcfusXT&a4j=5iNU#jgUG`=6yy2(PtTIdh&-B?sCOQ(3!CYsf~pzpi&8L5JFWYcUh z_DH~kH%Yi-k+G>T8VF~4XY5<4-GNxnw&`gPQk$*O+;^$_#Xi^Dk&J4wwCxl(`;SZ4 z3_uA;nP)VJu#awsYlu9PWWT}5ek>(PiSX|qS@xj?#@$D)hQfN_0nMqi1R$m z{g2G4059d#bg1brmZ2VBXsSoJALg7(=bIeuNEtTa|u z@pl6Y9-hhuX2kIg(}lXThdogyq2UiB-HLhms*>B<tLKFwpm+X@~m!Flp-J+K}+|11RKDVbn z^tV82>*DO}>gKeG0^(gCH4daT;?yFrd4s}S72=ToRzBHQT0cm#FCRN#i#+it_%arp z=}JL-6TF_uX=pR(@&alfzYaz39y2t6rCc)zV`CSAxFnQ+t^1+t^N6KUUO^IKZLtvt zld6!ar)mw2MWU5gEAYPeM<&-eBy_r*D*opZRdLJB0xeZZ-gr|0>gI3g!7t#}vr=tlsNNtvxcf0zIMVrxr`B_OP}vCNQLOKW3-HalpJ+|Z-tLEG1? zYZIE+kiJ^E1ms7^`TfH1m}SvZgw7Vp;cY{`NZ2WZ2771cC6eXv+N8VpZ$dq8ZG+`( z?+o6jCF--@lxl@&B%M#Z1j^s*59mhRP#s^WFVF-j17l}BBKfO%YS6Xvp=yK}X&HVH z%=}xADDN^44fvZEC%9|vv_1M}X<#G;pX>R7866^QQUXOZBXWX)Aik_H=?LnMpcfJn z8njP7@+}*|wV-ETmt84(`{ryV0vhXJZjBEEVh~^Jt_)6;=#;#U&Qz{ic4=v8Wi}CP zHnwn;_;MNyeNlMRRbO-k-Hdo~O z@iV6qW020$#A=d0CM9qduKJk2ttmcINsB1n0p^45&KU{4hWa}V;=_XlqQ*5AN7pmy zNVzF8U43UGBoqRE4lvvp8cG^5`}8c;Xzpy2ty`|*@h^V)T4aZDM2|Q=sy(vuX!o#` z8P^U_v9rofG0uZnFrEAAIc0_K=5CF|$@Mc{7NJ-ya8#5?-=ii;9BK$fp3x&&{PQ3EU(H@<$2X zU31J@MR!THD^zB$a~MgV@Qs4WNXJnSCp;Lep{Lg?4+s2F zJB+=t^W2|>CnzO8(~sLlGR+mgDRiE}+whOM_l+%Y3d-}n)b?Q(Y$#+YdvNwR5y>C$ zVGkah+}dUgf;}#Wqlork3Q|zy_$gS*%>j;@oVkDpn=;-+>@Bjc5jt60ou<_#ZvH~M zHtRGoEoSTy`uvp}3aWuH<(w@QRp@snJ%U-x^~1=pZih1N(8 zMW=%5lnTyP`2(R>kjGXaJgJDBMg01>+n)|rYO`O78>4}oh@m|F*`+0rj+t>;e6ZEK z=W3g7cpH4+7nn(R;#F)9?NO`5WbFg4;j>Tq9 zY5-R;b`>drxnM;cVscvsQrXdA7|ASQcimY6B%CJ$qAm$Uljmob#04YF8cZfE1d&~b z^!?!{y}iBi^767EAh;Vk5h1==lYOyVbFq~ZNo;#U@MPOEN>p$`AD|qx`*l>i%DGSw{@^YFxDu0T;d)sh2nPVV1 z26+~6f5a;DI=O%j(U6&fjP*9#y=AxgyI_LR(P!UsncV(%(0&oGZral`{KPfqG^VZ| z&(W*ti78an!zXT&q%62B%1(hpr>G`DS+00ch$89dx@6K&Fj)q?j|c24@VwKf>pQJ{ z)u}U?2z!f{XNmNr1-sy+E(*Srd3wb%_r-vhK<$uz@Q{S_%gu9fGBgg5&xi-PdF!@& zSP@n^Fz4Q?`HyI?ta0Kr^0tbPRIN9a3lCW)`YLUc_i&#Cw=nqQMGnfuu_69mB4u>% zB5=UK0U6Ta2W(C#WaxHyJvpn@sr_IXO9{WMNs9_Equ`LdD4B#0b8z>T30{Q1d|I>XL!pYCZI1=^gt#yBnGd&< znam|X^ln@MDV-Ma0-{SxIiFxn#^Jl*=hIV0HH-mj|L8Z?93R577jI~Fk$x7(-{roS zfQ;DuBl-}3}ft5~;Q-3Bn6u*5taArc9?oh*R?Nmz@) zWL9?eCdbttAUkepX*v1!gbaZ&dlXjRan;)*+#|t>!iPr-^mb>Ie0lr=iJrH+03$y| z;v|sr=US0E{2lFZ%6Wdx({!E9njnAe>aE93pS>nN?W!~p;yh?jn$q(KvQ-V=sqZ|f z8Kp-6&h}2c9$rp&UpcpaHG6`*OU>qhIAyQPdp3uS^rW9jMqVEcye#9;?I>akMQ^-K zA3sqs(8z#&DmTUh_eH#of#9OX64CmgMqn59)eD-eT@(>dn@%Yek2ox1Tuji8#BdMT z^gW&~DzIV1%k37uNI_OgsVoQ+t><%RC;7%#1|=JQt>2qAI@*1A(Ic}m;V}_0s?f=^ zhJpSH>Wd0P)^24?E-@bFKrnL7HDjMwXi0(oO6k9V;MMYo2Ye`o2PZAIim(4d$flfO ziL`YjObgIaZTJQXs%d?+NqwCZUlVN&zPPm);;fTnV*dLfB+CD)Y<^jG+wG+HAUw@|-~<0=|F5ye&{ZWI&ZhZOwfP zN6g8qtk{An+bgUy)Wr1}L=4|EtH&B1ypjQAvVr=nVUu^#b5jL6*zaxyzBEp^shQf? z)xOFMG87B^uCQdT1e-pW%=}*Uc8q=0O}6%0ANqxF1%{ZcR=-6;HJ=7}Lfw+m+<^>E?+N#m$So7V>Ok5l_G`@!8} z5P6xJ)7XCZ4RCqx;?tP@mw*oxD5Ai?ot@&*%Y$0;6D@i6uwPaM8h=M$tf>OF#F=w% z5C3);rygv+%oi{0lf`&aJ116KR=H+%(}{2*+vHi7gl<{zm`LsO^Ce|n>;s0ET4)2I zI;78&=pHUrXITx^|9a{g2Q3)VL-u8QM{m(Yc=Za)g_2y7xJ67hx!X;c;@7gDUPo@koTzjo}@?mvKh#YhuN*$aJf%*fA82NY;G6)%{Ap>tDNT zwU~O{7JdpTN@a5c=GAr>Uq`_-FK3nRtpVDlul`yOh%V-{Jg5A zP!g@$nU(SwAZwy&5eXqrwazDd2-{B|cneB@-B_O3`1Yk!7;*7iAxewiDmU`)hO3Di zsdvcyXZVK(?HhirM<^d@HZ&B8RtSrjT=PSrTT$WI?MEsd8Iw&)iiJvk_+Gl`ZWK|& z>C4o$JZYN9dSbRoeCY-ukKw$kyOdV6jLW3H}dI+B6yIa1Qu(Y%Ai(OA* z{uiSY5|egAk~6C-KcVTf;2RqmtRs@clMBWMDNajf0Dg>6L>eo<#_HLRe0(wSM3;<+ zH|v3d)Ur`(ah=(oz{T?eBs!y3R{-9}He_a1J2KOk83%|6bGjJSi3XXeQju zCl4DE*lplH<-d4FQ44LHsG3v;!ICrjv6F7Sn4dpC_N+a);hLj27nr;68ltm=*CckC z)T3{-B^2ekvAS*;jXqS$@V{!R7n$PY{R(1^R^GuQIdPn&Q&cNu+53uDi+HgGUL!UV zUL0hWz4@I)!lhwp{F-v`EGq8M#rp(B zOVVPhd{Sr5eks8+gwvoU>zm$HGQzahr=!nxY*Q#+7EEoH3y0U(;xdX&+5#mMZ9Uu_ z^YAOQU@P^|E~`)frsM%1@AaIlU?jVXvC@wS@ES+wTA@I?$dy#>`OI&^#mUNuD@jYU zb>q#-=3R`%4}ASbnB@7Auvz_F2$T6!8{y}Q4|9xGq8!t;o0%klBAP-Ba;b4TA}p-s z2oVO(Qf83RrSdJv%M0o@{iGnbO&qbP-G_U?4nI6t?Oh*C0oWfj@SSE~4CoA>KS(_@ zt`#hkP2nf%B$t$lexGK5k7c&Pum-- za;$iLauA4=g{kAWnK7h{alHr4l*xI7xXucy34Y@lXMv8I$hD%|N_s1is@xO^RM%E7x?@hne5n6! zLvqw2O5pI?ecMJYlakB4KVc`+sbq68wjgnQPh_tIybn^s zakCxS*QXE;6xQ4w9R32F4}2_4k+|(lfaJn-WWe#Y%x~8K^->ZuRFMF77J z1^fTQ)!CY22Er+HovJLTcVIx&{lL`QTeMrYV~%+|!m!F2vI8 zw1t!0wdN)Wq|m$YA?zw9E-o%S{K7%?q<1>^)qhA=|1_pvjZtQqDT928mWA0J{rOC} zBYv^1`n(iX0i@TP0RB?!+-C8I;^}_{hIPCXxrrjm)xwj%`Rk(Dx?670-CgIhGgT&i zYTHCJqF8c^Tlc}p=bGoRcxPM0XCaO!Jwg8Wzcie8aaDjJlercx*-7$QeN0P!%kVd+ z<$}YP35~XkCGj~wI+XnJnpLlo<*YcBq9=rCdL`k7X-3G0Tai+UXvNoTN`3BpDxw$- zCjTLkjB&YuJktdEX!r5x>FJG(79bBTmhq zVcx}+{g?QY+NU#@Rbn+!WKjRHq`I1)oqcbmJEAj`VldS!|BEM&-5q;wBinXl5~$i1 z>({({Ff~yE~Odh|xa}OhL z27L0T1tU{cmPk}}&} zPztHCFxM5A)l=k(q&M0_O|^5B@yV0I$eFW7v^`Y{7@$=go|djeEUqP zRa8<^KLK%A+UhnKuD}qPr2%G4h(d4Cp+Zb8-c##bd)v51YI~F?mun@kJ)Ox^&dYfc zO~4q^Pc39gbD!fxL5&`M8h}?~0_Uxu0tRm`>*#_Pu*rjxHT#d$lc2cLrW_XJ2};sG zD!ZfNqd-s&FIe7IInR5z7LUA8Z^Tq1CuN|j0>va6FN`^Tm37*MDZFD*J>fVYlM0Rs zEE_`@%-N~iK8r9TG=!_WItAh14YCs)j}**TYm0s+xx{0V*G~2RJAX~0;CpQ!8LH`A zV=ZR+3_zT53ixqedUe&J@;%A9rs*?d<-cF1a;Vdo$Vu4JGv@3TOLYvdY&qPatC9FXKJF<49f9)+QT!#kxCjC zFxha49AZAr1V#dBGc7guLO~%pn$ZxFZ8=yT5>HP8r7j739B6|0Ce$iZZ>8#{xr2q* zyE6JNs+3BDN{+=!Ys_5Yds^u5m($!9)3l9|X%#DA%zJ~_)LA7vGO0&I*+O}n?XTZ! zGx3Z`diDoqAV%GoXiE#guKqs;kflc-WOJ0udAZQa;a?Z{q{`Jz>E$}8Qk7|<=}^Op ziay!lh74E)@@6^&3J@K#<0QFPl+o>3F+3(mM8GJ*p24xmyWxIm$-wSD*S>=9_K&gB z|MZh1GVIGaVDvOJG_bxcb%jxLf*rri0)FG07hwd|GeD!**C--vu@w&64<8s97_=*` zrvTHQl$dDfiLPjFZXUaP-o@Fuys{Dp2ZxP`iHbQwvAXcC;X|MyBU98Cz|!mP?q;vw z_p7Qph45KdYpDD+FkgeZyW7CwNqSY`RD4}?wHS}L*o;CVzS-*v)2nlXTwE@Usb%M}vS7#5U8e8vU(D65>gW^| z6@`R^ zQQ`fWs+$0=Ru=;6gXlRhBql)q16Z9jI$IYtP7rq8_CY_>c= zs@;jdXjBwL9BClN$8`mTKJNRU!PW2E9tBeZgX6sgeGya0RL#uD;GkznDb-S_Qs*{T zkBR(gK7vB+v&sXg%bUST)DF;5IUJVS&lD4qKNe`a9Xly27pM!uQ5lt$yt{_L%pc(c z)6h&xN&+hPVDMUAFYZI|#eb)6bFgQ1j9 zU61oRx9{gSMlM`OmHAQnC!i)&Qt-%d|E!CFPR`Ya;){bkEo;*0=sh%=Nk&Irp7r5i zA!7J8M6V>ExWUB$gY+ArVV96&hEashQ3Ls4iqF;`F~D$LTzKp@-o04}BS07zAE>Ru z3<;TiqEW`&)iy={;n3T?Ou#DU!Syi3 z0PfL{M|k`fg*`R-?q^SvX=0_s#C)r&+^%=$uHNt{Yox?) zZEotQsbtGnxMD}-$*li zqggN4{hyCoU)JOEC?CsEO%c5+G3mh4*Cz#J-Pr|av50E6ISJ5nv|J&vaG+9e0Z~|_ z@X!m@MuT^7aG&_Ox;Sa(1Z43G?v69Cjc%A0KTEI>s`aWinwiVYPv6=f@Be!+BlsgS zKzx?eLY7^*>hhANMV(yq6Tj=uq#gl*h{4%+BX94mHFL|$E}32NN4;&!b@DOR*494( zRA~MfoQSlYQ0F4vAmw{EH%HKpHoeejG_OsEek>WFBAeqIiwLQUdd&Aofw1qQJl`kZ z!tI6s+0TrDFe6~F33yW-wq^!1iu zXT==F1;58bbWUo(7UVqQA+;I>TlTG?T0{QKE1F-ryQ1%0)UyiW(NbJ`SC~oM@z5KZmM#+$6U}17 zxf&N{2!yz(n%_nF=f&+6MgNJH5-dqYB{em*q@?6Of-;wfZTY#3-gB?ny?0KgezJMN zX3BS_xVc@e^68_UQs!>Xw$YD?>v@%-{wk)iruiu8`sKx)S8w`rv!Tka?o0GfrN;Nb z$kF}9cyt(`7TBlnpCc=k0FSP*Z6&j0(j|X_kkta7l)L2UHdbw zVdLk55aqDr9Nss9)CbaHL$(b+@Q1N^It*$W4))i6x?KrB9B}SMT}KJ#Dp{^cavSBr=#QQ>I&Gp|A-x+rQXBX0?gm|__#|9 zd;Z+q`K!E{Ej!TRQGKp*Fa?CXtm(nM&wuaGT_Oba=g%LR+#{8b{Cw|@m4PH!C>0g2 z91XzgAwU?+tH1(C9ukjIY>mPbd_FPAzvwB`>eh*m$LUY?|qDJeJq`4z&ZED$?k4VZF1JkAOa_#>X{t z)#bv~EIjL`r{gIKFAVVLgw>g3za;S4(IK2pf$hyP1avwCa0v~KjsF}Dik$X-d7MYg zUA>tH0lL+|?MN>B{Si2k0R%HOo`4bOcmP-|EWl)nJ&61EP0~fSdr(a5Dt0W!(x|>V zTvV*av^#uzqS)yacnM=tVEz)bb#8WT{?BRTJLEC}lNGu?xV~PvyXEk<`FeUf79gD9 zMQ#uP=2Gn)=u2vPMFkHls|_kc7BFquIOGLTMK7AL91-EOzw&Cy$$+l9ENkN8l$4YJ zCYtBzZihAy#Bgu|{@BOQzDSX-kLpZ7!ClYNGA}bTGdp`7`ThGIn?atCbIx&JT&35g zV0xNN7)c=}W>smaEfYQoZ8)G=AixVFmEvvZV*pm|(Vf@T_l*>Je0&UKe<&#_d3kvO zJoNVV2BK-K%rFuliBVowMgsA^3L;>Zlb7%AiCqFtW%XeK?n$Yuu8WHckck;imxjSt z9@Ti>9XwLmy^H6vzWuNKH{j;~#=HAJc6ZPfw5`lEQ`39bqdzVzi!+K!wmgwmpD|j3 zHYsP*sa|!=!Yb25I*tA062Q5s`s>1?>a?ZLiB^avhI6m_q z=X#&S_z0ZEXRDCU$X8m|$oWrfe5S|=1*t8BNe9S<2Z3fZwoU|VtP8a@Gl==JB9NBc zu@DAV-tN0;oEezrii`O7wtD zau1smsQ?2$?+uasuR`!Ilp&;pFDOKTG^i>AzH|s_U}_l2iY;&$$NhUj^V}oAczy-8 z@dqktM{#j+F|n3XvtEE~w!N})G;LLk`RGwm7VvygdOEPZTlPQJkF>6cuf3Y*s6u0dN5Z;KI4Qyj(&;LR(wgdZAoa$Kd*G z&aGxD|I$O)F8N@(f}w|4QN4i2QZ`K<3Nh`r)lo?`oMMlhgT50<4kWH z?0Q{YInYxqtXhZVM{a=SzbEw>{74*dUY`Y;+@4$=h6)O*&(8zUb*g%Paf6z_xpEo| zd+Sfm1t{-60CGo>aQsPOPs zAYa;J$T_FlAFE=Z`Yv8kUcRl01pt#AKqB^@`+r)1oaQp0jmJ`n$=nzKm?f&48L|-o z`>xs(&;b!YFpcjnuC8?S^v@nXFmvI7D2aGgjE(XO31w$xnV4t;uS9+qDFDaa3_mV@ ztEZN};E9u5*#3KU4uB*evV!8`^<5G`BAj$zWQUVC*VUqIzij zAFp21%U#=0pJj0JA~mIX*iIwFRqvkTFE+i(ofHyYgd}s>OfPNL^}Yc_6`of zOmTscdN$l1j%ckCUEx~|>Z~qr;KipSjJD$2@A~I{M|tN>BY9$F>HV~IkL!%C?zX(7un5(Vo-6{N75=~7 z=e2${h<8DwtK#+F&QUZ8g#{x~)L z34$WQyvj!EUmi_eY4Pj}ul7e`Q+&Z$!h{qOX_K=EN9@JNWSpFwK;3>9fEK{9E2fnP z7oMHjQ!Hs%sH=bY@WI-;;QyY=LUEMdf-62thEzD(srWV0Lt(ckc3UPF9Chw$*H?$L((eBlT`9A6@VGs&%MWSyk1hfCd3ZRUZf#&y)HKIF z3->P8j)e!uTlX!uH5jZD3I*l5Ge5w!$`LxkCM+B8nJU-3C3p(kYd3=JGOoTV!}Qak z^t3u_>$*33P1Z3uPM`9j^0pIF{lY~Ja6|xaqMgC}ZrM|3aUK^(3Hb@<5bNW;AS5L0 zRU5}VUZ z(QYpbf%^5Sk5v}wkB~LdQE_*Vd36S4C`IU$5deKMK!AEL*q=0~rKKfIbu)e6-uCNK zOjA?s7tu`v!y@m!h9bbf+>O6DW}q@jmpB0Ow`{w=0~we^2ZNX z%*}z!{n!LaV|;dgNuuXVI6W%6>4;9Wd$U`P$*PaNcAOPMv2}4 zNL)SFUBeSp&QKxk$yf5HKUlQapJRYm0kX@p*TAmDX1MdMfwB}K5z!f7jjj*=_*x>dZELrnxrSa*5+&;_Eb~6M z*K2F$yUBn-djtYvl~=$y^f$hJt*vRb87u3*-gx(I$ycx&>dU75(l0gbKHi?Fxdfj5 z$8Q$|`mO@fQ{kB=nW)P6_|C)i!$VECWBxaPylrgyE{^-2${hs(O6UfZ@Dl~Z4AIfN za1@P&#k$(#7vtGkqTw>5t3x$Nr-;q?BJ&#Kz7J@i_Xxf|z~d1{8c+ zg?s+%F9A}y*9YVjfsf|IyQIqhuRjZXru8CcCGXw>+7b&dP@~kV`BWpL>1t$=nkUNa z$D*K`4lkc)e5t$hH}CaM!WC$62s&PG9?_4P%Dj_o6^lYfx)6*(l!+DM z2w8*Btcb$ks09@!y~v)mtP3o6)vwB=Mw9Jx4}sQi+q!_}vPy{8ov$sIwJnYfWsiz7 zIBY;x#R6gFv%qZHKnr6kaF!*4j)ZX4*fkr zNmQFEf=_cdH!9h_=<1ARys;`G2$V4Ct_&`nnSE*TF<*#2t<6j)z!ddFb`m7(T$>i? z9Uk9U5|0hfv9D343CT!-5-Nd4LW48H6~+A_IZKNMCr+ic9G` zN&m01u>Nl)sqahcFHQ!O%=!Z-D@=3(!{w|uasO8C=$ctrI7v!nd^i`h0pVfM*5%;& zppPA=bRAIcOrgYm8c9JkCE)aU;UZPd47qk8{6rkqFM7bAG`PNUj~sCCDb3(nTESwH zEU{p^9OpxBHs4i}CM$sdLb-R(3kij}^pr|C9Kp9t4YH|pO4Ai|@?~L)+3DYAR(5py zkgzbCZ3c}oxK%5v$a01Oy1PY^PCm|33}GRljjnKu$QSHJ40V-{1WlV8x~37&2Fbyg zD_T?vS!U^iM8wg1n<#D1_XQj*4VrF%7Y^w63|^27x?&3v9L})R+W85@&uNOVia6Zi zqM)L&!5#^cGLo5I)3mOgnd!`99aUaLp<@1cGL?FAAc16eLTxV)*<6GdWH1EEFyKqJ znWUi5%Qu3?i5uO_s@7pGc^&<%|^F;k)eFzk_rRY;64aN6i{@|I&c-+4W*vMN=xb{=njupYS)ix zDSUi9T+c7%C|o#SyzYR~G0I|Oqwq%4Q?_Tj6d2oS!K!Ym@)e=9PAyB^kos_$FFcMn zjncaGx>zXQCQ$W0p6Pp&Q1BLOzZcs?J6$>^GHP~PwXReT6~5?mnAL?lLHQ-<-mc3h z^>_u=(LEovMBMUI6M4jgTg{p3NZ1#X-iJ{ItvU^SlE<|NQb}28>y?27&0IU@$CJ6R z8&hKJu@7e{85^{?B44P<>Qr^!KP;=EEVN|F<&;nMl4KQuR_ zrvCH4AAeJdT>|JBVAi|0qga(<+rECeg{lV?$kO-q|8fDNYatIdK9P9VhTPoT*RL%m zs;!Y7v0f;Y{|0sph^q!e;P|nDfq}_MNpbOa#lNK7$6R86E~Zt*GGb6vc)v~HjFcM zRYX%%3c>EYP)7zX`BS0#e}q8l6k?_#3{Gc}BZy6_Cq)Bazk-*=zsM*tSk=jMVg`gc zIj`;4g@x8ZK{9^}lWn&_!u=21nW@W4N?>d)fDs40-2En>-RHyi^nx5pi;8R!h#UVn z7^JWlT->|TpRB}QW+s0s41fUa-{pF&MVL&z%k>k?E}bRuu9*O>|CDmU>}%H38W;+T z8;8o8H2Y(Xb2Y(4L1i{J8uKQVo^PGwD{=hfaX{Rw#$f)uSO=^i8`NZ~NL+(KI6=KQc~|42I9nRzJzBb0>0mj4kS|r3nKi5cIZtyO_E}EGKRlo z9g2ZKDX*Y_L?Rpd!5X%>1Av&tJ`B7Dg&KE{8cCLCDmFwf-@i!>`1^b$F|*|H&^X9= zM3H#SeUE8RQvoZ13p`T!iC9!li6C;AlD*hGKs_r*1HQ9XopDf!-kmortugZ;tI zFMk7W3q2#FmE~o_v3iX8G|L|`0}*LRS8MBui3uRHul&vKQn}EVNNYh90oIl=(-t*! z*ODTqi_Br>?2O!*)=<>_Po{}Lq6K(vXQ2am08p|3#l>xWc?xAoJArCOQJo_%G`=Illg3Nq?i_nU zl4nkx?*0Tl8y$SQJ$y#u_qz#6UT!osll>fF?KIx4H5^6bcN3VL7x~z9(S)OM%KCmC29$jkos4$?{=UO6$C9}}B!d7FEB~*2=?loUb)CRrIh>fChB6(4} z%d5}|D%JU#(#~v0p@Q5`c=>p7p|WI{sGd%{Wtu1Y19~!! zDI(hvoawCVu{Sm%*1x=nVIn}maFbs8u7;G)g;hL@QqS_5h zqS{6(Mp<{Mgb>O_uI0Nb=`azYwWw;HnF&u(qiRva#}(Z{b>v#;ysyNJaiX+7OhUJ8 zbc?=Bj*AL0blXR=bCYYZaNe1~E{VPoHdq_QZe3G-8l0xa11xlA8I9^orGN%06w(=# zF#62$y^2&s;B^y(K+=Q?Vdb2i@1iPPI#ps|5YP4dmZn{GL8+`NG}+{-I6&nBuhN9k zk$Dg8`i<&naM3It8Ra zIX>uV70p?v+!~<9kB&^}a~ySseRPb-(-A|LI0%1ItlpjMMT}D@+RVKfN)>4`^Qf!= zc%DbbM8oB7v{l->H=9nbjrj$WY+|cjgDjyK+u{eLZ!nXdk-i#mkBs}BZ~sAP9;Pr& z+`JJzY<4lvi-k~7%IJh{FB*8(i`x%!M&DrCgzBb>tWuN{j2``TseR>J<53+hz#JI+ zpG^6FED%hh!{VWd18 zdWZ?rTaCBoUxEizzeeMri+&6cY}MeE9IQ&-Pl^X9)wc7Gi) z9eBMIqbK=#gh?QktNi;fdALP<;)r3J$9<{W9`4`n)pYB-e02~p&M!QP#;mOpi}oht zn)5Y)%0^5ahTa@TP*zPazxvU`-l6dxM;4n+f3vY0n>Q#=*@ymht$P7ZEoWpc%Y40~ zUp3NDrC1OzQLvq5q3r%+anF%wwTy2Roxx0ct(81df!l$HdPgsXw)9-rm9N@tC6OkS zQDyFV-UR?})1(<7u(2la!^E5y0>{-|45Pjeo5g^Bim$v7ONEe46$@AZ#I4SA@= z`RzTwuiAu+k$AclYNw~iNtKJ!qBsRL5rG}Az4S_^Ul;O>Pl-SN_!_<5@qZa809ik z15uR0_pdTZ^KO$zIe9^gs~Ecv)(rI_VEr?*HQ?Te?r@#8%KUDQ)oPLW%U#kWVG-JJ z;ezhb7&h#>!f#ZdlYjV>J<2yub=0Pv+zSxx<8Y{Imfcrpyd3K#$aX!SH5>$!C$txT zUm6e7ewWw@VxpzBb9CJGl?K+jh=sOac81sXqf**Px|{*;R0PLx?5J<9uRGbOrdwYAJOQ0AW9+}k6-qj4w9SFXcVJ9*%M@SOHQ6W@NcasIqq(cZhmOH`1KD#aJkxrAq}ZYGdN-pfIez|vp`T4(9$A{X+Xt6 zATUaJxF6eXk}Pp|tNqmx2keQJ^TtM3*R|GTbWKq3NP1pgD-KZ13XI~~OaN}f zUgHFqJ$-zlZ~tftyU9#S_5h@rd&*bhmb>}q$RlX@4DURP5q=DLVssB}*>^KcUV-uz zOS={S`3pe@Ow@3VL}nO5jW z1h%wg`kxI<&1R>it+)j3UV z-|NU1n>|`s8B$H=xpC!k7xEW~fI`9}Tk95mi^_6oLCL=0{d^SsuL%(m5vS>Q zf|^EYwA#Y(%VbKx(Bt7zLl_71^5x>_IDA)hpZ~!8uN)!P8*MaRz|P;w%bOJ9ESH;S z;~*_S+ZBTYf-|AN{SpL`03u*ewQ5D5To(g*f~AGUg?drnJlk=)kdNq)JJnhLrr<}@ z-rki$p`<@rZywSdc#Lu&g}j7ymSZAPR8hJ{Q-?Io4RF;8?UI_h7E|wo@2|m4rUBoL z_2b8Zk96|ai#pZ>Sadcc84+oE( z2|}m%_6Red$tJB7o#?o?U4}8X|~Vk&Xn?bcnrW<>J9Kz_sOdmPt3XYy(?j#NyP(?wwtzE=p{TkF*)qaH)(L; zE@)y(h+otiZg7wVj}HqAqmH(o-?;=yr9+fsK0Zq6*EfGhEq6_D{hNVxt8U3$`Jx!# zHZi*qceX2s?_Kwn=nmIJLY}lY1NfAz zzPYXUWsO%`V_MIDd^1(6!ljm6fxz@AK*-yk93b-Ojn>uir65iB5t4f;l|qpck0cyeN)epwBwj!HR4 zE%n`%?9U+B0CLe$l*4|Ih$=U)n)cNV0rlgd?o)W<29!0Z$v{1VKy2g_97&bapFVvG zf>3Ok0g}J@RjMW>4u|eSE6HGR)ivkqJLQI$XXYWlLSQ%G;SDN*T0UE|&ItwAG&0?Y zof=l$2C?XovIrmdZHx6HIlW40cWD7=H)*)ftX~8WBQCxqQC?DF4~$RsIR~xba=l*2 zOA*M^lYL%ZUP>}j$cLU>oInJ~`Gcm^;~OX$|I_`pm+2_ACL9y~d$5^KjpxeXy(e>D zz`1UMbEyTIg3g^SE;Ef^dov<=_lf!aTm4_YxJhQs-}`&1T`cpUpdjGXW<@lnq@<+k z^b3EI@?iprHZUr{z{C|t^7mEi74x+sKF22~d*>Ijoe;Vswf3D@PgcvE(P*oB!1w2W z>&m|j5%2(K^aEv939v|1ROn~S-dKoBsL$qm>YUesYZdh^$KUDk08S`h250U7X9mqT6jhC2CH2jx1N5#Svg$5q zxwz!ag&Z{>hO=`@a9@R_!olv51VVVxP=ifxdQVS}T(&Hun>Z6KDW<%`dN zfSFu^!|CYgK!s2RNQ4>-LOwXDSfTYG!s^Ft8EPWXjg1X2aRv~>I{W(ggrTjcCu_07 zw*Gvkt1^B<+Gc#=zF&vFx=rCvYC3dm1j@}@FA9V5KDUKW|9JzFYKKhn zQrP+9A&mgn*#*h=jI=w@Vs2sGdTyHjCjiD&^a^(ty*TPmckb00UVL43qR?a;MRN&q zPel`{k{fMPVci&T)5|w#PQBS>cuD$o&IkauX07np&DcCh|2k6jaavujFNu=~Kak~PMs1NI~bb|m|v$N7ql zEyZ=OmPLNlo;>&VQ6g3-o{q33Y`hwIJp^SqKYSe7_nq$e?NdpFG^JzM=_b+!^X$E4 z8g}zR;O9<9oz=cub59%EWRW+}`Hdvuq+VTf82O%h5uLz6nQiA%p@GPHc zIv%~ls7kNwjwP)Xcyu8;-QjO$bex)4WOaEc#BB!|%E@u;ne@>nK2Q?%%C%f&9tz?o z7jcV3TT(?dm7^!s<~`2aq>77jpR^=CSP>!;_6W?dd6~*FM*DT>ZSIIbcmhtBBVx4x zPVG>8o9y&kI8(-2OX8fy+le>)-Y4PbF~8?1oWGmU1BkZCrWuzf8!+&0$n-f=2H!0A znS+8m_C-PEE_>o<`_T#M=P240Stc1HkwpYt->z9mh@6JlQ$W>!pCXcVme!2c9!s7> zA07H!E_5*~`WmA_<^wc7;XU3E9c1o0Y3uD1=d_Gno8NMKzq5qf(`)%wD3*yjz27lr z*cPBxUq9cpBzS@ysCv$VD;yTzV zB4VmAm#5!(Jf6OT3b3FaX)djcXuv3?S zhCdC8hf>lis0NV^YQam)jY?GmKu73|I4aSu3*`u%|s#T6Tw6<8!*1?YnI<555` zv1{S|Ctt2Me_q1P>!7~Zc#T?R_y~NLvwr!op6-}^fzcZ&8t`8@l>kD#T6Bs2{g(N~G@4Ne?&5p>^-2Fm^x+o99O8Zlh! zz{9Xt->p-Qv3u9OCPWjP#TbK~#Ig+oA43Rlf+^D9)=^-X5y})quvTl~dR{q=UrXkH zO~@9qM-#k|7+;6wP+$AbM3;PnICWT#*x)knlFZrG^N(An*}MA9b}a`-eDh;ygx;(L zjC!-U{`Sg71)+}!PpEv~$8kVK7)f#jl05ENPKF51A%}q{zLGtoS89Cy_Ta_`_C4qP zg1AuSZ4Ev@l7}_6aSzJGj7%$7(J%+6oKAgfrpBPb;JX4S`SP`{yET9ENL!$?F?8WJ zT%XS*kIf!bR4Thl8ZSxajTy98t)1i!80U>F&-;*j2CT&@OF9!Pm?96S?`sqb#%J5A zv2d&Bctv&q>RdBkQ`|#QQ&XZUt8ayF|CF6?tlkhH^5dDgxcarWrs03EZu-_&&ehNi zH>%d7o?g~N-Pm)TFH3j4K6A{1-OT(c*v{6Y`*qFebotIQem@8-XHIv`N+8~(`F=8R z8O+;~2k2h@xsfz7+08L?gi8eqj(5|Jgvd!r0mtx@&IU%%&+hY2eOLGW+f}W8#RIo^4GN!yWU z8}X6-f|ImLtpQGA8nnE@faS714`YrncaclZNou%z{#;`^WyUtd;O)NRzWxIKYp4uF z<2RBp07Dg{+Rc3b5PX~MUr;o+wM8Sv!^?|@3IXt@Y=idesn9cCNlJqBgFap)2HZQp;7 z_|qk|K~?t_R-UP+8U1j?4_V4FbsJ>g2w3Jj33Jfd!MjI4xvR+Xd(%v%ewl)-xz$6N z^JQn({+=FBaR#CQ50DpZs&H3b^;?<|Nl78KK;{c>vd&OBJ>Xy+d)dhptas4QwSV3q zu<1!BPzXvoKt}@8@`|8R=9<(q-#r|Ch;)#DX9C+($dV(V@*=8m>XT{~^MdhnK94xF zPv=d}t8LJ3z?4jH-MU3D=0d8g&mKOkhJNxnJ}YZxdb(U1EEQo}Y6qw7$;i`3=DN=Q zP4i{$Vrpl;EV4Qif_0&3Drz}L$(xhdH2}5=RT~_-;Op0}Dx?j(12r#a4dReHehDT> z@(@q@dTVPNyb8_bs5uHp&iJZ%pSaej^I`_OR$F}_5Q7A-(?s=@+1A3@&cM-*z_`raImj{IjlbSL_Un$#3S33F#TN@=5xaSEHtn z775$!RvSw5t!G?8^JfG?80(MvmSQGm+Yd-z>1@#Lfry`P2QtCqaxa{g%4PkL5**$oFo`F&Pcd-u7D~$&D|h8tVL3gkP{E6bm~mkgqj5j5cWX( z6QHl2e!mtuM>?p*mt20Yk}f1KiK%Aq8O4*}xOp3VvoLULk_whke3M z)w$&RiSS#P{WawIHhCA-8>V;y;nOGi=ysuR+aRYa{I7U_4K;3r=}eI0^FPF`$hcGBbKaE8>D2F8D-8qIGz6+&1Ud zmi3e<-r+`mQLg3g_g<5Ba)>h1#cBRY3K&Z4SXMke-(dz45Y9Qp5#N;rY7QvL$p7ZU z9JfeG3yO+-Oq!tqD}`;L{-2KU{1J!M9z_JU_Ah;BH61me@H6<73i47K1XtJ&?@V(* zJtBeWHVro=mwVuzR*zLAeyO9*DYAKAe|?nKk0xH(39o`rr|kG8AJb#uyOiYvc87Ze zO=N0WdU`rAzPJTQp2LZY2t4jn$Y}}+8~VGO_-K{++~8o|H1*$lT;=Nex(VoFF@^Wv zJ6VhT18(Uw11+ndqHo)ri`(D(BIk+;YC>g&?r@47?xv@MK8IH?6Ss6B_b9Z$W!il9 zk9HQ;Mk{X4yiXg~?w30up2ftF77g7cEBLu+BA}lcM#sjAv`b_Y3IhE6A|>{vS>Jms zeLI|e)a32#>RLr82JfmEHfs2*z|ieEjGf4;n>g@ux_|-=^I!?V(roAZ=0VsBjMjQx zX{ic>yt^it5c*(3r2hJ^$OaJlGaN30PhsPr~rj?AbC}j3U6X6pU4U|CStaHUP+_ znV{;d=VF^u($I(-S~01yQMa-A&a9C`CeA=k8g8hsZxwtiZhigQgM7mcFv2l0Fw z50!fbEyN-jjIu%AfE^g9&)*EIA0vQ-nKp2=F=p1_!Qq* zj!d@Db4wrqsiyEzF|vy;lBs}}3}9B1M^?Gt`OVJ7g%1?ww*(%S>Xm`sHJ}JsiR1?PE|G9FfGUTS4aT~*qnJ7mUfSU8KXZ-$~Kacyln{7-H|t!PG5yQ znNYm2fE7^u)a+F*@a#P `stateOfCharge`)\ + https://www.laub-home.de/wiki/InfluxDB_2_Measurements_umbenennen (DE) + * Open InfluxDB 2 web interface (`http://:8086`) + * On 'DataExplorer' tab click on 'Script Editor' + * Replace `old`, `new` and the bucket name with your values. + ``` + from(bucket: "example-bucket") + |> range(start: 2021-11-21T00:00:00Z, stop: 2021-11-22T00:00:00Z) + |> filter(fn: (r) => r._measurement == "old") + |> set(key: "_measurement", value: "new") + |> to(bucket: "example-bucket") + ``` +3. Delete the old one (`stateOfCapacity`) + ```shell + # InfluxDB Host + INFLUXHOST=localhost + # openHAB Database + INFLUXDB=openhab_db + # InflusDB API Key + INFLUXDBAUTH="TkrV8yQ8adcwwwwedsiuhf5V1OhXasdfadfeGgtzsb_bfucYeHSeTID-JlB7AKBZjE47TCwf8w-jGCFzpChw==" + # Measurement to delete + MEASUREMENT="LaubIot07BME680_Temperature" + + curl -s --get http://$INFLUXHOST:8086/query?db=$INFLUXDB \ + --header "Authorization: Token $INFLUXDBAUTH" \ + --data-urlencode "q=DROP MEASUREMENT $MEASUREMENT" + ``` +4. Install new adapter. Write to new state diff --git a/src/lib/states.ts b/src/lib/states.ts index 29ac23d..bc8dcbd 100644 --- a/src/lib/states.ts +++ b/src/lib/states.ts @@ -157,7 +157,7 @@ export class InverterStates { }, { interval: UpdateIntervalID.HIGH, - state: {id: 'storage.stateOfCapacity', name: 'State of capacity', type: 'number', unit: '%', role: 'value.battery', desc: 'SOC'}, + state: {id: 'storage.stateOfCharge', name: 'State of charge', type: 'number', unit: '%', role: 'value.battery', desc: 'SOC'}, register: {reg: 37760, type: ModbusDatatype.uint16, length: 1, gain: 10} }, {