From 73a03971079425d5a0915a1fe1c27339ed2b78fc Mon Sep 17 00:00:00 2001
From: Christian Ehrlicher <ch.ehrlicher@gmx.de>
Date: Tue, 6 Sep 2022 17:48:46 +0200
Subject: [PATCH] RPI: be able to handle more than one inverter with the
 volkszaehler plugin

---
 tools/rpi/ahoy.yml.example    | 50 ++++++++++++++++----------------
 tools/rpi/hoymiles/outputs.py | 54 +++++++++++++++++++++++++----------
 2 files changed, 65 insertions(+), 39 deletions(-)

diff --git a/tools/rpi/ahoy.yml.example b/tools/rpi/ahoy.yml.example
index a7afb01c..644508e5 100644
--- a/tools/rpi/ahoy.yml.example
+++ b/tools/rpi/ahoy.yml.example
@@ -30,30 +30,32 @@ ahoy:
 
   volkszaehler:
     disabled: true
-    url: 'http://localhost/middleware/'
-    channels:
-      - type: 'temperature'
-        uid:  'ad578a40-1d97-11ed-8e8b-fda01a416575'
-      - type: 'frequency'
-        uid:  ''
-      - type: 'ac_power0'
-        uid:  '7ca5ac50-1e41-11ed-927f-610c4cb2c69e'
-      - type: 'ac_voltage0'
-        uid:  '9a38e2e0-1d94-11ed-b539-25f8607ac030'
-      - type: 'ac_current0'
-        uid:  'a9a4daf0-1e41-11ed-b68c-eb73eef3d21d'
-      - type: 'dc_power0'
-        uid:  '38eb3ca0-1e53-11ed-b830-792e70a592fa'
-      - type: 'dc_voltage0'
-        uid:  ''
-      - type: 'dc_current0'
-        uid:  ''
-      - type: 'dc_power1'
-        uid:  '51c0e9d0-1e53-11ed-b574-8bc81547eb8f'
-      - type: 'dc_voltage1'
-        uid:  ''
-      - type: 'dc_current1'
-        uid:  ''
+    inverters:
+      - serial: 114172220003
+        url: 'http://localhost/middleware/'
+        channels:
+          - type: 'temperature'
+            uid:  'ad578a40-1d97-11ed-8e8b-fda01a416575'
+          - type: 'frequency'
+            uid:  ''
+          - type: 'ac_power0'
+            uid:  '7ca5ac50-1e41-11ed-927f-610c4cb2c69e'
+          - type: 'ac_voltage0'
+            uid:  '9a38e2e0-1d94-11ed-b539-25f8607ac030'
+          - type: 'ac_current0'
+            uid:  'a9a4daf0-1e41-11ed-b68c-eb73eef3d21d'
+          - type: 'dc_power0'
+            uid:  '38eb3ca0-1e53-11ed-b830-792e70a592fa'
+          - type: 'dc_voltage0'
+            uid:  ''
+          - type: 'dc_current0'
+            uid:  ''
+          - type: 'dc_power1'
+            uid:  '51c0e9d0-1e53-11ed-b574-8bc81547eb8f'
+          - type: 'dc_voltage1'
+            uid:  ''
+          - type: 'dc_current1'
+            uid:  ''
 
   dtu:
     serial: 99978563001
diff --git a/tools/rpi/hoymiles/outputs.py b/tools/rpi/hoymiles/outputs.py
index a0bfdfef..a6f798ee 100644
--- a/tools/rpi/hoymiles/outputs.py
+++ b/tools/rpi/hoymiles/outputs.py
@@ -208,14 +208,10 @@ try:
 except ModuleNotFoundError:
     pass
 
-class VolkszaehlerOutputPlugin(OutputPluginFactory):
-    def __init__(self, config, **params):
-        """
-        Initialize VolkszaehlerOutputPlugin
-        """
-        super().__init__(**params)
-
-        self.session = requests.Session()
+class VzInverterOutput:
+    def __init__(self, config, session):
+        self.session = session
+        self.serial = config.get('serial')
         self.baseurl = config.get('url', 'http://localhost/middleware/')
         self.channels = dict()
         for channel in config.get('channels', []):
@@ -224,7 +220,7 @@ class VolkszaehlerOutputPlugin(OutputPluginFactory):
             if uid and ctype:
                 self.channels[ctype] = uid
 
-    def store_status(self, response, **params):
+    def store_status(self, data, session):
         """
         Publish StatusResponse object
 
@@ -232,15 +228,9 @@ class VolkszaehlerOutputPlugin(OutputPluginFactory):
 
         :raises ValueError: when response is not instance of StatusResponse
         """
-
-        if not isinstance(response, StatusResponse):
-            raise ValueError('Data needs to be instance of StatusResponse')
-
         if len(self.channels) == 0:
             return
 
-        data = response.__dict__()
-
         ts = int(round(data['time'].timestamp() * 1000))
 
         # AC Data
@@ -277,3 +267,37 @@ class VolkszaehlerOutputPlugin(OutputPluginFactory):
                 raise ValueError('Could not send request (%s)' % url)
         except ConnectionError as e:
             raise ValueError('Could not send request (%s)' % e)
+
+class VolkszaehlerOutputPlugin(OutputPluginFactory):
+    def __init__(self, config, **params):
+        """
+        Initialize VolkszaehlerOutputPlugin
+        """
+        super().__init__(**params)
+
+        self.session = requests.Session()
+        self.inverters = dict()
+        for inverterconfig in config.get('inverters', []):
+            serial = inverterconfig.get('serial')
+            output = VzInverterOutput(inverterconfig, self.session)
+            self.inverters[serial] = output
+
+    def store_status(self, response, **params):
+        """
+        Publish StatusResponse object
+
+        :param hoymiles.decoders.StatusResponse response: StatusResponse object
+
+        :raises ValueError: when response is not instance of StatusResponse
+        """
+        if not isinstance(response, StatusResponse):
+            raise ValueError('Data needs to be instance of StatusResponse')
+
+        if len(self.inverters) == 0:
+            return
+
+        data = response.__dict__()
+        serial = data["inverter_ser"]
+        if serial in self.inverters:
+            output = self.inverters[serial]
+            output.store_status(data, self.session)