Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
| ||||||
Hand tools and fabrication machines | ||||||
| ||||||
| ||||||
|
Day's, months and years are moving very fast. I used to think about future, how do we can survive after became older, what are the problems will be there etc. By the time saw this contest about "Living in Motion" I decide to make something which is useful for older people. I had seen many people struggle to walk in older age with walking stick, so I decided to add some power to the stick what they hold. Yes its called "Smart Walking Stick"
What Smart WalkingStick can do?
This stick has the power to control the home appliance like lights, Air coolers, Fans and TV etc. Also the stick has sensors to detect the "Free Fall" or any "Hazards" and triggers the alert via whats-app or buzzers. Nowadays most of the time older age peoples are living alone at home so this stick can full-fill the needs for them.
Making of smart walking stickAt first step I have defined 3 application to showcase the demo.
1) Controlling Lights.
2) Controlling Fan
3) Controlling Music System.
these are three basic requirements I felt for older people.
I took few of KW41z boards and implemented the IoT network with "Thread" protocol and connected this to lights, Fan and music system.
For Music system I used DF Mp3 player with SD card. Added some mp3 songs in it. Via UART or Pin we can control the player. Power bank and 3W PC Speaker I used to complete the music setup.
For Fan I used RGB Cooling fan, the speed can be controlled via PWM.
For Lights just 20Watt LED light used and controlled via SSD relay.
Finally all these thread nodes are controlled from the Rapid IoT kit. Implemented the application to control via button press. This Rapid Iot can be connected mobile to push the notification or alerts to cloud via android app. Also it sends the notification via whats-app. (twillio).
Brought the normal walking stick from amazon and customized as per my needs removed some part and moved the LED control button below. Fixed the rapid iot kit on it and it can be easily reachable to control it.
Finally everything was set and the working demo is here. I have plan to implement this for old aged people home.
After winning 1st prize , this project is showcased on the CES 2020 at Lasvegas
Here is the another version of video.
#include <raspi.h>
#include "board.h"
#include "fsl_uart.h"
#include <math.h>
#include "pin_mux.h"
#include "clock_config.h"
#include "uart.h"
#include "backlight.h"
#include "emwin_support.h"
#include "GUI.h"
#include "fsl_ili9341.h"
#include "port_interrupts.h"
#include "images.h"
#include "uidraw.h"
#include "button.h"
#include "pixy.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define BOARD_SW_IRQ PORTE_IRQn
#define BOARD_SW_IRQ_HANDLER PORTE_IRQHandler
#define APP_MAX_COUNT 5
#define APP_TIMER 10
#define APP_LOCK_TIMER 2500
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
uint8_t txbuff[] = "version\r\n";
uint8_t ifconfig[] = "ifconfig\r\n";
uint8_t AIData[4] = {0};
/* Whether the SW button is pressed */
volatile bool g_ButtonPress = false;
volatile uint8_t g_ButtonValue = 0;
volatile uint32_t g_cloud_counter=0;
volatile uint32_t g_lock_counter=0;
volatile uint8_t g_AppIndex = 0;
volatile uint8_t g_AppLocked = 0;
volatile uint8_t g_AppLockDisable = 0;
volatile uint8_t g_AppStatus[5] = {0,0,0,0,0};
volatile uint8_t g_AppValue[5] = {0,0,0,0,0};
volatile uint32_t frame_update=500u;
extern uint8_t masterRxData[128];
extern uint8_t RxRpiBuffer[8];
extern volatile uint8_t rxRpiBlockReceived;
extern volatile uint8_t rxRpiDataCounter;
uint32_t color_array[] = {GUI_WHITE,GUI_MAGENTA, GUI_BLUE, GUI_GREEN, GUI_YELLOW};
pixy_colormode_t *pixy_cmode=masterRxData;
volatile uint16_t dx=0;
volatile uint16_t dy=0;
volatile uint16_t pdx=0;
volatile uint16_t pdy=0;
volatile uint8_t track_index=0;
volatile int8_t track_value=0;
volatile int8_t track_last_value=0;
/* Functions required for emwin / Display */
uint32_t DSPI2_GetFreq(void)
{
return CLOCK_GetBusClkFreq();
}
void Init_Display()
{
Display_Connect(); /* triggers GUI_Init() */
Backlight_SetLevel(BLIGHT_LEVEL_HIGH);
GUI_SetBkColor(GUI_BLACK);
GUI_SetColor(GUI_WHITE);
}
#define GUI_FONT_TITLE GUI_Font8x18
#define GUI_FONT_NORMAL GUI_Font8x16
uint8_t Init_Backlight(void)
{
backlight_fct_t BACKLIGHT_fct;
BACKLIGHT_fct.connect_hw = Backlight_Connect;
BACKLIGHT_fct.disconnect_hw = Backlight_Disconnect;
BACKLIGHT_fct.set_level = Backlight_Set_Level;
Backlight_Init_Driver(&BACKLIGHT_fct);
if (Backlight_Init_Hw())
return 1;
return 0;
}
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief Main function
*/
int main(void)
{
BOARD_InitPins();
BOARD_Boot_Clock_RUN();
BOARD_INIT_GPIOS();
//BOARD_Init_SPI_2();
BOARD_Init_RGB_BLIGHT();
PORT_IRQ_EnablePortAIrq();
PORT_IRQ_EnablePortEIrq();
THR_UART_Init();
//RPI_UART_Init();
//PIXY_Init();
Init_Backlight();
Init_Display();
GUI_Clear();
GUI_SetColor(GUI_BLACK);
GUI_SetBkColor(GUI_WHITE);
GUI_SetFont(&GUI_Font20B_1);
GUI_SetPenSize(8);
GUI_Clear();
//GUI_BMP_Draw(bglogo_176x176, 0, 0);
//App_WaitMsec(3000);
GUI_BMP_Draw(bg_176x176, 0, 0);
//App_WaitMsec(100);
draw_apppage(g_AppIndex,0,0);
//PIXY_Send_Data(PIXY_GET_VERSION);
//App_WaitMsec(1);
//PIXY_Get_Data();
// PIXY_SetLED(0,0,255);
GPIO_PinWrite(GPIOA, 11, 0);
GPIO_PinWrite(GPIOB, 8, 0);
GPIO_PinWrite(GPIOA, 13, 0);
GPIO_PinWrite(GPIOA, 14, 0);
while(1){
if(g_ButtonPress){
switch(g_ButtonValue){
case 0:
break;
case 1:
g_AppIndex++;
if(g_AppIndex>1){
g_AppIndex=0;
}
draw_apppage(g_AppIndex,1,0);
break;
case 2:
frame_update=frame_update-100;
if(frame_update<=100){
frame_update=500;
}
break;
}
g_ButtonValue = 0;
g_ButtonPress = false;
}
getCCBlocks();
App_WaitMsec(1);
//PIXY_Get_Data();
if(0){//g_AppIndex==0){
switch(pixy_cmode->sign){
case 1:
GUI_SetColor(GUI_MAGENTA);
GUI_FillRect(0, 144, 176, 176);
dx= ((315 - pixy_cmode->xpos)*176)/315;
GUI_SetColor(GUI_WHITE);
GUI_FillCircle(dx, 160, 10);
track_index=1;
break;
case 2:
GUI_SetColor(GUI_BLUE);
GUI_FillRect(0, 144, 176, 176);
dx= ((315 - pixy_cmode->xpos)*176)/315;
GUI_SetColor(GUI_WHITE);
GUI_FillCircle(dx, 160, 10);
track_index=2;
break;
case 3:
GUI_SetColor(GUI_GREEN);
GUI_FillRect(0, 144, 176, 176);
dx= ((315 - pixy_cmode->xpos)*176)/315;
GUI_SetColor(GUI_WHITE);
GUI_FillCircle(dx, 160, 10);
track_index=3;
break;
case 4:
GUI_SetColor(GUI_YELLOW);
GUI_FillRect(0, 144, 176, 176);
dx= ((315 - pixy_cmode->xpos)*176)/315;
GUI_SetColor(GUI_WHITE);
GUI_FillCircle(dx, 160, 10);
track_index=4;
break;
}
}
App_WaitMsec(frame_update);
}
}
/*==================================================================================================
Include Files
==================================================================================================*/
/* General Includes */
#include "EmbeddedTypes.h"
#include <string.h>
/* FSL Framework */
#include "shell.h"
#include "Keyboard.h"
#include "RNG_Interface.h"
#include "PWR_Interface.h"
/* Network */
#include "ip_if_management.h"
#include "event_manager.h"
/* Application */
#include "end_device_app.h"
#include "shell_ip.h"
#include "thread_utils.h"
#include "thread_network.h"
#include "thread_app_callbacks.h"
#include "app_init.h"
#include "app_stack_config.h"
#include "app_thread_config.h"
#include "app_led.h"
#include "app_temp_sensor.h"
#include "coap.h"
#include "app_socket_utils.h"
#if THR_ENABLE_EVENT_MONITORING
#include "app_event_monitoring.h"
#endif
#if THR_ENABLE_MGMT_DIAGNOSTICS
#include "thread_mgmt.h"
#include "thci.h"
#endif
#if UDP_ECHO_PROTOCOL
#include "app_echo_udp.h"
#endif
/*==================================================================================================
Private macros
==================================================================================================*/
#ifndef APP_MSG_QUEUE_SIZE
#define APP_MSG_QUEUE_SIZE 20
#endif
#if (THREAD_USE_SHELL == FALSE)
#define shell_write(a)
#define shell_refresh()
#define shell_printf(a,...)
#endif
#define gThrDefaultInstanceId_c 0
#define APP_LED_URI_PATH "/led"
#define APP_TEMP_URI_PATH "/temp"
#define APP_SINK_URI_PATH "/sink"
#define APP_DEFAULT_DEST_ADDR in6addr_realmlocal_allthreadnodes
#define APP_SW_WAKE_UP_TIMEOUT 5000 /* miliseconds */
/*==================================================================================================
Private type definitions
==================================================================================================*/
/*==================================================================================================
Private global variables declarations
==================================================================================================*/
static instanceId_t mThrInstanceId = gInvalidInstanceId_c; /*!< Thread Instance ID */
static bool_t mJoiningIsAppInitiated = FALSE;
/*==================================================================================================
Private prototypes
==================================================================================================*/
static void App_HandleKeyboard(void *param);
static void App_UpdateStateLeds(appDeviceState_t deviceState);
static void APP_JoinEventsHandler(thrEvCode_t evCode);
static void APP_SwWakeUpCb(void *pParam);
static void APP_InitCoapDemo(void);
static void APP_ReportTemp(void *pParam);
static void APP_SendDataSinkCreate(void *pParam);
static void APP_SendDataSinkRelease(void *pParam);
#if gKBD_KeysCount_c > 1
static void APP_SendLedRgbOn(void *pParam);
static void APP_SendLedRgbOff(void *pParam);
static void APP_SendLedFlash(void *pParam);
static void APP_SendLedColorWheel(void *pParam);
#endif
static void APP_LocalDataSinkRelease(void *pParam);
static void APP_ProcessLedCmd(uint8_t *pCommand, uint8_t dataLen);
static void APP_CoapGenericCallback(coapSessionStatus_t sessionStatus, void *pData, coapSession_t *pSession, uint32_t dataLen);
static void APP_CoapLedCb(coapSessionStatus_t sessionStatus, void *pData, coapSession_t *pSession, uint32_t dataLen);
static void APP_CoapTempCb(coapSessionStatus_t sessionStatus, void *pData, coapSession_t *pSession, uint32_t dataLen);
static void APP_CoapSinkCb(coapSessionStatus_t sessionStatus, void *pData, coapSession_t *pSession, uint32_t dataLen);
/*==================================================================================================
Public global variables declarations
==================================================================================================*/
const coapUriPath_t gAPP_LED_URI_PATH = {SizeOfString(APP_LED_URI_PATH), (uint8_t *)APP_LED_URI_PATH};
const coapUriPath_t gAPP_TEMP_URI_PATH = {SizeOfString(APP_TEMP_URI_PATH), (uint8_t *)APP_TEMP_URI_PATH};
const coapUriPath_t gAPP_SINK_URI_PATH = {SizeOfString(APP_SINK_URI_PATH), (uint8_t *)APP_SINK_URI_PATH};
/* Application state/mode */
appDeviceState_t gAppDeviceState[THR_MAX_INSTANCES];
appDeviceMode_t gAppDeviceMode[THR_MAX_INSTANCES];
/* Pointer application task message queue */
taskMsgQueue_t *mpAppThreadMsgQueue;
/* Flag used to stop the attaching retries */
bool_t gbRetryInterrupt = TRUE;
/* CoAP instance */
uint8_t mAppCoapInstId = THR_ALL_FFs8;
/* Destination address for CoAP commands */
ipAddr_t gCoapDestAddress;
/* Timer used to keep the device in Up state for an amount of time */
tmrTimerID_t gAppSwWakeUpTimer = gTmrInvalidTimerID_c;
extern bool_t gEnable802154TxLed;
/*==================================================================================================
Public functions
==================================================================================================*/
/*!*************************************************************************************************
\fn void APP_Init(void)
\brief This function is used to initialize application.
***************************************************************************************************/
void APP_Init
(
void
)
{
/* Initialize pointer to application task message queue */
mpAppThreadMsgQueue = &appThreadMsgQueue;
/* Initialize main thread message queue */
ListInit(&appThreadMsgQueue.msgQueue,APP_MSG_QUEUE_SIZE);
/* Set default device mode/state */
APP_SetState(gThrDefaultInstanceId_c, gDeviceState_FactoryDefault_c);
APP_SetMode(gThrDefaultInstanceId_c, gDeviceMode_Configuration_c);
/* Initialize keyboard handler */
pfAppKeyboardHandler = App_HandleKeyboard;
/* Use one instance ID for application */
mThrInstanceId = gThrDefaultInstanceId_c;
#if THR_ENABLE_EVENT_MONITORING
/* Initialize event monitoring */
APP_InitEventMonitor(mThrInstanceId);
#endif
if(gThrStatus_Success_c == THR_StartInstance(mThrInstanceId, pStackCfg[0]))
{
/* Initialize CoAP demo */
APP_InitCoapDemo();
#if USE_TEMPERATURE_SENSOR
/* Initialize Temperature sensor/ADC module*/
APP_InitADC(ADC_0);
#endif
#if THREAD_USE_THCI && THR_ENABLE_MGMT_DIAGNOSTICS
(void)MgmtDiagnostic_RegisterAppCb(THCI_MgmtDiagnosticAppCb);
#endif
#if THREAD_USE_SHELL && SOCK_DEMO
/* Initialize use sockets - used from shell */
APP_InitUserSockets(mpAppThreadMsgQueue);
#endif
#if APP_AUTOSTART
if(!THR_GetAttr_IsDevConnected(mThrInstanceId))
{
mJoiningIsAppInitiated = TRUE;
if(THR_NwkJoin(mThrInstanceId, THR_APP_JOIN_DISCOVERY_METHOD) != gThrStatus_Success_c)
{
/* User can treat join failure according to their application */
}
}
#endif
}
}
/*!*************************************************************************************************
\fn void App_Handler(void)
\brief Application Handler. In this configuration is called on the task with the lowest priority
***************************************************************************************************/
void APP_Handler
(
void
)
{
bool_t handleMsg = TRUE;
while(handleMsg == TRUE)
{
handleMsg = NWKU_MsgHandler(&appThreadMsgQueue);
/* For BareMetal break the while(1) after 1 run */
if(!gUseRtos_c && MSG_Pending(&appThreadMsgQueue.msgQueue))
{
(void)OSA_EventSet(appThreadMsgQueue.taskEventId, NWKU_GENERIC_MSG_EVENT);
break;
}
}
}
/*!*************************************************************************************************
\fn void APP_NwkScanHandler(void *param)
\brief This function is used to handle network scan results in asynchronous mode.
***************************************************************************************************/
void APP_NwkScanHandler
(
void *param
)
{
thrEvmParams_t *pEventParams = (thrEvmParams_t *)param;
thrNwkScanResults_t *pScanResults = &pEventParams->pEventData->nwkScanCnf;
/* Handle the network scan result here */
if(pScanResults)
{
#if THREAD_USE_SHELL
SHELL_NwkScanPrint(pScanResults);
#endif
MEM_BufferFree(pScanResults);
}
/* Free Event Buffer */
MEM_BufferFree(pEventParams);
}
/*!*************************************************************************************************
\fn void Stack_to_APP_Handler(void *param)
\brief This function is used to handle stack events in asynchronous mode.
\param [in] param Pointer to stack event
***************************************************************************************************/
void Stack_to_APP_Handler
(
void *param
)
{
thrEvmParams_t *pEventParams = (thrEvmParams_t *)param;
/* Uncomment for multicast address */
//ipAddr_t mCastGroup = MCAST_3EAD_ADDRESS;
switch(pEventParams->code)
{
case gThrEv_GeneralInd_ResetToFactoryDefault_c:
App_UpdateStateLeds(gDeviceState_FactoryDefault_c);
break;
case gThrEv_GeneralInd_InstanceRestoreStarted_c:
case gThrEv_GeneralInd_ConnectingStarted_c:
APP_SetMode(mThrInstanceId, gDeviceMode_Configuration_c);
App_UpdateStateLeds(gDeviceState_JoiningOrAttaching_c);
gEnable802154TxLed = FALSE;
break;
case gThrEv_NwkJoinCnf_Success_c:
case gThrEv_NwkJoinCnf_Failed_c:
APP_JoinEventsHandler(pEventParams->code);
break;
case gThrEv_GeneralInd_Connected_c:
App_UpdateStateLeds(gDeviceState_NwkConnected_c);
/* Set application CoAP destination to all nodes on connected network */
gCoapDestAddress = APP_DEFAULT_DEST_ADDR;
APP_SetMode(mThrInstanceId, gDeviceMode_Application_c);
/* Enable LED for 80215.4 tx activity */
gEnable802154TxLed = TRUE;
#if UDP_ECHO_PROTOCOL
ECHO_ProtocolInit(mpAppThreadMsgQueue);
#endif
/* Uncomment to register multicast address */
//IP_IF_AddMulticastGroup6(gIpIfSlp0_c, &mCastGroup);
break;
case gThrEv_GeneralInd_ConnectingFailed_c:
case gThrEv_GeneralInd_Disconnected_c:
APP_SetMode(mThrInstanceId, gDeviceMode_Configuration_c);
App_UpdateStateLeds(gDeviceState_NwkFailure_c);
break;
#if gLpmIncluded_d
case gThrEv_GeneralInd_AllowDeviceToSleep_c:
PWR_AllowDeviceToSleep();
break;
case gThrEv_GeneralInd_DisallowDeviceToSleep_c:
PWR_DisallowDeviceToSleep();
break;
#endif
default:
break;
}
/* Free event buffer */
MEM_BufferFree(pEventParams->pEventData);
MEM_BufferFree(pEventParams);
}
/*!*************************************************************************************************
\fn void APP_Commissioning_Handler(void *param)
\brief This function is used to handle Commissioning events in synchronous mode.
\param [in] param Pointer to Commissioning event
***************************************************************************************************/
void APP_Commissioning_Handler
(
void *param
)
{
thrEvmParams_t *pEventParams = (thrEvmParams_t *)param;
switch(pEventParams->code)
{
/* Joiner Events */
case gThrEv_MeshCop_JoinerDiscoveryStarted_c:
break;
case gThrEv_MeshCop_JoinerDiscoveryFailed_c:
break;
case gThrEv_MeshCop_JoinerDiscoveryFailedFiltered_c:
break;
case gThrEv_MeshCop_JoinerDiscoverySuccess_c:
break;
case gThrEv_MeshCop_JoinerDtlsSessionStarted_c:
App_UpdateStateLeds(gDeviceState_JoiningOrAttaching_c);
break;
case gThrEv_MeshCop_JoinerDtlsError_c:
case gThrEv_MeshCop_JoinerError_c:
App_UpdateStateLeds(gDeviceState_FactoryDefault_c);
break;
case gThrEv_MeshCop_JoinerAccepted_c:
break;
}
/* Free event buffer */
MEM_BufferFree(pEventParams);
}
/*!*************************************************************************************************
\fn void App_SedWakeUpFromKeyBoard(void)
\brief This is a callback fuction called when the device is waked from keyboard.
***************************************************************************************************/
void App_SedWakeUpFromKeyBoard
(
void
)
{
/* Keep the device Up for 5 seconds - using a timer */
if(gAppSwWakeUpTimer == gTmrInvalidTimerID_c)
{
gAppSwWakeUpTimer = TMR_AllocateTimer();
}
if(gAppSwWakeUpTimer != gTmrInvalidTimerID_c)
{
TMR_StartTimer(gAppSwWakeUpTimer, gTmrSingleShotTimer_c, APP_SW_WAKE_UP_TIMEOUT, APP_SwWakeUpCb, NULL);
}
}
/*==================================================================================================
Private functions
==================================================================================================*/
/*!*************************************************************************************************
\private
\fn static void APP_InitCoapDemo(void)
\brief Initialize CoAP demo.
***************************************************************************************************/
static void APP_InitCoapDemo
(
void
)
{
coapRegCbParams_t cbParams[] = {{APP_CoapLedCb, (coapUriPath_t *)&gAPP_LED_URI_PATH},
{APP_CoapTempCb, (coapUriPath_t *)&gAPP_TEMP_URI_PATH},
{APP_CoapSinkCb, (coapUriPath_t *)&gAPP_SINK_URI_PATH}};
/* Register Services in COAP */
coapStartUnsecParams_t coapParams = {COAP_DEFAULT_PORT, AF_INET6};
mAppCoapInstId = COAP_CreateInstance(NULL, &coapParams, gIpIfSlp0_c, (coapRegCbParams_t *)cbParams,
NumberOfElements(cbParams));
}
/*!*************************************************************************************************
\private
\fn static void APP_ConfigModeHandleKeyboard(uint32_t keyEvent)
\brief This is a handler for KBD module events. Device is in configuration mode.
\param [in] keyEvent The keyboard module event
***************************************************************************************************/
static void APP_ConfigModeHandleKeyboard
(
uint32_t keyEvent
)
{
switch(keyEvent)
{
case gKBD_EventPB1_c:
#if gKBD_KeysCount_c > 1
case gKBD_EventPB2_c:
case gKBD_EventPB3_c:
case gKBD_EventPB4_c:
#endif
if((APP_GetState(mThrInstanceId) == gDeviceState_FactoryDefault_c) ||
(APP_GetState(mThrInstanceId) == gDeviceState_NwkFailure_c))
{
App_UpdateStateLeds(gDeviceState_JoiningOrAttaching_c);
mJoiningIsAppInitiated = TRUE;
/* join the network */
if(THR_NwkJoin(mThrInstanceId, THR_APP_JOIN_DISCOVERY_METHOD) != gThrStatus_Success_c)
{
/* User can treat join failure according to their application */
}
}
break;
case gKBD_EventLongPB1_c:
#if gKBD_KeysCount_c > 1
case gKBD_EventLongPB2_c:
case gKBD_EventLongPB3_c:
case gKBD_EventLongPB4_c:
#endif
break;
/* Factory reset */
case gKBD_EventVeryLongPB1_c:
#if gKBD_KeysCount_c > 1
case gKBD_EventVeryLongPB2_c:
case gKBD_EventVeryLongPB3_c:
case gKBD_EventVeryLongPB4_c:
#endif
THR_FactoryReset();
break;
default:
break;
}
}
/*!*************************************************************************************************
\private
\fn static void APP_AppModeHandleKeyboard(uint32_t keyEvent)
\brief This is a handler for KBD module events. Device is in application mode.
\param [in] keyEvent The keyboard module event
***************************************************************************************************/
static void APP_AppModeHandleKeyboard
(
uint32_t keyEvent
)
{
#if gLpmIncluded_d
/* restart wake up timer */
App_SedWakeUpFromKeyBoard();
#endif
switch(keyEvent)
{
case gKBD_EventPB1_c:
/* Data sink create */
(void)NWKU_SendMsg(APP_SendDataSinkCreate, NULL, mpAppThreadMsgQueue);
break;
#if gKBD_KeysCount_c > 1
case gKBD_EventPB2_c:
/* Report temperature */
(void)NWKU_SendMsg(APP_ReportTemp, NULL, mpAppThreadMsgQueue);
break;
case gKBD_EventPB3_c:
/* Remote led RGB - on */
(void)NWKU_SendMsg(APP_SendLedRgbOn, NULL, mpAppThreadMsgQueue);
break;
case gKBD_EventPB4_c:
/* Remote led RGB - off */
(void)NWKU_SendMsg(APP_SendLedRgbOff, NULL, mpAppThreadMsgQueue);
break;
#endif
case gKBD_EventLongPB1_c:
/* Remote data sink release */
(void)NWKU_SendMsg(APP_SendDataSinkRelease, NULL, mpAppThreadMsgQueue);
break;
#if gKBD_KeysCount_c > 1
case gKBD_EventLongPB2_c:
/* Local data sink release */
(void)NWKU_SendMsg(APP_LocalDataSinkRelease, NULL, mpAppThreadMsgQueue);
break;
case gKBD_EventLongPB3_c:
/* Remote led flash */
(void)NWKU_SendMsg(APP_SendLedFlash, NULL, mpAppThreadMsgQueue);
break;
case gKBD_EventLongPB4_c:
/* Remote led - color wheel */
(void)NWKU_SendMsg(APP_SendLedColorWheel, NULL, mpAppThreadMsgQueue);
break;
#endif
case gKBD_EventVeryLongPB1_c:
#if gKBD_KeysCount_c > 1
case gKBD_EventVeryLongPB2_c:
case gKBD_EventVeryLongPB3_c:
case gKBD_EventVeryLongPB4_c:
#endif
/* Factory reset */
THR_FactoryReset();
break;
default:
break;
}
}
/*!*************************************************************************************************
\private
\fn static void App_HandleKeyboard(void *param)
\brief This is a handler for KBD module events.
\param [in] param The keyboard module event
***************************************************************************************************/
static void App_HandleKeyboard
(
void *param
)
{
uint32_t events = (uint32_t)(param);
if(APP_GetMode(mThrInstanceId) == gDeviceMode_Configuration_c)
{
/* Device is in configuration mode */
APP_ConfigModeHandleKeyboard(events);
}
else
{
/* Device is in application mode */
APP_AppModeHandleKeyboard(events);
}
}
/*!*************************************************************************************************
\private
\fn static void App_UpdateLedState(appDeviceState_t deviceState)
\brief Called when Application state and LEDs must be updated.
\param [in] deviceState The current device state
***************************************************************************************************/
static void App_UpdateStateLeds
(
appDeviceState_t deviceState
)
{
APP_SetState(mThrInstanceId, deviceState);
Led_SetState(APP_GetMode(mThrInstanceId), APP_GetState(mThrInstanceId));
}
/*!*************************************************************************************************
\private
\fn static void APP_JoinEventsHandler(thrEvCode_t evCode)
\brief This function is used to the handle join failed event.
\param [in] evCode Event code
***************************************************************************************************/
static void APP_JoinEventsHandler
(
thrEvCode_t evCode
)
{
if(mJoiningIsAppInitiated)
{
if(evCode == gThrEv_NwkJoinCnf_Failed_c)
{
if(gbRetryInterrupt)
{
/* Retry to join the network */
if(THR_NwkJoin(mThrInstanceId, THR_APP_JOIN_DISCOVERY_METHOD) != gThrStatus_Success_c)
{
/* User can treat join failure according to their application */
}
return;
}
mJoiningIsAppInitiated = FALSE;
}
else if(evCode == gThrEv_NwkJoinCnf_Success_c)
{
mJoiningIsAppInitiated = FALSE;
}
}
}
/*!*************************************************************************************************
\fn static void APP_SwWakeUpCb(void *pParam)
\brief This is a callback fuction called when the device is waked from keyboard.
After this callback the device will enter in low power
\param [in] pParam Not used
***************************************************************************************************/
static void APP_SwWakeUpCb
(
void *pParam
)
{
TMR_StopTimer(gAppSwWakeUpTimer);
#if gLpmIncluded_d
PWR_AllowDeviceToSleep();
#endif
}
/*==================================================================================================
Coap Demo functions:
==================================================================================================*/
/*!*************************************************************************************************
\private
\fn static void APP_CoapGenericCallback(coapSessionStatus_t sessionStatus, void *pData,
coapSession_t *pSession, uint32_t dataLen)
\brief This function is the generic callback function for CoAP message.
\param [in] sessionStatus Status for CoAP session
\param [in] pData Pointer to CoAP message payload
\param [in] pSession Pointer to CoAP session
\param [in] dataLen Length of CoAP payload
***************************************************************************************************/
static void APP_CoapGenericCallback
(
coapSessionStatus_t sessionStatus,
void *pData,
coapSession_t *pSession,
uint32_t dataLen
)
{
/* If no ACK was received, try again */
if(sessionStatus == gCoapFailure_c)
{
if(FLib_MemCmp(pSession->pUriPath->pUriPath, (coapUriPath_t*)&gAPP_TEMP_URI_PATH.pUriPath,
pSession->pUriPath->length))
{
(void)NWKU_SendMsg(APP_ReportTemp, NULL, mpAppThreadMsgQueue);
}
}
/* Process data, if any */
}
/*!*************************************************************************************************
\private
\fn static void APP_ReportTemp(void *pParam)
\brief This open a socket and report the temperature to gCoapDestAddress.
\param [in] pParam Not used
***************************************************************************************************/
static void APP_ReportTemp
(
void *pParam
)
{
coapSession_t *pSession = NULL;
/* Get Temperature */
uint8_t *pTempString = App_GetTempDataString();
uint32_t ackPloadSize;
ifHandle_t ifHandle = THR_GetIpIfPtrByInstId(mThrInstanceId);
if(!IP_IF_IsMyAddr(ifHandle->ifUniqueId, &gCoapDestAddress))
{
pSession = COAP_OpenSession(mAppCoapInstId);
if(NULL != pSession)
{
coapMsgTypesAndCodes_t coapMessageType = gCoapMsgTypeNonPost_c;
pSession->pCallback = NULL;
FLib_MemCpy(&pSession->remoteAddr, &gCoapDestAddress, sizeof(ipAddr_t));
ackPloadSize = strlen((char *)pTempString);
COAP_SetUriPath(pSession, (coapUriPath_t *)&gAPP_TEMP_URI_PATH);
if(!IP6_IsMulticastAddr(&gCoapDestAddress))
{
coapMessageType = gCoapMsgTypeConPost_c;
pSession->pCallback = APP_CoapGenericCallback;
}
COAP_Send(pSession, coapMessageType, pTempString, ackPloadSize);
}
}
/* Print temperature in shell */
shell_write("\r");
shell_write((char *)pTempString);
shell_refresh();
MEM_BufferFree(pTempString);
}
/*!*************************************************************************************************
\private
\fn static nwkStatus_t APP_SendDataSinkCommand(uint8_t *pCommand, uint8_t dataLen)
\brief This function is used to send a Data Sink command to APP_DEFAULT_DEST_ADDR.
\param [in] pCommand Pointer to command data
\param [in] dataLen Data length
\return nwkStatus_t Status of the command
***************************************************************************************************/
static nwkStatus_t APP_SendDataSinkCommand
(
uint8_t *pCommand,
uint8_t dataLen
)
{
nwkStatus_t status = gNwkStatusFail_c;
coapSession_t *pSession = COAP_OpenSession(mAppCoapInstId);
if(pSession)
{
ipAddr_t coapDestAddress = APP_DEFAULT_DEST_ADDR;
pSession->pCallback = NULL;
FLib_MemCpy(&pSession->remoteAddr, &coapDestAddress, sizeof(ipAddr_t));
COAP_SetUriPath(pSession, (coapUriPath_t*)&gAPP_SINK_URI_PATH);
status = COAP_Send(pSession, gCoapMsgTypeNonPost_c, pCommand, dataLen);
}
return status;
}
/*!*************************************************************************************************
\private
\fn static void APP_SendDataSinkCreate(void *pParam)
\brief This function is used to send a Data Sink Create command to APP_DEFAULT_DEST_ADDR.
\param [in] pParam Not used
***************************************************************************************************/
static void APP_SendDataSinkCreate
(
void *pParam
)
{
uint8_t aCommand[] = {"create"};
/* Send command over the air */
if(APP_SendDataSinkCommand(aCommand, sizeof(aCommand)) == gNwkStatusSuccess_c)
{
/* Local data sink create */
(void)THR_GetIP6Addr(mThrInstanceId, gMLEIDAddr_c, &gCoapDestAddress, NULL);
}
}
/*!*************************************************************************************************
\private
\fn static void APP_SendDataSinkRelease(void *pParam)
\brief This function is used to send a Data Sink Release command to APP_DEFAULT_DEST_ADDR.
\param [in] pParam Pointer to stack event
***************************************************************************************************/
static void APP_SendDataSinkRelease
(
void *pParam
)
{
uint8_t aCommand[] = {"release"};
/* Send command over the air */
if(APP_SendDataSinkCommand(aCommand, sizeof(aCommand)) == gNwkStatusSuccess_c)
{
/* Local data sink release */
APP_LocalDataSinkRelease(pParam);
}
}
#if gKBD_KeysCount_c > 1
/*!*************************************************************************************************
\private
\fn static void APP_SendLedCommand(uint8_t *pCommand, uint8_t dataLen)
\brief This function is used to send a Led command to gCoapDestAddress.
\param [in] pCommand Pointer to command data
\param [in] dataLen Data length
***************************************************************************************************/
static void APP_SendLedCommand
(
uint8_t *pCommand,
uint8_t dataLen
)
{
ifHandle_t ifHandle = THR_GetIpIfPtrByInstId(mThrInstanceId);
if(!IP_IF_IsMyAddr(ifHandle->ifUniqueId, &gCoapDestAddress))
{
coapSession_t *pSession = COAP_OpenSession(mAppCoapInstId);
if(pSession)
{
coapMsgTypesAndCodes_t coapMessageType = gCoapMsgTypeNonPost_c;
pSession->pCallback = NULL;
FLib_MemCpy(&pSession->remoteAddr, &gCoapDestAddress, sizeof(ipAddr_t));
COAP_SetUriPath(pSession,(coapUriPath_t *)&gAPP_LED_URI_PATH);
if(!IP6_IsMulticastAddr(&gCoapDestAddress))
{
coapMessageType = gCoapMsgTypeConPost_c;
pSession->pCallback = APP_CoapGenericCallback;
}
else
{
APP_ProcessLedCmd(pCommand, dataLen);
}
COAP_Send(pSession, coapMessageType, pCommand, dataLen);
}
}
else
{
APP_ProcessLedCmd(pCommand, dataLen);
}
}
/*!*************************************************************************************************
\private
\fn static void APP_SendLedRgbOn(void *pParam)
\brief This function is used to send a Led RGB On command over the air.
\param [in] pParam Not used
***************************************************************************************************/
static void APP_SendLedRgbOn
(
void *pParam
)
{
uint8_t aCommand[] = {"rgb r000 g000 b000"};
uint8_t redValue, greenValue, blueValue;
/* Red value on: 0x01 - 0xFF */
redValue = (uint8_t)NWKU_GetRandomNoFromInterval(0x01, THR_ALL_FFs8);
/* Green value on: 0x01 - 0xFF */
greenValue = (uint8_t)NWKU_GetRandomNoFromInterval(0x01, THR_ALL_FFs8);
/* Blue value on: 0x01 - 0xFF */
blueValue = (uint8_t)NWKU_GetRandomNoFromInterval(0x01, THR_ALL_FFs8);
NWKU_PrintDec(redValue, aCommand + 5, 3, TRUE); //aCommand + strlen("rgb r")
NWKU_PrintDec(greenValue, aCommand + 10, 3, TRUE); //aCommand + strlen("rgb r000 g")
NWKU_PrintDec(blueValue, aCommand + 15, 3, TRUE); //aCommand + strlen("rgb r000 g000 b")
APP_SendLedCommand(aCommand, sizeof(aCommand));
}
/*!*************************************************************************************************
\private
\fn static void APP_SendLedRgbOff(void *pParam)
\brief This function is used to send a Led RGB Off command over the air.
\param [in] pParam Not used
***************************************************************************************************/
static void APP_SendLedRgbOff
(
void *pParam
)
{
uint8_t aCommand[] = {"rgb r000 g000 b000"};
APP_SendLedCommand(aCommand, sizeof(aCommand));
}
/*!*************************************************************************************************
\private
\fn static void APP_SendLedFlash(void *pParam)
\brief This function is used to send a Led flash command over the air.
\param [in] pParam Not used
***************************************************************************************************/
static void APP_SendLedFlash
(
void *pParam
)
{
uint8_t aCommand[] = {"flash"};
APP_SendLedCommand(aCommand, sizeof(aCommand));
}
/*!*************************************************************************************************
\private
\fn static void APP_SendLedColorWheel(void *pParam)
\brief This function is used to send a Led color wheel command over the air.
\param [in] pParam Pointer to stack event
***************************************************************************************************/
static void APP_SendLedColorWheel
(
void *pParam
)
{
uint8_t aCommand[] = {"color wheel"};
APP_SendLedCommand(aCommand, sizeof(aCommand));
}
#endif
/*!*************************************************************************************************
\private
\fn static void APP_LocalDataSinkRelease(void *pParam)
\brief This function is used to restore the default destination address for CoAP messages.
\param [in] pParam Pointer to stack event
***************************************************************************************************/
static void APP_LocalDataSinkRelease
(
void *pParam
)
{
ipAddr_t defaultDestAddress = APP_DEFAULT_DEST_ADDR;
FLib_MemCpy(&gCoapDestAddress, &defaultDestAddress, sizeof(ipAddr_t));
(void)pParam;
}
/*!*************************************************************************************************
\private
\fn static void APP_CoapLedCb(coapSessionStatus_t sessionStatus, void *pData,
coapSession_t *pSession, uint32_t dataLen)
\brief This function is the callback function for CoAP LED message.
\brief It performs the required operations and sends back a CoAP ACK message.
\param [in] sessionStatus Status for CoAP session
\param [in] pData Pointer to CoAP message payload
\param [in] pSession Pointer to CoAP session
\param [in] dataLen Length of CoAP payload
***************************************************************************************************/
static void APP_CoapLedCb
(
coapSessionStatus_t sessionStatus,
void *pData,
coapSession_t *pSession,
uint32_t dataLen
)
{
/* Process the command only if it is a POST method */
if((pData) && (sessionStatus == gCoapSuccess_c) && (pSession->code == gCoapPOST_c))
{
APP_ProcessLedCmd(pData, dataLen);
}
/* Send the reply if the status is Success or Duplicate */
if((gCoapFailure_c != sessionStatus) && (gCoapConfirmable_c == pSession->msgType))
{
/* Send CoAP ACK */
COAP_Send(pSession, gCoapMsgTypeAckSuccessChanged_c, NULL, 0);
}
}
/*!*************************************************************************************************
\private
\fn static void APP_ProcessLedCmd(uint8_t *pCommand, uint8_t dataLen)
\brief This function is used to process a LED command (on, off, flash, toggle, rgb, color wheel).
\param [in] pCommand Pointer to command data
\param [in] dataLen Data length
***************************************************************************************************/
static void APP_ProcessLedCmd
(
uint8_t *pCommand,
uint8_t dataLen
)
{
/* Set mode state */
APP_SetMode(mThrInstanceId, gDeviceMode_Application_c);
/* Process command */
if(FLib_MemCmp(pCommand, "on", 2))
{
App_UpdateStateLeds(gDeviceState_AppLedOn_c);
}
else if(FLib_MemCmp(pCommand, "off", 3))
{
App_UpdateStateLeds(gDeviceState_AppLedOff_c);
}
else if(FLib_MemCmp(pCommand, "toggle", 6))
{
App_UpdateStateLeds(gDeviceState_AppLedToggle_c);
}
else if(FLib_MemCmp(pCommand, "flash", 5))
{
App_UpdateStateLeds(gDeviceState_AppLedFlash_c);
}
else if(FLib_MemCmp(pCommand, "rgb", 3))
{
char* p = (char *)pCommand + strlen("rgb");
uint8_t redValue = 0, greenValue = 0, blueValue = 0;
appDeviceState_t appState = gDeviceState_AppLedRgb_c;
dataLen -= strlen("rgb");
while(dataLen != 0)
{
if(*p == 'r')
{
p++;
dataLen--;
redValue = NWKU_atoi(p);
}
...
This file has been truncated, please download it to see its full contents.
Comments