Skip to content

Commit 66d92c4

Browse files
authored
Merge pull request #13 from JasperE84/dev
v1.0.6 fixes faulty config parsing of cron values and adds more descriptive exception messages when kiosk api query fails
2 parents eb1d012 + 55ad5ff commit 66d92c4

File tree

6 files changed

+101
-72
lines changed

6 files changed

+101
-72
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ Result:
122122
# Changelog
123123
| Version | Description |
124124
| --- | --- |
125+
| 1.0.5 | Fixed a bug parsing the environment cron settings, which are in string format, but were interpreted as int, causing an exception |
126+
| 1.0.5 | FusionSolar API will now immediately be queried on startup if debug mode is enabled (so no waiting for cron to trigger is required for testing) |
125127
| 1.0.5 | Added InfluxDB support for an optional secondary grid telemetry EAN configuration (pvoutput output is only supported on the primary EAN) |
126128
| 1.0.5 | Bugfix for InfluxDB v1 implementation and removed auto-database creation for VictoriaMetrics compatibility |
127129
| 1.0.3 | Grid transformer usage measurement polling from Kenter's meetdata.nl API has been implemented |

gridrelay.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,27 @@ def __init__(self, conf: PvConf, logger):
2424
def start(self):
2525
self.logger.debug("GridRelay waiting 5sec to initialize docker-compose containers")
2626
time.sleep(5)
27+
28+
daystobackfill = self.conf.gridrelaydaystobackfill
2729

2830
while 1:
2931
try:
30-
grid_measurement_data = self.gridkenter.fetch_gridkenter_data(self.conf.gridrelaysysname, self.conf.gridrelaykenterean, self.conf.gridrelaykentermeterid, self.conf.gridrelaydaysback)
31-
self.write_gridkenter_to_influxdb(grid_measurement_data)
32-
self.write_gridkenter_to_pvoutput(grid_measurement_data)
33-
34-
if self.conf.gridrelaysys02enabled:
35-
grid_measurement_data = self.gridkenter.fetch_gridkenter_data(self.conf.gridrelaysysname02, self.conf.gridrelaykenterean02, self.conf.gridrelaykentermeterid02, self.conf.gridrelaydaysback)
32+
for daysback in range(self.conf.gridrelaydaysback, self.conf.gridrelaydaysback + 1 + daystobackfill):
33+
grid_measurement_data = self.gridkenter.fetch_gridkenter_data(self.conf.gridrelaysysname, self.conf.gridrelaykenterean, self.conf.gridrelaykentermeterid, daysback)
3634
self.write_gridkenter_to_influxdb(grid_measurement_data)
37-
#No support for pvoutput on 2 EAN codes yet (needs summing of kenter data or pvoutput support for 2 distinct systems)
38-
#self.write_gridkenter_to_pvoutput(grid_measurement_data)
35+
self.write_gridkenter_to_pvoutput(grid_measurement_data)
36+
37+
if self.conf.gridrelaysys02enabled:
38+
grid_measurement_data = self.gridkenter.fetch_gridkenter_data(self.conf.gridrelaysysname02, self.conf.gridrelaykenterean02, self.conf.gridrelaykentermeterid02, daysback)
39+
self.write_gridkenter_to_influxdb(grid_measurement_data)
40+
#No support for pvoutput on 2 EAN codes yet (needs summing of kenter data or pvoutput support for 2 distinct systems)
41+
#self.write_gridkenter_to_pvoutput(grid_measurement_data)
42+
43+
# Wait 5 secs for next backfill day
44+
if daystobackfill > 0: time.sleep(5);
3945

