{"id":20501992,"url":"https://github.com/alekras/mqtt_client","last_synced_at":"2025-04-13T19:51:44.618Z","repository":{"id":62429936,"uuid":"55186866","full_name":"alekras/mqtt_client","owner":"alekras","description":"MQTT client is designed for communication in Machine to Machine (M2M) and Internet of Things (IoT) contexts and implements MQTT protocol versions 3.1, 3.1.1 and 5.0. The client is written in Erlang and tested with MQTT servers like Mosquitto and RabbitMQ.","archived":false,"fork":false,"pushed_at":"2024-10-24T01:04:07.000Z","size":396,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-27T10:37:44.757Z","etag":null,"topics":["erlang","iot","mqtt","mqtt-client"],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alekras.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-03-31T22:23:03.000Z","updated_at":"2024-10-24T01:04:11.000Z","dependencies_parsed_at":"2024-05-09T04:28:06.017Z","dependency_job_id":"41d54002-9872-4250-af3f-503656134f22","html_url":"https://github.com/alekras/mqtt_client","commit_stats":{"total_commits":69,"total_committers":6,"mean_commits":11.5,"dds":0.6956521739130435,"last_synced_commit":"6e77c48172bfe05b259f7f8638e1c57a2ed96ebb"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekras%2Fmqtt_client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekras%2Fmqtt_client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekras%2Fmqtt_client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alekras%2Fmqtt_client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alekras","download_url":"https://codeload.github.com/alekras/mqtt_client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248602313,"owners_count":21131616,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erlang","iot","mqtt","mqtt-client"],"created_at":"2024-11-15T19:18:50.257Z","updated_at":"2025-04-13T19:51:44.599Z","avatar_url":"https://github.com/alekras.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Introduction\nThe client allows to connect to MQTT server and send/receive messages according to MQTT messaging protocol versions 3.1, 3.1.1 and 5.0.\nThe client is written in Erlang. \nThe client was tested with RabbitMQ and Mosquitto server on Windows/Linux/MacOSX boxes.\n\n## Architecture\nMQTT client is an OTP application. Top level component is supervisor\nthat is monitoring a child client processes. \nSo the application can create a multiple client instances these keep \nconnections to different servers concurrently. Session state data are storing in database (DETS and MySQL in current version)\n\n## Getting started\n### Installation\nTo start with the client you have to complete three steps below:\n\n1. Install [Erlang](http://www.erlang.org/download.html).\n2. Install [Rebar3](https://www.rebar3.org/).\n3. (optional) Install [Mosquitto](https://mosquitto.org/) or [RabbitMQ](https://www.rabbitmq.com/) (with MQTT plugin) server.\n\n\n### Building\n#### Download or clone from Github\nTo get the client code from GIT repository type command (to clone from SourceForge GIT repository):\n\n```bash\ngit clone https://git.code.sf.net/p/mqtt-client/code erl.mqtt.client\n```\nFor GitHub repository type:\n\n```bash\ngit clone https://github.com/alekras/mqtt_client.git erl.mqtt.client\n```\nEclipse project exists under folder erl.mqtt.client. You do not need to use Eclipse to build the client but \nif you want you can use convenience of Eclipse and Erlide plugin.\n\n#### Compiling\nAfter you have got source code of the client then change directory to the erl.mqtt.client:\n\n```bash\ncd erl.mqtt.client\n```\nRun rebar3 for this project. You have to add path to rebar3 to OS PATH variable or just use the whole path:\n\n```bash\n/opt/local/bin/rebar3 compile\n```\nRebar will fetch code of all dependencies and compile source files of main project and all dependencies.\n\n### Testing\nNext step is running the examples. For testing we need to run MQTT server locally or use external servers running outside in Internet.\n 1. Suppose you install Mosquitto MQTT server as 'localhost' that opened 1883 port \nfor listening a TCP/IP connections from clients.\nYou have to setup 'quest' account with 'guest' password.\n 2. You can connect to public available MQTT server broker.hivemq.com with ports:\n  - clear tcp: 1883\n  - ssl/tls: 8883\n  - clear websocket (ws): 8000\n  - secure websocket: 8884\n 3. Other public MQTT Broker broker.emqx.io has ports:\n  - clear tcp: 1883\n  - ssl/tls: 8883\n  - clear websocket (ws): 8083\n  - secure websocket: 8084\n 4. Erlang MQTT server is running on lucky3p.com with ports:\n  - clear websocket (ws): 8880 (we will use this configuration for below examples)\n  - secure websocket: 4443\n\nWe will test the client from Erlang shell:\n\n```erlang\nerl -pa _build/default/lib/*/ebin\nErlang/OTP 24 [erts-12.3.2.15] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]\n\nEshell V12.3.2.15  (abort with ^G)\n1\u003e\n```\n\n## Run application\nAfter we start Erlang shell for testing we need to start application 'mqtt_client' that represents describing client.\n\n```erlang\n1\u003e application:start(mqtt_client).\n15:05:54.062 [info] running apps: \n    {mqtt_common,\"MQTT common library\",\"2.1.0\"}\n    {ssl,\"Erlang/OTP SSL application\",\"10.7.3.9\"}\n    {public_key,\"Public key infrastructure\",\"1.12.0.2\"}\n    {asn1,\"The Erlang ASN1 compiler version 5.0.18.2\",\"5.0.18.2\"}\n    {crypto,\"CRYPTO\",\"5.0.6.4\"}\n    {inets,\"INETS  CXC 138 49\",\"7.5.3.4\"}\n    {sasl,\"SASL  CXC 138 11\",\"4.1.2\"}\n    {lager,\"Erlang logging framework\",\"3.9.2\"}\n    {goldrush,\"Erlang event stream processor\",\"0.1.9\"}\n    {compiler,\"ERTS  CXC 138 10\",\"8.1.1.5\"}\n    {syntax_tools,\"Syntax tools\",\"2.6\"}\n    {stdlib,\"ERTS  CXC 138 10\",\"3.17.2.4\"}\n    {kernel,\"ERTS  CXC 138 10\",\"8.3.2.4\"}\nok\n```\nLoad records definitions to console environment. This is optional operation but it makes our next steps more easy and clear \nby using defined records in mqtt.hrl:\n\n```erlang\n2\u003e rr(\"_build/default/lib/mqtt_common/include/mqtt.hrl\").\n[connect,connection_state,primary_key,publish,session_state,\n sslsocket,storage_connectpid,storage_publish,storage_retain,\n storage_subscription,subs_primary_key,subscription_options,\n user]\n```\nIt is time to create client process. We will register the process under name 'publisher':\n\n```erlang\n3\u003e Publisher_pid = mqtt_client:create(publisher).\n\u003c0.148.0\u003e\n```\nWe can use in following steps either 'publisher' registered name or Publisher_pid.\n\n## Connection\nRecord #connect encapsulates connection information we need to connect to MQTT server.\nLets assign record #connect{} to Conn_def value:\n\n(To easy copy/paste:\n\nConn_def = #connect{\nclient_id = \"publisher\",\nhost = \"lucky3p.com\",\nport = 8880,\nversion = '5.0',\nconn_type = web_socket,\nuser_name = \"guest\",\npassword = \u003c\u003c\"guest\"\u003e\u003e,\nclean_session = 1\n}.\n\n)\n\n```erlang\n4\u003e Conn_def = #connect{\n4\u003e client_id = \"publisher\",\n4) host = \"lucky3p.com\",\n4) port = 8880,\n4) version = '5.0',\n4) conn_type = web_socket,\n4\u003e user_name = \"guest\",\n4\u003e password = \u003c\u003c\"guest\"\u003e\u003e,\n4\u003e clean_session = 1\n4\u003e }.\n#connect{client_id = \"publisher\",user_name = \"guest\",\n         password = \u003c\u003c\"guest\"\u003e\u003e,host = \"lucky3p.com\",port = 8880,\n         will_publish = undefined,clean_session = 1,\n         keep_alive = 6000,properties = [],version = '5.0',\n         conn_type = web_socket}\n```\nAnd finally connect our client to MQTT server at lucky3p.com:8880 \n\n```erlang\n5\u003e ok = mqtt_client:connect(publisher, Conn_def, fun(Event, Argument) -\u003e  io:fwrite(user,\"Publisher:: Event:~p Arg:~p~n\", [Event, Argument]) end).\nok\n20:20:03.952 [info] [ClId:\u003c\u003c\"publisher\"\u003e\u003e PkId:none Op:connack Vrs:'5.0'] client is successfuly connected to {70,133,222,59}:8880\nPublisher:: Event:onConnect Arg:{0,\"Success\",[]}\n6\u003e\n```\nWe have client with name = 'publisher' (or PID = Publisher_pid = \u003c0.148.0\u003e) connected to MQTT server now.\nWe have defined callback function (CBF) for this connection. This function will act as 'application' \nfrom MQTT protocol terminology. When client receives message or some events\nfrom server then callback function will be invoked and the message will be passed to it.\nSee detailed explanation of CBF below.\nYou can see on console lines starting with output like this:\n\n```erlang\n20:20:03.952 [info] ...\n```\nThis is Lager's output log statement from mqtt_client application. By default Lager is configured \nto output to console.\n\nLet's create one more client with different client Id and connect it to the same MQTT server. This new\ninstance of client we will use as a subscriber to receive messages from the publisher created above:\n\n```erlang\n6\u003e Subscriber_pid = mqtt_client:create(subscriber).\n\u003c0.188.0\u003e\n7\u003e Conn_def_subs = Conn_def#connect{client_id = \"subscriber\"}.\n#connect{client_id = \"subscriber\",user_name = \"guest\",\n         password = \u003c\u003c\"guest\"\u003e\u003e,host = \"lucky3p.com\",port = 8880,\n         will_publish = undefined,clean_session = 1,\n         keep_alive = 6000,properties = [],version = '5.0',\n         conn_type = web_socket}\n8\u003e ok = mqtt_client:connect(subscriber, Conn_def_subs, fun(Event, Argument) -\u003e  io:fwrite(user,\"Subscriber:: Event:~p Arg:~p~n\", [Event, Argument]) end).\nok\nSubscriber:: Event:onConnect Arg:{0,\"Success\",[]}\n20:23:56.090 [info] [ClId:\u003c\u003c\"subscriber\"\u003e\u003e PkId:none Op:connack Vrs:'5.0'] client is successfuly connected to {70,133,222,59}:8880\n9\u003e\n```\n\n## Subscribe and publish\n\nTo finish set up of the subscriber connection we need to subscribe it to some topic for example \"Test\" topic and QoS = 1:\n\n```erlang\n9\u003e mqtt_client:subscribe(Subscriber_pid, [{\"Test\", 1}]).\nok\nSubscriber:: Event:onSubscribe Arg:{[1],[]}\n20:25:39.102 [info] [ClId:\u003c\u003c\"subscriber\"\u003e\u003e PkId:100 Op:suback Vrs:'5.0'] process subscribed to topics [{\"Test\",{subscription_options,1,0,0,0,0}}] with return codes: [1]\n10\u003e\n```\nNow we can publish message to \"Test\" topic.\n\n```erlang\n10\u003e mqtt_client:publish(Publisher_pid, #publish{topic = \"Test\"}, \u003c\u003c\"Test Message Payload.\"\u003e\u003e).\nok\n20:28:15.125 [info] [ClId:\u003c\u003c\"publisher\"\u003e\u003e PkId:none Op:publish Vrs:'5.0']Process published message to topic=\"Test\":0\n```\nAfter short moment subscriber receives this message and fire callback function:\n\n```erlang\nSubscriber:: Event:onReceive Arg:{{subscription_options,1,0,0,0,0},\n                                  {publish,\"Test\",0,0,0,\n                                      \u003c\u003c\"Test Message Payload.\"\u003e\u003e,[],none,in,\n                                      infinity}}\n20:28:15.133 [info] [ClId:\u003c\u003c\"subscriber\"\u003e\u003e PkId:none Op:publish Vrs:'5.0'] process send publish message to client application [topic \"Test\":0, dup=0, retain=0]\n11\u003e \n```\nCallback function has two arguments. First argument is an atom that represents type of event triggered for the client.\nSecond argument is an error description or received message:\n\n```erlang\nArg = {Topic_QoS, Message#publish{}}\n```\n@todo: configuration, callback function details\n\n## TLS/SSL and Web socket Connection\n\nTo establish TCP connection secured by TLS/SSL or web-socket connection \nwe need to assign to record field #connect.conn_type a corresponded value:\n\nconn_type description\n'clear'\n'ssl' or 'tls' \n'web_socket' \n'web_sec_socket'\n\nNote that we need to set up corresponded port. How configure Mosquitto server\n[see here](https://dzone.com/articles/secure-communication-with-tls-and-the-mosquitto-broker/).\nIf we want to pass additional properties to SSL application on client side we can do it using options list:\n\n```erlang\n11\u003e ok = mqtt_client:connect(subscriber, Conn_def_subs, \n11\u003e fun(Event, Argument) -\u003e  io:fwrite(user,\"Subscriber:: Event:~p Arg:~p~n\", [Event, Argument]) end, \n11\u003e [{certfile,\"client.crt\"}, {verify, verify_none}]).\n```\n\n## References\n\n1. [https://mosquitto.org/] - Mosquitto MQTT server.\n2. [https://www.rabbitmq.com/] - RabbitMQ server with MQTT plugin.\n3. [https://sourceforge.net/projects/mqtt-server/] - Erlang MQTT server.\n4. [http://www.hivemq.com/demos/websocket-client/] - MQTT websocket client.\n5. [http://www.mqttfx.org/] - MQTT client.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falekras%2Fmqtt_client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falekras%2Fmqtt_client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falekras%2Fmqtt_client/lists"}