MQTT-SN Client (Asymcute)

Asymcute is an asynchronous MQTT-SN implementation.

About

Asymcute is a asynchronous MQTT-SN client implementation, aiming at providing the user a high degree of flexibility. It provides a flexible interface that allows users to issue any number of concurrent requests to one or more different gateways simultaneously.

Implementation state

Implemented features:

  • Connecting to multiple gateways simultaneously
  • Registration of topic names
  • Publishing of data (QoS 0 and QoS 1)
  • Subscription to topics
  • Pre-defined topic IDs as well as short and normal topic names

Missing features:

  • Gateway discovery process not implemented
  • Last will feature not implemented
  • No support for QoS level 2
  • No support for wildcard characters in topic names when subscribing
  • Actual granted QoS level on subscription is ignored

enum @180
ASYMCUTE_OK =  0
all is good
ASYMCUTE_OVERFLOW = -1
error: insufficient buffer space
ASYMCUTE_GWERR = -2
error: bad gateway connection state
ASYMCUTE_NOTSUP = -3
error: feature not supported
ASYMCUTE_BUSY = -4
error: context already in use
ASYMCUTE_REGERR = -5
error: registration invalid
ASYMCUTE_SUBERR = -6
error: subscription invalid
enum @181
ASYMCUTE_TIMEOUT
request timed out
ASYMCUTE_CANCELED
request was canceled
ASYMCUTE_REJECTED
request was rejected
ASYMCUTE_CONNECTED
connected to gateway
ASYMCUTE_DISCONNECTED
connection got disconnected
ASYMCUTE_REGISTERED
topic was registered
ASYMCUTE_PUBLISHED
data was published
ASYMCUTE_SUBSCRIBED
client was subscribed to topic
ASYMCUTE_UNSUBSCRIBED
client was unsubscribed from topic
struct asymcute_con asymcute_con_t

Forward type declaration for connections contexts.

struct asymcute_req asymcute_req_t

Forward type declaration for request contexts.

struct asymcute_sub asymcute_sub_t

Forward type declaration for subscription contexts.

struct asymcute_topic asymcute_topic_t

Forward type declaration for topic definitions.

struct asymcute_will asymcute_will_t

Forward type declaration for last will definitions.

