I ave a setup with a few Modbus RTU devices, each with about 50 addresses I want to send via MQTT once they change. I know thereś the “JSON Simple” method, but I want to send a customized JSON. How can I do that? What I though of was to use value trigger-based MQTT, so a macro could loop over the list of devices and addresses, and change the value of a register that MQTT is looking for. But there are a few potential issues with this approach, which I do not know how to overcome:
- For the loop over the devices and address, is it possible to GetData using dynamic device names? Or using the <device_name>#<address_offset> syntax?
- For the register trigger, is the trigger running asynchronous to the macros? I ask because, for example, if the first iteration of the loop sets the trigger, then on the second iteration the trigger is reset-set again - would that make MQTT to recognize both sends?
Hi @rbborges,
Your HMI does support JSON Advanced, which is a customized JSON message. Some information on using JSON Advanced can be found within this video tutorial (at 11:21).
hi @cody.bearden , many thanks for the speedy response!
I know that the HMI supports a custom JSON. My problem at hand is that I have 10 devices, and I monitor 50 registers in each of them for changes, to send via MQTT when any of those change. I have to send using a specific JSON format, different from what JSON Simple generates, like this:
{
“device”: 1,
“address”: 900,
“value”: 5678,
“timestamp”: 1738067768
}
My understanding is that, by using JSON Advances, I can only define a single payload there, right? A solution I though of was to:
- dynamically set each one of the fields of the JSON above in the memory of the HMI, with MQTT send triggerd by a value, then
- have a macro to loop over each address of each device, then
- when a change is detected, write to the appropriate addresses in the HMI (which will be used by the MQTT JSON Advanced payload) and change the value of the trigger variable.
Bu I have a question for the approach above: while the macro is running, when the trigger is set, does the MQTT asynchronously detect that and do what it has to do?
Hi @rbborges,
Could you please clarify if the message sent when a specific variable changes is different from their normal publishing of 50 values?
Hi @cody.bearden
let’s say we monitor address 900 to 949, for devices 1 to 10.
When address 900 of device 1 changes its value, an MQTT message with the format
{
“device”: 1,
“address”: 900,
“value”: <new_value>,
“timestamp”: <unix_epoch_time>
}
is sent.
Then, when, let’s say, parameter 930 of device 3 changes:
{
“device”: 3,
“address”: 930,
“value”: <new_value>,
“timestamp”: <unix_epoch_time>
}
and so on and so forth
Hello @rbborges,
I thought I’d chime in after looking at the requirements. I think this is feasible, but my concern would be overhead. It is possible to add many different messages even under the same topic name, what you have described is 500 possible messages, which would be a lot to maintain or change going forward.
I think that using a macro will be the easiest solution here, but this will still be a bit complex. Here is an untested example that may help:
macro_command main()
short previous[50], current[50]
short i = 0
short address = 0, value = 0
bool on = true, off = false
GetData(previous[0], "Local HMI", RW, 0, 50) // Get previous 50 values saved in the HMI
GetData(current[0], "Device 1", 4x, 900, 50) // Get current 50 values saved in the device 1
for i = 0 to 49
if current[i] <> previous[i] then // If current value does not equal previous value
address = 900 + i
value = current[i]
SetData(current[i], "Local HMI", RW, 0 + i, 1) // Save current data into 'previous' memory
SetData(address, "Local HMI", LW, 100, 1) // Move address into publish memory
SetData(value, "Local HMI", LW, 101, 1) // Move value into publish memory
DELAY(250)
SetData(on, "Local HMI", LB, 1, 1) // Trigger publish
end if
next
end macro_command
-
The topic is published via a bit trigger of LB-1:
-
The address and value are sourced from the placeholders used within the macro: