// Copyright 2015 by Thorsten von Eicken, see LICENSE.txt
//
// Adapted from: github.com/tuanpmt/esp_bridge, Created on: Jan 9, 2015, Author: Minh
# include "esp8266.h"
# include "cmd.h"
# include <cgiwifi.h>
# ifdef MQTT
# include <mqtt_cmd.h>
# endif
# ifdef REST
# include <rest.h>
# endif
# ifdef CMD_DBG
# define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
# else
# define DBG(format, ...) do { } while(0)
# endif
static void cmdNull ( CmdPacket * cmd ) ;
static void cmdSync ( CmdPacket * cmd ) ;
static void cmdWifiStatus ( CmdPacket * cmd ) ;
static void cmdAddCallback ( CmdPacket * cmd ) ;
// keep track of last status sent to uC so we can notify it when it changes
static uint8_t lastWifiStatus = wifiIsDisconnected ;
static bool wifiCbAdded = false ;
// Command dispatch table for serial -> ESP commands
const CmdList commands [ ] = {
{ CMD_NULL , " NULL " , cmdNull } , // no-op
{ CMD_SYNC , " SYNC " , cmdSync } , // synchronize
{ CMD_WIFI_STATUS , " WIFI_STATUS " , cmdWifiStatus } ,
{ CMD_CB_ADD , " ADD_CB " , cmdAddCallback } ,
# ifdef MQTT
{ CMD_MQTT_SETUP , " MQTT_SETUP " , MQTTCMD_Setup } ,
{ CMD_MQTT_PUBLISH , " MQTT_PUB " , MQTTCMD_Publish } ,
{ CMD_MQTT_SUBSCRIBE , " MQTT_SUB " , MQTTCMD_Subscribe } ,
{ CMD_MQTT_LWT , " MQTT_LWT " , MQTTCMD_Lwt } ,
# endif
# ifdef REST
{ CMD_REST_SETUP , " REST_SETUP " , REST_Setup } ,
{ CMD_REST_REQUEST , " REST_REQ " , REST_Request } ,
{ CMD_REST_SETHEADER , " REST_SETHDR " , REST_SetHeader } ,
# endif
} ;
//===== List of registered callbacks (to uC)
// WifiCb plus 10 for sensors
# define MAX_CALLBACKS 12
CmdCallback callbacks [ MAX_CALLBACKS ] ; // cleared in cmdSync
uint32_t ICACHE_FLASH_ATTR
cmdAddCb ( char * name , uint32_t cb ) {
for ( uint8_t i = 0 ; i < MAX_CALLBACKS ; i + + ) {
//os_printf("cmdAddCb: index %d name=%s cb=%p\n", i, callbacks[i].name,
// (void *)callbacks[i].callback);
// find existing callback or add to the end
if ( os_strncmp ( callbacks [ i ] . name , name , CMD_CBNLEN ) = = 0 | | callbacks [ i ] . name [ 0 ] = = ' \0 ' ) {
os_strncpy ( callbacks [ i ] . name , name , sizeof ( callbacks [ i ] . name ) ) ;
callbacks [ i ] . name [ CMD_CBNLEN - 1 ] = 0 ; // strncpy doesn't null terminate
callbacks [ i ] . callback = cb ;
DBG ( " cmdAddCb: '%s'->0x%x added at %d \n " , callbacks [ i ] . name , cb , i ) ;
return 1 ;
}
}
return 0 ;
}
CmdCallback * ICACHE_FLASH_ATTR
cmdGetCbByName ( char * name ) {
for ( uint8_t i = 0 ; i < MAX_CALLBACKS ; i + + ) {
//os_printf("cmdGetCbByName: index %d name=%s cb=%p\n", i, callbacks[i].name,
// (void *)callbacks[i].callback);
// if callback doesn't exist or it's null
if ( os_strncmp ( callbacks [ i ] . name , name , CMD_CBNLEN ) = = 0 ) {
DBG ( " cmdGetCbByName: cb %s found at index %d \n " , name , i ) ;
return & callbacks [ i ] ;
}
}
os_printf ( " cmdGetCbByName: cb %s not found \n " , name ) ;
return 0 ;
}
//===== Wifi callback
// Callback from wifi subsystem to notify us of status changes
static void ICACHE_FLASH_ATTR
cmdWifiCb ( uint8_t wifiStatus ) {
if ( wifiStatus ! = lastWifiStatus ) {
DBG ( " cmdWifiCb: wifiStatus=%d \n " , wifiStatus ) ;
lastWifiStatus = wifiStatus ;
CmdCallback * wifiCb = cmdGetCbByName ( " wifiCb " ) ;
if ( ( uint32_t ) wifiCb - > callback ! = - 1 ) {
uint8_t status = wifiStatus = = wifiGotIP ? 5 : 1 ;
cmdResponseStart ( CMD_RESP_CB , ( uint32_t ) wifiCb - > callback , 1 ) ;
cmdResponseBody ( ( uint8_t * ) & status , 1 ) ;
cmdResponseEnd ( ) ;
}
}
}
//===== Command handlers
// Command handler for Null command
static void ICACHE_FLASH_ATTR
cmdNull ( CmdPacket * cmd ) {
}
// Command handler for sync command
static void ICACHE_FLASH_ATTR
cmdSync ( CmdPacket * cmd ) {
CmdRequest req ;
cmdRequest ( & req , cmd ) ;
if ( cmd - > argc ! = 0 | | cmd - > value = = 0 ) {
cmdResponseStart ( CMD_RESP_V , 0 , 0 ) ;
cmdResponseEnd ( ) ;
return ;
}
// clear callbacks table
os_memset ( callbacks , 0 , sizeof ( callbacks ) ) ;
// register our callback with wifi subsystem
if ( ! wifiCbAdded ) {
wifiAddStateChangeCb ( cmdWifiCb ) ;
wifiCbAdded = true ;
}
// send OK response
cmdResponseStart ( CMD_RESP_V , cmd - > value , 0 ) ;
cmdResponseEnd ( ) ;
// save the MCU's callback and trigger an initial callback
cmdAddCb ( " wifiCb " , cmd - > value ) ;
lastWifiStatus = 0xff ; // set to invalid value so we immediately send status cb in all cases
cmdWifiCb ( wifiState ) ;
return ;
}
// Command handler for wifi status command
static void ICACHE_FLASH_ATTR
cmdWifiStatus ( CmdPacket * cmd ) {
cmdResponseStart ( CMD_RESP_V , wifiState , 0 ) ;
cmdResponseEnd ( ) ;
return ;
}
// Command handler to add a callback to the named-callbacks list, this is for a callback to the uC
static void ICACHE_FLASH_ATTR
cmdAddCallback ( CmdPacket * cmd ) {
CmdRequest req ;
cmdRequest ( & req , cmd ) ;
if ( cmd - > argc ! = 1 | | cmd - > value = = 0 ) return ;
char name [ 16 ] ;
uint16_t len ;
// get the callback name
len = cmdArgLen ( & req ) ;
if ( len > 15 ) return ; // max size of name is 15 characters
if ( cmdPopArg ( & req , ( uint8_t * ) name , len ) ) return ;
name [ len ] = 0 ;
DBG ( " cmdAddCallback: name=%s \n " , name ) ;
cmdAddCb ( name , cmd - > value ) ; // save the sensor callback
}