Skip to content

Commit

Permalink
1.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Hans IJntema committed Mar 5, 2022
1 parent a98b1fb commit 128818d
Show file tree
Hide file tree
Showing 4 changed files with 409 additions and 35 deletions.
29 changes: 29 additions & 0 deletions README.md
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
92 changes: 57 additions & 35 deletions config.py → config.rename.py
100755 → 100644
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"
144 changes: 144 additions & 0 deletions hadiscovery.py
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, "")
Loading

0 comments on commit 128818d

Please sign in to comment.