From a463012f8dcdb538e9c5d7adca9c94adeaba8b74 Mon Sep 17 00:00:00 2001 From: Christof Musik Date: Tue, 12 Mar 2024 09:57:59 +0100 Subject: [PATCH] Huawei Smartlogger: add battery control similar to dongle configuration (#12877) This is v2 of the configuration. The main difference is that it is mostly backward compatible to the old smartlogger configuration. The only change is that it is now using register 40521 (active power without battery discharge) instead of 40525 (active power including battery discharge). The grid information comes from the powermeter which has usually the unit id 11. The pv informations come directly from smartlogger (unit id 0, hardcoded). The battery information is fetched from the hybrid inverter. A typical configuration should look like this: ``` meters: - name: grid type: template template: huawei-smartlogger usage: grid id: 11 host: host.fqdn port: 502 - name: pv type: template template: huawei-smartlogger usage: pv host: host.fqdn port: 502 - name: battery type: template template: huawei-smartlogger usage: battery id: 3 host: host.fqdn port: 502 capacity: 10 ``` --- .../definition/meter/huawei-smartlogger.yaml | 217 +++++++++++++++++- util/modbus/register.go | 2 + 2 files changed, 214 insertions(+), 5 deletions(-) diff --git a/templates/definition/meter/huawei-smartlogger.yaml b/templates/definition/meter/huawei-smartlogger.yaml index 29ee92896..bb48fb11f 100644 --- a/templates/definition/meter/huawei-smartlogger.yaml +++ b/templates/definition/meter/huawei-smartlogger.yaml @@ -5,19 +5,73 @@ products: generic: SmartLogger params: - name: usage - choice: ["pv"] - - name: host - - name: port - default: 502 + choice: ["grid", "pv", "battery"] + allinone: true + - name: storageunit + type: number + default: 1 + advanced: true + - name: modbus + choice: ["tcpip"] + - name: timeout + default: 15s + - name: capacity + advanced: true render: | type: custom + {{- if eq .usage "grid" }} + power: + source: modbus + {{- include "modbus" . | indent 2 }} + timeout: {{ .timeout }} + connectdelay: 1s + register: + address: 32278 # Active power + type: holding + decode: int32 + scale: 1 + energy: + source: modbus + {{- include "modbus" . | indent 2 }} + timeout: {{ .timeout }} + register: + address: 32349 # Negative active electricity + type: holding + decode: int64 + scale: 0.01 + currents: + - source: modbus + {{- include "modbus" . | indent 2 }} + timeout: {{ .timeout }} + register: + address: 32272 # Huawei phase A grid current + type: holding + decode: int32 + scale: 0.1 + - source: modbus + {{- include "modbus" . | indent 2 }} + timeout: {{ .timeout }} + register: + address: 32274 # Huawei phase B grid current + type: holding + decode: int32 + scale: 0.1 + - source: modbus + {{- include "modbus" . | indent 2 }} + timeout: {{ .timeout }} + register: + address: 32276 # Huawei phase C grid current + type: holding + decode: int32 + scale: 0.1 + {{- end }} {{- if eq .usage "pv" }} power: source: modbus id: 0 uri: {{ .host }}:{{ .port }} register: - address: 40525 # Active power + address: 40521 # Active power type: holding decode: int32 energy: @@ -30,3 +84,156 @@ render: | decode: uint32 scale: 0.1 {{- end }} + {{- if eq .usage "battery" }} + power: + source: modbus + {{- include "modbus" . | indent 2 }} + timeout: {{ .timeout }} + connectdelay: 1s + register: + {{- if eq .storageunit "1" }} + address: 37001 + {{- end }} + {{- if eq .storageunit "2" }} + address: 37743 + {{- end }} + type: holding + decode: int32nan + scale: -1 + energy: + source: modbus + {{- include "modbus" . | indent 2 }} + timeout: {{ .timeout }} + register: + {{- if eq .storageunit "1" }} + address: 37068 # [Energy storage unit 1] Total discharge + {{- end }} + {{- if eq .storageunit "2" }} + address: 37755 # [Energy storage unit 2] Total discharge + {{- end }} + type: holding + decode: uint32nan + scale: 0.01 + soc: + source: modbus + {{- include "modbus" . | indent 2 }} + timeout: {{ .timeout }} + register: + {{- if eq .storageunit "1" }} + address: 37004 + {{- end }} + {{- if eq .storageunit "2" }} + address: 37738 + {{- end }} + type: holding + decode: uint16nan + scale: 0.1 + batterymode: + source: watchdog + timeout: 30s + reset: 1 # reset watchdog on normal + set: + source: switch + switch: + - case: 1 # normal + set: + source: const + value: 0 # stop + set: + source: modbus + {{- include "modbus" . | indent 10 }} + register: + address: 47100 # Forcible charge/discharge + type: writesingle + encoding: uint16 + - case: 2 # hold + set: + source: sequence + set: + - source: const + value: 2 # discharge + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47100 # Forcible charge/discharge + type: writesingle + encoding: uint16 + - source: const + value: 0 # duration + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47246 # Forcible charge/discharge setting mode + type: writesingle + encoding: uint16 + - source: const + value: 1 # Minute + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47083 # Forced charging and discharging period + type: writesingle + encoding: uint16 + - source: const + value: 0 # W + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47249 # Forcible discharge power + type: writemultiple + encoding: uint32 + - case: 3 # charge + set: + source: sequence + set: + - source: const + value: 1 # charge + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47100 # Forcible charge/discharge + type: writesingle + encoding: uint16 + - source: const + value: 0 # duration + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47246 # Forcible charge/discharge setting mode + type: writesingle + encoding: uint16 + - source: const + value: 1 # Minute + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47083 # Forced charging and discharging period + type: writesingle + encoding: uint16 + - source: const + value: 2500 # W + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47247 # Forcible charge power + type: writemultiple + encoding: uint32 + - source: const + value: 1 # Enable + set: + source: modbus + {{- include "modbus" . | indent 12 }} + register: + address: 47087 # Charge from grid + type: writemultiple + encoding: uint32 + capacity: {{ .capacity }} # kWh + {{- end }} diff --git a/util/modbus/register.go b/util/modbus/register.go index f857f846d..8a5cbcc09 100644 --- a/util/modbus/register.go +++ b/util/modbus/register.go @@ -115,6 +115,8 @@ func (r Register) DecodeFunc() (func([]byte) float64, error) { return asFloat64(encoding.Float32LswFirst), nil // 64 bit + case "int64": + return asFloat64(encoding.Int64), nil case "uint64": return asFloat64(encoding.Uint64), nil case "uint64nan":