Skip to content

Instantly share code, notes, and snippets.

@fsmunoz
Created June 24, 2013 14:02
Show Gist options
  • Save fsmunoz/5850260 to your computer and use it in GitHub Desktop.
Save fsmunoz/5850260 to your computer and use it in GitHub Desktop.
Simple example of MQTT message publish in Common Lisp and ABCL, using the Eclipse Paho client
;; Simple example of MQTT message publish using Common Lisp and ABCL
;;
;; Uses the Eclipse Paho client
;;
;; Author: Frederico Munoz <[email protected]>
;; Date: 22-Jun-2013
;; Keywords: mqtt, messaging, m2m, telemetry, abcl, iot, paho, lisp
;;
;; Copying and distribution of this file, with or without modification,
;; are permitted in any medium without royalty provided the copyright
;; notice and this notice are preserved. This file is offered as-is,
;; without any warranty.
;;
;; See http://www.eclipse.org/paho/ for the Eclipse Paho
;; implementation of MQTT, including the
;; org.eclipse.paho.client.mqttv3.jar JAR file which is used in this
;; example and should be in the classpath.
;;
;; No ASDF system definition is provided given the simplicity of the
;; code, the following should work with the appropriate file paths:
;;
;; $ java -cp /opt/abcl-bin-1.1.1/abcl.jar:org.eclipse.paho.client.mqttv3.jar org.armedbear.lisp.Main --noinform --noinit --nosystem --load abcl-mqtt.lisp
;; Added jar:file:/opt/abcl-bin-1.1.1/abcl-contrib.jar!/quicklisp/ to ASDF.
;; Added jar:file:/opt/abcl-bin-1.1.1/abcl-contrib.jar!/mvn/ to ASDF.
;; Added jar:file:/opt/abcl-bin-1.1.1/abcl-contrib.jar!/jss/ to ASDF.
;; Added jar:file:/opt/abcl-bin-1.1.1/abcl-contrib.jar!/jfli/ to ASDF.
;; Added jar:file:/opt/abcl-bin-1.1.1/abcl-contrib.jar!/asdf-jar/ to ASDF.
;; Added jar:file:/opt/abcl-bin-1.1.1/abcl-contrib.jar!/asdf-install/ to ASDF.
;; Added jar:file:/opt/abcl-bin-1.1.1/abcl-contrib.jar!/abcl-asdf/ to ASDF.
;;
;; "Connected to tcp://m2m.eclipse.org:1883"
;; "*** PUBLISHING TO TOPIC abcltest ***"
;; "*** DELIVERY COMPLETE ***"
;; $
;;
;; This code only shows how to publish, but there are several MQTT
;; clients that can be used to subscribe to the topic. The Mosquitto
;; MQTT implementation (http://mosquitto.org/) comes with a client
;; which can be used thus:
;;
;; $ mosquitto_sub -h m2m.eclipse.org -t "abcltest" -v
;; abcltest But at least, out of my bitterness at what I'll never be, There's the quick calligraphy of these lines, The broken archway to the Impossible.
;; ^C
;; $
;;
;; The code uses Alan Ruttenberg's JSS3, which uses the
;; SHARPSIGN-DOUBLE-QUOTE macro which dynamically introspected JVM
;; method lookup via a very Lisp-y mechanism. I have left the package
;; name in the calls to make it obviour where JSS is used, but it is
;; trivial to just add #:jss to the :use in the defpackage (and use
;; (new "Foo") instead of (jss::new "Foo")).
(defpackage #:abcl-mqtt
(:use #:cl))
(require :abcl-contrib)
(require :jss)
(in-package #:abcl-mqtt)
(defparameter broker-url "tcp://m2m.eclipse.org:1883") ; Eclipse sandbox server, see http://m2m.eclipse.org/sandbox.html for details on use
(defparameter mqtt-topic-name "abcltest")
(defparameter mqtt-message (or (car EXT:*COMMAND-LINE-ARGUMENT-LIST*) ; If there is no command-line argument then use a quote from Pessoa's Tobacco Shop
"But at least, out of my bitterness at what I'll never be, There's the quick calligraphy of these lines, The broken archway to the Impossible."))
(defparameter client-id "FSM-ABCL-Test")
(defun mqtt-callback ()
"Function called after delivery confirmation"
(jss::jinterface-implementation "org.eclipse.paho.client.mqttv3.MqttCallback"
"connectionLost"
(lambda (cause)
(print cause))
"messageArrived"
(lambda (topic message) ;; not used
(print (format nil "Topic: ~A" (#"getName" topic)))
(print (format nil "Message: ~A" (#"getPayload" message))))
"deliveryComplete"
(lambda (token)
(print "*** DELIVERY COMPLETE ***"))))
(defun mqtt-connect (topic broker-url client-id)
"Establishes a MQTT connection to TOPIC; returns the mqtt client object"
(let ((mqtt-conn-options (jss::new 'MqttConnectOptions))
(mqtt-client (jss::new 'MqttClient broker-url client-id)))
(#"setCleanSession" mqtt-conn-options jss::+true+)
(#"setKeepAliveInterval" mqtt-conn-options 30)
(print (format nil "Connected to ~A" broker-url))
(#"setCallback" mqtt-client (mqtt-callback))
(#"connect" mqtt-client mqtt-conn-options)
mqtt-client))
(defun mqtt-create-message (message)
"Creates a MQTT message from MESSAGE, a string"
(let ((mqtt-message (jss::new 'MqttMessage (#"getBytes" message))))
(#"setQos" mqtt-message 0)
(#"setRetained" mqtt-message jss::+false+)
mqtt-message))
(defun mqtt-publish (topic message)
"Publishes MESSAGE to TOPIC"
(print (format nil "*** PUBLISHING TO TOPIC ~A ***" (#"toString" topic)))
(#"waitForCompletion" (#"publish" topic message)))
(defun testmq ()
"Main demo function, creates the connection and sends the message"
(let* ((client (mqtt-connect mqtt-topic-name broker-url client-id))
(topic (#"getTopic" client mqtt-topic-name))
(message (mqtt-create-message mqtt-message)))
(mqtt-publish topic message)
(sleep 0.2)
(#"disconnect" client)))
;; Make it all work
(testmq)
(cl-user::quit)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment