Wirepas SDK
control_router/app.c
/* Copyright 2020 Wirepas Ltd. All Rights Reserved.
*
* See file LICENSE.txt for full license details.
*
*/
/*
* \file app.c
* \brief This file is the control router application to be used with the
* control_node application.
*/
#include <string.h>
#include "api.h"
#include "control_router.h"
#include "app_scheduler.h"
#include "shared_data.h"
#include "led.h"
#include "../control_node/common.h"
#define DEBUG_LOG_MODULE_NAME "ROUT APP"
#ifdef DEBUG_LOG_MAX_LEVEL_APP
#define DEBUG_LOG_MAX_LEVEL DEBUG_LOG_MAX_LEVEL_APP
#else
#define DEBUG_LOG_MAX_LEVEL LVL_INFO
#endif
#include "debug_log.h"
#define APP_CONFIG_CTRL_ROUTER_TYPE 0xC0
#define LIGHT_TASK_EXEC_TIME_US 30
#define MAX_LIGHT_TURN_ON_DELAY_MS 250
#define COARSE_TO_MS(delay) ((1000u * (delay)) >> 7)
#define MS_TO_COARSE(delay) (((delay) * 128) / 1000u)
static bool m_received_config;
static control_app_ack_t m_ack_config;
static uint16_t m_filter_id;
static bool m_light_state;
static app_lib_data_receive_res_e received_switch_cb(
const shared_data_item_t * item,
const app_lib_data_received_t * data);
void received_appconfig (uint16_t type, uint8_t length, uint8_t * value_p);
static shared_data_item_t m_switch_received_item = {
.cb = received_switch_cb,
.filter = {
.src_endpoint = SRC_EP_SWITCH,
.dest_endpoint = DEST_EP_SWITCH,
.multicast_cb = NULL
}
};
shared_app_config_filter_t m_da_appconfig_item = {
.type = APP_CONFIG_CTRL_ROUTER_TYPE,
.cb = received_appconfig,
.call_cb_always = false
};
static uint32_t light_task(void)
{
LOG(LVL_INFO, "Turn %s light (defered task).",
m_light_state?"On":"Off");
Led_set(0, m_light_state);
}
static app_lib_data_receive_res_e received_switch_cb(
const shared_data_item_t * item,
{
(void) item;
// Switch event sent by a control node.
if (data->num_bytes == sizeof(control_app_switch_t))
{
control_app_switch_t * swtch = (control_app_switch_t *) &(data->bytes[0]);
control_app_switch_fwd_t swtch_fwd;
app_lib_data_to_send_t tx_switch_def =
{
.bytes = (const uint8_t *)&swtch_fwd,
.num_bytes = sizeof(control_app_switch_fwd_t),
/* This packet will only be received by CSMA nodes. */
.src_endpoint = SRC_EP_SWITCH,
.dest_endpoint = DEST_EP_SWITCH,
.dest_address = APP_ADDR_BROADCAST
};
LOG(LVL_INFO, "Received Switch %s Event (delay:%d).",
swtch->button_pressed?"On":"Off",
COARSE_TO_MS(data->delay));
m_light_state = swtch->button_pressed;
swtch_fwd.src_addr = data->src_address;
memcpy(&swtch_fwd.pkt, swtch, sizeof(control_app_switch_t));
/* Send packet to light groups. */
res = Shared_Data_sendData(&tx_switch_def, NULL);
{
LOG(LVL_ERROR, "Error sending data (res:%d)", res);
}
}
// Switch event forwarded by a control router.
else if (data->num_bytes == sizeof(control_app_switch_fwd_t))
{
control_app_switch_fwd_t * swtch_fwd =
(control_app_switch_fwd_t *) &(data->bytes[0]);
LOG(LVL_INFO, "Received a forwarded Switch %s Event (delay:%d).",
swtch_fwd->pkt.button_pressed?"On":"Off",
COARSE_TO_MS(data->delay));
m_light_state = swtch_fwd->pkt.button_pressed;
}
else
{
LOG(LVL_ERROR, "Invalid packet length.");
}
// Light delay already expired turn on/off the light immediately.
if (COARSE_TO_MS(data->delay) >= MAX_LIGHT_TURN_ON_DELAY_MS)
{
LOG(LVL_INFO, "Turn %s light immediately.",
m_light_state?"On":"Off");
Led_set(0, m_light_state);
}
else
{
// Exec task in 250ms - travel_time.
light_task,
MAX_LIGHT_TURN_ON_DELAY_MS - COARSE_TO_MS(data->delay),
LIGHT_TASK_EXEC_TIME_US);
{
LOG(LVL_ERROR, "Error adding Task (res:%d)", res);
}
}
}
static bool acklistener_cb(const ack_gen_input_t * in,
{
(void) in;
if (m_received_config)
{
LOG(LVL_INFO, "Generate ACK");
out->data = (void *) &m_ack_config;
out->length = sizeof(control_app_ack_t);
return true;
}
return false;
}
void received_appconfig(uint16_t type, uint8_t length, uint8_t * value_p)
{
(void) type;
if (length != sizeof(control_app_appconfig_t))
{
LOG(LVL_ERROR, "Appconfig, invalid length.");
return;
}
control_app_appconfig_t * pkt = (control_app_appconfig_t *) value_p;
m_received_config = true;
m_ack_config.diag_period_ms = pkt->ack.diag_period_ms;
m_ack_config.packet_ttl_ms = pkt->ack.packet_ttl_ms;
LOG(LVL_INFO, "Received appconfig");
LOG(LVL_DEBUG, " - diag_period_ms: %u", m_ack_config.diag_period_ms);
LOG(LVL_DEBUG, " - packet_ttl_ms: %u", m_ack_config.packet_ttl_ms);
}
void App_init(const app_global_functions_t * functions)
{
(void) functions;
app_res_e app_res;
.ack_gen_cb = acklistener_cb
};
LOG(LVL_INFO, "Starting Control Router");
// Basic configuration of the node with a unique node address
{
// Could not configure the node
// It should not happen except if one of the config value is invalid
return;
}
app_res = lib_settings->setNodeRole(APP_LIB_SETTINGS_ROLE_AUTOROLE_LL);
if (app_res != APP_RES_OK)
{
LOG(LVL_ERROR, "Error setting node role (res:%d)", app_res);
return;
}
ctrl_ret = Control_Router_init(&conf);
if (ctrl_ret != CONTROL_RET_OK)
{
LOG(LVL_ERROR, "Error initializing control library (ret:%d)",
ctrl_ret);
}
app_res = Shared_Data_addDataReceivedCb(&m_switch_received_item);
if (app_res != APP_RES_OK)
{
LOG(LVL_ERROR, "Error adding Data callback (res:%d)", app_res);
}
app_cfg_res = Shared_Appconfig_addFilter(&m_da_appconfig_item,
&m_filter_id);
if (app_cfg_res != SHARED_APP_CONFIG_RES_OK)
{
LOG(LVL_ERROR, "Error adding AppConfig filter (res:%d)", app_cfg_res);
}
m_light_state = false;
m_received_config = false;
/*
* Start the stack.
* This is really important step, otherwise the stack will stay stopped and
* will not be part of any network. So the device will not be reachable
* without reflashing it
*/
lib_state->startStack();
}
APP_SCHEDULER_RES_OK
@ APP_SCHEDULER_RES_OK
Definition: app_scheduler.h:50
LVL_INFO
#define LVL_INFO
Definition: debug_log.h:83
Led_set
led_res_e Led_set(uint8_t led_id, bool state)
Turn the given LED on or off.
app_lib_data_send_res_e
app_lib_data_send_res_e
A result code returned from lib_data->sendData().
Definition: wms_data.h:136
LVL_ERROR
#define LVL_ERROR
Definition: debug_log.h:85
APP_SCHEDULER_STOP_TASK
#define APP_SCHEDULER_STOP_TASK
Value to return from task to remove it.
Definition: app_scheduler.h:37
APP_LIB_DATA_SEND_FLAG_UNACK_CSMA_CA
@ APP_LIB_DATA_SEND_FLAG_UNACK_CSMA_CA
Definition: wms_data.h:120
app_res_e
app_res_e
Definition: wms_app.h:201
APP_ADDR_BROADCAST
@ APP_ADDR_BROADCAST
Send packet as broadcast to all nodes.
Definition: wms_app.h:245
control_router_conf_t::ack_gen_cb
app_llhead_acklistener_f ack_gen_cb
Definition: control_router.h:21
control_router.h
Shared_Data_addDataReceivedCb
app_res_e Shared_Data_addDataReceivedCb(shared_data_item_t *item)
Add a new packet received item to the list. If the item is already in the list it is only updated.
app_lib_data_received_t::num_bytes
size_t num_bytes
Definition: wms_data.h:284
node_configuration.h
APP_LIB_DATA_RECEIVE_RES_HANDLED
@ APP_LIB_DATA_RECEIVE_RES_HANDLED
Definition: wms_data.h:188
ack_gen_output_t::data
void * data
Definition: wms_advertiser.h:99
App_Scheduler_addTask_execTime
app_scheduler_res_e App_Scheduler_addTask_execTime(task_cb_f cb, uint32_t delay_ms, uint32_t exec_time_us)
Add a task.
SHARED_APP_CONFIG_RES_OK
@ SHARED_APP_CONFIG_RES_OK
Definition: shared_appconfig.h:18
app_lib_data_received_t::src_address
app_addr_t src_address
Definition: wms_data.h:286
app_scheduler_res_e
app_scheduler_res_e
List of return code.
Definition: app_scheduler.h:47
ack_gen_output_t
Output structure for for callback function set by lib_advertiser->setRouterAckGenCb().
Definition: wms_advertiser.h:95
APP_LIB_DATA_NO_TRACKING_ID
#define APP_LIB_DATA_NO_TRACKING_ID
When sending data and no tracking of packet is requested, this ID may be used.
Definition: wms_data.h:60
APP_RES_OK
@ APP_RES_OK
Definition: wms_app.h:204
SHARED_DATA_NET_MODE_ALL
@ SHARED_DATA_NET_MODE_ALL
Definition: shared_data.h:53
shared_app_config_res_e
shared_app_config_res_e
List of return code.
Definition: shared_appconfig.h:15
app_lib_data_receive_res_e
app_lib_data_receive_res_e
Return value of data reception callback.
Definition: wms_data.h:184
app_scheduler.h
app_lib_data_to_send_t
A struct for lib_data->sendData().
Definition: wms_data.h:323
app_global_functions_t
List of global functions, passed to App_entrypoint()
Definition: wms_app.h:157
Shared_Appconfig_addFilter
shared_app_config_res_e Shared_Appconfig_addFilter(shared_app_config_filter_t *filter, uint16_t *filter_id)
Add a new app config type filter to the list. If the item is already in the list it is only updated.
debug_log.h
led.h
Board-independent LED functions.
CONTROL_RET_OK
@ CONTROL_RET_OK
Definition: control_node_int.h:24
configureNodeFromBuildParameters
__STATIC_INLINE app_res_e configureNodeFromBuildParameters()
Wrapper on top of configureNode to get parameters from build system and hardcoded values from chip (f...
Definition: node_configuration.h:224
shared_appconfig.h
LVL_DEBUG
#define LVL_DEBUG
Macros to define several log levels: Debug, Info, Warning, Error.
Definition: debug_log.h:82
app_lib_data_received_t
Struct passed to data reception callback functions.
Definition: wms_data.h:279
control_router_conf_t
Configuration structure for Control node router.
Definition: control_router.h:16
ack_gen_output_t::length
uint8_t length
Definition: wms_advertiser.h:102
LOG_INIT
#define LOG_INIT()
Definition: debug_log.h:66
shared_data.h
shared_app_config_filter_t
Structure holding all parameters for app config type filtering.
Definition: shared_appconfig.h:64
APP_LIB_DATA_SEND_RES_SUCCESS
@ APP_LIB_DATA_SEND_RES_SUCCESS
Definition: wms_data.h:139
ack_gen_input_t
Input data structure for callback function set by lib_advertiser->setRouterAckGenCb().
Definition: wms_advertiser.h:69
LOG
#define LOG(level, fmt,...)
Print a log message if its severity is lower or equal to DEBUG_LOG_MAX_LEVEL.
Definition: debug_log.h:173
Shared_Data_sendData
app_lib_data_send_res_e Shared_Data_sendData(app_lib_data_to_send_t *data, app_lib_data_data_sent_cb_f sent_cb)
Send data. The packet to send is represented as a app_lib_data_to_send_t struct.
app_lib_data_received_t::bytes
const uint8_t * bytes
Definition: wms_data.h:282
APP_LIB_DATA_QOS_NORMAL
@ APP_LIB_DATA_QOS_NORMAL
Definition: wms_data.h:84
shared_app_config_filter_t::type
uint16_t type
Definition: shared_appconfig.h:68
app_lib_data_received_t::delay
uint32_t delay
Definition: wms_data.h:288
control_node_ret_e
control_node_ret_e
Return codes of control functions.
Definition: control_node_int.h:21
APP_LIB_SETTINGS_ROLE_AUTOROLE_LL
@ APP_LIB_SETTINGS_ROLE_AUTOROLE_LL
Definition: wms_settings.h:83
Control_Router_init
control_node_ret_e Control_Router_init(control_router_conf_t *conf)
Initialize Directed Advertiser libray for router node.
api.h