32
32
#include MQTT_CERT_INC
33
33
#endif
34
34
35
+ #ifndef MQTT_TOPIC_LEN
36
+ #define MQTT_TOPIC_LEN 100
37
+ #endif
38
+
35
39
typedef struct {
36
40
mqtt_client_t * mqtt_client_inst ;
37
41
struct mqtt_connect_client_info_t mqtt_client_info ;
38
42
char data [MQTT_OUTPUT_RINGBUF_SIZE ];
39
- char topic [100 ];
43
+ char topic [MQTT_TOPIC_LEN ];
40
44
uint32_t len ;
41
45
ip_addr_t mqtt_server_address ;
42
46
bool connect_done ;
@@ -79,6 +83,15 @@ typedef struct {
79
83
#define MQTT_WILL_MSG "0"
80
84
#define MQTT_WILL_QOS 1
81
85
86
+ #ifndef MQTT_DEVICE_NAME
87
+ #define MQTT_DEVICE_NAME "pico"
88
+ #endif
89
+
90
+ // Set to 1 to add the client name to topics, to support multiple devices using the same server
91
+ #ifndef MQTT_UNIQUE_TOPIC
92
+ #define MQTT_UNIQUE_TOPIC 0
93
+ #endif
94
+
82
95
/* References for this implementation:
83
96
* raspberry-pi-pico-c-sdk.pdf, Section '4.1.1. hardware_adc'
84
97
* pico-examples/adc/adc_console/adc_console.c */
@@ -105,6 +118,16 @@ static void pub_request_cb(__unused void *arg, err_t err) {
105
118
}
106
119
}
107
120
121
+ static const char * full_topic (MQTT_CLIENT_DATA_T * state , const char * name ) {
122
+ #if MQTT_UNIQUE_TOPIC
123
+ static char full_topic [MQTT_TOPIC_LEN ];
124
+ snprintf (full_topic , sizeof (full_topic ), "/%s%s" , state -> mqtt_client_info .client_id , name );
125
+ return full_topic ;
126
+ #else
127
+ return name ;
128
+ #endif
129
+ }
130
+
108
131
static void control_led (MQTT_CLIENT_DATA_T * state , bool on ) {
109
132
// Publish state on /state topic and on/off led board
110
133
const char * message = on ? "On" : "Off" ;
@@ -113,14 +136,12 @@ static void control_led(MQTT_CLIENT_DATA_T *state, bool on) {
113
136
else
114
137
cyw43_arch_gpio_put (CYW43_WL_GPIO_LED_PIN , 0 );
115
138
116
- char state_topic [128 ];
117
- snprintf (state_topic , sizeof (state_topic ), "%s/state" , state -> topic );
118
- mqtt_publish (state -> mqtt_client_inst , state_topic , message , strlen (message ), MQTT_PUBLISH_QOS , MQTT_PUBLISH_RETAIN , pub_request_cb , state );
139
+ mqtt_publish (state -> mqtt_client_inst , full_topic (state , "/led/state" ), message , strlen (message ), MQTT_PUBLISH_QOS , MQTT_PUBLISH_RETAIN , pub_request_cb , state );
119
140
}
120
141
121
142
static void publish_temperature (MQTT_CLIENT_DATA_T * state ) {
122
143
static float old_temperature ;
123
- const char temperature_key [] = "/temperature" ;
144
+ const char * temperature_key = full_topic ( state , "/temperature" ) ;
124
145
float temperature = read_onboard_temperature (TEMPERATURE_UNITS );
125
146
if (temperature != old_temperature ) {
126
147
old_temperature = temperature ;
@@ -156,32 +177,37 @@ static void unsub_request_cb(void *arg, err_t err) {
156
177
157
178
static void sub_unsub_topics (MQTT_CLIENT_DATA_T * state , bool sub ) {
158
179
mqtt_request_cb_t cb = sub ? sub_request_cb : unsub_request_cb ;
159
- mqtt_sub_unsub (state -> mqtt_client_inst , "/led" , MQTT_SUBSCRIBE_QOS , cb , state , sub );
160
- mqtt_sub_unsub (state -> mqtt_client_inst , "/print" , MQTT_SUBSCRIBE_QOS , cb , state , sub );
161
- mqtt_sub_unsub (state -> mqtt_client_inst , "/ping" , MQTT_SUBSCRIBE_QOS , cb , state , sub );
162
- mqtt_sub_unsub (state -> mqtt_client_inst , "/exit" , MQTT_SUBSCRIBE_QOS , cb , state , sub );
180
+ mqtt_sub_unsub (state -> mqtt_client_inst , full_topic ( state , "/led" ) , MQTT_SUBSCRIBE_QOS , cb , state , sub );
181
+ mqtt_sub_unsub (state -> mqtt_client_inst , full_topic ( state , "/print" ) , MQTT_SUBSCRIBE_QOS , cb , state , sub );
182
+ mqtt_sub_unsub (state -> mqtt_client_inst , full_topic ( state , "/ping" ) , MQTT_SUBSCRIBE_QOS , cb , state , sub );
183
+ mqtt_sub_unsub (state -> mqtt_client_inst , full_topic ( state , "/exit" ) , MQTT_SUBSCRIBE_QOS , cb , state , sub );
163
184
}
164
185
165
186
static void mqtt_incoming_data_cb (void * arg , const u8_t * data , u16_t len , u8_t flags ) {
166
187
MQTT_CLIENT_DATA_T * state = (MQTT_CLIENT_DATA_T * )arg ;
188
+ #if MQTT_UNIQUE_TOPIC
189
+ const char * basic_topic = state -> topic + strlen (state -> mqtt_client_info .client_id ) + 1 ;
190
+ #else
191
+ const char * basic_topic = state -> topic ;
192
+ #endif
167
193
strncpy (state -> data , (const char * )data , len );
168
194
state -> len = len ;
169
195
state -> data [len ] = '\0' ;
170
196
171
197
DEBUG_printf ("Topic: %s, Message: %s\n" , state -> topic , state -> data );
172
- if (strcmp (state -> topic , "/led" ) == 0 )
198
+ if (strcmp (basic_topic , "/led" ) == 0 )
173
199
{
174
- if (lwip_stricmp ((const char * )state -> data , "On" ) == 0 )
200
+ if (lwip_stricmp ((const char * )state -> data , "On" ) == 0 || strcmp (( const char * ) state -> data , "1" ) == 0 )
175
201
control_led (state , true);
176
- else if (lwip_stricmp ((const char * )state -> data , "Off" ) == 0 )
202
+ else if (lwip_stricmp ((const char * )state -> data , "Off" ) == 0 || strcmp (( const char * ) state -> data , "0 " ) == 0 )
177
203
control_led (state , false);
178
- } else if (strcmp (state -> topic , "/print" ) == 0 ) {
204
+ } else if (strcmp (basic_topic , "/print" ) == 0 ) {
179
205
INFO_printf ("%.*s\n" , len , data );
180
- } else if (strcmp (state -> topic , "/ping" ) == 0 ) {
206
+ } else if (strcmp (basic_topic , "/ping" ) == 0 ) {
181
207
char buf [11 ];
182
208
snprintf (buf , sizeof (buf ), "%u" , to_ms_since_boot (get_absolute_time ()) / 1000 );
183
- mqtt_publish (state -> mqtt_client_inst , "/pong" , buf , strlen (buf ), MQTT_PUBLISH_QOS , MQTT_PUBLISH_RETAIN , pub_request_cb , state );
184
- } else if (strcmp (state -> topic , "/exit" ) == 0 ) {
209
+ mqtt_publish (state -> mqtt_client_inst , full_topic ( state , "/pong" ) , buf , strlen (buf ), MQTT_PUBLISH_QOS , MQTT_PUBLISH_RETAIN , pub_request_cb , state );
210
+ } else if (strcmp (basic_topic , "/exit" ) == 0 ) {
185
211
state -> stop_client = true; // stop the client when ALL subscriptions are stopped
186
212
sub_unsub_topics (state , false); // unsubscribe
187
213
}
@@ -276,9 +302,20 @@ int main(void) {
276
302
panic ("Failed to inizialize CYW43" );
277
303
}
278
304
279
- // Use board unique id for the client id
280
- static char client_id_buf [PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1 ];
281
- pico_get_unique_board_id_string (client_id_buf , sizeof (client_id_buf ));
305
+ // Use board unique id
306
+ char unique_id_buf [5 ];
307
+ pico_get_unique_board_id_string (unique_id_buf , sizeof (unique_id_buf ));
308
+ for (int i = 0 ; i < sizeof (unique_id_buf ) - 1 ; i ++ ) {
309
+ unique_id_buf [i ] = tolower (unique_id_buf [i ]);
310
+ }
311
+
312
+ // Generate a unique name, e.g. pico1234
313
+ char client_id_buf [sizeof (MQTT_DEVICE_NAME ) + sizeof (unique_id_buf ) - 1 ];
314
+ memcpy (& client_id_buf [0 ], MQTT_DEVICE_NAME , sizeof (MQTT_DEVICE_NAME ) - 1 );
315
+ memcpy (& client_id_buf [sizeof (MQTT_DEVICE_NAME ) - 1 ], unique_id_buf , sizeof (unique_id_buf ) - 1 );
316
+ client_id_buf [sizeof (client_id_buf ) - 1 ] = 0 ;
317
+ INFO_printf ("Device name %s\n" , client_id_buf );
318
+
282
319
state .mqtt_client_info .client_id = client_id_buf ;
283
320
state .mqtt_client_info .keep_alive = MQTT_KEEP_ALIVE_S ; // Keep alive in sec
284
321
#if defined(MQTT_USERNAME ) && defined(MQTT_PASSWORD )
@@ -288,7 +325,9 @@ int main(void) {
288
325
state .mqtt_client_info .client_user = NULL ;
289
326
state .mqtt_client_info .client_pass = NULL ;
290
327
#endif
291
- state .mqtt_client_info .will_topic = MQTT_WILL_TOPIC ;
328
+ static char will_topic [MQTT_TOPIC_LEN ];
329
+ strncpy (will_topic , full_topic (& state , MQTT_WILL_TOPIC ), sizeof (will_topic ));
330
+ state .mqtt_client_info .will_topic = will_topic ;
292
331
state .mqtt_client_info .will_msg = MQTT_WILL_MSG ;
293
332
state .mqtt_client_info .will_qos = MQTT_WILL_QOS ;
294
333
state .mqtt_client_info .will_retain = true;
0 commit comments