MQTT Transmission Gateway Scripting

Hi,

I’m trying to write a gateway script which will read tag values and publish them as MQTT message/s to an external MQTT broker. I’m using the system.cirruslink.engine.publish(“Server”, “a/b/c”, str(“hello world”).encode(), 0, 0)" function but I’m getting this error in the logs: "Not publishing RPC message on “a/b/c” - Server definition for ‘Server’ does not exist. "
I have already configured the Broker as a server definition within the MQTT Transmission module settings but the script isn’t finding it. I believe I need to first run the .createConfig({}) function within the scope of the script.

Would someone be able to help me out with an example of creating a new server config using a url: “ssl://example.broker.url:8883”, certificates “CA, cert, private” and then publishing a simple message “hello world” to a topic “a/b/c” ? I’m not able to find anything in the documentation.

Cheers, Kieran.

You shouldn’t need to create any additional configuration via .createConfig() if the MQTT Engine Server Setting configuration already exists. When making the engine.publish() call, the first argument should be the MQTT Engine Server Setting name as it shows up in the Ignition web portal. For example, your engine.publish() call is looking for an MQTT Engine Server Setting with the name “Server”. I hope this helps.

I’ve setup a server in the gateway MQTT Transmission → settings called “MQTT Server” which is connected and working fine. When I try to call system.cirruslink.transmission.publish(“MQTT Server”, “a/b/c”, “hello world”, 0, 0) in the script console I get this error in the logs that the server config doesn’t exist.

Just confirming this is the transmission not the engine module if that makes any difference.

If I were to .createConfig() how would I go about it?

That looks like it should work as you have it. Double check that you don’t somehow have extra whitespace in the Transmission side Server Setting name. We don’t do a trim on the Server Setting name before doing the comparison. You’re correct in that you need to reference the Transmission side Server Setting name in the transmission.publish() call and the Engine side Server Setting name in the engine.publish() call.

We’re working on the public facing docs for .createConfig() across all of our modules, but it isn’t ready for public consumption yet. I’ll work up a .createConfig example for you and will reply back with it.

Just checked, no whitespace in the server name. Excellent, that would be great thanks. I’ll look out for the example. Cheers

You will see the same error you’re seeing if the RPC client is disconnected from the server and its quite misleading because the referenced Server Setting does really exist, its just that the client is null/disconnected.

Ensure you have the “Auto-reconnect RPC Client” configuration setting Enabled under Config → MQTT Transmission → [Your Server Setting] → Advanced → Auto-reconnect RPC Client and that you restart the Transmission module to ensure the RPC client gets connected initially.

Then try calling transmission.publish() again. We’ll update the error message you’re seeing to be more helpful/correct in a future module release.

Here is the example createConfig() snippet I promised with the proper cert creation logic. Let me know if you run into any issues or have any questions.

# Get Set ID
def getSetId():
  sets = system.cirruslink.transmission.readConfig("Sets");
  for config in sets:
    if config["Name"] == "Default":
      global setId
      setId = config["Id"]

# Create CA Cert Chain
caChainProps = {}
caChainProps["Name"] = "CA Chain"
caChainProps["FileContents"] = ("-----BEGIN CERTIFICATE-----\n" +
"LINE1\n" +
"MQ8wDQYDVQQIDAZLYW5zYXMxFDASBgNVBAcMC1NwcmluZyBIaWxsMR4wHAYDVQQK\n" +
"LINE3\n" +
"LINE4\n" +
"LINE5\n" +
"ETC\n" +
"ETC\n" +
"NfKkNSLtui2QpCV0dwY8XX8=\n" +
"-----END CERTIFICATE-----\n" +
"-----BEGIN CERTIFICATE-----\n" +
"LINE1\n" +
"VQQGEwJVUzEPMA0GA1UECAwGS2Fuc2FzMRQwEgYDVQQHDAtTcHJpbmcgSGlsbDEe\n" +
"LINE3\n" +
"LINE4\n" +
"LINE5\n" +
"ETC\n" +
"ETC\n" +
"CRTeBexRtq4VSm/Oi5fIT+euBLZTTsDdF+sxzJi9TP60Y0tD\n" +
"-----END CERTIFICATE-----\n")
caChainProps["Description"] = "ca-chain.cert.pem"
system.cirruslink.transmission.createConfig("Cert Files", caChainProps)


# Get Certificate IDs
certFiles = system.cirruslink.transmission.readConfig("Cert Files");
for config in certFiles:
  if config["Name"] == "CA Chain":
    caChain = config["Id"]

# Configure Tx Server Setting
getSetId()
serverProps = {}
serverProps["Name"] = "Chariot SCADA"
serverProps["Url"] = "ssl://mqttserver:8883"
serverProps["ServerSet"] = setId
serverProps["Username"] = "admin"
serverProps["Password"] = "changeme"
serverProps["CaCertFile"] = caChain
system.cirruslink.transmission.createConfig("Servers", serverProps)

Hi Nathan,

Thanks for that script, much appreciated.

I realised I didn’t have “Auto-reconnect RPC Client” enabled on the Server config. I enabled that and found a new problem - the RPC client is not being started for my Server config.

I tried reinitialising the Module, stopping and starting the server/transmitter etc but the RPC client is still not connecting and a “transmission.publish()” call isn’t working from the script console.

The MQTT client uses a cert tied to the Client ID in MQTT config. I’m assuming since you can only have one Client using the cert config, the RPC is not able to connect while the transmitter client is already connected? Perhaps you know what’s going on and how to fix this issue?

Kind regards,

I believe the reason the RPC client is not connecting is because the MQTT Client ID has been statically configured. Due to this configuration, only one client will be able to connect with this Client ID. If more than one client connects using the same Client ID, the first connection will be terminated to allow the next connection through. Can you try temporarily clearing your client ID configured under the Transmission Server Setting and then see if the RPC client connects as you expect?