-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Hans IJntema
committed
Mar 5, 2022
1 parent
a98b1fb
commit 128818d
Showing
4 changed files
with
409 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Trannergy MQTT | ||
MQTT client for Trannergy solar inverter (PVL5400). Written in Python 3.x | ||
This program might also work for Ginlong and Omnik inverters. | ||
The inverter has to be connected to the LAN network where this script is running. | ||
|
||
Includes Home Assistant MQTT Auto Discovery. | ||
## Usage: | ||
* Copy `systemd/trannergy-mqtt.service` to `/etc/systemd/system` | ||
* Adapt path in `trannergy-mqtt.service` to your install location (default: `/opt/iot/trannergy`) | ||
* Copy `config.rename.py` to `config.py` and adapt for your configuration (minimal: mqtt ip, username, password) | ||
* `sudo systemctl enable trannery-mqtt` | ||
* `sudo systemctl start trannergy-mqtt` | ||
|
||
Use | ||
http://mqtt-explorer.com/ | ||
to test & inspect MQTT messages | ||
|
||
## Requirements | ||
* paho-mqtt | ||
* python 3.x | ||
|
||
Tested under Linux; there is no reason why it does not work under Windows. | ||
|
||
## Licence | ||
GPL v3 | ||
|
||
## Versions | ||
1.2.2: | ||
* Initial version on github |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,57 @@ | ||
#!/usr/bin/python3 | ||
|
||
""" | ||
Rename to config.py | ||
Configure: | ||
- MQTT client | ||
- Debug level | ||
""" | ||
|
||
# [ LOGLEVELS ] | ||
# DEBUG, INFO, WARNING, ERROR, CRITICAL | ||
loglevel = "INFO" | ||
|
||
# Using local dns names was not always reliable with PAHO | ||
MQTT_BROKER = "192.168.1.1" | ||
MQTT_PORT = 1883 | ||
MQTT_CLIENT_UNIQ = 'mqtt-trannergy' | ||
MQTT_QOS = 1 | ||
MQTT_USERNAME = "ijntema" | ||
MQTT_PASSWORD = "mosquitto0000" | ||
|
||
# Max nrof MQTT messages per second | ||
# Set to 0 for unlimited rate | ||
MQTT_RATE = 100 | ||
|
||
MQTT_TOPIC_PREFIX = "solar/trannergy/roof_w" | ||
|
||
# [ InfluxDB ] | ||
# Add a influxdb database tag, for Telegraf processing (database:INFLUXDB) | ||
# This is not required for core functionality of this parser | ||
# Set to None if Telegraf is not used | ||
INFLUXDB = "solar" | ||
#INFLUXDB = None | ||
#!/usr/bin/python3 | ||
|
||
""" | ||
Rename to config.py | ||
Configure: | ||
- MQTT client | ||
- Debug level | ||
""" | ||
|
||
# [ LOGLEVELS ] | ||
# DEBUG, INFO, WARNING, ERROR, CRITICAL | ||
loglevel = "INFO" | ||
|
||
# Using local dns names was not always reliable with PAHO | ||
MQTT_BROKER = "192.168.1.1" | ||
MQTT_PORT = 1883 | ||
MQTT_CLIENT_UNIQ = 'mqtt-trannergy' | ||
MQTT_QOS = 1 | ||
MQTT_USERNAME = "ijntema" | ||
MQTT_PASSWORD = "mosquitto0000" | ||
|
||
# Max nrof MQTT messages per second transmitted by MQTT client | ||
# Set to 0 for unlimited rate | ||
MQTT_RATE = 100 | ||
|
||
MQTT_TOPIC_PREFIX = "solar/trannergy/roof_w" | ||
|
||
# [ InfluxDB ] | ||
# Add a influxdb database tag, for Telegraf processing (database:INFLUXDB) | ||
# This is not required for core functionality of this parser | ||
# Set to None if Telegraf is not used | ||
INFLUXDB = "solar" | ||
#INFLUXDB = None | ||
|
||
#[ TRANNERGY INVERTER ] | ||
INV_SERIAL = "PVL5400N177E4008" | ||
|
||
# Required when using TCPCLIENT reader | ||
INV_SERIAL_LOGGER = 625830567 | ||
INV_IP = "192.168.1.53" | ||
INV_TCPCLIENTPORT = 8899 | ||
|
||
# NROF parameter reads from inverter per hour (60 equals every minute) | ||
INV_READ_RATE = 60 | ||
|
||
# Select one of the two available readers | ||
# | ||
# If supported: can read high frequent all inverter parameters | ||
INV_READER="TCPCLIENT" | ||
|
||
# Inverter sends every 5 minutes an update of all parameters | ||
# Configure in inverter | ||
# Advanced settings | ||
# Server: ip address to ip where this python script is running; port 3203 | ||
#INV_READER="LISTEN" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
#!/usr/bin/python3 | ||
|
||
""" | ||
Send Home Assistant Auto Discovery MQTT messages | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
""" | ||
import copy | ||
import time | ||
import threading | ||
import json | ||
|
||
# Local imports | ||
import config as cfg | ||
|
||
# Logging | ||
import __main__ | ||
import logging | ||
import os | ||
script = os.path.basename(__main__.__file__) | ||
script = os.path.splitext(script)[0] | ||
logger = logging.getLogger(script + "." + __name__) | ||
|
||
|
||
class Discovery(threading.Thread): | ||
|
||
def __init__(self, stopper, mqtt, version): | ||
""" | ||
class init | ||
Keyword arguments: | ||
:param threading.Event() stopper: | ||
:param mqtt.mqttclient() mqtt: reference to mqtt client | ||
:param str version: version of the program | ||
""" | ||
|
||
logger.debug(">>") | ||
super().__init__() | ||
self.__stopper = stopper | ||
self.__mqtt = mqtt | ||
self.__version = version | ||
self.__interval = 3600/cfg.HA_INTERVAL | ||
self.__lastmqtt = 0 | ||
self.__listofjsondicts = list() | ||
|
||
|
||
def __del__(self): | ||
logger.debug(">>") | ||
|
||
|
||
def __create_discovery_JSON(self): | ||
""" | ||
Create the HA/MQTT Autodiscovery messages | ||
https://www.home-assistant.io/docs/mqtt/discovery/ | ||
https://www.home-assistant.io/integrations/sensor/ | ||
https://developers.home-assistant.io/docs/core/entity/sensor/#long-term-statistics | ||
Returns: | ||
None | ||
""" | ||
d = {} | ||
|
||
# create device JSON | ||
d["name"] = "trannergy inverter" | ||
d["unique_id"] = "trannergy-device" | ||
d["state_topic"] = cfg.MQTT_TOPIC_PREFIX + "/status" | ||
d["icon"] = "mdi:home-automation" | ||
d["device"] = {"name": "trannergy inverter", | ||
"sw_version": self.__version, | ||
"model": "PVL5400N/trannergy-mqtt", | ||
"manufacturer": "hansij66 @github.com", | ||
"identifiers": ["trannergy"] | ||
} | ||
self.__listofjsondicts.append( copy.deepcopy(d) ) | ||
|
||
# Create entries | ||
d.clear() | ||
d["unique_id"] = "p_ac1" | ||
d["state_topic"] = cfg.MQTT_TOPIC_PREFIX | ||
d["name"] = "Power generated L1" | ||
d["unit_of_measurement"] = "W" | ||
# d["state_class"] = "measurement" | ||
d["value_template"] = "{{value_json.p_ac1}}" | ||
d["device_class"] = "power" | ||
d["icon"] = "mdi:gauge" | ||
d["device"] = {"identifiers": ["trannergy"]} | ||
self.__listofjsondicts.append( copy.deepcopy(d)) | ||
|
||
d.clear() | ||
d["unique_id"] = "yield_total" | ||
d["state_topic"] = cfg.MQTT_TOPIC_PREFIX | ||
d["name"] = "EL generated" | ||
d["unit_of_measurement"] = "Wh" | ||
d["value_template"] = "{{value_json.yield_total}}" | ||
d["device_class"] = "energy" | ||
d["state_class"] = "total" | ||
d["icon"] = "mdi:counter" | ||
d["device"] = {"identifiers": ["trannergy"]} | ||
self.__listofjsondicts.append(copy.deepcopy(d)) | ||
|
||
def run(self): | ||
""" | ||
Returns: | ||
None | ||
""" | ||
logger.debug(">>") | ||
|
||
self.__create_discovery_JSON() | ||
|
||
# infinite loop | ||
if cfg.HA_DISCOVERY: | ||
while not self.__stopper.is_set(): | ||
# calculate time elapsed since last MQTT | ||
t_elapsed = int(time.time()) - self.__lastmqtt | ||
|
||
if t_elapsed > self.__interval: | ||
for dict in self.__listofjsondicts: | ||
topic = "homeassistant/sensor/" + cfg.HA_MQTT_DISCOVERY_TOPIC_PREFIX + "/" + dict["unique_id"] + "/config" | ||
self.__mqtt.do_publish(topic, json.dumps(dict, separators=(',', ':')), retain=True) | ||
self.__lastmqtt = int(time.time()) | ||
else: | ||
# wait... | ||
time.sleep(0.5) | ||
|
||
# If configured, remove MQTT Auto Discovery configuration | ||
if cfg.HA_DELETECONFIG: | ||
for dict in self.__listofjsondicts: | ||
topic = "homeassistant/sensor/" + cfg.MQTT_TOPIC_PREFIX + "/" + dict["unique_id"] + "/config" | ||
self.__mqtt.do_publish(topic, "") |
Oops, something went wrong.