Skip to content

Commit 60b6d78

Browse files
committed
feat[auth, client-id]: support username/password authentication; support
custom mqtt client ids
1 parent b4c79d4 commit 60b6d78

File tree

4 files changed

+32
-11
lines changed

4 files changed

+32
-11
lines changed

examples/mqtt_client_example/src/mqtt_client_example.erl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ start() ->
2727
%% Start the MQTT client.
2828
%%
2929
Config = #{
30-
url => "mqtt://mqtt.eclipseprojects.io",
30+
url => "mqtt://broker.hivemq.com",
31+
% username => "some-user", % optional
32+
% password => "some-password", % optional)
33+
% client_id => "atomvm-client", % optional (generated if missing)
3134
connected_handler => fun handle_connected/1
3235
},
3336
{ok, _MQTT} = mqtt_client:start(Config),

markdown/mqtt_client.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ The input parameter to the `start/1` function is an Erlang `map` structure, cont
6363

6464
%% erlang
6565
Config = #{
66-
url => "mqtt://mqtt.eclipseprojects.io",
66+
url => "mqtt://broker.hivemq.com",
6767
connected_handler => fun handle_connected/1,
6868
disconnected_handler => fun handle_disconnected/1,
6969
error_handler => handle_error/2

ports/atomvm_mqtt_client.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//
1717

1818
#include "atomvm_mqtt_client.h"
19+
#include "smp.h"
1920

2021
#include <atom.h>
2122
#include <bif.h>
@@ -61,6 +62,7 @@ static const char *const unsubscribe_failed_atom = ATOM_STR("\x12", "unsu
6162
static const char *const unsubscribed_atom = ATOM_STR("\xC", "unsubscribed");
6263
static const char *const url_atom = ATOM_STR("\x3", "url");
6364
static const char *const username_atom = ATOM_STR("\x8", "username");
65+
static const char *const client_id_atom = ATOM_STR("\x9", "client_id");
6466

6567
// error codes
6668
static const char *const bad_username_atom = ATOM_STR("\x0C", "bad_username");
@@ -700,12 +702,11 @@ void atomvm_mqtt_client_init(GlobalContext *global)
700702
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
701703
}
702704

703-
// NB. Caller assumes ownership of returned string
704-
static char *maybe_get_string(term kv, AtomString key, GlobalContext *global)
705+
static char* maybe_get_string_or_default(term kv, AtomString key, char* default_value, GlobalContext *global)
705706
{
706707
term value_term = interop_kv_get_value(kv, key, global);
707708
if (!term_is_string(value_term) && !term_is_binary(value_term)) {
708-
return NULL;
709+
return default_value;
709710
}
710711

711712
int ok;
@@ -717,6 +718,12 @@ static char *maybe_get_string(term kv, AtomString key, GlobalContext *global)
717718
return value_str;
718719
}
719720

721+
// NB. Caller assumes ownership of returned string
722+
static char *maybe_get_string(term kv, AtomString key, GlobalContext *global)
723+
{
724+
return maybe_get_string_or_default(kv, key, NULL, global);
725+
}
726+
720727
// NB. Caller assumes ownership of returned string
721728
// static char *get_string_default(term kv, AtomString key, AtomString default_value, GlobalContext *global)
722729
// {
@@ -785,16 +792,23 @@ Context *atomvm_mqtt_client_create_port(GlobalContext *global, term opts)
785792
UNUSED(port);
786793
char *username_str = maybe_get_string(opts, username_atom, global);
787794
char *password_str = maybe_get_string(opts, password_atom, global);
788-
// char *cert_str = maybe_get_string(opts, cert_atom, global);
795+
char *client_id = maybe_get_string_or_default(opts, client_id_atom, get_default_client_id(), global);
789796

790797
// Note that char * values passed into this struct are copied into the MQTT state
791-
const char *client_id = get_default_client_id();
792798
esp_mqtt_client_config_t mqtt_cfg = {
793799
#if ESP_IDF_VERSION_MAJOR >= 5
794800
.broker.address.uri = url_str,
795-
.credentials.client_id = client_id
801+
.credentials = {
802+
.username = username_str,
803+
.client_id = client_id,
804+
.authentication = {
805+
.password = password_str
806+
}
807+
},
796808
#else
797809
.uri = url_str,
810+
.username = username_str,
811+
.password = password_str
798812
.client_id = client_id,
799813
.user_context = (void *) ctx
800814
#endif
@@ -805,6 +819,7 @@ Context *atomvm_mqtt_client_create_port(GlobalContext *global, term opts)
805819
free(host_str);
806820
free(username_str);
807821
free(password_str);
822+
free(client_id);
808823

809824
if (UNLIKELY(IS_NULL_PTR(client))) {
810825
ESP_LOGE(TAG, "Error: Unable to initialize MQTT client.\n");

src/mqtt_client.erl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@
9292
error_handler => fun((mqtt(), error()) -> any()),
9393
username => binary_or_string(),
9494
password => binary_or_string(),
95-
client_id => binary_or_string(),
96-
trusted_cert => binary_or_string()
95+
client_id => binary_or_string()
9796
}.
9897

9998
-type error_type() :: esp_tls | connection_refused | undefined.
@@ -494,7 +493,11 @@ init(Config) ->
494493
try
495494
Self = self(),
496495
Port = erlang:open_port({spawn, "atomvm_mqtt_client"}, [
497-
{receiver, Self}, {url, maps:get(url, Config)}
496+
{receiver, Self},
497+
{url, maps:get(url, Config)},
498+
{username, maps:get(username, Config)},
499+
{password, maps:get(password, Config)},
500+
{client_id, maps:get(client_id, Config)}
498501
]),
499502
{ok, #state{
500503
port = Port,

0 commit comments

Comments
 (0)