1 /*
2 * Copyright (c) 2024 Analog Devices, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(app_main, LOG_LEVEL_DBG);
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/net/mqtt.h>
12 #include <zephyr/net/net_if.h>
13 #include <zephyr/net/net_mgmt.h>
14 #include <zephyr/net/conn_mgr_monitor.h>
15
16 #include "mqtt_client.h"
17 #include "device.h"
18
19 #define NET_L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
20
21 /* MQTT client struct */
22 static struct mqtt_client client_ctx;
23
24 /* MQTT publish work item */
25 struct k_work_delayable mqtt_publish_work;
26
27 static struct net_mgmt_event_callback net_l4_mgmt_cb;
28
29 /* Network connection semaphore */
30 K_SEM_DEFINE(net_conn_sem, 0, 1);
31
net_l4_evt_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)32 static void net_l4_evt_handler(struct net_mgmt_event_callback *cb,
33 uint32_t mgmt_event, struct net_if *iface)
34 {
35 switch (mgmt_event) {
36 case NET_EVENT_L4_CONNECTED:
37 k_sem_give(&net_conn_sem);
38 LOG_INF("Network connectivity up!");
39 break;
40 case NET_EVENT_L4_DISCONNECTED:
41 LOG_INF("Network connectivity down!");
42 break;
43 default:
44 break;
45 }
46 }
47
48 /** Print the device's MAC address to console */
log_mac_addr(struct net_if * iface)49 void log_mac_addr(struct net_if *iface)
50 {
51 struct net_linkaddr *mac;
52
53 mac = net_if_get_link_addr(iface);
54
55 LOG_INF("MAC Address: %02X:%02X:%02X:%02X:%02X:%02X",
56 mac->addr[0], mac->addr[1], mac->addr[3],
57 mac->addr[3], mac->addr[4], mac->addr[5]);
58 }
59
60 /** The system work queue is used to handle periodic MQTT publishing.
61 * Work queuing begins when the MQTT connection is established.
62 * Use CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL to set the publish frequency.
63 */
64
publish_work_handler(struct k_work * work)65 static void publish_work_handler(struct k_work *work)
66 {
67 int rc;
68
69 if (mqtt_connected) {
70 rc = app_mqtt_publish(&client_ctx);
71 if (rc != 0) {
72 LOG_INF("MQTT Publish failed [%d]", rc);
73 }
74 k_work_reschedule(&mqtt_publish_work,
75 K_SECONDS(CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL));
76 } else {
77 k_work_cancel_delayable(&mqtt_publish_work);
78 }
79 }
80
main(void)81 int main(void)
82 {
83 int rc;
84 struct net_if *iface;
85
86 devices_ready();
87
88 iface = net_if_get_default();
89 if (iface == NULL) {
90 LOG_ERR("No network interface configured");
91 return -ENETDOWN;
92 }
93
94 log_mac_addr(iface);
95
96 /* Register callbacks for L4 events */
97 net_mgmt_init_event_callback(&net_l4_mgmt_cb, &net_l4_evt_handler, NET_L4_EVENT_MASK);
98 net_mgmt_add_event_callback(&net_l4_mgmt_cb);
99
100 LOG_INF("Bringing up network..");
101
102 #if defined(CONFIG_NET_DHCPV4)
103 net_dhcpv4_start(iface);
104 #else
105 /* If using static IP, L4 Connect callback will happen,
106 * before conn mgr is initialised, so resend events here
107 * to check for connectivity
108 */
109 conn_mgr_mon_resend_status();
110 #endif
111
112 /* Wait for network to come up */
113 while (k_sem_take(&net_conn_sem, K_MSEC(MSECS_NET_POLL_TIMEOUT)) != 0) {
114 LOG_INF("Waiting for network connection..");
115 }
116
117 rc = app_mqtt_init(&client_ctx);
118 if (rc != 0) {
119 LOG_ERR("MQTT Init failed [%d]", rc);
120 return rc;
121 }
122
123 /* Initialise MQTT publish work item */
124 k_work_init_delayable(&mqtt_publish_work, publish_work_handler);
125
126 /* Thread main loop */
127 while (1) {
128 /* Block until MQTT connection is up */
129 app_mqtt_connect(&client_ctx);
130
131 /* We are now connected, begin queueing periodic MQTT publishes */
132 k_work_reschedule(&mqtt_publish_work,
133 K_SECONDS(CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL));
134
135 /* Handle MQTT inputs and connection */
136 app_mqtt_run(&client_ctx);
137 }
138
139 return rc;
140 }
141