Skip to content

Commit b68dd52

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

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-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: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ static const char *const unsubscribe_failed_atom = ATOM_STR("\x12", "unsu
6161
static const char *const unsubscribed_atom = ATOM_STR("\xC", "unsubscribed");
6262
static const char *const url_atom = ATOM_STR("\x3", "url");
6363
static const char *const username_atom = ATOM_STR("\x8", "username");
64+
static const char *const client_id_atom = ATOM_STR("\x9", "client_id");
6465

6566
// error codes
6667
static const char *const bad_username_atom = ATOM_STR("\x0C", "bad_username");
@@ -700,12 +701,11 @@ void atomvm_mqtt_client_init(GlobalContext *global)
700701
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
701702
}
702703

703-
// NB. Caller assumes ownership of returned string
704-
static char *maybe_get_string(term kv, AtomString key, GlobalContext *global)
704+
static char* maybe_get_string_or_default(term kv, AtomString key, char* default_value, GlobalContext *global)
705705
{
706706
term value_term = interop_kv_get_value(kv, key, global);
707707
if (!term_is_string(value_term) && !term_is_binary(value_term)) {
708-
return NULL;
708+
return default_value;
709709
}
710710

711711
int ok;
@@ -717,6 +717,12 @@ static char *maybe_get_string(term kv, AtomString key, GlobalContext *global)
717717
return value_str;
718718
}
719719

720+
// NB. Caller assumes ownership of returned string
721+
static char *maybe_get_string(term kv, AtomString key, GlobalContext *global)
722+
{
723+
return maybe_get_string_or_default(kv, key, NULL, global);
724+
}
725+
720726
// NB. Caller assumes ownership of returned string
721727
// static char *get_string_default(term kv, AtomString key, AtomString default_value, GlobalContext *global)
722728
// {
@@ -785,16 +791,23 @@ Context *atomvm_mqtt_client_create_port(GlobalContext *global, term opts)
785791
UNUSED(port);
786792
char *username_str = maybe_get_string(opts, username_atom, global);
787793
char *password_str = maybe_get_string(opts, password_atom, global);
788-
// char *cert_str = maybe_get_string(opts, cert_atom, global);
794+
char *client_id = maybe_get_string_or_default(opts, client_id_atom, get_default_client_id(), global);
789795

790796
// Note that char * values passed into this struct are copied into the MQTT state
791-
const char *client_id = get_default_client_id();
792797
esp_mqtt_client_config_t mqtt_cfg = {
793798
#if ESP_IDF_VERSION_MAJOR >= 5
794799
.broker.address.uri = url_str,
795-
.credentials.client_id = client_id
800+
.credentials = {
801+
.username = username_str,
802+
.client_id = client_id,
803+
.authentication = {
804+
.password = password_str
805+
}
806+
},
796807
#else
797808
.uri = url_str,
809+
.username = username_str,
810+
.password = password_str
798811
.client_id = client_id,
799812
.user_context = (void *) ctx
800813
#endif
@@ -805,6 +818,7 @@ Context *atomvm_mqtt_client_create_port(GlobalContext *global, term opts)
805818
free(host_str);
806819
free(username_str);
807820
free(password_str);
821+
free(client_id);
808822

809823
if (UNLIKELY(IS_NULL_PTR(client))) {
810824
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)