46+
# Don't backfill after initial backfill
47+
daystobackfill = 0
4048
except:
4149
self.logger.exception(
4250
"Uncaught exception in GridRelay data processing loop."

pv.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
1414
streamHandler.setFormatter(formatter)
1515
logger.addHandler(streamHandler)
16-
logger.info("PyFusionSolarDataRelay 1.0.5 started")
16+
logger.info("PyFusionSolarDataRelay 1.0.6 started")
1717

1818
# Config
1919
conf = PvConf(logger)

pvconf.py

Lines changed: 62 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ def apply_default_settings(self):
3939
self.gridrelaykenterpasswd = "passwd"
4040
# Grid infrastructure measurements in The Netherlands, show up in the API with a 3-5 days delay.
4141
self.gridrelaydaysback = 3
42+
# Setting this to 30 would try to backfill gridkenter data on startup for any day between 3 days back (gridrelaydaysback) and 3+30=33 days back.
43+
self.gridrelaydaystobackfill = 0
4244
# If fusionsolar updates every 30mins and meetdata.nl has values per 15min, set this to 2 so that intervals between two datasources match to avoid weird pvoutput graphs.
4345
self.gridrelaypvoutputspan = 2
4446

@@ -79,63 +81,6 @@ def apply_default_settings(self):
7981
self.mqttpasswd = "fusionsolar"
8082
self.mqtttopic = "energy/pyfusionsolar"
8183

82-
def print(self):
83-
self.logger.info(f"Current settings:")
84-
self.logger.info(f"_Generic:")
85-
self.logger.info(f"debug: {self.debug}")
86-
self.logger.info(f"_FusionSolar:")
87-
self.logger.info(f"enabled: {self.fusionsolar}")
88-
self.logger.info(f"fusionsolarurl: {self.fusionsolarurl}")
89-
self.logger.info(f"fusionsolarkkid: {self.fusionsolarkkid}")
90-
self.logger.info(f"sysname: {self.pvsysname}")
91-
self.logger.info(f"fusionhourcron: {self.fusionhourcron}")
92-
self.logger.info(f"fusionminutecron: {self.fusionminutecron}")
93-
self.logger.info(f"_Influxdb:")
94-
self.logger.info(f"influx: {self.influx}")
95-
self.logger.info(f"influx2: {self.influx2}")
96-
self.logger.info(f"host: {self.ifhost}")
97-
self.logger.info(f"port: {self.ifport}")
98-
self.logger.info(f"_Influxdb_v1:")
99-
self.logger.info(f"database: {self.if1dbname}")
100-
self.logger.info(f"user: {self.if1user}")
101-
self.logger.info(f"password: **secret**")
102-
self.logger.info(f"_Influxdb_v2:")
103-
self.logger.info(f"protocol: {self.if2protocol}")
104-
self.logger.info(f"organization: {self.if2org}")
105-
self.logger.info(f"bucket: {self.if2bucket}")
106-
self.logger.info(f"token: {self.if2token}")
107-
self.logger.info(f"_PVOutput.org:")
108-
self.logger.info(f"Enabled: {self.pvoutput}")
109-
self.logger.info(f"System ID: {self.pvoutputsystemid}")
110-
self.logger.info(f"API Key: {self.pvoutputapikey}")
111-
self.logger.info(f"API Url: {self.pvoutputurl}")
112-
self.logger.info(f"API BatchUrl: {self.pvoutputbatchurl}")
113-
self.logger.info(f"_MQTT")
114-
self.logger.info(f"Enabled: {self.mqtt}")
115-
self.logger.info(f"Host: {self.mqtthost}")
116-
self.logger.info(f"Port: {self.mqttport}")
117-
self.logger.info(f"Auth: {self.mqttauth}")
118-
self.logger.info(f"User: {self.mqttuser}")
119-
self.logger.info(f"Passwd: {self.mqttpasswd}")
120-
self.logger.info(f"Topic: {self.mqtttopic}")
121-
self.logger.info(f"_GridRelay")
122-
self.logger.info(f"Enabled: {self.gridrelay}")
123-
self.logger.info(f"Interval: {self.gridrelayinterval}")
124-
self.logger.info(f"PVOutput span: {self.gridrelaypvoutputspan}")
125-
self.logger.info(f"Kenter URL: {self.gridrelaykenterurl}")
126-
self.logger.info(f"Days back: {self.gridrelaydaysback}")
127-
self.logger.info(f"Kenter User: {self.gridrelaykenteruser}")
128-
self.logger.info(f"Kenter Passwd: {self.gridrelaykenterpasswd}")
129-
130-
self.logger.info(f"System name 01: {self.gridrelaysysname}")
131-
self.logger.info(f"Kenter EAN 01: {self.gridrelaykenterean}")
132-
self.logger.info(f"Kenter MeterId 01: {self.gridrelaykentermeterid}")
133-
134-
self.logger.info(f"System name 02: {self.gridrelaysysname02}")
135-
self.logger.info(f"Kenter EAN 02: {self.gridrelaykenterean02}")
136-
self.logger.info(f"Kenter MeterId: {self.gridrelaykentermeterid02}")
137-
138-
13984
def getenv(self, envvar):
14085
envval = os.getenv(envvar)
14186
self.logger.debug(f"Pulled '{envvar}={envval}' from the environment")
@@ -154,9 +99,9 @@ def apply_environment_settings(self):
15499
if os.getenv("pvsysname") != None:
155100
self.pvsysname = self.getenv("pvsysname")
156101
if os.getenv("pvfusionhourcron") != None:
157-
self.fusionhourcron = int(self.getenv("pvfusionhourcron"))
102+
self.fusionhourcron = self.getenv("pvfusionhourcron")
158103
if os.getenv("pvfusionminutecron") != None:
159-
self.fusionminutecron = int(self.getenv("pvfusionminutecron"))
104+
self.fusionminutecron = self.getenv("pvfusionminutecron")
160105
if os.getenv("pvinflux") != None:
161106
self.influx = self.getenv("pvinflux") == "True"
162107
if os.getenv("pvinflux2") != None:
@@ -218,6 +163,8 @@ def apply_environment_settings(self):
218163
self.gridrelaykenterpasswd = self.getenv("pvgridrelaykenterpasswd")
219164
if os.getenv("pvgridrelaydaysback") != None:
220165
self.gridrelaydaysback = int(self.getenv("pvgridrelaydaysback"))
166+
if os.getenv("pvgridrelaydaystobackfill") != None:
167+
self.gridrelaydaystobackfill = int(self.getenv("pvgridrelaydaystobackfill"))
221168
if os.getenv("pvgridrelaypvoutputspan") != None:
222169
self.gridrelaypvoutputspan = int(self.getenv("pvgridrelaypvoutputspan"))
223170

@@ -237,3 +184,59 @@ def apply_environment_settings(self):
237184
if os.getenv("pvgridrelaykentermeterid02") != None:
238185
self.gridrelaykentermeterid02 = self.getenv("pvgridrelaykentermeterid02")
239186

187+
def print(self):
188+
self.logger.info(f"Current settings:")
189+
self.logger.info(f"_Generic:")
190+
self.logger.info(f"debug: {self.debug}")
191+
self.logger.info(f"_FusionSolar:")
192+
self.logger.info(f"enabled: {self.fusionsolar}")
193+
self.logger.info(f"fusionsolarurl: {self.fusionsolarurl}")
194+
self.logger.info(f"fusionsolarkkid: {self.fusionsolarkkid}")
195+
self.logger.info(f"sysname: {self.pvsysname}")
196+
self.logger.info(f"fusionhourcron: {self.fusionhourcron}")
197+
self.logger.info(f"fusionminutecron: {self.fusionminutecron}")
198+
self.logger.info(f"_Influxdb:")
199+
self.logger.info(f"influx: {self.influx}")
200+
self.logger.info(f"influx2: {self.influx2}")
201+
self.logger.info(f"host: {self.ifhost}")
202+
self.logger.info(f"port: {self.ifport}")
203+
self.logger.info(f"_Influxdb_v1:")
204+
self.logger.info(f"database: {self.if1dbname}")
205+
self.logger.info(f"user: {self.if1user}")
206+
self.logger.info(f"password: **secret**")
207+
self.logger.info(f"_Influxdb_v2:")
208+
self.logger.info(f"protocol: {self.if2protocol}")
209+
self.logger.info(f"organization: {self.if2org}")
210+
self.logger.info(f"bucket: {self.if2bucket}")
211+
self.logger.info(f"token: {self.if2token}")
212+
self.logger.info(f"_PVOutput.org:")
213+
self.logger.info(f"Enabled: {self.pvoutput}")
214+
self.logger.info(f"System ID: {self.pvoutputsystemid}")
215+
self.logger.info(f"API Key: {self.pvoutputapikey}")
216+
self.logger.info(f"API Url: {self.pvoutputurl}")
217+
self.logger.info(f"API BatchUrl: {self.pvoutputbatchurl}")
218+
self.logger.info(f"_MQTT")
219+
self.logger.info(f"Enabled: {self.mqtt}")
220+
self.logger.info(f"Host: {self.mqtthost}")
221+
self.logger.info(f"Port: {self.mqttport}")
222+
self.logger.info(f"Auth: {self.mqttauth}")
223+
self.logger.info(f"User: {self.mqttuser}")
224+
self.logger.info(f"Passwd: {self.mqttpasswd}")
225+
self.logger.info(f"Topic: {self.mqtttopic}")
226+
self.logger.info(f"_GridRelay")
227+
self.logger.info(f"Enabled: {self.gridrelay}")
228+
self.logger.info(f"Interval: {self.gridrelayinterval}")
229+
self.logger.info(f"PVOutput span: {self.gridrelaypvoutputspan}")
230+
self.logger.info(f"Kenter URL: {self.gridrelaykenterurl}")
231+
self.logger.info(f"Days back: {self.gridrelaydaysback}")
232+
self.logger.info(f"Days to backfill: {self.gridrelaydaystobackfill}")
233+
self.logger.info(f"Kenter User: {self.gridrelaykenteruser}")
234+
self.logger.info(f"Kenter Passwd: {self.gridrelaykenterpasswd}")
235+
236+
self.logger.info(f"System name 01: {self.gridrelaysysname}")
237+
self.logger.info(f"Kenter EAN 01: {self.gridrelaykenterean}")
238+
self.logger.info(f"Kenter MeterId 01: {self.gridrelaykentermeterid}")
239+
240+
self.logger.info(f"System name 02: {self.gridrelaysysname02}")
241+
self.logger.info(f"Kenter EAN 02: {self.gridrelaykenterean02}")
242+
self.logger.info(f"Kenter MeterId: {self.gridrelaykentermeterid02}")

pvfusionsolar.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,25 @@ def fetch_fusionsolar_status(self):
2222
)
2323
except Exception as e:
2424
raise Exception(
25-
"Error fetching data from FusionSolar Kiosk API: '{}'".format(str(e))
25+
"Error fetching data from FusionSolar Kiosk API: '{}'".format(
26+
str(e).replace('\n', '')
27+
)
2628
)
2729

