-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlorawan_reporter.cpp
218 lines (176 loc) · 7.05 KB
/
lorawan_reporter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#include "mbed.h"
#include "lorawan_reporter.h"
#include "lora_radio_helper.h"
#include "trace_helper.h"
#define TRACE_GROUP "lrw"
/******************************************************************************
* Definitions & Declarations
******************************************************************************/
using namespace events;
// Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
// This example only communicates with much shorter messages (<30 bytes).
// If longer messages are used, these buffers must be changed accordingly.
uint8_t tx_buffer[30];
uint8_t rx_buffer[30];
static LoRaWANInterface lorawan(radio); // Constructing Mbed LoRaWANInterface
// and passing it the radio object from lora_radio_helper.
static lorawan_app_callbacks_t callbacks; // Application specific callbacks
static Thread lora_event_thread; // Thread that'll run the event queue's dispatch function.
// This event queue is the global event queue for both the application and stack.
// To conserve memory, the stack is designed to run in the same thread as the application, and,
// the application is responsible for providing an event queue to the stack
// that will be used for ISR deferment as well as application information event queuing.
static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
// Event handler.
// This will be passed to the LoRaWAN stack to queue events for the application which in turn drive the application.
static void lora_event_handler(lorawan_event_t event);
/******************************************************************************
* Initialize
******************************************************************************/
int lrw_init()
{
lorawan_status_t retcode; // stores the status of a call to LoRaWAN protocol
// Initialize LoRaWAN stack
if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK)
{
tr_debug("%s: Init failed!\r\n", __FUNCTION__);
return -1;
}
tr_debug("%s: Initialized\r\n", __FUNCTION__);
// Prepare application callbacks
callbacks.events = mbed::callback(lora_event_handler);
lorawan.add_app_callbacks(&callbacks);
// Set number of retries in case of CONFIRMED messages
if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER) != LORAWAN_STATUS_OK)
{
tr_debug("%s: set_confirmed_msg_retries() failed!\r\n", __FUNCTION__);
return -1;
}
tr_debug("%s: CONFIRMED message retries: %d\r\n", __FUNCTION__, CONFIRMED_MSG_RETRY_COUNTER);
// Enable adaptive data rate
if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK)
{
tr_debug("%s: Enable ADR failed!\r\n", __FUNCTION__);
return -1;
}
tr_debug("%s: ADR Enabled\r\n", __FUNCTION__);
// Connect to the network
retcode = lorawan.connect();
if (retcode == LORAWAN_STATUS_OK ||
retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS)
{
}
else
{
tr_debug("%s: Connection error, code = %d\r\n", __FUNCTION__, retcode);
return -1;
}
tr_debug("%s: Connection - In Progress ...\r\n", __FUNCTION__);
// Make your event queue dispatching events forever
// ev_queue.dispatch_forever();
lora_event_thread.start(callback(&ev_queue, &EventQueue::dispatch_forever)); // So, lrw_init() is a non-blocking function.
return 0;
}
/******************************************************************************
* Sends a message to the Network Server
******************************************************************************/
static void lrw_send_message()
{
uint16_t packet_len;
int16_t retcode;
int sensor_value = 5555; // Read data value
packet_len = sprintf((char *) tx_buffer, "Dummy Sensor Value is %d", sensor_value);
retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len, MSG_UNCONFIRMED_FLAG);
if (retcode < 0)
{
if (retcode == LORAWAN_STATUS_WOULD_BLOCK)
{
tr_debug("%s: WOULD BLOCK\r\n", __FUNCTION__);
if (MBED_CONF_LORA_DUTY_CYCLE_ON) // Retry in 3 seconds
{
ev_queue.call_in(3000, lrw_send_message);
}
}
else
{
tr_debug("%s: Error code = %d\r\n", __FUNCTION__, retcode);
}
return;
}
tr_debug("%s: %d bytes scheduled for transmission\r\n", __FUNCTION__, retcode);
memset(tx_buffer, 0, sizeof(tx_buffer));
}
/******************************************************************************
* Receive a message from the Network Server
******************************************************************************/
static void lrw_receive_message()
{
uint8_t port;
int flags;
int16_t retcode = lorawan.receive(rx_buffer, sizeof(rx_buffer), port, flags);
if (retcode < 0) {
tr_debug("%s: Error code = %d\r\n", __FUNCTION__, retcode);
return;
}
tr_debug("%s: RX Data on port %u (%d bytes): ", __FUNCTION__, port, retcode);
for (uint8_t i = 0; i < retcode; i++) {
tr_debug("%02x ", rx_buffer[i]);
}
tr_debug("\r\n");
memset(rx_buffer, 0, sizeof(rx_buffer));
}
/******************************************************************************
* Event handler
******************************************************************************/
static void lora_event_handler(lorawan_event_t event)
{
switch (event) {
case CONNECTED:
tr_debug("%s: Connection - Successful\r\n", __FUNCTION__);
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
lrw_send_message();
} else {
ev_queue.call_every(TX_TIMER, lrw_send_message);
}
break;
case DISCONNECTED:
ev_queue.break_dispatch();
tr_debug("%s: Disconnected Successfully\r\n", __FUNCTION__);
break;
case TX_DONE:
tr_debug("%s: Message Sent to Network Server\r\n", __FUNCTION__);
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
lrw_send_message();
}
break;
case TX_TIMEOUT:
case TX_ERROR:
case TX_CRYPTO_ERROR:
case TX_SCHEDULING_ERROR:
tr_debug("%s: Transmission Error - EventCode = %d\r\n", __FUNCTION__, event);
// try again
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
lrw_send_message();
}
break;
case RX_DONE:
tr_debug("%s: Received message from Network Server\r\n", __FUNCTION__);
lrw_receive_message();
break;
case RX_TIMEOUT:
case RX_ERROR:
tr_debug("%s: Error in reception - Code = %d \r\n", __FUNCTION__, event);
break;
case JOIN_FAILURE:
tr_debug("%s: OTAA Failed - Check Keys\r\n", __FUNCTION__);
break;
case UPLINK_REQUIRED:
tr_debug("%s: Uplink required by NS\r\n", __FUNCTION__);
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
lrw_send_message();
}
break;
default:
MBED_ASSERT("Unknown Event");
}
}