Files
solaredge_modbus_mqtt/solaredge_modbus_mqtt.py
T
Marijn Koesen debf01e220 Read all registers at once
When you read the registers one-by-one, which is what the solaredge_mobus
library is doing, you run into the issue where the value and the scale
are sometimes out of sync.

This happens mostly when the values go up or down a lot, like at the
beginning and at the end of the day. At these times the SolarEdge
inverter can change the scale of the values it's returning.

When you read the value register, the scale might be -2, but in the
time between that request, and the request for the scale, the inverter
has changed the scale to -3. So in the next register read, you will get
-3 for the scale, but have a value in the scale of -2. Now when you do
the value calculation, you end up with a factor 10 difference.

So it's better, and also _much_ faster to read out all the registers
at once and then parse the values from this bigger read out.

I'm planning to do a MR back to solaredge_modbus with this change, so
for now i've just included that code into this project.
2020-06-06 18:40:00 +02:00

78 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import json
import os
import solaredge_modbus
import sys
import time
import paho.mqtt.client as mqtt
import yaml
from solaredge_modbus_mqtt import SolarData
from solaredge_modbus_mqtt import MyInverter
from pymodbus.exceptions import ConnectionException
if __name__ == '__main__':
argparser = argparse.ArgumentParser()
argparser.add_argument('--config', type=str, default=os.environ.get('CONFIG_FILE', 'config.yaml'), help='Path to the config.yaml')
args = argparser.parse_args()
with open(args.config, 'r') as stream:
try:
config = yaml.safe_load(stream)
except yaml.YAMLError as exc:
print(exc)
try:
mqtt = mqtt.Client(client_id='', clean_session=True, userdata=None, protocol=mqtt.MQTTv311, transport='tcp')
mqtt.username_pw_set(config['mqtt']['user'], config['mqtt']['pass'])
mqtt.connect(config['mqtt']['host'], config['mqtt']['port'], 60)
except OSError as err:
print('Cannot connect to MQTT on {0}:{1}, error: {2}'.format(config['mqtt']['host'], config['mqtt']['port'], err))
sys.exit(1)
inverter = MyInverter(
host=config['modbus']['host'],
port=config['modbus']['port'],
timeout=config['modbus']['timeout'],
unit=config['modbus']['unit']
)
run = True
publishedAutoDiscovery = False
while run:
try:
raw = inverter.read()
solar_data = SolarData(raw)
except ConnectionException as err:
print('Cannot connect to SolarEdge Modbus server on {0}:{1}, error: {2}'.format(config['modbus']['host'], config['modbus']['port'], err))
sys.exit(2)
mqtt.loop()
if (publishedAutoDiscovery == False):
for k, v in solar_data.data.items():
message = {
'name': 'SolarEdge ' + k.replace('_', ' ').title(),
'unique_id': 'solaredge_' + k,
'unit_of_measurement': SolarData.fields[k]['unit'] if 'unit' in SolarData.fields[k] else '',
'state_topic': config['mqtt']['state_topic'] + '/' + k,
'force_update': 'True',
'device': {
'identifiers': ['solaredge_inverter'],
'name': 'SolarEdge Inverter'
}
}
mqtt.publish(
config['mqtt']['auto_discovery_topic'] + '/' + str(k) + '/config',
json.dumps(message),
qos=0,
retain=True
)
publishedAutoDiscovery = True
for k, v in solar_data.data.items():
mqtt.publish(config['mqtt']['state_topic'] + '/' + k, payload=str(v), qos=0, retain=False)
time.sleep(config['poll_interval'])