Hello,
I try to transfer the thread_mqtt_sn_client_publisher example from the pca10056 to the pca10059.
Before that, I tried out the example with the pca10056, a boarder router (RPi + pca10059) and homeassistant server. I was able to send a message via mqttsn by pressing a button on the DK to homeassistant. Everthing worked as expected.
Now I want to do the same with the pca10059. But since I have not enough buttons on the dongle, I tried to connect to the network within my main with some time to wait for each step and then periodically publish a message:
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "app_scheduler.h"
#include "app_timer.h"
#include "bsp_thread.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_delay.h"
#include "mqttsn_client.h"
#include "thread_utils.h"
#include <openthread/thread.h>
#define SEARCH_GATEWAY_TIMEOUT 5 /**< MQTT-SN Gateway discovery procedure timeout in [s]. */
#define SCHED_QUEUE_SIZE 32 /**< Maximum number of events in the scheduler queue. */
#define SCHED_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum app_scheduler event size. */
static mqttsn_client_t m_client; /**< An MQTT-SN client instance. */
static mqttsn_remote_t m_gateway_addr; /**< A gateway address. */
static uint8_t m_gateway_id; /**< A gateway ID. */
static mqttsn_connect_opt_t m_connect_opt; /**< Connect options for the MQTT-SN client. */
static uint8_t m_led_state = 0; /**< Previously sent BSP_LED_2 command. */
static uint16_t m_msg_id = 0; /**< Message ID thrown with MQTTSN_EVENT_TIMEOUT. */
static char m_client_id[] = "nRF52840_publisher"; /**< The MQTT-SN Client's ID. */
static char m_topic_name[] = "nRF52840_resources/led3"; /**< Name of the topic corresponding to subscriber's BSP_LED_2. */
static mqttsn_topic_t m_topic = /**< Topic corresponding to subscriber's BSP_LED_2. */
{
.p_topic_name = (unsigned char *)m_topic_name,
.topic_id = 0,
};
/***************************************************************************************************
* @section MQTT-SN
**************************************************************************************************/
/**@brief Turns the MQTT-SN network indication LED on.
*
* @details This LED is on when an MQTT-SN client is in connected or awake state.
*/
static void light_on(void)
{
LEDS_ON(BSP_LED_3_MASK);
}
/**@brief Turns the MQTT-SN network indication LED off.
*
* @details This LED is on when an MQTT-SN client is in disconnected or asleep state.
*/
static void light_off(void)
{
LEDS_OFF(BSP_LED_3_MASK);
}
/**@brief Initializes MQTT-SN client's connection options.
*/
static void connect_opt_init(void)
{
m_connect_opt.alive_duration = MQTTSN_DEFAULT_ALIVE_DURATION,
m_connect_opt.clean_session = MQTTSN_DEFAULT_CLEAN_SESSION_FLAG,
m_connect_opt.will_flag = MQTTSN_DEFAULT_WILL_FLAG,
m_connect_opt.client_id_len = strlen(m_client_id),
memcpy(m_connect_opt.p_client_id, (unsigned char *)m_client_id, m_connect_opt.client_id_len);
}
/**@brief Processes GWINFO message from a gateway.
*
* @details This function updates MQTT-SN Gateway information.
*
* @param[in] p_event Pointer to MQTT-SN event.
*/
static void gateway_info_callback(mqttsn_event_t * p_event)
{
m_gateway_addr = *(p_event->event_data.connected.p_gateway_addr);
m_gateway_id = p_event->event_data.connected.gateway_id;
}
/**@brief Processes CONNACK message from a gateway.
*
* @details This function launches the topic registration procedure if necessary.
*/
static void connected_callback(void)
{
light_on();
uint32_t err_code = mqttsn_client_topic_register(&m_client,
m_topic.p_topic_name,
strlen(m_topic_name),
&m_msg_id);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("REGISTER message could not be sent. Error code: 0x%x\r\n", err_code);
}
}
/**@brief Processes DISCONNECT message from a gateway. */
static void disconnected_callback(void)
{
light_off();
}
/**@brief Processes REGACK message from a gateway.
*
* @param[in] p_event Pointer to MQTT-SN event.
*/
static void regack_callback(mqttsn_event_t * p_event)
{
m_topic.topic_id = p_event->event_data.registered.packet.topic.topic_id;
NRF_LOG_INFO("MQTT-SN event: Topic has been registered with ID: %d.\r\n",
p_event->event_data.registered.packet.topic.topic_id);
}
/**@brief Processes retransmission limit reached event. */
static void timeout_callback(mqttsn_event_t * p_event)
{
NRF_LOG_INFO("MQTT-SN event: Timed-out message: %d. Message ID: %d.\r\n",
p_event->event_data.error.msg_type,
p_event->event_data.error.msg_id);
}
/**@brief Processes results of gateway discovery procedure. */
static void searchgw_timeout_callback(mqttsn_event_t * p_event)
{
NRF_LOG_INFO("MQTT-SN event: Gateway discovery result: 0x%x.\r\n", p_event->event_data.discovery);
}
/**@brief Function for handling MQTT-SN events. */
void mqttsn_evt_handler(mqttsn_client_t * p_client, mqttsn_event_t * p_event)
{
switch(p_event->event_id)
{
case MQTTSN_EVENT_GATEWAY_FOUND:
NRF_LOG_INFO("MQTT-SN event: Client has found an active gateway.\r\n");
gateway_info_callback(p_event);
break;
case MQTTSN_EVENT_CONNECTED:
NRF_LOG_INFO("MQTT-SN event: Client connected.\r\n");
connected_callback();
break;
case MQTTSN_EVENT_DISCONNECT_PERMIT:
NRF_LOG_INFO("MQTT-SN event: Client disconnected.\r\n");
disconnected_callback();
break;
case MQTTSN_EVENT_REGISTERED:
NRF_LOG_INFO("MQTT-SN event: Client registered topic.\r\n");
regack_callback(p_event);
break;
case MQTTSN_EVENT_PUBLISHED:
NRF_LOG_INFO("MQTT-SN event: Client has successfully published content.\r\n");
break;
case MQTTSN_EVENT_TIMEOUT:
NRF_LOG_INFO("MQTT-SN event: Retransmission retries limit has been reached.\r\n");
timeout_callback(p_event);
break;
case MQTTSN_EVENT_SEARCHGW_TIMEOUT:
NRF_LOG_INFO("MQTT-SN event: Gateway discovery procedure has finished.\r\n");
searchgw_timeout_callback(p_event);
break;
default:
break;
}
}
/***************************************************************************************************
* @section State
**************************************************************************************************/
static void state_changed_callback(uint32_t flags, void * p_context)
{
NRF_LOG_INFO("State changed! Flags: 0x%08x Current role: %d\r\n",
flags, otThreadGetDeviceRole(p_context));
}
/***************************************************************************************************
* @section Buttons
**************************************************************************************************/
static void publish(void)
{
uint32_t err_code = mqttsn_client_publish(&m_client, m_topic.topic_id, "Hello", 1, &m_msg_id);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("PUBLISH message could not be sent. Error code: 0x%x\r\n", err_code)
}
}
/***************************************************************************************************
* @section Initialization
**************************************************************************************************/
/**@brief Function for initializing the Application Timer Module.
*/
static void timer_init(void)
{
uint32_t err_code = app_timer_init();
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the LEDs.
*/
static void leds_init(void)
{
LEDS_CONFIGURE(LEDS_MASK);
LEDS_OFF(LEDS_MASK);
}
/**@brief Function for initializing the nrf log module.
*/
static void log_init(void)
{
ret_code_t err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
}
/**@brief Function for initializing the Thread Stack.
*/
static void thread_instance_init(void)
{
thread_configuration_t thread_configuration =
{
.radio_mode = THREAD_RADIO_MODE_RX_ON_WHEN_IDLE,
.autocommissioning = true,
.autostart_disable = false,
};
thread_init(&thread_configuration);
thread_cli_init();
thread_state_changed_callback_set(state_changed_callback);
}
/**@brief Function for initializing the MQTTSN client.
*/
static void mqttsn_init(void)
{
uint32_t err_code = mqttsn_client_init(&m_client,
MQTTSN_DEFAULT_CLIENT_PORT,
mqttsn_evt_handler,
thread_ot_instance_get());
APP_ERROR_CHECK(err_code);
connect_opt_init();
}
/**@brief Function for initializing scheduler module.
*/
static void scheduler_init(void)
{
APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
}
int main(int argc, char *argv[])
{
log_init();
scheduler_init();
timer_init();
leds_init();
thread_instance_init();
thread_bsp_init();
mqttsn_init();
nrf_delay_ms(10000);
mqttsn_client_search_gateway(&m_client, SEARCH_GATEWAY_TIMEOUT);
nrf_delay_ms(10000);
mqttsn_client_connect(&m_client, &m_gateway_addr, m_gateway_id, &m_connect_opt);
nrf_delay_ms(10000);
while (true)
{
thread_process();
app_sched_execute();
if (NRF_LOG_PROCESS() == false)
{
thread_sleep();
}
nrf_delay_ms(2000);
publish();
}
}
Unfortunately, I dont receive any input, when I start listining to the topic in homeassistant.
What do I have to consider, when transferring the code to the dongle.
I changed everything in the makefile and linker script to fit the specifications of the dongle.
Regards
Maboo
Ps: I use Linux, SDK17, VS-Code, pca10059