void(* asymcute_evt_cb_t()

Event callback used for communicating connection and request related events to the user.

Parameters

req:pointer to the request context that triggered the event, may be NULL of unsolicited events
evt_type:type of the event

void(* asymcute_sub_cb_t()

Callback triggered on events for active subscriptions.

Parameters

sub:pointer to subscription context triggering this event
evt_type:type of the event
data:incoming data for PUBLISHED events, may be NULL
len:length of data in bytes
arg:user supplied argument

unsigned(* asymcute_to_cb_t()

Context specific timeout callback, only used internally.

bool asymcute_req_in_use(const asymcute.h::asymcute_req_t * req)

Check if a given request context is currently used.

Parameters

req:request context to check

Return values

  • true if context is currently used
  • false if context is not used
bool asymcute_sub_active(const asymcute.h::asymcute_sub_t * sub)

Check if a given subscription is currently active.

Parameters

sub:subscription context to check

Return values

  • true if subscription is active
  • false if subscription is not active
void asymcute_topic_reset(asymcute.h::asymcute_topic_t * topic)

Reset the given topic.

Parameters

topic:topic to reset

bool asymcute_topic_is_reg(const asymcute.h::asymcute_topic_t * topic)

Check if a given topic is currently registered with a gateway.

Parameters

topic:topic to check

Return values

  • true if topic is registered
  • false if topic is not registered
bool asymcute_topic_is_init(const asymcute.h::asymcute_topic_t * topic)

Check if a given topic is initialized.

Parameters

topic:topic to check

Return values

  • true if topic is initialized
  • false if topic is not initialized
bool asymcute_topic_equal(const asymcute.h::asymcute_topic_t * a, const asymcute.h::asymcute_topic_t * b)

Compare two given topics and check if they are equal.

Parameters

a:topic A
b:topic B

Return values

  • true if both topics are equal
  • false if topics differ
int asymcute_topic_init(asymcute.h::asymcute_topic_t * topic, const char * topic_name, uint16_t topic_id)

Initialize the given topic.

Parameters

topic:topic to initialize
topic_name:topic name (ASCII), may be NULL if topic should use a pre-defined topic ID
topic_id:pre-defined topic ID, or don’t care if topic_name is given

Return values

  • ASYMCUTE_OK on success
  • ASYMCUTE_REGERR if topic is already registered
  • ASYMCUTE_OVERFLOW if topic name does not fit into buffer or if pre- defined topic ID is invalid
int asymcute_listener_run(asymcute.h::asymcute_con_t * con, char * stack, msp430_types.h::size_t stacksize, char priority, asymcute.h::asymcute_evt_cb_t callback)

Start a listener thread.

Note

Must have higher priority then the handler thread (defined by asymcute.h::ASYMCUTE_HANDLER_PRIO)

Parameters

con:connection context to use for this connection
stack:stack used to run the listener thread
stacksize:size of stack in bytes
priority:priority of the listener thread created by this function
callback:user callback for notification about connection related events

Return values

  • ASYMCUTE_OK on success
  • ASYMCUTE_BUSY if connection context is already in use
void asymcute_handler_run(void)

Start the global Asymcute handler thread for processing timeouts and keep alive events.

This function is typically called during system initialization.

bool asymcute_is_connected(const asymcute.h::asymcute_con_t * con)

Check if the given connection context is connected to a gateway.

Parameters

con:connection to check

Return values

  • true if context is connected
  • false if not connected
int asymcute_connect(asymcute.h::asymcute_con_t * con, asymcute.h::asymcute_req_t * req, sock/udp.h::sock_udp_ep_t * server, const char * cli_id, bool clean, asymcute.h::asymcute_will_t * will)

Connect to the given MQTT-SN gateway.

Parameters

con:connection to use
req:request context to use for CONNECT procedure
server:UDP endpoint of the target gateway
cli_id:client ID to register with the gateway
clean:set true to start a clean session
will:last will (currently not implemented)

Return values

  • ASYMCUTE_OK if CONNECT message has been sent
  • ASYMCUTE_NOTSUP if last will was given (temporary until implemented)
  • ASYMCUTE_OVERFLOW if cli_id is larger than ASYMCUTE_ID_MAXLEN
  • ASYMCUTE_GWERR if the connection is not in idle state
  • ASYMCUTE_BUSY if the given request context is already in use
int asymcute_disconnect(asymcute.h::asymcute_con_t * con, asymcute.h::asymcute_req_t * req)

Close the given connection.

Parameters

con:connection to close
req:request context to use for DISCONNECT procedure

Return values

  • ASYMCUTE_OK if DISCONNECT message has been sent
  • ASYMCUTE_GWERR if connection context is not connected
  • ASYMCUTE_BUSY if the given request context is already in use
int asymcute_register(asymcute.h::asymcute_con_t * con, asymcute.h::asymcute_req_t * req, asymcute.h::asymcute_topic_t * topic)

Register a given topic with the connected gateway.

Parameters

con:connection to use
req:request context to use for REGISTER procedure
topic:topic to register

Return values

  • ASYMCUTE_OK if REGISTER message has been sent
  • ASYMCUTE_REGERR if topic is already registered
  • ASYMCUTE_GWERR if not connected to a gateway
  • ASYMCUTE_BUSY if the given request context is already in use
int asymcute_publish(asymcute.h::asymcute_con_t * con, asymcute.h::asymcute_req_t * req, const asymcute.h::asymcute_topic_t * topic, const void * data, msp430_types.h::size_t data_len, uint8_t flags)

Publish the given data to the given topic.

Parameters

con:connection to use
req:request context used for PUBLISH procedure
topic:publish data to this topic
data:actual payload to send
data_len:size of data in bytes
flags:additional flags (QoS level, DUP, and RETAIN)

Return values

  • ASYMCUTE_OK if PUBLISH message has been sent
  • ASYMCUTE_NOTSUP if unsupported flags have been set
  • ASYMCUTE_OVERFLOW if data does not fit into transmit buffer
  • ASYMCUTE_REGERR if given topic is not registered
  • ASYMCUTE_GWERR if not connected to a gateway
  • ASYMCUTE_BUSY if the given request context is already in use
int asymcute_subscribe(asymcute.h::asymcute_con_t * con, asymcute.h::asymcute_req_t * req, asymcute.h::asymcute_sub_t * sub, asymcute.h::asymcute_topic_t * topic, asymcute.h::asymcute_sub_cb_t callback, void * arg, uint8_t flags)

Subscribe to a given topic.

Parameters

con:connection to use
req:request context used for SUBSCRIBE procedure
sub:subscription context to store subscription state
topic:topic to subscribe to, must be initialized (see asymcute.h::asymcute_topic_init())
callback:user callback triggered on events for this subscription
arg:user supplied argument passed to the event callback
flags:additional flags (QoS level and DUP)

Return values

  • ASYMCUTE_OK if SUBSCRIBE message has been sent
  • ASYMCUTE_NOTSUP if invalid or unsupported flags have been set
  • ASYMCUTE_REGERR if topic is not initialized
  • ASYMCUTE_GWERR if not connected to a gateway
  • ASYMCUTE_SUBERR if already subscribed to the given topic
  • ASYMCUTE_BUSY if the given request context is already in use
int asymcute_unsubscribe(asymcute.h::asymcute_con_t * con, asymcute.h::asymcute_req_t * req, asymcute.h::asymcute_sub_t * sub)

Cancel an active subscription.

Parameters

con:connection to use
req:request context used for UNSUBSCRIBE procedure
sub:subscription to cancel

Return values

  • ASYMCUTE_OK if UNSUBSCRIBE message has been sent
  • ASYMCUTE_SUBERR if subscription is not currently active
  • ASYMCUTE_GWERR if not connected to a gateway
  • ASYMCUTE_BUSY if the given request context is already in use
ASYMCUTE_BUFSIZE

Default buffer size used for receive and request buffers.

1
(128U)
ASYMCUTE_HANDLER_PRIO

Default priority for Asymcute’s handler thread.

1
(THREAD_PRIORITY_MAIN - 2)
ASYMCUTE_HANDLER_STACKSIZE

Default stack size for Asymcute’s handler thread.

1
(THREAD_STACKSIZE_DEFAULT)
ASYMCUTE_LISTENER_PRIO

Default priority for an Asymcute listener thread.

1
(THREAD_PRIORITY_MAIN - 3)

Note

Must be of higher priority than asymcute.h::ASYMCUTE_HANDLER_PRIO

ASYMCUTE_LISTENER_STACKSIZE

Default stack size for an Asymcute listener thread.

1
(THREAD_STACKSIZE_DEFAULT)
ASYMCUTE_ID_MAXLEN

Maximum client ID length.

1
(32U)

Note

Must be less than (256 - 8) and less than (ASYMCUTE_BUFSIZE - 8)

ASYMCUTE_TOPIC_MAXLEN

Maximum topic length.

1
(32U)

Note

Must be less than (256 - 8) AND less than (ASYMCUTE_BUFSIZE - 8).

ASYMCUTE_KEEPALIVE

Keep alive interval [in s] communicated to the gateway.

1
(360)       /* -> 6 min*/

For the default value, see spec v1.2, section 7.2 -> T_WAIT: > 5 min

ASYMCUTE_KEEPALIVE_PING

Interval to use for sending periodic ping messages.

1
((ASYMCUTE_KEEPALIVE / 4) * 3)

The default behavior of this implementation is to send ping messages as soon as three quarters of the keep alive interval have passed.

Note

Must be less than ASYMCUTE_KEEPALIVE

ASYMCUTE_T_RETRY

Resend interval [in seconds].

1
(10U)       /* -> 10 sec */

For the default value, see spec v1.2, section 7.2 -> T_RETRY: 10 to 15 sec

ASYMCUTE_N_RETRY

Number of retransmissions until requests time out.

1
(3U)

For the default value, see spec v1.2, section 7.2 -> N_RETRY: 3-5

struct asymcute_req

Asymcute request context.

mutex_t lock

synchronization lock

struct asymcute_req * next

the requests list entry

asymcute.h::asymcute_con_t * con

connection the request is using

asymcute.h::asymcute_to_cb_t cb

internally used callback

void * arg

internally used additional state

event_callback_t to_evt

timeout event

event_timeout_t to_timer

timeout timer

uint8_t data()

buffer holding the request’s data

msp430_types.h::size_t data_len

length of the request packet in byte

uint16_t msg_id

used message id for this request

uint8_t retry_cnt

retransmission counter

struct asymcute_con

Asymcute connection context.

mutex_t lock

synchronization lock

sock/udp.h::sock_udp_t sock

socket used by a connections

sock/udp.h::sock_udp_ep_t server_ep

the gateway’s UDP endpoint

asymcute.h::asymcute_req_t * pending

list holding pending requests

asymcute.h::asymcute_sub_t * subscriptions

list holding active subscriptions

asymcute.h::asymcute_evt_cb_t user_cb

event callback provided by user

event_callback_t keepalive_evt

keep alive event

event_timeout_t keepalive_timer

keep alive timer

uint16_t last_id

last used message ID for this connection

uint8_t keepalive_retry_cnt

keep alive transmission counter

uint8_t state

connection state

uint8_t rxbuf()

connection specific receive buf

char cli_id()

buffer to store client ID

struct asymcute_topic

Data-structure for holding topics and their registration status.

asymcute.h::asymcute_con_t * con

connection used for registration

char name()

topic string (ACSII only)

uint8_t flags

normal, short, or pre-defined

uint16_t id

topic id

struct asymcute_sub

Data-structure holding the state of subscriptions.

asymcute.h::asymcute_sub_t * next

the subscriptions list entry

asymcute.h::asymcute_topic_t * topic

topic we subscribe to

asymcute.h::asymcute_sub_cb_t cb

called on incoming data

void * arg

user supplied callback argument

struct asymcute_will

Data structure for defining a last will.

const char * topic

last will topic

void * msg

last will message content

msp430_types.h::size_t msg_len

length of last will message content