mirror of
https://github.com/lumapu/ahoy.git
synced 2025-04-28 17:56:21 +02:00
RPi:MQTT support QoS, Retain and Last-Will
To support Quality of Service, Retain and Last-Will Switch in ahoy.yml.example
This commit is contained in:
parent
96d64faf62
commit
c8af9c2e9a
3 changed files with 58 additions and 22 deletions
|
@ -28,6 +28,11 @@ ahoy:
|
|||
password: 'password'
|
||||
useTLS: False
|
||||
insecureTLS: False #set True for e.g. self signed certificates.
|
||||
QoS: 0
|
||||
Retain: True
|
||||
last_will:
|
||||
topic: Appelweg_PV/114181807700 # defaults to 'hoymiles/{serial}'
|
||||
payload: "LAST-WILL-MESSAGE: Please check my HOST and Process!"
|
||||
|
||||
# Influx2 output
|
||||
influxdb:
|
||||
|
|
|
@ -17,10 +17,31 @@ from suntimes import SunTimes
|
|||
import argparse
|
||||
import yaml
|
||||
from yaml.loader import SafeLoader
|
||||
# import paho.mqtt.client
|
||||
import hoymiles
|
||||
import logging
|
||||
|
||||
################################################################################
|
||||
""" Signal Handler """
|
||||
################################################################################
|
||||
# from signal import signal, Signals, SIGINT, SIGTERM, SIGKILL, SIGHUP
|
||||
from signal import *
|
||||
def signal_handler(sig_num, frame):
|
||||
signame = Signals(sig_num).name
|
||||
logging.info(f'Stop by Signal {signame} ({sig_num})')
|
||||
print (f'Stop by Signal <{signame}> ({sig_num}) at: {time.strftime("%d.%m.%Y %H:%M:%S")}')
|
||||
|
||||
if mqtt_client:
|
||||
mqtt_client.disco()
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
signal(SIGINT, signal_handler) # Interrupt from keyboard (CTRL + C)
|
||||
signal(SIGTERM, signal_handler) # Signal Handler from terminating processes
|
||||
signal(SIGHUP, signal_handler) # Hangup detected on controlling terminal or death of controlling process
|
||||
# signal(SIGKILL, signal_handler) # Signal Handler SIGKILL and SIGSTOP cannot be caught, blocked, or ignored!!
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
class InfoCommands(IntEnum):
|
||||
InverterDevInform_Simple = 0 # 0x00
|
||||
InverterDevInform_All = 1 # 0x01
|
||||
|
|
|
@ -179,10 +179,18 @@ class MqttOutputPlugin(OutputPluginFactory):
|
|||
mqtt_client.tls_set()
|
||||
mqtt_client.tls_insecure_set(config.get('insecureTLS',False))
|
||||
mqtt_client.username_pw_set(config.get('user', None), config.get('password', None))
|
||||
mqtt_client.will_set(str(config.get('last_will', {}).get('topic', 'hoymiles')), str(config.get('last_will', None).get('payload', None)))
|
||||
|
||||
mqtt_client.connect(config.get('host', '127.0.0.1'), config.get('port', 1883))
|
||||
mqtt_client.loop_start()
|
||||
|
||||
self.client = mqtt_client
|
||||
self.qos = config.get('QoS', 0) # Quality of Service
|
||||
self.ret = config.get('Retain', True) # Retain Message
|
||||
|
||||
def disco(self, **params):
|
||||
self.client.loop_stop() # Stop loop
|
||||
self.client.disconnect() # disconnect
|
||||
|
||||
def store_status(self, response, **params):
|
||||
"""
|
||||
|
@ -202,17 +210,17 @@ class MqttOutputPlugin(OutputPluginFactory):
|
|||
|
||||
# Global Head
|
||||
if data['time'] is not None:
|
||||
self.client.publish(f'{topic}/time', data['time'].strftime("%d.%m.%y - %H:%M:%S"))
|
||||
self.client.publish(f'{topic}/time', data['time'].strftime("%d.%m.%y - %H:%M:%S"), self.qos, self.ret)
|
||||
|
||||
# AC Data
|
||||
phase_id = 0
|
||||
phase_sum_power = 0
|
||||
for phase in data['phases']:
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/voltage', phase['voltage'])
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/current', phase['current'])
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/power', phase['power'])
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/Q_AC', phase['reactive_power'])
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/frequency', phase['frequency'])
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/voltage', phase['voltage'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/current', phase['current'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/power', phase['power'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/Q_AC', phase['reactive_power'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter/{phase_id}/frequency', phase['frequency'], self.qos, self.ret)
|
||||
phase_id = phase_id + 1
|
||||
phase_sum_power += phase['power']
|
||||
|
||||
|
@ -220,36 +228,38 @@ class MqttOutputPlugin(OutputPluginFactory):
|
|||
string_id = 0
|
||||
string_sum_power = 0
|
||||
for string in data['strings']:
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/voltage', string['voltage'])
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/current', string['current'])
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/power', string['power'])
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldDay', string['energy_daily'])
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldTotal', string['energy_total']/1000)
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/Irradiation', string['irradiation'])
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/voltage', string['voltage'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/current', string['current'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/power', string['power'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldDay', string['energy_daily'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/YieldTotal', string['energy_total']/1000, self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/emeter-dc/{string_id}/Irradiation', string['irradiation'], self.qos, self.ret)
|
||||
string_id = string_id + 1
|
||||
string_sum_power += string['power']
|
||||
|
||||
# Global
|
||||
if data['event_count'] is not None:
|
||||
self.client.publish(f'{topic}/total_events', data['event_count'])
|
||||
self.client.publish(f'{topic}/total_events', data['event_count'], self.qos, self.ret)
|
||||
if data['powerfactor'] is not None:
|
||||
self.client.publish(f'{topic}/PF_AC', data['powerfactor'])
|
||||
self.client.publish(f'{topic}/Temp', data['temperature'])
|
||||
self.client.publish(f'{topic}/PF_AC', data['powerfactor'], self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/Temp', data['temperature'], self.qos, self.ret)
|
||||
if data['yield_total'] is not None:
|
||||
self.client.publish(f'{topic}/YieldTotal', data['yield_total']/1000)
|
||||
self.client.publish(f'{topic}/YieldTotal', data['yield_total']/1000, self.qos, self.ret)
|
||||
if data['yield_today'] is not None:
|
||||
self.client.publish(f'{topic}/YieldToday', data['yield_today']/1000)
|
||||
self.client.publish(f'{topic}/Efficiency', data['efficiency'])
|
||||
self.client.publish(f'{topic}/YieldToday', data['yield_today']/1000, self.qos, self.ret)
|
||||
self.client.publish(f'{topic}/Efficiency', data['efficiency'], self.qos, self.ret)
|
||||
|
||||
|
||||
elif isinstance(response, HardwareInfoResponse):
|
||||
self.client.publish(f'{topic}/Firmware/Version',\
|
||||
f'{data["FW_ver_maj"]}.{data["FW_ver_min"]}.{data["FW_ver_pat"]}')
|
||||
f'{data["FW_ver_maj"]}.{data["FW_ver_min"]}.{data["FW_ver_pat"]}', self.qos, self.ret)
|
||||
|
||||
self.client.publish(f'{topic}/Firmware/Build_at',\
|
||||
f'{data["FW_build_dd"]}/{data["FW_build_mm"]}/{data["FW_build_yy"]}T{data["FW_build_HH"]}:{data["FW_build_MM"]}')
|
||||
f'{data["FW_build_dd"]}/{data["FW_build_mm"]}/{data["FW_build_yy"]}T{data["FW_build_HH"]}:{data["FW_build_MM"]}',\
|
||||
self.qos, self.ret)
|
||||
|
||||
self.client.publish(f'{topic}/Firmware/HWPartId', f'{data["FW_HW_ID"]}')
|
||||
self.client.publish(f'{topic}/Firmware/HWPartId',\
|
||||
f'{data["FW_HW_ID"]}', self.qos, self.ret)
|
||||
|
||||
else:
|
||||
raise ValueError('Data needs to be instance of StatusResponse or a instance of HardwareInfoResponse')
|
||||
|
|
Loading…
Add table
Reference in a new issue