-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.c
More file actions
320 lines (290 loc) · 12.7 KB
/
app.c
File metadata and controls
320 lines (290 loc) · 12.7 KB
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/***************************************************************************//**
* @file
* @brief Core application logic.
*******************************************************************************
* # License
* <b>Copyright 2025 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*******************************************************************************
* # Experimental Quality
* This code has not been formally tested and is provided as-is. It is not
* suitable for production environments. In addition, this code will not be
* maintained and there may be no bug maintenance planned for these resources.
* Silicon Labs may update projects from time to time.
******************************************************************************/
#include "app/framework/include/af.h"
#include "app/framework/util/af-main.h"
#include "app/util/common/common.h"
#include "app/framework/plugin/network-steering/network-steering.h"
#include "app/framework/plugin/find-and-bind-initiator/find-and-bind-initiator.h"
#include "sl_simple_button_instances.h"
#if defined(SL_CATALOG_LED0_PRESENT)
#include "sl_led.h"
#include "sl_simple_led_instances.h"
#define led_turn_on(led) sl_led_turn_on(led)
#define led_turn_off(led) sl_led_turn_off(led)
#define led_toggle(led) sl_led_toggle(led)
#define STATUS_LED (&sl_led_led0)
#else // !SL_CATALOG_LED0_PRESENT
#define led_turn_on(led)
#define led_turn_off(led)
#define led_toggle(led)
#endif // SL_CATALOG_LED0_PRESENT
#define led_stop(led) do { \
led_turn_off(led); \
sl_zigbee_af_event_set_inactive(&led_event); \
} while (0)
#define BUTTON0 0
// Delay for find and bind handler execution
#define FIND_AND_BIND_DELAY_MS 3000
#define TEMPERATURE_MEASUREMENT_ENDPOINT 1
#define TEMPERATURE_UPDATE_DELAY_MS 2000
#define LED_BLINK_PERIOD_MS 2000
// -----------------------------------------------------------------------------
// Global Variables
// -----------------------------------------------------------------------------
static bool commissioning = false; // Holds the commissioning status
static int16_t temperature = 2200; // Example temperature, value x 100, -10 to 80
// Custom event controls
static sl_zigbee_af_event_t run_temperature_event_control;
static sl_zigbee_af_event_t network_control_event_control;
static sl_zigbee_af_event_t attribute_report_event_control;
static sl_zigbee_af_event_t led_event;
// -----------------------------------------------------------------------------
// Static Function Declarations
// -----------------------------------------------------------------------------
static void run_temperature_event_handler(sl_zigbee_af_event_t *event);
static void network_control_event_handler(sl_zigbee_af_event_t *event);
static void attribute_report_event_handler(sl_zigbee_af_event_t *event);
static void led_event_handler(sl_zigbee_af_event_t *event);
// -----------------------------------------------------------------------------
// Callback Handler
// -----------------------------------------------------------------------------
/** @brief Main Init
*
* This function is called from the application's main function. It gives the
* application a chance to do any initialization required at system startup. Any
* code that you would normally put into the top of the application's main()
* routine should be put into this function. This is called before the clusters,
* plugins, and the network are initialized so some functionality is not yet
* available.
* Note: No callback in the Application Framework is
* associated with resource cleanup. If you are implementing your application on
* a Unix host where resource cleanup is a consideration, we expect that you
* will use the standard Posix system calls, including the use of atexit() and
* handlers for signals such as SIGTERM, SIGINT, SIGCHLD, SIGPIPE and so on. If
* you use the signal() function to register your signal handler, please mind
* the returned value which may be an Application Framework function. If the
* return value is non-null, please make sure that you call the returned
* function from your handler to avoid negating the resource cleanup of the
* Application Framework itself.
*
*/
void sl_zigbee_af_main_init_cb(void)
{
sl_zigbee_af_event_init(&run_temperature_event_control,
run_temperature_event_handler);
sl_zigbee_af_event_set_delay_ms(&run_temperature_event_control,
TEMPERATURE_UPDATE_DELAY_MS);
sl_zigbee_af_isr_event_init(&network_control_event_control,
network_control_event_handler);
// finding_and_binding_event_handler);
sl_zigbee_af_event_init(&attribute_report_event_control,
attribute_report_event_handler);
sl_zigbee_af_event_init(&led_event, led_event_handler);
}
/** @brief Stack Status
*
* This function is called by the application framework from the stack status
* handler. This callbacks provides applications an opportunity to be notified
* of changes to the stack status and take appropriate action. The framework
* will always process the stack status after the callback returns.
*/
void sl_zigbee_af_stack_status_cb(sl_status_t status)
{
if (status == SL_STATUS_NETWORK_DOWN) {
sl_zigbee_af_event_set_inactive(&attribute_report_event_control);
led_stop(STATUS_LED);
} else if (status == SL_STATUS_NETWORK_UP) {
sl_802154_short_addr_t node_id = sl_zigbee_af_get_node_id();
sl_zigbee_app_debug_print("NodeID = %x\n", node_id);
}
}
/** @brief Complete network steering.
*
* This callback is fired when the Network Steering plugin is complete.
*
* @param status On success this will be set to SL_STATUS_OK to indicate a
* network was joined successfully. On failure this will be the status code of
* the last join or scan attempt. Ver.: always
*
* @param totalBeacons The total number of 802.15.4 beacons that were heard,
* including beacons from different devices with the same PAN ID. Ver.: always
* @param joinAttempts The number of join attempts that were made to get onto
* an open Zigbee network. Ver.: always
*
* @param finalState The finishing state of the network steering process. From
* this, one is able to tell on which channel mask and with which key the
* process was complete. Ver.: always
*/
void sl_zigbee_af_network_steering_complete_cb(sl_status_t status,
uint8_t totalBeacons,
uint8_t joinAttempts,
uint8_t finalState)
{
sl_zigbee_app_debug_print("%s network %s: 0x%02X\n",
"Join",
"complete",
status);
if (status != SL_STATUS_OK) {
led_stop(STATUS_LED);
}
commissioning = false;
}
/** @brief Complete
*
* This callback is fired by the initiator when the Find and Bind process is
* complete.
*
* @param status Status code describing the completion of the find and bind
* process Ver.: always
*/
void sl_zigbee_af_find_and_bind_initiator_complete_cb(sl_status_t status)
{
sl_zigbee_app_debug_print("Find and bind initiator %s: 0x%X\n",
"complete",
status);
if (status != SL_STATUS_OK) {
sl_zigbee_app_debug_print("Ensure a valid binding target!\n");
sl_zigbee_af_event_set_inactive(&attribute_report_event_control);
}
led_stop(STATUS_LED);
}
/** @brief
*
* Application framework equivalent of ::emberRadioNeedsCalibratingHandler
*/
void sl_zigbee_af_radio_needs_calibrating_cb(void)
{
sl_mac_calibrate_current_channel();
}
/***************************************************************************
* A callback called in interrupt context whenever a button changes its state.
*
* @remark Can be implemented by the application if required. This function
* can contain the functionality to be executed in response to changes of state
* in each of the buttons, or callbacks to appropriate functionality.
*
* @note The button state should not be updated in this function, it is updated
* by specific button driver prior to arriving here
*
* @param[out] handle Pointer to button instance
******************************************************************************/
void sl_button_on_change(const sl_button_t *handle)
{
if (SL_SIMPLE_BUTTON_INSTANCE(BUTTON0) == handle) {
if (sl_button_get_state(handle) == SL_SIMPLE_BUTTON_RELEASED) {
sl_zigbee_af_event_set_active(&network_control_event_control);
}
}
}
static void led_event_handler(sl_zigbee_af_event_t *event)
{
sl_zigbee_af_event_set_inactive(&led_event);
if (commissioning) {
led_toggle(STATUS_LED);
sl_zigbee_af_event_set_delay_ms(&led_event, LED_BLINK_PERIOD_MS << 1);
}
}
/**
* This function is called whenever a temperature measurement is enabled
*/
static void run_temperature_event_handler(sl_zigbee_af_event_t *event)
{
sl_zigbee_af_event_set_inactive(&run_temperature_event_control);
sl_zigbee_app_debug_println("%s", __func__);
temperature += 500;
if (temperature > 8000) {
temperature = -1000;
}
sl_zigbee_app_debug_println("Running temperature measurement: %d\n", temperature);
sl_zigbee_af_event_set_active(&attribute_report_event_control);
sl_zigbee_af_event_set_delay_ms(&run_temperature_event_control,
TEMPERATURE_UPDATE_DELAY_MS);
}
/** @brief Attributes report Event Handler
*
* This event handler write the attribute which triggers an automatic
* report of the occupancy to the Client via the Occupancy Sensing
* cluster.
*
*/
static void attribute_report_event_handler(sl_zigbee_af_event_t *event)
{
sl_zigbee_af_status_t status = SL_ZIGBEE_ZCL_STATUS_FAILURE;
sl_zigbee_af_event_set_inactive(&attribute_report_event_control);
if (sl_zigbee_af_network_state() != SL_ZIGBEE_JOINED_NETWORK) {
return;
}
status = sl_zigbee_af_write_server_attribute(TEMPERATURE_MEASUREMENT_ENDPOINT,
ZCL_TEMP_MEASUREMENT_CLUSTER_ID,
ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID,
(uint8_t *)&temperature,
ZCL_INT16S_ATTRIBUTE_TYPE);
if (status != SL_ZIGBEE_ZCL_STATUS_SUCCESS) {
sl_zigbee_app_debug_print("Failed to report temperature: 0x%X\n", status);
} else {
sl_zigbee_app_debug_print("Temperature reported: %d\n", temperature);
}
}
/** @brief Network Control Event Handler
*
* This event handler is called in response to it's respective control
* activation.
*
*/
static void network_control_event_handler(sl_zigbee_af_event_t *event)
{
sl_status_t status;
sl_zigbee_af_event_set_inactive(&network_control_event_control);
if (sl_zigbee_network_state() == SL_ZIGBEE_JOINED_NETWORK) {
// Clear binding table
status = sl_zigbee_clear_binding_table();
sl_zigbee_app_debug_print("%s 0x%x", "Clear binding table\n", status);
// Leave network
status = sl_zigbee_leave_network(SL_ZIGBEE_LEAVE_NWK_WITH_NO_OPTION);
sl_zigbee_app_debug_print("Leave network: 0x%X\n", status);
commissioning = false;
} else if (!commissioning) {
// If not in a network, attempt to join one
status = sl_zigbee_af_network_steering_start();
sl_zigbee_app_debug_print("Join network start: 0x%X\n", status);
sl_zigbee_af_event_set_active(&led_event);
commissioning = true;
}
}
void app_init() {
sl_zigbee_app_debug_print("Running");
sl_zigbee_af_event_set_active(&run_temperature_event_control);
}