MQTT broker

This page shows practical MQTT patterns in Rye:

  • Quick publish to a public broker
  • Local broker publish+subscribe demo
  • Guarding examples so they don’t fail when MQTT isn’t available

Prerequisites

  • An MQTT broker. For local tests, use mqtt://localhost:1883 (e.g., Mosquitto).
  • For the public broker examples we use test.mosquitto.org. Do not send sensitive data.

Quick publish to public broker

Publishes a single message to a test topic. Useful to sanity-check network access and DNS.

; Publish a message to a public broker topic
print "Connecting to public MQTT broker"

client: Open mqtt://test.mosquitto.org:1883/rye-test-p
|^check "couldn't connect to MQTT"

^ensure client .Is-connected "Not really connected"

client .Publish-simple topic: "rye/test" "Hello from Rye!"
|^check "failed to send the message"

print2 "Message sent to: " topic

client .Disconnect |^check "failed to disconnect"
  • Replace the topic rye/test if needed.
  • This uses a higher-level convenience API (Publish-simple) to keep the snippet short.

Subscribe and print messages (public broker)

Subscribes to a topic and prints received messages. This example keeps running.

client: Open mqtt://test.mosquitto.org:1883/rye-test
|^check "couldn't connect to MQTT"

^ensure client .Is-connected "Not really connected"

handler: fn { txt msg } {
  print "\n-NEW-MESSAGE----" ,
  print txt , print ""
  print [ "Topic:" msg."topic" ]
  print [ "QoS:" msg."qos" ]
  print [ "Retained:" msg."retained" ]
}

topic: "rye/test"
client .Subscribe topic 1 ?handler

print "listening ..."
select { }            ; keep running
  • In one terminal run the subscriber; in another, run the publisher from the previous section and confirm you see messages printed.

Local broker: subscribe and publish in-process (guarded)

This self-contained demo connects to a local broker, subscribes to a topic, then publishes a few messages. If MQTT isn’t built in your binary, it prints a friendly message and exits successfully.

; MQTT publish/subscribe demo (guarded). Requires local broker at mqtt://localhost:1883

private { mqtt-connect } |type? |= 'word
|either {
  cli: mqtt-connect { url: "mqtt://localhost:1883" client-id: "rye-demo" }
  topic: "rye/demo"
  ; subscribe with a simple handler
  mqtt-subscribe cli topic { msg |
    print join { "recv: " (msg -> "payload" |->string) }
  }
  ; publish a few messages
  mqtt-publish cli topic "hello"
  mqtt-publish cli topic "world"
  sleep-ms 100
  mqtt-disconnect cli
} {
  print "MQTT not available in this build."
}

Tips

  • Ensure a local MQTT broker is running (e.g., Mosquitto on port 1883).
  • Client IDs should be unique per connection.

Error handling patterns

When connecting to a remote service, prefer returning-words that add context and exit on errors:

client: Open mqtt://broker:1883/my-client |^check "connect failed"
^ensure client .Is-connected "not connected"
client .Publish-simple topic: "app/heartbeat" "ok" |^check "publish failed"
client .Disconnect |^check "disconnect failed"
  • |^check adds context to the error and returns from the function/main script.
  • ^ensure converts a falsy value into a failure and returns.

CLI-friendly patterns

For small tools, parse arguments and apply a consistent error style:

args: rye .Args?     ; argv as a Rye block
spec: {
  program "mqtt-pub"
  -b|broker string optional "mqtt://localhost:1883"
  -t|topic  string required
  -m|msg    string required
}
res: parse-args args spec |^fix { print generate-help spec , .format-parse-errors .print , exit 1 }

client: Open res."broker"/rye-pub |^check "connect failed"
^ensure is-positive client .Is-connected "not connected"
client .Publish-simple topic: res."topic" res."msg" |^check "publish failed"
client .Disconnect |^check "disconnect failed"
  • This integrates neatly with Rye’s CLI dialect and error handling.

Troubleshooting

  • Broker not reachable: verify host/port, firewall, and credentials if used.
  • Public broker rate limits: public services may throttle or disconnect aggressively—use your own broker for serious work.
  • Client ID conflicts: ensure each client uses a distinct client-id.

See also

  • Examples in the Rye repo:
    • examples/mqtt/publisher.rye and examples/mqtt/subscriber.rye
    • examples/batteries/mqtt_02_publish_subscribe.rye
  • MQTT project: https://mqtt.org/
  • Mosquitto broker: https://mosquitto.org/