2830
try:
2931
response_json = response.json()
3032
except Exception as e:
33+
content = response.content.decode("utf-8")
34+
if content:
35+
content_first_100 = content[:200]
36+
else:
37+
content_first_100 = ""
38+
3139
raise Exception(
32-
"Error while parsing JSON response from Kiosk API: '{}'".format(str(e))
40+
"Error while decoding the JSON Kiosk API response, did you set the right fusionsolarurl and fusionsolarkkid in your conf? Kiosk link still working?: '{}', raw JSON content: '{}'".format(
41+
str(e).replace('\n', ''),
42+
content_first_100.replace('\n', '')
43+
)
3344
)
3445

3546
if not "data" in response_json:
@@ -42,8 +53,9 @@ def fetch_fusionsolar_status(self):
4253
response_json_data = json.loads(response_json_data_decoded)
4354
except Exception as e:
4455
raise Exception(
45-
"Error while parsing JSON response data element from FusionSolar Kiosk API: '{}'".format(
46-
str(e)
56+
"Error while parsing JSON response data element from FusionSolar Kiosk API: '{}' Data element content from FusionSolar API: {}".format(
57+
str(e).replace('\n', ''),
58+
response_json["data"]
4759
)
4860
)
4961

pvrelay.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ def __init__(self, conf: PvConf, logger):
2525
self.logger.debug("PvRelay waiting 5sec to initialize docker-compose containers")
2626
time.sleep(5)
2727

28+
if self.conf.debug:
29+
self.logger.info("Starting process_fusionsolar_request() at init, before waiting for cron, because we're in debug mode")
30+
self.process_fusionsolar_request()
31+
2832
sched = BlockingScheduler(standalone = True)
2933
sched.add_job(self.process_fusionsolar_request, trigger='cron', hour=self.conf.fusionhourcron, minute=self.conf.fusionminutecron)
3034
sched.start()

0 commit comments

Comments
 (0)