1 /*
2 * Class A LoRaWAN sample application
3 *
4 * Copyright (c) 2020 Manivannan Sadhasivam <mani@kernel.org>
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <device.h>
10 #include <lorawan/lorawan.h>
11 #include <zephyr.h>
12
13 #define DEFAULT_RADIO_NODE DT_ALIAS(lora0)
14 BUILD_ASSERT(DT_NODE_HAS_STATUS(DEFAULT_RADIO_NODE, okay),
15 "No default LoRa radio specified in DT");
16 #define DEFAULT_RADIO DT_LABEL(DEFAULT_RADIO_NODE)
17
18 /* Customize based on network configuration */
19 #define LORAWAN_DEV_EUI { 0xDD, 0xEE, 0xAA, 0xDD, 0xBB, 0xEE,\
20 0xEE, 0xFF }
21 #define LORAWAN_JOIN_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
22 0x00, 0x00 }
23 #define LORAWAN_APP_KEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE,\
24 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88,\
25 0x09, 0xCF, 0x4F, 0x3C }
26
27 #define DELAY K_MSEC(10000)
28
29 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
30 #include <logging/log.h>
31 LOG_MODULE_REGISTER(lorawan_class_a);
32
33 char data[] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'};
34
dl_callback(uint8_t port,bool data_pending,int16_t rssi,int8_t snr,uint8_t len,const uint8_t * data)35 static void dl_callback(uint8_t port, bool data_pending,
36 int16_t rssi, int8_t snr,
37 uint8_t len, const uint8_t *data)
38 {
39 LOG_INF("Port %d, Pending %d, RSSI %ddB, SNR %ddBm", port, data_pending, rssi, snr);
40 if (data) {
41 LOG_HEXDUMP_INF(data, len, "Payload: ");
42 }
43 }
44
lorwan_datarate_changed(enum lorawan_datarate dr)45 static void lorwan_datarate_changed(enum lorawan_datarate dr)
46 {
47 uint8_t unused, max_size;
48
49 lorawan_get_payload_sizes(&unused, &max_size);
50 LOG_INF("New Datarate: DR_%d, Max Payload %d", dr, max_size);
51 }
52
main(void)53 void main(void)
54 {
55 const struct device *lora_dev;
56 struct lorawan_join_config join_cfg;
57 uint8_t dev_eui[] = LORAWAN_DEV_EUI;
58 uint8_t join_eui[] = LORAWAN_JOIN_EUI;
59 uint8_t app_key[] = LORAWAN_APP_KEY;
60 int ret;
61
62 struct lorawan_downlink_cb downlink_cb = {
63 .port = LW_RECV_PORT_ANY,
64 .cb = dl_callback
65 };
66
67 lora_dev = device_get_binding(DEFAULT_RADIO);
68 if (!lora_dev) {
69 LOG_ERR("%s Device not found", DEFAULT_RADIO);
70 return;
71 }
72
73 ret = lorawan_start();
74 if (ret < 0) {
75 LOG_ERR("lorawan_start failed: %d", ret);
76 return;
77 }
78
79 lorawan_register_downlink_callback(&downlink_cb);
80 lorawan_register_dr_changed_callback(lorwan_datarate_changed);
81
82 join_cfg.mode = LORAWAN_ACT_OTAA;
83 join_cfg.dev_eui = dev_eui;
84 join_cfg.otaa.join_eui = join_eui;
85 join_cfg.otaa.app_key = app_key;
86 join_cfg.otaa.nwk_key = app_key;
87
88 LOG_INF("Joining network over OTAA");
89 ret = lorawan_join(&join_cfg);
90 if (ret < 0) {
91 LOG_ERR("lorawan_join_network failed: %d", ret);
92 return;
93 }
94
95 LOG_INF("Sending data...");
96 while (1) {
97 ret = lorawan_send(2, data, sizeof(data),
98 LORAWAN_MSG_CONFIRMED);
99
100 /*
101 * Note: The stack may return -EAGAIN if the provided data
102 * length exceeds the maximum possible one for the region and
103 * datarate. But since we are just sending the same data here,
104 * we'll just continue.
105 */
106 if (ret == -EAGAIN) {
107 LOG_ERR("lorawan_send failed: %d. Continuing...", ret);
108 k_sleep(DELAY);
109 continue;
110 }
111
112 if (ret < 0) {
113 LOG_ERR("lorawan_send failed: %d", ret);
114 return;
115 }
116
117 LOG_INF("Data sent!");
118 k_sleep(DELAY);
119 }
120 }
121