This commit is contained in:
Klaus K Wilting 2018-04-15 12:12:06 +02:00
parent 342f135d41
commit 0b0dc9c02b
9 changed files with 161 additions and 169 deletions

View File

@ -102,10 +102,10 @@ Multiple command/parameter pairs can be concatenated and sent in one single payl
Note: all settings are stored in NVRAM and will be reloaded when device starts. To reset device to factory settings press button (if device has one), or send remote command 09 02 09 00 unconfirmed(!) once.
0x01 set Wifi scan RSSI limit
0x01 set scan RSSI limit
1 ... 255 used for wifi scan radius (greater values increase wifi scan radius, values 50...110 make sense)
0 = Wifi rssi limiter disabled [default]
1 ... 255 used for wifi and bluetooth scan radius (greater values increase scan radius, values 50...110 make sense)
0 = RSSI limiter disabled [default]
0x02 set counter mode
@ -163,7 +163,10 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
0 ... 255 duration of a BLE scan cycle in seconds
e.g. 15 -> 1 cycle runs for 15 seconds [default]
0x0D (unused)
0x0D (NOT YET IMPLEMENTED) set BLE and WIFI vendorfilter mode
0 = disabled (use to count devices, not people)
1 = enabled [default]
0x0E set BLE scan mode
@ -196,8 +199,9 @@ device answers with it's current configuration. The configuration is a C structu
byte 11: BLE scan cycle duration in seconds (0..255)
byte 12: BLE scan mode (1=on, 0=0ff)
byte 13: Wifi antenna switch (0=internal, 1=external)
byte 14: RGB LED luminosity (0..100 %)
bytes 15-24: Software version (ASCII format)
byte 14: Vendorfilter mode (0=disabled, 1=enabled)
byte 15: RGB LED luminosity (0..100 %)
bytes 16-25: Software version (ASCII format)
0x81 get device uptime

View File

@ -10,9 +10,9 @@
; ---> SELECT TARGET PLATFORM HERE! <---
[platformio]
env_default = heltec_wifi_lora_32
;env_default = heltec_wifi_lora_32
;env_default = ttgov1
;env_default = ttgov2
env_default = ttgov2
;env_default = lopy
;env_default = lopy4
;env_default = lolin32lite_lora
@ -55,6 +55,7 @@ build_flags =
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
;override lora settings from LMiC library in lmic/config.h and use main.h instead
-Dttgov1
-D_lmic_config_h_
@ -77,6 +78,7 @@ build_flags =
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
;override lora settings from LMiC library in lmic/config.h and use main.h instead
-D_lmic_config_h_
-Dttgov2
@ -99,6 +101,7 @@ build_flags =
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
;override lora settings from LMiC library in lmic/config.h and use main.h instead
-Dlopy
-D_lmic_config_h_
@ -121,6 +124,7 @@ build_flags =
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
;override lora settings from LMiC library in lmic/config.h and use main.h instead
-D_lmic_config_h_
-Dlopy4
@ -143,6 +147,7 @@ build_flags =
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
;override lora settings from LMiC library in lmic/config.h and use main.h instead
-D_lmic_config_h_
-Dlolin32lite_lora
@ -165,6 +170,7 @@ build_flags =
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
;override lora settings from LMiC library in lmic/config.h and use main.h instead
-D_lmic_config_h_
-Dlolin32_lora

View File

