Single MQTT JSON publish for multiples nodenames

Hi all

Is it possible to send a json with mqtt with data for multiples nodenames ? And how to do it ?

I read several modbus meters sequentially in python, which all post data to different nodenames, i.e. one publish per meter.

I think it would be much more efficient to be able to send one publish for all meters.

Thanks for your support

Regards

Titof

Hoped to have found the solution but does not work:

Instead to have:

mqtt_publish(‘emon/’+nodename1+’/’, json.dump({‘topic1’:value, ‘topic2’: value, …..])

mqtt_publish(‘emon/’+nodename2+’/’, json.dump({‘topic10’:value, ‘topic20’: value, …..])

the following does not works and shall have done it in a single mqtt access:

mqtt_publish(‘emon/, json.dump({‘nodename1/topic1’:value, ‘nodename1/topic2’: value, …..,’nodename2/topic10’:value, ‘nodename2/topic20’: value, …..])

No.

The nodename is taken from the topic it is posted to.

[edit]
The code could be refactored to take an array of JSON nodes such as

[{"node": {"input1":1, "input2":2}}]

I don’t think it does currently (but I could be wrong).

Interesting, I don’t think it was designed to do that, but the sub topic code must be doing the translation.

A JSON Linter wanted it like this (if anyone else is interested) :slight_smile:

{
  "nodename1/topic1": 1,
  "nodename1/topic2": 2,
  "nodename2/topic10": 1,
  "nodename2/topic20": 2
}

No… effectively doesn’t work

Creates all topics skipping the / under an empty nodename…

Oh right, I though you were saying it did work :frowning:

In debug phase there is always a step between what seems to work and what works really :wink:

1 Like

Hopefully I found one of your topic where you were in trouble to delete all these unusable inputs created.

Clean inputs without a process list GET http://192.168.8.201/input/clean

very efficient 9k+ wrong inputs deleted and web input page is now responding again :wink:

But still no solution to my original problem. Normally a mqtt broker supports subtopics,

So is there something to correct in the way that emoncms collect data from the mqtt broker ?

This is nothing to do with the Broker - yes they all support sub topics and subsub and subsubsub topics.

Of the key:value pair, your key is nodename1/topic1 - this is not a sub topic - just a key with a / in it.

emoncms handles sub topics by adding them into the same node but adding the subtopic name first to the key value.

No, it is doing what it was designed to do - process a single set of key:value pairs.

You are asking for a new feature to process an array of sets of key:value pairs.

The structure would be like this (time is optional)

[ 
  {
    "time":"2026-02-11T19:54:03",
    "node1": {
      "input1": 1,
      "input2": 2
    },
    "node2": {
      "input1": 1,
      "input2": 2
    }
  }
]

but the MQTT Input script would need to be amended.

Ok I look at emoncms_mqtt.php

But to begin I do not find where the / in the key name is removed. I found where it is removed for nodeid but not for the key. Is it removed in an other place when it is displayed in the website ?

I anticipate it is removed deeper in the model.

However, this will not solve your problem.

By default there is no loop around different nodeids - the nodeid is picked up from the topic in emon\topic and the function runs once for one node for every item of published data. It would need a complete refactor to do anything else.

I am not familiar at all with php but I will try to modify the code to add this functionnality.

My idea is to remame the actual message function as message_std, and then write a new message function. if the decoded json with depth 3 is OK, I call message_std with the original message, if a depth error , I decode with depth 4, and then loop like this:

foreach($jsondata as $topic=>$payload) {
    $loopmessage->topic= $topic;
    $loopmessage->payload=json_encode($payload);
    message_std($loopmessage);
}

will this work ?

Your entire project seems to be based on this assertion. Have you actually measured/tested it? How much more efficient will it be and is this improvement in efficiency important? Otherwise your project is likely to result in you having a non-standard system to maintain

My system is customized to fit my needs and so already “non standard”.

In order to be independent from inverter manufacturers , I have added Eastron AC and DC meters on DC strings (2x South, East + West), Battery , and AC for the two inverters, as well as the Gridmeter. So with 8 modbus meters I wrote my own python script to handle the data readings rather than using emonhub.

And as my only mean to control battery charge and discharge is by fooling the hybrid inverter with modified gridmeter data, I have implemented a fake slave modbus gridmeter. But everything shall work in realtime, i.e. 1 second loop time, it is why I hit the MQTT access limit and needed this special multinode publish implementation.

Concerning the single mqtt access for multiple nodes, this works well by publishing to a MultiNodes topic.

  1. rename the message function to message_singlenode

  2. define a new message function:

function message($message)

{   global $log;

    try {

        $value = $message->payload;

        if  ($message->topic == 'emon/MultiNodes' ) {

            $jsondata = json_decode($value,true,4);

            if ((json_last_error() === JSON_ERROR_NONE) && is_array($jsondata)) {

                // multiple nodeid JSON, 

                $log->info("Multiple Node JSON received, looping to original mqttmessage process");

                foreach($jsondata as $topic=>$payload) {

                    $loopmessage= new StdClass();

                    $loopmessage->topic= $topic;

                    $loopmessage->payload= json_encode($payload);

                    $log-info("Multiple Node loop ".$topic.'-->'.$loopmessage->payload);

                    message_singlenode($loopmessage);

                }

            }

        }

        else {

            message_singlenode($message);

        }  

    }

    catch (Exception $e) {

        $log->error($e);

    }

}