MQTT Publish Error

I am publishing to an MQTT device using system.cirruslink.engine.publish(). Everything works fine in terms of read/writes with the device. The issue I have is that I get the following error in the Gateway logs when running the publish function:

Error processing edit for tag path '[Device Tag Path]/relay/0/command': Bad_Unsupported("The target path '[Device Tag Path]/relay/0' cannot accept children tags.")

Any pointers into where to start looking? I understand that the issue lies with the command child topic, but this is the required path to write commands to the device.

I’m running on v8.1.4 of Maker Edition.

@wes0johnson, sorry to drag you in to this but you seem to be the go-to for MQTT :slight_smile:

Any advice would be greatly appreciated. Also, I am using v4.0.6 of the various Cirrus Link modules.

I’m not sure any of this has anything to do with MQTT specifically. First off, your tag path is wrong. You are using this:

[Device Tag Path]/relay/0/command

You should be using (note no slash after the tag provider):

[Device Tag Path]relay/0/command

Also, that error is coming from Ignition itself and suggests you are trying to add a ‘child tag’ to an existing leaf tag. You can only add child tags to UDTs and folders.

Thank you for the feedback @wes0johnson :slight_smile: I was just grasping at straws.

Apologies, I was trying to be concise and instead caused confusion :sweat_smile:. A true representation of the tag path would be: [TagProvider]devices/model-deviceID/relay/0/command

This is the clue I needed. It didn't flag in my brain that the 0 was a memory tag and couldn't have children.

The MQTT engine auto-generated the structure so that 0 was the last child (in the form of a memory tag). .../relay/0 is the topic to read the value from. .../relay/0/command is the topic to control the state of the device. In your opinion what would be be the best way to handle this situation?

Sorry if it seems like a dumb question, this is still a bit new to me :upside_down_face:

So, to read from the tag - as you noted you just read it using the path you denoted ending in
.../relay/0

When you ‘write to the tag’ you really aren’t ‘writing to the tag’ from an Ignition perspective. You need to publish an MQTT message to tell the remote device to update the tag. I don’t know the details of your device, but it sounds like you need to do something like this in an Ignition script.

system.cirruslink.engine.publish("Chariot SCADA", "the/topic/representing/write/to/relay/0", str("some required payload for the device").encode(), 0, 0)

You will need to review your device documentation to determine what the topic and payload must be in order to result in a write to that output relay. Note in this case there is no tag that represents a ‘command’. It is all done via scripting and the publish API in MQTT Engine.

I am using the publish function in my script :slight_smile: , here is an example of what I am doing:

def pubToDevice(device, command):
	# Dictionary of commands just in case they change in future firmware (easier to change in one place)
	commands = {
		'on':'on',
		'off':'off',
		'toggle':'toggle',
		'update':'update'
		}
	
	# Get the appropriate values
	topic = getDevice(device) + '/relay/0/command'
	pubCommand = str(commands[command]).encode()
	
	# Publish the command to the device
	system.cirruslink.engine.publish('Chariot SCADA', topic, pubCommand, 0, 0)

Publishing to the topic this way does work (e.g. updates the state of the device). The only issue I am having is that the error appears in the Gateway log.

This seems to be an issue with the way the device topics are setup more than anything else. For reference the devices are Shelly’s and here is the associated documentation.

Like I say it’s not a major issue as it’s not effecting functionality, it’s just spamming the Gateway event log with errors.

Ah - I think I see what is happening. I think you probably have not scoped your custom namespace subscription in MQTT Engine narrowly enough. MQTT Engine sees the publishes occurring from the device, presumably on a topic like this:

deviceId/relay/0

But, you are publishing on a topic like:

deviceId/relay/0/command

I would guess you have a subscription for the custom namespace something like one of these or some other subscription that results in you getting both of these messages back and MQTT Engine:

deviceId/#
deviceId/relay/#

You could fix this by scoping the topic subscription of the custom namespace to exclude the command messages. For example, something like either of these would work.

deviceId/+/+
+/+/+

I don’t know the full set of topics you may want to subscribe to so you may need to adjust this. The real issue here is that MQTT Engine sees the command topic and tries to add the new tag(s) to the tag tree. But, a leaf tag already exists above this path and it fails with this error message. So, by limiting the topic subscription it would prevent MQTT Engine from ever seeing those (and it doesn’t really need to anyway).

2 Likes

Now I’ve had a good read and a play, I understand what you are saying.

Thank you for taking the time to explain what’s going on :slight_smile: I’m a little less of a newb every day :laughing:

1 Like