@ -23,130 +23,9 @@ static const char *TAG = "bt_loop";
bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type);
// Prototypes
static const char *bt_gap_search_event_type_to_string(uint32_t searchEvt);
static const char *bt_addr_t_to_string(esp_ble_addr_type_t type);
static const char *bt_dev_type_to_string(esp_bt_dev_type_t type);
static const char *btsig_gap_type(uint32_t gap_type);
static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param;
esp_err_t status;
switch (event)
{
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
{
ESP_LOGD(TAG, "Start Scan, status: %d", p->scan_param_cmpl.status);
// This procedure keep the device scanning the peer device which advertising on the air.
status = esp_ble_gap_start_scanning(BLESCANTIME);
if (status != ESP_OK)
{
ESP_LOGE(TAG, "esp_ble_gap_start_scanning: rc=%d", status);
}
}
break;
case ESP_GAP_BLE_SCAN_RESULT_EVT:
{
ESP_LOGI(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", BT_BD_ADDR_HEX(p->scan_rst.bda));
ESP_LOGI(TAG, "Device type : %s", bt_dev_type_to_string(p->scan_rst.dev_type));
ESP_LOGI(TAG, "Search_evt : %s", bt_gap_search_event_type_to_string(p->scan_rst.search_evt));
ESP_LOGI(TAG, "Addr_type : %s", bt_addr_t_to_string(p->scan_rst.ble_addr_type));
ESP_LOGI(TAG, "RSSI : %d", p->scan_rst.rssi);
ESP_LOGI(TAG, "Flag : %d", p->scan_rst.flag);
//bit 0 (OFF) LE Limited Discoverable Mode
//bit 1 (OFF) LE General Discoverable Mode
//bit 2 (ON) BR/EDR Not Supported
//bit 3 (OFF) Simultaneous LE and BR/EDR to Same Device Capable (controller)
//bit 4 (OFF) Simultaneous LE and BR/EDR to Same Device Capable (Host)
ESP_LOGI(TAG, "num_resps : %d", p->scan_rst.num_resps);
if ( p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done
{ // restart scan
status = esp_ble_gap_start_scanning (BLESCANTIME);
if (status != ESP_OK)
{
ESP_LOGE(TAG, "esp_ble_gap_start_scanning: rc=%d", status);
}
return;
}
if (p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) // Inquiry result for a peer device
{
#ifdef VENDORFILTER
if ( (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_PUBLIC) ||
(p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_PUBLIC)
)
{
#endif
// add this device and show new count total if it was not previously added
mac_add((uint8_t *) p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE);
#ifdef VENDORFILTER
}
else
{
ESP_LOGI(TAG, "BLE device filtered");
}
#endif
/* to be improved in vendorfilter if:
// you can search for elements in the payload using the
// function esp_ble_resolve_adv_data()
//
// Like this, that scans for the "Complete name" (looking inside the payload buffer)
// uint8_t len;
// uint8_t *data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &len);
filter BLE devices using their advertisements to get filter alternative to vendor OUI
if vendorfiltering is on, we ...
- want to count: mobile phones and tablets
- don't want to count: beacons, peripherals (earphones, headsets, printers), cars and machines
see
https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/src/BLEAdvertisedDevice.cpp
http://www.libelium.com/products/meshlium/smartphone-detection/
https://www.question-defense.com/2013/01/12/bluetooth-cod-bluetooth-class-of-deviceclass-of-service-explained
https://www.bluetooth.com/specifications/assigned-numbers/baseband
"The Class of Device (CoD) in case of Bluetooth which allows us to differentiate the type of
device (smartphone, handsfree, computer, LAN/network AP). With this parameter we can
differentiate among pedestrians and vehicles."
*/
}
}
break;
default:
break;
}
} // gap_callback_handler
static const char *bt_dev_type_to_string(esp_bt_dev_type_t type) {
switch(type) {
case ESP_BT_DEVICE_TYPE_BREDR:
return "ESP_BT_DEVICE_TYPE_BREDR";
case ESP_BT_DEVICE_TYPE_BLE:
return "ESP_BT_DEVICE_TYPE_BLE";
case ESP_BT_DEVICE_TYPE_DUMO:
return "ESP_BT_DEVICE_TYPE_DUMO";
default:
return "Unknown";
}
} // bt_dev_type_to_string
static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
static const char *bt_addr_t_to_string(esp_ble_addr_type_t type) {
switch(type) {
@ -163,28 +42,6 @@ static const char *bt_addr_t_to_string(esp_ble_addr_type_t type) {
}
} // bt_addr_t_to_string
static const char *bt_gap_search_event_type_to_string(uint32_t searchEvt) {
switch(searchEvt) {
case ESP_GAP_SEARCH_INQ_RES_EVT:
return "ESP_GAP_SEARCH_INQ_RES_EVT";
case ESP_GAP_SEARCH_INQ_CMPL_EVT:
return "ESP_GAP_SEARCH_INQ_CMPL_EVT";
case ESP_GAP_SEARCH_DISC_RES_EVT:
return "ESP_GAP_SEARCH_DISC_RES_EVT";
case ESP_GAP_SEARCH_DISC_BLE_RES_EVT:
return "ESP_GAP_SEARCH_DISC_BLE_RES_EVT";
case ESP_GAP_SEARCH_DISC_CMPL_EVT:
return "ESP_GAP_SEARCH_DISC_CMPL_EVT";
case ESP_GAP_SEARCH_DI_DISC_CMPL_EVT:
return "ESP_GAP_SEARCH_DI_DISC_CMPL_EVT";
case ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT:
return "ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT";
default:
return "Unknown event type";
}
} // bt_gap_search_event_type_to_string
/*
static const char *btsig_gap_type(uint32_t gap_type) {
switch (gap_type)
{
@ -229,8 +86,106 @@ static const char *btsig_gap_type(uint32_t gap_type) {
default:
return "Unknown type";
}
}
*/
} // btsig_gap_type
static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param;
esp_err_t status;
ESP_LOGD(tag, "BT payload sniffed -> type: 0x%.2x -> %s", *p->scan_rst.ble_adv, btsig_gap_type(*p->scan_rst.ble_adv));
switch (event)
{
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
{ // restart scan
status = esp_ble_gap_start_scanning(BLESCANTIME);
if (status != ESP_OK)
{
ESP_LOGE(TAG, "esp_ble_gap_start_scanning: rc=%d", status);
}
}
break;
case ESP_GAP_BLE_SCAN_RESULT_EVT:
{
if ( p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done
{ // restart scan
status = esp_ble_gap_start_scanning (BLESCANTIME);
if (status != ESP_OK)
{
ESP_LOGE(TAG, "esp_ble_gap_start_scanning: rc=%d", status);
}
return;
}
if (p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) // Inquiry result for a peer device
{ // evaluate sniffed packet
ESP_LOGD(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", BT_BD_ADDR_HEX(p->scan_rst.bda));
ESP_LOGD(TAG, "Addr_type : %s", bt_addr_t_to_string(p->scan_rst.ble_addr_type));
ESP_LOGD(TAG, "RSSI : %d", p->scan_rst.rssi);
if (!( cfg.rssilimit == 0 ) || (p->scan_rst.rssi > cfg.rssilimit )) { // rssi is negative value
ESP_LOGI(TAG, "BLTH RSSI %d -> ignoring (limit: %d)", p->scan_rst.rssi, cfg.rssilimit);
break;
}
#ifdef VENDORFILTER
if (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RANDOM) goto skip;
if (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_RANDOM) goto skip;
#endif
// add this device and show new count total if it was not previously added
mac_add((uint8_t *) p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE);
break;
skip:
ESP_LOGD(TAG, "BT device filtered");
break;
/* to be improved in vendorfilter if:
// you can search for elements in the payload using the
// function esp_ble_resolve_adv_data()
//
// Like this, that scans for the "Complete name" (looking inside the payload buffer)
// uint8_t len;
// uint8_t *data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &len);
filter BLE devices using their advertisements to get filter alternative to vendor OUI
if vendorfiltering is on, we ...
- want to count: mobile phones and tablets
- don't want to count: beacons, peripherals (earphones, headsets, printers), cars and machines
see
https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/src/BLEAdvertisedDevice.cpp
http://www.libelium.com/products/meshlium/smartphone-detection/
https://www.question-defense.com/2013/01/12/bluetooth-cod-bluetooth-class-of-deviceclass-of-service-explained
https://www.bluetooth.com/specifications/assigned-numbers/baseband
"The Class of Device (CoD) in case of Bluetooth which allows us to differentiate the type of
device (smartphone, handsfree, computer, LAN/network AP). With this parameter we can
differentiate among pedestrians and vehicles."
*/
}
}
break;
default:
break;
}
} // gap_callback_handler
esp_err_t register_ble_functionality(void)
{
@ -250,14 +205,20 @@ esp_err_t register_ble_functionality(void)
static esp_ble_scan_params_t ble_scan_params =
{
.scan_type = BLE_SCAN_TYPE_PASSIVE,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_UND_RPA_DIR,
// .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
#ifdef VENDORFILTER
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR,
// ADV_IND, ADV_NONCONN_IND, ADV_SCAN_IND packets are used for broadcasting
// data in broadcast applications (e.g., Beacons), so we don't want them in vendorfilter mode
#else
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
#endif
.scan_interval = (uint16_t) (BLESCANINTERVAL / 0.625), // Time = N * 0.625 msec
.scan_window = (uint16_t) (BLESCANWINDOW / 0.625) // Time = N * 0.625 msec
};
ESP_LOGI(TAG, "Set GAP scan parameters");
ESP_LOGI(TAG, "Set GAP scan parameters");
// This function is called to set scan parameters.
status = esp_ble_gap_set_scan_params(&ble_scan_params);

View File

@ -30,6 +30,7 @@ void defaultConfig() {
cfg.blescantime = BLESCANTIME; // BLE scan cycle duration [seconds]
cfg.blescan = 1; // 0=disabled, 1=enabled
cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4)
cfg.vendorfilter = 1; // 0=disabled, 1=enabled
cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%)
strncpy( cfg.version, PROGVERSION, sizeof(cfg.version)-1 );
@ -113,6 +114,9 @@ void saveConfig() {
if( nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK || flash8 != cfg.wifiant )
nvs_set_i8(my_handle, "wifiant", cfg.wifiant);
if( nvs_get_i8(my_handle, "vendorfilter", &flash8) != ESP_OK || flash8 != cfg.vendorfilter )
nvs_set_i8(my_handle, "vendorfilter", cfg.vendorfilter);
if( nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK || flash8 != cfg.rgblum )
nvs_set_i8(my_handle, "rgblum", cfg.rgblum);
@ -240,6 +244,14 @@ void loadConfig() {
saveConfig();
}
if( nvs_get_i8(my_handle, "vendorfilter", &flash8) == ESP_OK ) {
cfg.vendorfilter = flash8;
ESP_LOGI(TAG, "vendorfilter = %i", flash8);
} else {
ESP_LOGI(TAG, "Vendorfilter mode set to default %i", cfg.vendorfilter);
saveConfig();
}
if( nvs_get_i8(my_handle, "rgblum", &flash8) == ESP_OK ) {
cfg.rgblum = flash8;
ESP_LOGI(TAG, "rgbluminosity = %i", flash8);

View File

@ -35,6 +35,7 @@ typedef struct {
int8_t blescantime; // BLE scan cycle duration [seconds]
int8_t blescan; // 0=disabled, 1=enabled
int8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4)
int8_t vendorfilter; // 0=disabled, 1=enabled
int8_t rgblum; // RGB Led luminosity (0..100%)
char version[10]; // Firmware version
} configData_t;

View File

@ -34,7 +34,7 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
#ifdef VENDORFILTER
vendor2int = ( (uint32_t)paddr[2] ) | ( (uint32_t)paddr[1] << 8 ) | ( (uint32_t)paddr[0] << 16 );
// No vendor filter for BLE
// use OUI vendor filter list only on Wifi, not on BLE
if ( (sniff_type==MAC_SNIFF_BLE) || std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end() ) {
#endif
@ -65,7 +65,7 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
rgb_set_color(COLOR_MAGENTA);
bles.insert(hashedmac); // add hashed MAC to BLE container
u8x8.setCursor(0,3);
u8x8.printf("BLE: %-4d", (int) bles.size());
u8x8.printf("BLTH: %-4d", (int) bles.size());
}
#endif
@ -74,8 +74,8 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
rgb_set_color(COLOR_NONE);
}
ESP_LOGI(TAG, "%s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLE:%d %s",
sniff_type==MAC_SNIFF_WIFI ? "WiFi":"BLE ",
ESP_LOGI(TAG, "%s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d %s",
sniff_type==MAC_SNIFF_WIFI ? "WiFi":"BLTH",
rssi, buff, hashedmac,
(int) wifis.size(),
#ifdef BLECOUNTER
@ -83,12 +83,12 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
#else
0,
#endif
added ? "New" : "Already seen");
added ? "new" : "known");
#ifdef VENDORFILTER
} else {
// Very noisy
//ESP_LOGI(TAG, "Filtered MAC %02X:%02X:%02X:%02X:%02X:%02X", paddr[0],paddr[1],paddr[2],paddr[3],paddr[5],paddr[5]);
ESP_LOGD(TAG, "Filtered MAC %02X:%02X:%02X:%02X:%02X:%02X", paddr[0],paddr[1],paddr[2],paddr[3],paddr[5],paddr[5]);
}
#endif

View File

@ -270,7 +270,7 @@ void sniffer_loop(void * pvParameters) {
yield();
channel = (channel % WIFI_CHANNEL_MAX) + 1; // rotates variable channel 1..WIFI_CHANNEL_MAX
wifi_sniffer_set_channel(channel);
ESP_LOGI(TAG, "Wifi set channel %d", channel);
ESP_LOGD(TAG, "Wifi set channel %d", channel);
snprintf(buff, sizeof(buff), "PAX:%d", (int) macs.size()); // convert 16-bit MAC counter to decimal counter value
u8x8.draw2x2String(0, 0, buff); // display number on unique macs total
@ -476,7 +476,7 @@ void setup() {
u8x8.printf("WIFI: 0");
#ifdef BLECOUNTER
u8x8.setCursor(0,3);
u8x8.printf("BLE: 0");
u8x8.printf("BLTH: 0");
#endif
u8x8.setCursor(0,5);
u8x8.printf(!cfg.rssilimit ? "RLIM: off" : "RLIM: %d", cfg.rssilimit);

View File

@ -1,7 +1,7 @@
#pragma once
// program version - note: increment version after modifications to configData_t struct!!
#define PROGVERSION "1.2.97" // use max 10 chars here!
#define PROGVERSION "1.2.98" // use max 10 chars here!
#define PROGNAME "PAXCNT"
// Verbose enables serial output

View File

@ -182,6 +182,14 @@ void set_wifiant(int val) {
#endif
};
void set_vendorfilter(int val) {
ESP_LOGI(TAG, "Remote command: set vendorfilter mode to %s", val ? "on" : "off");
switch (val) {
case 1: cfg.vendorfilter = val; break;
default: cfg.vendorfilter = 0; break;
}
};
void set_rgblum(int val) {
// Avoid wrong parameters
cfg.rgblum = (val>=0 && val<=100) ? (uint8_t) val : RGBLUMINOSITY;
@ -246,7 +254,7 @@ cmd_t table[] = {
{0x0a, set_wifiscancycle, true},
{0x0b, set_wifichancycle, true},
{0x0c, set_blescantime, true},
{0x0d, set_noop, false},
{0x0d, set_vendorfilter, false},
{0x0e, set_blescan, true},
{0x0f, set_wifiant, true},
{0x10, set_rgblum, true},