tbnobody / OpenDTU

Software for ESP32 to talk to Hoymiles/TSUN/Solenso Inverters
GNU General Public License v2.0
1.82k stars 509 forks source link

Feature Request: send all status information in JSON format via MQTT (configurable option) #225

Open madmartin opened 2 years ago

madmartin commented 2 years ago

Some people requested all the status information send in JSON format instead of single messages. This has advantages in saving the information in InfluxDB. The MQTT json messages should be able to switch on/off in the configuration.

@tbnobody I'll try to implement this and file a pull request.... Okay?

Sprinterfreak commented 2 years ago

No1!11!! MQTT uses topics for single values to be able to subscribe to single values. Use http to poll json status data instead.

Also using telegraf's mqtt is totally possible. I use this:

[[inputs.mqtt_consumer]]
  name_override = 'solar'
  servers = ['tcp://broker.local:1883']

#    'opendtu/dtu/uptime',
#    'opendtu/dtu/rssi',
  topics = [
    'opendtu/+/+/current',
    'opendtu/+/+/voltage',
    'opendtu/+/+/power',
    'opendtu/+/+/powerdc',
    'opendtu/+/+/yieldtotal',
    'opendtu/+/+/powerfactor',
    'opendtu/+/+/frequency',
    'opendtu/+/+/temperature',
    'opendtu/+/settings/limit',
  ]
  data_format = 'value'
  data_type = 'float'

[[processors.starlark]]
  namepass = ['solar']

  source = '''
def apply(metric):
  l_topic = metric.tags.get('topic', '//').split('/')

  metric.tags['location'] = l_topic[1]

  if l_topic[2] == "0":
    metric.tags['phase'] = "0"
  elif l_topic[2] in ["1", "2", "3", "4"]:
    metric.tags['string'] = str(int(l_topic[2]) - 1)

  if len(l_topic) >= 4:
    if l_topic[3] in ['power', 'powerdc']:
      metric.fields['power'] = metric.fields.pop('value', None)
    elif l_topic[3] == 'voltage':
      metric.fields['voltage'] = metric.fields.pop('value', None)
    elif l_topic[3] == 'current':
      metric.fields['current'] = metric.fields.pop('value', None)
    elif l_topic[3] == 'yieldtotal':
      metric.fields['energy'] = metric.fields.pop('value', None)
    elif l_topic[3] == 'limit':
      metric.fields['limit'] = metric.fields.pop('value', None)
    elif l_topic[3] == "temperature":
      metric.fields['temperature'] = metric.fields.pop('value', None)
    elif l_topic[3] == "powerfactor":
      metric.fields['powerfactor'] = metric.fields.pop('value', None)
    elif l_topic[3] == "frequency":
      metric.fields['frequency'] = metric.fields.pop('value', None)

  return metric
'''

[[outputs.influxdb_v2]] 
  urls = ['http://broker.local:8086']
  token = '<token>'
  organization = 'myorg'
  bucket = 'solar/autogen'
  namepass = ['solar']

The MQTT topic layout is of course questionable. This telegraf snippet converts the data structure to a layout which my python implementation used. So I could keep my dashboards.

rejoe2 commented 1 year ago

May I renew this request?

My personal focus is more on the data processing side, especially within FHEM. Receiving all retated data in just one corresponding json blob would be much more effective there, as every mesage will cause just one "event loop" regardless if the message just contains a single info or a set of x informations. As I plan to use the openDTU for a setup with 6xHM-1500 (starting in January) this would significantly reduce the generated overhead...

Polling imo is no real alternative to the MQTT way, and sending that kind of summarized JSON blobs is very common.

Thanks in advance for giving some thoughts on that again.

bwired-nl commented 1 year ago

Some people requested all the status information send in JSON format instead of single messages. This has advantages in saving the information in InfluxDB. The MQTT json messages should be able to switch on/off in the configuration.

@tbnobody I'll try to implement this and file a pull request.... Okay?

any update on this? thanks

stefan123t commented 3 months ago

@madmartin @rejoe2 @bwired-nl JSON could / should be implemented as an optional MQTT topic format. Please refer to the additional or missing MQTT topics in #759