get mqtt_client building
This commit is contained in:
parent
4b09a8611b
commit
d70d551638
5 changed files with 544 additions and 1 deletions
|
|
@ -41,3 +41,65 @@ target_link_libraries(wifi_scan
|
|||
)
|
||||
|
||||
pico_add_extra_outputs(wifi_scan)
|
||||
|
||||
|
||||
# Define the host name of the MQTT server in an environment variable or pass it to cmake,
|
||||
# e.g. cmake -DMQTT_SERVER=myserver ..
|
||||
|
||||
if ((NOT MQTT_SERVER) OR (NOT MQTT_USERNAME) OR (NOT MQTT_PASSWORD))
|
||||
message("Missing MQTT_SERVER or MQTT_USERNAME or MQTT_PASSWORD")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(MQTT_SERVER "${MQTT_SERVER}" CACHE INTERNAL "MQTT server")
|
||||
set(MQTT_USERNAME "${MQTT_USERNAME}" CACHE INTERNAL "MQTT user name")
|
||||
set(MQTT_PASSWORD "${MQTT_PASSWORD}" CACHE INTERNAL "MQTT password")
|
||||
set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "wifi ssid")
|
||||
set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "wifi password")
|
||||
|
||||
# Set path to the certificate include file
|
||||
if (NOT MQTT_CERT_PATH)
|
||||
set(MQTT_CERT_PATH ${CMAKE_CURRENT_LIST_DIR}/certs/${MQTT_SERVER})
|
||||
endif()
|
||||
|
||||
# Set the name of the certificate include file
|
||||
if (NOT MQTT_CERT_INC)
|
||||
set(MQTT_CERT_INC mqtt_client.inc)
|
||||
endif()
|
||||
|
||||
set(TARGET_NAME mqtt_client)
|
||||
|
||||
add_executable(${TARGET_NAME}
|
||||
mqtt_client.c
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME}
|
||||
pico_stdlib
|
||||
hardware_adc
|
||||
pico_cyw43_arch_lwip_threadsafe_background
|
||||
pico_lwip_mqtt
|
||||
pico_mbedtls
|
||||
pico_lwip_mbedtls
|
||||
)
|
||||
|
||||
target_include_directories(${TARGET_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
|
||||
)
|
||||
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE
|
||||
WIFI_SSID=\"${WIFI_SSID}\"
|
||||
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
|
||||
MQTT_SERVER=\"${MQTT_SERVER}\"
|
||||
MQTT_USERNAME=\"${MQTT_USERNAME}\"
|
||||
MQTT_PASSWORD=\"${MQTT_PASSWORD}\"
|
||||
)
|
||||
|
||||
pico_add_extra_outputs(${TARGET_NAME})
|
||||
|
||||
# Ignore warnings from lwip code
|
||||
set_source_files_properties(
|
||||
${PICO_LWIP_PATH}/src/apps/altcp_tls/altcp_tls_mbedtls.c
|
||||
PROPERTIES
|
||||
COMPILE_OPTIONS "-Wno-unused-result"
|
||||
)
|
||||
|
|
|
|||
23
lwipopts.h
23
lwipopts.h
|
|
@ -1,10 +1,33 @@
|
|||
#ifndef _LWIPOPTS_H
|
||||
#define _LWIPOPTS_H
|
||||
|
||||
// Need more memory for TLS
|
||||
#ifdef MQTT_CERT_INC
|
||||
#define MEM_SIZE 8000
|
||||
#endif
|
||||
|
||||
// Generally you would define your own explicit list of lwIP options
|
||||
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html)
|
||||
//
|
||||
// This example uses a common include to avoid repetition
|
||||
#include "lwipopts_examples_common.h"
|
||||
|
||||
#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL+1)
|
||||
|
||||
#ifdef MQTT_CERT_INC
|
||||
#define LWIP_ALTCP 1
|
||||
#define LWIP_ALTCP_TLS 1
|
||||
#define LWIP_ALTCP_TLS_MBEDTLS 1
|
||||
#ifndef NDEBUG
|
||||
#define ALTCP_MBEDTLS_DEBUG LWIP_DBG_ON
|
||||
#endif
|
||||
/* TCP WND must be at least 16 kb to match TLS record size
|
||||
or you will get a warning "altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!" */
|
||||
#undef TCP_WND
|
||||
#define TCP_WND 16384
|
||||
#endif // MQTT_CERT_INC
|
||||
|
||||
// This defaults to 4
|
||||
#define MQTT_REQ_MAX_IN_FLIGHT 5
|
||||
|
||||
#endif
|
||||
6
mbedtls_config.h
Normal file
6
mbedtls_config.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef MBEDTLS_CONFIG_TLS_CLIENT_H
|
||||
#define MBEDTLS_CONFIG_TLS_CLIENT_H
|
||||
|
||||
#include "mbedtls_config_examples_common.h"
|
||||
|
||||
#endif
|
||||
74
mbedtls_config_examples_common.h
Normal file
74
mbedtls_config_examples_common.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef MBEDTLS_CONFIG_EXAMPLES_COMMON_H
|
||||
#define MBEDTLS_CONFIG_EXAMPLES_COMMON_H
|
||||
|
||||
/* Workaround for some mbedtls source files using INT_MAX without including limits.h */
|
||||
#include <limits.h>
|
||||
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
|
||||
#define MBEDTLS_SSL_OUT_CONTENT_LEN 2048
|
||||
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_SHA256_SMALLER
|
||||
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_ERROR_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PKCS5_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
#define MBEDTLS_AES_FEWER_TABLES
|
||||
|
||||
/* TLS 1.2 */
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#define MBEDTLS_GCM_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
|
||||
// The following is needed to parse a certificate
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
#define MBEDTLS_BASE64_C
|
||||
|
||||
// The following significantly speeds up mbedtls due to NIST optimizations.
|
||||
#define MBEDTLS_ECP_NIST_OPTIM
|
||||
|
||||
#endif
|
||||
378
mqtt_client.c
Normal file
378
mqtt_client.c
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
/**
|
||||
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by elliot on 25/05/24.
|
||||
//
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include "pico/unique_id.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "hardware/adc.h"
|
||||
#include "lwip/apps/mqtt.h"
|
||||
#include "lwip/apps/mqtt_priv.h" // needed to set hostname
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/altcp_tls.h"
|
||||
|
||||
// Temperature
|
||||
#ifndef TEMPERATURE_UNITS
|
||||
#define TEMPERATURE_UNITS 'C' // Set to 'F' for Fahrenheit
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_SERVER
|
||||
#error Need to define MQTT_SERVER
|
||||
#endif
|
||||
|
||||
// This file includes your client certificate for client server authentication
|
||||
#ifdef MQTT_CERT_INC
|
||||
#include MQTT_CERT_INC
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_TOPIC_LEN
|
||||
#define MQTT_TOPIC_LEN 100
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
mqtt_client_t* mqtt_client_inst;
|
||||
struct mqtt_connect_client_info_t mqtt_client_info;
|
||||
char data[MQTT_OUTPUT_RINGBUF_SIZE];
|
||||
char topic[MQTT_TOPIC_LEN];
|
||||
uint32_t len;
|
||||
ip_addr_t mqtt_server_address;
|
||||
bool connect_done;
|
||||
int subscribe_count;
|
||||
bool stop_client;
|
||||
} MQTT_CLIENT_DATA_T;
|
||||
|
||||
#ifndef DEBUG_printf
|
||||
#ifndef NDEBUG
|
||||
#define DEBUG_printf printf
|
||||
#else
|
||||
#define DEBUG_printf(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INFO_printf
|
||||
#define INFO_printf printf
|
||||
#endif
|
||||
|
||||
#ifndef ERROR_printf
|
||||
#define ERROR_printf printf
|
||||
#endif
|
||||
|
||||
// how often to measure our temperature
|
||||
#define TEMP_WORKER_TIME_S 10
|
||||
|
||||
// keep alive in seconds
|
||||
#define MQTT_KEEP_ALIVE_S 60
|
||||
|
||||
// qos passed to mqtt_subscribe
|
||||
// At most once (QoS 0)
|
||||
// At least once (QoS 1)
|
||||
// Exactly once (QoS 2)
|
||||
#define MQTT_SUBSCRIBE_QOS 1
|
||||
#define MQTT_PUBLISH_QOS 1
|
||||
#define MQTT_PUBLISH_RETAIN 0
|
||||
|
||||
// topic used for last will and testament
|
||||
#define MQTT_WILL_TOPIC "/online"
|
||||
#define MQTT_WILL_MSG "0"
|
||||
#define MQTT_WILL_QOS 1
|
||||
|
||||
#ifndef MQTT_DEVICE_NAME
|
||||
#define MQTT_DEVICE_NAME "pico"
|
||||
#endif
|
||||
|
||||
// Set to 1 to add the client name to topics, to support multiple devices using the same server
|
||||
#ifndef MQTT_UNIQUE_TOPIC
|
||||
#define MQTT_UNIQUE_TOPIC 0
|
||||
#endif
|
||||
|
||||
/* References for this implementation:
|
||||
* raspberry-pi-pico-c-sdk.pdf, Section '4.1.1. hardware_adc'
|
||||
* pico-examples/adc/adc_console/adc_console.c */
|
||||
static float read_onboard_temperature(const char unit) {
|
||||
|
||||
/* 12-bit conversion, assume max value == ADC_VREF == 3.3 V */
|
||||
const float conversionFactor = 3.3f / (1 << 12);
|
||||
|
||||
float adc = (float)adc_read() * conversionFactor;
|
||||
float tempC = 27.0f - (adc - 0.706f) / 0.001721f;
|
||||
|
||||
if (unit == 'C' || unit != 'F') {
|
||||
return tempC;
|
||||
} else if (unit == 'F') {
|
||||
return tempC * 9 / 5 + 32;
|
||||
}
|
||||
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
static void pub_request_cb(__unused void *arg, err_t err) {
|
||||
if (err != 0) {
|
||||
ERROR_printf("pub_request_cb failed %d", err);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *full_topic(MQTT_CLIENT_DATA_T *state, const char *name) {
|
||||
#if MQTT_UNIQUE_TOPIC
|
||||
static char full_topic[MQTT_TOPIC_LEN];
|
||||
snprintf(full_topic, sizeof(full_topic), "/%s%s", state->mqtt_client_info.client_id, name);
|
||||
return full_topic;
|
||||
#else
|
||||
return name;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void control_led(MQTT_CLIENT_DATA_T *state, bool on) {
|
||||
// Publish state on /state topic and on/off led board
|
||||
const char* message = on ? "On" : "Off";
|
||||
if (on)
|
||||
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
|
||||
else
|
||||
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
|
||||
|
||||
mqtt_publish(state->mqtt_client_inst, full_topic(state, "/led/state"), message, strlen(message), MQTT_PUBLISH_QOS, MQTT_PUBLISH_RETAIN, pub_request_cb, state);
|
||||
}
|
||||
|
||||
static void publish_temperature(MQTT_CLIENT_DATA_T *state) {
|
||||
static float old_temperature;
|
||||
const char *temperature_key = full_topic(state, "/temperature");
|
||||
float temperature = read_onboard_temperature(TEMPERATURE_UNITS);
|
||||
if (temperature != old_temperature) {
|
||||
old_temperature = temperature;
|
||||
// Publish temperature on /temperature topic
|
||||
char temp_str[16];
|
||||
snprintf(temp_str, sizeof(temp_str), "%.2f", temperature);
|
||||
INFO_printf("Publishing %s to %s\n", temp_str, temperature_key);
|
||||
mqtt_publish(state->mqtt_client_inst, temperature_key, temp_str, strlen(temp_str), MQTT_PUBLISH_QOS, MQTT_PUBLISH_RETAIN, pub_request_cb, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void sub_request_cb(void *arg, err_t err) {
|
||||
MQTT_CLIENT_DATA_T* state = (MQTT_CLIENT_DATA_T*)arg;
|
||||
if (err != 0) {
|
||||
panic("subscribe request failed %d", err);
|
||||
}
|
||||
state->subscribe_count++;
|
||||
}
|
||||
|
||||
static void unsub_request_cb(void *arg, err_t err) {
|
||||
MQTT_CLIENT_DATA_T* state = (MQTT_CLIENT_DATA_T*)arg;
|
||||
if (err != 0) {
|
||||
panic("unsubscribe request failed %d", err);
|
||||
}
|
||||
state->subscribe_count--;
|
||||
assert(state->subscribe_count >= 0);
|
||||
|
||||
// Stop if requested
|
||||
if (state->subscribe_count <= 0 && state->stop_client) {
|
||||
mqtt_disconnect(state->mqtt_client_inst);
|
||||
}
|
||||
}
|
||||
|
||||
static void sub_unsub_topics(MQTT_CLIENT_DATA_T* state, bool sub) {
|
||||
mqtt_request_cb_t cb = sub ? sub_request_cb : unsub_request_cb;
|
||||
mqtt_sub_unsub(state->mqtt_client_inst, full_topic(state, "/led"), MQTT_SUBSCRIBE_QOS, cb, state, sub);
|
||||
mqtt_sub_unsub(state->mqtt_client_inst, full_topic(state, "/print"), MQTT_SUBSCRIBE_QOS, cb, state, sub);
|
||||
mqtt_sub_unsub(state->mqtt_client_inst, full_topic(state, "/ping"), MQTT_SUBSCRIBE_QOS, cb, state, sub);
|
||||
mqtt_sub_unsub(state->mqtt_client_inst, full_topic(state, "/exit"), MQTT_SUBSCRIBE_QOS, cb, state, sub);
|
||||
}
|
||||
|
||||
static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags) {
|
||||
MQTT_CLIENT_DATA_T* state = (MQTT_CLIENT_DATA_T*)arg;
|
||||
#if MQTT_UNIQUE_TOPIC
|
||||
const char *basic_topic = state->topic + strlen(state->mqtt_client_info.client_id) + 1;
|
||||
#else
|
||||
const char *basic_topic = state->topic;
|
||||
#endif
|
||||
strncpy(state->data, (const char *)data, len);
|
||||
state->len = len;
|
||||
state->data[len] = '\0';
|
||||
|
||||
DEBUG_printf("Topic: %s, Message: %s\n", state->topic, state->data);
|
||||
if (strcmp(basic_topic, "/led") == 0)
|
||||
{
|
||||
if (lwip_stricmp((const char *)state->data, "On") == 0 || strcmp((const char *)state->data, "1") == 0)
|
||||
control_led(state, true);
|
||||
else if (lwip_stricmp((const char *)state->data, "Off") == 0 || strcmp((const char *)state->data, "0") == 0)
|
||||
control_led(state, false);
|
||||
} else if (strcmp(basic_topic, "/print") == 0) {
|
||||
INFO_printf("%.*s\n", len, data);
|
||||
} else if (strcmp(basic_topic, "/ping") == 0) {
|
||||
char buf[11];
|
||||
snprintf(buf, sizeof(buf), "%u", to_ms_since_boot(get_absolute_time()) / 1000);
|
||||
mqtt_publish(state->mqtt_client_inst, full_topic(state, "/uptime"), buf, strlen(buf), MQTT_PUBLISH_QOS, MQTT_PUBLISH_RETAIN, pub_request_cb, state);
|
||||
} else if (strcmp(basic_topic, "/exit") == 0) {
|
||||
state->stop_client = true; // stop the client when ALL subscriptions are stopped
|
||||
sub_unsub_topics(state, false); // unsubscribe
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len) {
|
||||
MQTT_CLIENT_DATA_T* state = (MQTT_CLIENT_DATA_T*)arg;
|
||||
strncpy(state->topic, topic, sizeof(state->topic));
|
||||
}
|
||||
|
||||
static void temperature_worker_fn(async_context_t *context, async_at_time_worker_t *worker) {
|
||||
MQTT_CLIENT_DATA_T* state = (MQTT_CLIENT_DATA_T*)worker->user_data;
|
||||
publish_temperature(state);
|
||||
async_context_add_at_time_worker_in_ms(context, worker, TEMP_WORKER_TIME_S * 1000);
|
||||
}
|
||||
static async_at_time_worker_t temperature_worker = { .do_work = temperature_worker_fn };
|
||||
|
||||
static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) {
|
||||
MQTT_CLIENT_DATA_T* state = (MQTT_CLIENT_DATA_T*)arg;
|
||||
if (status == MQTT_CONNECT_ACCEPTED) {
|
||||
state->connect_done = true;
|
||||
sub_unsub_topics(state, true); // subscribe;
|
||||
|
||||
// indicate online
|
||||
if (state->mqtt_client_info.will_topic) {
|
||||
mqtt_publish(state->mqtt_client_inst, state->mqtt_client_info.will_topic, "1", 1, MQTT_WILL_QOS, true, pub_request_cb, state);
|
||||
}
|
||||
|
||||
// Publish temperature every 10 sec if it's changed
|
||||
temperature_worker.user_data = state;
|
||||
async_context_add_at_time_worker_in_ms(cyw43_arch_async_context(), &temperature_worker, 0);
|
||||
} else if (status == MQTT_CONNECT_DISCONNECTED) {
|
||||
if (!state->connect_done) {
|
||||
panic("Failed to connect to mqtt server");
|
||||
}
|
||||
}
|
||||
else {
|
||||
panic("Unexpected status");
|
||||
}
|
||||
}
|
||||
|
||||
static void start_client(MQTT_CLIENT_DATA_T *state) {
|
||||
#if LWIP_ALTCP && LWIP_ALTCP_TLS
|
||||
const int port = MQTT_TLS_PORT;
|
||||
INFO_printf("Using TLS\n");
|
||||
#else
|
||||
const int port = MQTT_PORT;
|
||||
INFO_printf("Warning: Not using TLS\n");
|
||||
#endif
|
||||
|
||||
state->mqtt_client_inst = mqtt_client_new();
|
||||
if (!state->mqtt_client_inst) {
|
||||
panic("MQTT client instance creation error");
|
||||
}
|
||||
INFO_printf("IP address of this device %s\n", ipaddr_ntoa(&(netif_list->ip_addr)));
|
||||
INFO_printf("Connecting to mqtt server at %s\n", ipaddr_ntoa(&state->mqtt_server_address));
|
||||
|
||||
cyw43_arch_lwip_begin();
|
||||
if (mqtt_client_connect(state->mqtt_client_inst, &state->mqtt_server_address, port, mqtt_connection_cb, state, &state->mqtt_client_info) != ERR_OK) {
|
||||
panic("MQTT broker connection error");
|
||||
}
|
||||
#if LWIP_ALTCP && LWIP_ALTCP_TLS
|
||||
// This is important for MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||
mbedtls_ssl_set_hostname(altcp_tls_context(state->mqtt_client_inst->conn), MQTT_SERVER);
|
||||
#endif
|
||||
mqtt_set_inpub_callback(state->mqtt_client_inst, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, state);
|
||||
cyw43_arch_lwip_end();
|
||||
}
|
||||
|
||||
// Call back with a DNS result
|
||||
static void dns_found(const char *hostname, const ip_addr_t *ipaddr, void *arg) {
|
||||
MQTT_CLIENT_DATA_T *state = (MQTT_CLIENT_DATA_T*)arg;
|
||||
if (ipaddr) {
|
||||
state->mqtt_server_address = *ipaddr;
|
||||
start_client(state);
|
||||
} else {
|
||||
panic("dns request failed");
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
stdio_init_all();
|
||||
INFO_printf("mqtt client starting\n");
|
||||
|
||||
adc_init();
|
||||
adc_set_temp_sensor_enabled(true);
|
||||
adc_select_input(4);
|
||||
|
||||
static MQTT_CLIENT_DATA_T state;
|
||||
|
||||
if (cyw43_arch_init()) {
|
||||
panic("Failed to inizialize CYW43");
|
||||
}
|
||||
|
||||
// Use board unique id
|
||||
char unique_id_buf[5];
|
||||
pico_get_unique_board_id_string(unique_id_buf, sizeof(unique_id_buf));
|
||||
for(int i=0; i < sizeof(unique_id_buf) - 1; i++) {
|
||||
unique_id_buf[i] = tolower(unique_id_buf[i]);
|
||||
}
|
||||
|
||||
// Generate a unique name, e.g. pico1234
|
||||
char client_id_buf[sizeof(MQTT_DEVICE_NAME) + sizeof(unique_id_buf) - 1];
|
||||
memcpy(&client_id_buf[0], MQTT_DEVICE_NAME, sizeof(MQTT_DEVICE_NAME) - 1);
|
||||
memcpy(&client_id_buf[sizeof(MQTT_DEVICE_NAME) - 1], unique_id_buf, sizeof(unique_id_buf) - 1);
|
||||
client_id_buf[sizeof(client_id_buf) - 1] = 0;
|
||||
INFO_printf("Device name %s\n", client_id_buf);
|
||||
|
||||
state.mqtt_client_info.client_id = client_id_buf;
|
||||
state.mqtt_client_info.keep_alive = MQTT_KEEP_ALIVE_S; // Keep alive in sec
|
||||
#if defined(MQTT_USERNAME) && defined(MQTT_PASSWORD)
|
||||
state.mqtt_client_info.client_user = MQTT_USERNAME;
|
||||
state.mqtt_client_info.client_pass = MQTT_PASSWORD;
|
||||
#else
|
||||
state.mqtt_client_info.client_user = NULL;
|
||||
state.mqtt_client_info.client_pass = NULL;
|
||||
#endif
|
||||
static char will_topic[MQTT_TOPIC_LEN];
|
||||
strncpy(will_topic, full_topic(&state, MQTT_WILL_TOPIC), sizeof(will_topic));
|
||||
state.mqtt_client_info.will_topic = will_topic;
|
||||
state.mqtt_client_info.will_msg = MQTT_WILL_MSG;
|
||||
state.mqtt_client_info.will_qos = MQTT_WILL_QOS;
|
||||
state.mqtt_client_info.will_retain = true;
|
||||
#if LWIP_ALTCP && LWIP_ALTCP_TLS
|
||||
// TLS enabled
|
||||
#ifdef MQTT_CERT_INC
|
||||
static const uint8_t ca_cert[] = TLS_ROOT_CERT;
|
||||
static const uint8_t client_key[] = TLS_CLIENT_KEY;
|
||||
static const uint8_t client_cert[] = TLS_CLIENT_CERT;
|
||||
// This confirms the indentity of the server and the client
|
||||
state.mqtt_client_info.tls_config = altcp_tls_create_config_client_2wayauth(ca_cert, sizeof(ca_cert),
|
||||
client_key, sizeof(client_key), NULL, 0, client_cert, sizeof(client_cert));
|
||||
#if ALTCP_MBEDTLS_AUTHMODE != MBEDTLS_SSL_VERIFY_REQUIRED
|
||||
WARN_printf("Warning: tls without verification is insecure\n");
|
||||
#endif
|
||||
#else
|
||||
state->client_info.tls_config = altcp_tls_create_config_client(NULL, 0);
|
||||
WARN_printf("Warning: tls without a certificate is insecure\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
cyw43_arch_enable_sta_mode();
|
||||
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
||||
panic("Failed to connect");
|
||||
}
|
||||
INFO_printf("\nConnected to Wifi\n");
|
||||
|
||||
// We are not in a callback so locking is needed when calling lwip
|
||||
// Make a DNS request for the MQTT server IP address
|
||||
cyw43_arch_lwip_begin();
|
||||
int err = dns_gethostbyname(MQTT_SERVER, &state.mqtt_server_address, dns_found, &state);
|
||||
cyw43_arch_lwip_end();
|
||||
|
||||
if (err == ERR_OK) {
|
||||
// We have the address, just start the client
|
||||
start_client(&state);
|
||||
} else if (err != ERR_INPROGRESS) { // ERR_INPROGRESS means expect a callback
|
||||
panic("dns request failed");
|
||||
}
|
||||
|
||||
while (!state.connect_done || mqtt_client_is_connected(state.mqtt_client_inst)) {
|
||||
cyw43_arch_poll();
|
||||
cyw43_arch_wait_for_work_until(make_timeout_time_ms(10000));
|
||||
}
|
||||
|
||||
INFO_printf("mqtt client exiting\n");
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue