BorisBrock / Sunalyzer

A free and open source solar monitoring system.
MIT License
35 stars 6 forks source link

Grabber failure for Fronius system #79

Closed n9yty closed 1 week ago

n9yty commented 2 weeks ago

I was excited to find this. Trying it out with my new Fronius Primo inverter:

2024-08-29 21:01:04 INFO     Starting Sunalyzer grabber version 0.31.0
2024-08-29 21:01:04 INFO     Grabber: Reading backend configuration from config.yml
2024-08-29 21:01:04 INFO     Verbose logging is enabled
2024-08-29 21:01:04 INFO     Grabber: Setting tme zone to Amiercas/Chicago
2024-08-29 21:01:04 INFO     Grabber: Time is now 21:01:04 08/29/24 Amiercas
2024-08-29 21:01:04 INFO     Grabber: Loading device adapter 'Fronius'
2024-08-29 21:01:04 INFO     Fronius device: configured host name is x.x.x.x
2024-08-29 21:01:04 DEBUG    Starting new HTTP connection (1): x.x.x.x:80
2024-08-29 21:01:04 DEBUG    http://x.x.x.x:80 "GET /solar_api/v1/GetPowerFlowRealtimeData.fcgi HTTP/11" 200 923
2024-08-29 21:01:04 DEBUG    Starting new HTTP connection (1): x.x.x.x:80
2024-08-29 21:01:04 DEBUG    http://x.x.x.x:80 "GET /solar_api/v1/GetMeterRealtimeData.cgi?Scope=System HTTP/11" 200 310
2024-08-29 21:01:04 ERROR    Fronius device: Error: connecting to the device failed
2024-08-29 21:01:04 ERROR    creating the device adapter failed
Traceback (most recent call last):
  File "//backend/grabber.py", line 373, in main
    device = load_device_plugin(device_name)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "//backend/grabber.py", line 219, in load_device_plugin
    device = class_(config)
             ^^^^^^^^^^^^^^
  File "/backend/devices/Fronius.py", line 31, in __init__
    self.update()
  File "/backend/devices/Fronius.py", line 105, in update
    self.copy_data(r_inverter.json(), r_meter.json())
  File "/backend/devices/Fronius.py", line 43, in copy_data
    str_total_consumed_from_grid_wh = meter_data["Body"]["Data"]["0"]["EnergyReal_WAC_Plus_Absolute"]
                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
KeyError: '0'

This is similar to what I saw when I tried the fronius-json-tools python script I found.

I noticed it also had:

Traceback (most recent call last):
  File "/home/plex/fronius/fronius-json-tools-master/./livedata2db.py", line 59, in <module>
    data['meter_timestamp2'] = meter_data['Body']['Data']['0']['TimeStamp']
KeyError: '0'

If I hit the URL directly I get this:

{
   "Body" : {
      "Data" : {}
   },
   "Head" : {
      "RequestArguments" : {
         "DeviceClass" : "Meter",
         "Scope" : "System"
      },
      "Status" : {
         "Code" : 0,
         "Reason" : "",
         "UserMessage" : ""
      },
      "Timestamp" : "2024-08-29T16:09:28-05:00"
   }
}

Is the data in a different format? Is something not set up right in the Fronius to return the data properly? I'd love to work through this and help get it supported if possible.

n9yty commented 2 weeks ago

Ah, I don't have a Fronius Smart Meter, so the Meter Data is coming back empty. Perhaps this needs to be accounted for in the code? It doesn't seem there is a configuration option that would handle this.

The inverter data looks like this:

{
   "Body" : {
      "Data" : {
         "DAY_ENERGY" : {
            "Unit" : "Wh",
            "Values" : {
               "1" : 32820
            }
         },
         "PAC" : {
            "Unit" : "W",
            "Values" : {
               "1" : 5324
            }
         },
         "TOTAL_ENERGY" : {
            "Unit" : "Wh",
            "Values" : {
               "1" : 49680
            }
         },
         "YEAR_ENERGY" : {
            "Unit" : "Wh",
            "Values" : {
               "1" : 49680
            }
         }
      }
   },
   "Head" : {
      "RequestArguments" : {
         "DeviceClass" : "Inverter",
         "Scope" : "System"
      },
      "Status" : {
         "Code" : 0,
         "Reason" : "",
         "UserMessage" : ""
      },
      "Timestamp" : "2024-08-29T16:14:13-05:00"
   }
}
n9yty commented 2 weeks ago

Yes, this was it. I just cut out that section and hardcoded them to zeroes, but probably something better could be done?

Changes in backend/devices/Fronius.py:

         # Meter data
-        str_total_consumed_from_grid_wh = meter_data["Body"]["Data"]["0"]["EnergyReal_WAC_Plus_Absolute"]
-        total_consumed_from_grid_kwh = float(
-            str_total_consumed_from_grid_wh) * 0.001
-        str_total_fed_in_wh = meter_data["Body"]["Data"]["0"]["EnergyReal_WAC_Minus_Absolute"]
-        total_fed_in_kwh = float(str_total_fed_in_wh) * 0.001
+        if ( len(meter_data["Body"]["Data"]) > 0 ):
+            str_total_consumed_from_grid_wh = meter_data["Body"]["Data"]["0"]["EnergyReal_WAC_Plus_Absolute"]
+            total_consumed_from_grid_kwh = float(
+                str_total_consumed_from_grid_wh) * 0.001
+            str_total_fed_in_wh = meter_data["Body"]["Data"]["0"]["EnergyReal_WAC_Minus_Absolute"]
+            total_fed_in_kwh = float(str_total_fed_in_wh) * 0.001
+        else:
+            str_total_consumed_from_grid_wh = 0
+            total_consumed_from_grid_kwh = 0
+            str_total_fed_in_wh = 0
+            total_fed_in_kwh = 0

and I ran into one more error solved by this in the same file:

-        str_grid_power_w = inverter_data["Body"]["Data"]["Site"]["P_Grid"]
+        str_grid_power_w = inverter_data["Body"]["Data"]["Site"]["P_Grid"] or 0

Now it is running and capturing the data. Yes, it is only half the picture, but it is all of the picture that I have. :)

BorisBrock commented 2 weeks ago

Hi, when I designed this project, I had my own setup consisting of a Fronius inverter + smart meter in mind. But you're right: it would be nice to disable the smart meter part with a simple config switch, in case only an inverter is present.

I'll add that to my todo list, but of course a pull request would be welcome as well ;-)

n9yty commented 2 weeks ago

I would also love to see that currently pending pull request accepted, as I do have an Emporia monitor that could perhaps provide at least total usage to help see the difference between consumption and usage. Being able to define multiple devices as that patch allows would be great. In fact, then it might even be worth defining the Fronius device as two devices, the inverter and the meter and then a user would configure based on what they have.