diff --git a/customer_app/bl602_blemsh_node/Makefile b/customer_app/bl602_blemsh_node/Makefile new file mode 100644 index 00000000..a5863be6 --- /dev/null +++ b/customer_app/bl602_blemsh_node/Makefile @@ -0,0 +1,49 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := bl602_blemesh_node +PROJECT_PATH := $(abspath .) +PROJECT_BOARD := evb +export PROJECT_PATH PROJECT_BOARD +#CONFIG_TOOLPREFIX := + +-include ./proj_config.mk + +ifeq ($(origin BL60X_SDK_PATH), undefined) +BL60X_SDK_PATH_GUESS ?= $(shell pwd) +BL60X_SDK_PATH ?= $(BL60X_SDK_PATH_GUESS)/../.. +$(info ****** Please SET BL60X_SDK_PATH ******) +$(info ****** Trying SDK PATH [$(BL60X_SDK_PATH)]) +endif + +COMPONENTS_NETWORK := sntp dns_server +COMPONENTS_BLSYS := bltime blfdt blmtd blota bloop loopadc looprt loopset +COMPONENTS_VFS := romfs atcmd cjson +ifeq ($(CONFIG_BT_TL),1) +COMPONENTS_BLE := blecontroller +else +COMPONENTS_BLE := blecontroller blestack +endif + +INCLUDE_COMPONENTS += freertos_riscv_ram bl602 bl602_std bl602_wifi bl602_wifidrv hal_drv lwip lwip_dhcpd mbedtls vfs yloop utils cli httpc netutils blog blog_testc +INCLUDE_COMPONENTS += easyflash4 lwip_altcp_tls_mbedtls +INCLUDE_COMPONENTS += $(COMPONENTS_NETWORK) +INCLUDE_COMPONENTS += $(COMPONENTS_BLSYS) +INCLUDE_COMPONENTS += $(COMPONENTS_VFS) +INCLUDE_COMPONENTS += $(PROJECT_NAME) + +ifeq ($(CONFIG_BT),1) +INCLUDE_COMPONENTS += $(COMPONENTS_BLE) +ifeq ($(CONFIG_BT_MESH),1) +INCLUDE_COMPONENTS += blemesh +endif +ifeq ($(CONFIG_BT_MESH_MODEL),1) +INCLUDE_COMPONENTS += blemesh_model +endif +ifeq ($(CONFIG_BT_MESH_SYNC),1) +INCLUDE_COMPONENTS += blsync_ble +endif +endif +include $(BL60X_SDK_PATH)/make_scripts_riscv/project.mk diff --git a/customer_app/bl602_blemsh_node/README.md b/customer_app/bl602_blemsh_node/README.md new file mode 100644 index 00000000..a783fe85 --- /dev/null +++ b/customer_app/bl602_blemsh_node/README.md @@ -0,0 +1,44 @@ +# Bluetooh mesh node demo user guide + +This demo code button pin is IO12. Please add the following setting to corresponding dts file :this node feature is " button" and mode is " multipress". this node will trigger three event , customer can set "press time" setting. + + This mesh node default provision mode is PB-GATT. This demo has two button event: + +1. short press: enable unprovisioned advertising (PB-GATT). + +2. long press : reset node. + +```c +gpio2 { + status = "okay"; + pin = <12>; + feature = "button"; + active = "Hi"; + mode = "multipress"; + button { + debounce = <10>; + short_press_ms { + start = <100>; + end = <2000>; + kevent = <2>; + }; + long_press_ms { + start = <3000>; + end = <5000>; + kevent = <3>; + }; + longlong_press_ms { + start = <10000>; + kevent = <4>; + }; + trig_level = "Lo"; + }; + hbn_use = "disable"; +}; +``` + + + + + + \ No newline at end of file diff --git a/customer_app/bl602_blemsh_node/bl602_blemesh_node/bouffalo.mk b/customer_app/bl602_blemsh_node/bl602_blemesh_node/bouffalo.mk new file mode 100644 index 00000000..e12ff417 --- /dev/null +++ b/customer_app/bl602_blemsh_node/bl602_blemesh_node/bouffalo.mk @@ -0,0 +1,26 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +include $(BL60X_SDK_PATH)/components/network/ble/ble_common.mk + +ifeq ($(CONFIG_ENABLE_PSM_RAM),1) +CPPFLAGS += -DCONF_USER_ENABLE_PSRAM +endif + +ifeq ($(CONFIG_ENABLE_CAMERA),1) +CPPFLAGS += -DCONF_USER_ENABLE_CAMERA +endif + +ifeq ($(CONFIG_ENABLE_BLSYNC),1) +CPPFLAGS += -DCONF_USER_ENABLE_BLSYNC +endif + +ifeq ($(CONFIG_ENABLE_VFS_SPI),1) +CPPFLAGS += -DCONF_USER_ENABLE_VFS_SPI +endif + +ifeq ($(CONFIG_ENABLE_VFS_ROMFS),1) +CPPFLAGS += -DCONF_USER_ENABLE_VFS_ROMFS +endif diff --git a/customer_app/bl602_blemsh_node/bl602_blemesh_node/main.c b/customer_app/bl602_blemsh_node/bl602_blemesh_node/main.c new file mode 100644 index 00000000..6905aaff --- /dev/null +++ b/customer_app/bl602_blemsh_node/bl602_blemesh_node/main.c @@ -0,0 +1,485 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "bl602_adc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include +#include +#include +#include +#include +#include +#include "ble_lib_api.h" +#include "hal_pds.h" +#include "bl_rtc.h" +#include "utils_string.h" + +#include "mesh_node.h" + +#define TIME_5MS_IN_32768CYCLE (164) // (5000/(1000000/32768)) + +bool pds_start = false; + + +extern uint8_t _heap_start; +extern uint8_t _heap_size; // @suppress("Type cannot be resolved") +extern uint8_t _heap_wifi_start; +extern uint8_t _heap_wifi_size; // @suppress("Type cannot be resolved") +static HeapRegion_t xHeapRegions[] = +{ + { &_heap_start, (unsigned int) &_heap_size}, //set on runtime + { &_heap_wifi_start, (unsigned int) &_heap_wifi_size }, + { NULL, 0 }, /* Terminates the array. */ + { NULL, 0 } /* Terminates the array. */ +}; + + +void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName ) +{ + puts("Stack Overflow checked\r\n"); + while (1) { + /*empty here*/ + } +} + +void vApplicationMallocFailedHook(void) +{ + printf("Memory Allocate Failed. Current left size is %d bytes\r\n", + xPortGetFreeHeapSize() + ); + while (1) { + /*empty here*/ + } +} + +void vApplicationIdleHook(void) +{ + if(!pds_start){ + __asm volatile( + " wfi " + ); + /*empty*/ + } +} + +#if ( configUSE_TICKLESS_IDLE != 0 ) +void vApplicationSleep( TickType_t xExpectedIdleTime_ms ) +{ +#if defined(CFG_BLE_PDS) + int32_t bleSleepDuration_32768cycles = 0; + int32_t expectedIdleTime_32768cycles = 0; + eSleepModeStatus eSleepStatus; + bool freertos_max_idle = false; + + if (pds_start == 0) + return; + + if(xExpectedIdleTime_ms + xTaskGetTickCount() == portMAX_DELAY){ + freertos_max_idle = true; + }else{ + xExpectedIdleTime_ms -= 1; + expectedIdleTime_32768cycles = 32768 * xExpectedIdleTime_ms / 1000; + } + + if((!freertos_max_idle)&&(expectedIdleTime_32768cycles < TIME_5MS_IN_32768CYCLE)){ + return; + } + + /*Disable mtimer interrrupt*/ + *(volatile uint8_t*)configCLIC_TIMER_ENABLE_ADDRESS = 0; + + eSleepStatus = eTaskConfirmSleepModeStatus(); + if(eSleepStatus == eAbortSleep || ble_controller_sleep_is_ongoing()) + { + /*A task has been moved out of the Blocked state since this macro was + executed, or a context siwth is being held pending.Restart the tick + and exit the critical section. */ + /*Enable mtimer interrrupt*/ + *(volatile uint8_t*)configCLIC_TIMER_ENABLE_ADDRESS = 1; + //printf("%s:not do ble sleep\r\n", __func__); + return; + } + + bleSleepDuration_32768cycles = ble_controller_sleep(); + + if(bleSleepDuration_32768cycles < TIME_5MS_IN_32768CYCLE) + { + /*BLE controller does not allow sleep. Do not enter a sleep state.Restart the tick + and exit the critical section. */ + /*Enable mtimer interrrupt*/ + //printf("%s:not do pds sleep\r\n", __func__); + *(volatile uint8_t*)configCLIC_TIMER_ENABLE_ADDRESS = 1; + } + else + { + printf("%s:bleSleepDuration_32768cycles=%ld\r\n", __func__, bleSleepDuration_32768cycles); + if(eSleepStatus == eStandardSleep && ((!freertos_max_idle) && (expectedIdleTime_32768cycles < bleSleepDuration_32768cycles))) + { + hal_pds_enter_with_time_compensation(1, expectedIdleTime_32768cycles - 40);//40);//20); + } + else + { + hal_pds_enter_with_time_compensation(1, bleSleepDuration_32768cycles - 40);//40);//20); + } + } +#endif +} +#endif + +static void proc_hellow_entry(void *pvParameters) +{ + vTaskDelay(500); + blemesh_node(); + while (1) { + printf("%s: RISC-V rv32imafc\r\n", __func__); + vTaskDelay(10000); + } + vTaskDelete(NULL); +} + + + +#if defined(CFG_BLE_PDS) +static void cmd_start_pds(char *buf, int len, int argc, char **argv) +{ + if(argc != 2) + { + printf("Invalid params\r\n"); + return; + } + get_uint8_from_string(&argv[1], (uint8_t *)&pds_start); + if (pds_start == 1) + { + hal_pds_init(); + } +} +#endif +static void _cli_init() +{ + +} + +static int get_dts_addr(const char *name, uint32_t *start, uint32_t *off) +{ + uint32_t addr = hal_board_get_factory_addr(); + const void *fdt = (const void *)addr; + uint32_t offset; + + if (!name || !start || !off) { + return -1; + } + + offset = fdt_subnode_offset(fdt, 0, name); + if (offset <= 0) { + log_error("%s NULL.\r\n", name); + return -1; + } + + *start = (uint32_t)fdt; + *off = offset; + + return 0; +} + +static void __opt_feature_init(void) +{ +#ifdef CONF_USER_ENABLE_VFS_ROMFS + romfs_register(); +#endif +} + +static void event_cb_key_event(input_event_t *event, void *private_data) +{ + switch (event->code) { + case KEY_1: + { + printf("[KEY_1] [EVT] INIT DONE %lld\r\n", aos_now_ms()); + printf("short press \r\n"); + mesh_node_open(); + } + break; + case KEY_2: + { + printf("[KEY_2] [EVT] INIT DONE %lld\r\n", aos_now_ms()); + printf("long press \r\n"); + mesh_node_reset(); + } + break; + case KEY_3: + { + printf("[KEY_3] [EVT] INIT DONE %lld\r\n", aos_now_ms()); + printf("longlong press \r\n"); + } + break; + default: + { + printf("[KEY] [EVT] Unknown code %u, %lld\r\n", event->code, aos_now_ms()); + /*nothing*/ + } + } +} + +#if defined(CONFIG_BT_TL) +extern void uart_init(uint8_t uartid); +#endif + +static void aos_loop_proc(void *pvParameters) +{ + int fd_console; + uint32_t fdt = 0, offset = 0; + static StackType_t proc_stack_looprt[512]; + static StaticTask_t proc_task_looprt; + + /*Init bloop stuff*/ + looprt_start(proc_stack_looprt, 512, &proc_task_looprt); + loopset_led_hook_on_looprt(); + +// easyflash_init(); + vfs_init(); + vfs_device_init(); + + /* uart */ +#if 1 + if (0 == get_dts_addr("uart", &fdt, &offset)) { + vfs_uart_init(fdt, offset); + } +#else + vfs_uart_init_simple_mode(0, 7, 16, 2 * 1000 * 1000, "/dev/ttyS0"); +#endif + if (0 == get_dts_addr("gpio", &fdt, &offset)) { + fdt_button_module_init((const void *)fdt, (int)offset); + } + + __opt_feature_init(); + aos_loop_init(); + + fd_console = aos_open("/dev/ttyS0", 0); + if (fd_console >= 0) { + printf("Init CLI with event Driven\r\n"); + aos_cli_init(0); + aos_poll_read_fd(fd_console, aos_cli_event_cb_read_get(), (void*)0x12345678); + + } + + + aos_register_event_filter(EV_KEY, event_cb_key_event, NULL); + + //tsen_adc_init(); + + #if defined(CONFIG_BT_TL) + //uart's pinmux has been configured in vfs_uart_init(load uart1's pin info from devicetree) + uart_init(1); + ble_controller_init(configMAX_PRIORITIES - 1); + #endif + + aos_loop_run(); + + puts("------------------------------------------\r\n"); + puts("+++++++++Critical Exit From Loop++++++++++\r\n"); + puts("******************************************\r\n"); + vTaskDelete(NULL); +} + +void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) +{ + /* If the buffers to be provided to the Idle task are declared inside this + function then they must be declared static - otherwise they will be allocated on + the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + //static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + static StackType_t uxIdleTaskStack[512]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + //*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; + *pulIdleTaskStackSize = 512;//size 512 words is For ble pds mode, otherwise stack overflow of idle task will happen. +} + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the +application must provide an implementation of vApplicationGetTimerTaskMemory() +to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) +{ + /* If the buffers to be provided to the Timer task are declared inside this + function then they must be declared static - otherwise they will be allocated on + the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + +void user_vAssertCalled(void) __attribute__ ((weak, alias ("vAssertCalled"))); +void vAssertCalled(void) +{ + volatile uint32_t ulSetTo1ToExitFunction = 0; + + taskDISABLE_INTERRUPTS(); + while( ulSetTo1ToExitFunction != 1 ) { + __asm volatile( "NOP" ); + } +} + +static void _dump_boot_info(void) +{ + char chip_feature[40]; + const char *banner; + + puts("Booting BL602 Chip...\r\n"); + + /*Display Banner*/ + if (0 == bl_chip_banner(&banner)) { + puts(banner); + } + puts("\r\n"); + /*Chip Feature list*/ + puts("\r\n"); + puts("------------------------------------------------------------\r\n"); + puts("RISC-V Core Feature:"); + bl_chip_info(chip_feature); + puts(chip_feature); + puts("\r\n"); + + puts("Build Version: "); + puts(BL_SDK_VER); // @suppress("Symbol is not resolved") + puts("\r\n"); + + puts("Build Version: "); + puts(BL_SDK_VER); // @suppress("Symbol is not resolved") + puts("\r\n"); + + puts("PHY Version: "); + puts(BL_SDK_PHY_VER); // @suppress("Symbol is not resolved") + puts("\r\n"); + + puts("RF Version: "); + puts(BL_SDK_RF_VER); // @suppress("Symbol is not resolved") + puts("\r\n"); + + puts("Build Date: "); + puts(__DATE__); + puts("\r\n"); + puts("Build Time: "); + puts(__TIME__); + puts("\r\n"); + puts("------------------------------------------------------------\r\n"); + +} + +static void system_init(void) +{ + blog_init(); + bl_irq_init(); + bl_sec_init(); + bl_sec_test(); + bl_dma_init(); + bl_rtc_init(); + hal_boot2_init(); + + /* board config is set after system is init*/ + hal_board_cfg(0); +} + +static void system_thread_init() +{ + /*nothing here*/ +} + +void bfl_main() +{ + static StackType_t aos_loop_proc_stack[1024]; + static StaticTask_t aos_loop_proc_task; + static StackType_t proc_hellow_stack[512]; + static StaticTask_t proc_hellow_task; + + bl_sys_early_init(); + + /*Init UART In the first place*/ + bl_uart_init(0, 16, 7, 255, 255, 2 * 1000 * 1000); + puts("Starting bl602 now....\r\n"); + + bl_sys_init(); + + _dump_boot_info(); + + vPortDefineHeapRegions(xHeapRegions); + printf("Heap %u@%p, %u@%p\r\n", + (unsigned int)&_heap_size, &_heap_start, + (unsigned int)&_heap_wifi_size, &_heap_wifi_start + ); + + system_init(); + system_thread_init(); + + puts("[OS] Starting proc_hellow_entry task...\r\n"); + xTaskCreateStatic(proc_hellow_entry, (char*)"hellow", 512, NULL, 15, proc_hellow_stack, &proc_hellow_task); + puts("[OS] Starting aos_loop_proc task...\r\n"); + xTaskCreateStatic(aos_loop_proc, (char*)"event_loop", 1024, NULL, 15, aos_loop_proc_stack, &aos_loop_proc_task); + puts("[OS] Starting OS Scheduler...\r\n"); + vTaskStartScheduler(); +} diff --git a/customer_app/bl602_blemsh_node/bl602_blemesh_node/mesh_node.c b/customer_app/bl602_blemsh_node/bl602_blemesh_node/mesh_node.c new file mode 100644 index 00000000..0600dabf --- /dev/null +++ b/customer_app/bl602_blemsh_node/bl602_blemesh_node/mesh_node.c @@ -0,0 +1,532 @@ +#include +#include "conn.h" +#include "gatt.h" +#include "FreeRTOS.h" +#include "task.h" +#include "cli.h" +#include "include/mesh.h" +#include "errno.h" +#include "bluetooth.h" +#include "ble_lib_api.h" +#include "mesh.h" +#include "net.h" +#include "transport.h" +#include "foundation.h" +#include "mesh_settings.h" +#include "adv.h" +#include "beacon.h" +#include "hci_core.h" +#include "log.h" +#include "mesh_node.h" +#include "hci_driver.h" +#include "gen_srv.h" +#include +#if defined(CONFIG_BT_SETTINGS) +#include "easyflash.h" +#endif +#include <../../../components/network/ble/blestack/src/include/bluetooth/crypto.h> +#include "local_operation.h" +#define CUR_FAULTS_MAX 4 + +static bool blemesh_inited = false; + +#if defined(CONFIG_BT_MESH_LOW_POWER) +//below value is for Tmall Genie +static u8_t dev_uuid[16] = {0xA8,0x01,0x71,0x5e,0x1c,0x00,0x00,0xe4,0x46,0x46,0x63,0xa7,0xf8,0x02,0x00,0x00}; +static u8_t auth_value[16] = {0x78,0x8A,0xE3,0xEE,0x0F,0x2A,0x7E,0xFA,0xD3,0x67,0x35,0x81,0x41,0xFE,0x1B,0x06}; +#else +static u8_t dev_uuid[16] = {0xA8,0x01,0x71,0xe0,0x1a,0x00,0x00,0x0f,0x7e,0x35,0x63,0xa7,0xf8,0x02,0x00,0x00}; +static u8_t auth_value[16] = {0x7f,0x80,0x1a,0xf4,0xa0,0x8c,0x50,0x39,0xae,0x7d,0x7b,0x44,0xa0,0x92,0xd9,0xc2}; +#endif + +static bt_mesh_input_action_t input_act; +static u8_t input_size; +static u8_t cur_faults[CUR_FAULTS_MAX]; +static u8_t reg_faults[CUR_FAULTS_MAX * 2]; + +static struct { + u16_t local; + u16_t dst; + u16_t net_idx; + u16_t app_idx; +} net = { + .local = BT_MESH_ADDR_UNASSIGNED, + .dst = BT_MESH_ADDR_UNASSIGNED, +}; + +#if defined(BL602) +#define vOutputString(...) printf(__VA_ARGS__) +#else +#define vOutputString(...) bl_print(SYSTEM_UART_ID, PRINT_MODULE_CLI, __VA_ARGS__) +#endif +static const char *bearer2str(bt_mesh_prov_bearer_t bearer); +static void prov_reset(void); +static void gen_dev_uuid(void); +static void link_open(bt_mesh_prov_bearer_t bearer); +static void link_close(bt_mesh_prov_bearer_t bearer); +static int output_number(bt_mesh_output_action_t action, u32_t number); + +static int output_string(const char *str); +static void prov_input_complete(void); +static void prov_complete(u16_t net_idx, u16_t addr); +static void prov_reset(void); +static int input(bt_mesh_input_action_t act, u8_t size); +static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count); +static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr, + u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count); +static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id, + u16_t *company_id, u8_t *faults, u8_t *fault_count); +static int fault_get_reg(struct bt_mesh_model *model, u16_t cid, + u8_t *test_id, u8_t *faults, u8_t *fault_count); +static int fault_clear(struct bt_mesh_model *model, uint16_t cid); +static int fault_test(struct bt_mesh_model *model, uint8_t test_id, uint16_t cid); +static void attn_on(struct bt_mesh_model *model); +static void attn_off(struct bt_mesh_model *model); + +static void blemesh_init(void); + +static void blemesh_pb_gatt(void); +static void blemesh_pb_adv(void); + +static struct bt_mesh_prov prov = { + .uuid = dev_uuid, + .oob_info = 0, + .link_open = link_open, + .link_close = link_close, + .complete = prov_complete, + .reset = prov_reset, + .static_val = auth_value, + .static_val_len = 16, + .output_size = 6, + .output_actions = (BT_MESH_DISPLAY_NUMBER | BT_MESH_DISPLAY_STRING), + .output_number = output_number, + .output_string = output_string, + .input_size = 6, + .input_actions = (BT_MESH_ENTER_NUMBER | BT_MESH_ENTER_STRING), + .input = input, + .input_complete = prov_input_complete, +}; + +static const struct bt_mesh_health_srv_cb health_srv_cb = { + .fault_get_cur = fault_get_cur, + .fault_get_reg = fault_get_reg, + .fault_clear = fault_clear, + .fault_test = fault_test, + .attn_on = attn_on, + .attn_off = attn_off, +}; + +static struct bt_mesh_health_srv health_srv = { + .cb = &health_srv_cb, +}; + +static struct bt_mesh_health_cli health_cli = { + .current_status = health_current_status, +}; + +BT_MESH_HEALTH_PUB_DEFINE(health_pub, CUR_FAULTS_MAX); + +static struct bt_mesh_cfg_cli cfg_cli = { +}; + +static struct bt_mesh_cfg_srv cfg_srv = { + .relay = BT_MESH_RELAY_ENABLED, + .beacon = BT_MESH_BEACON_ENABLED,//BT_MESH_BEACON_DISABLED, +#if defined(CONFIG_BT_MESH_FRIEND) + .frnd = BT_MESH_FRIEND_DISABLED, +#else + .frnd = BT_MESH_FRIEND_NOT_SUPPORTED, +#endif +#if defined(CONFIG_BT_MESH_GATT_PROXY) + .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED, +#else + .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED, +#endif + + .default_ttl = 7, + + /* 6 transmissions with 20ms interval */ + .net_transmit = BT_MESH_TRANSMIT(5, 20), + /* 3 transmissions with 20ms interval */ + .relay_retransmit = BT_MESH_TRANSMIT(2, 20), +}; + + +struct bt_mesh_gen_onoff_srv onoff_srv = { +}; + + +static void borad_rgb_init(void) +{ + + bl_gpio_enable_output(LED_RED_PIN,1,0); + bl_gpio_enable_output(LED_GREEN_PIN,1,0); + bl_gpio_enable_output(LED_BLUE_PIN,1,0); + bl_gpio_output_set(LED_RED_PIN,1); + bl_gpio_output_set(LED_GREEN_PIN,1); + bl_gpio_output_set(LED_BLUE_PIN,1); + +} +static void borad_rgb_off(void) +{ + + bl_gpio_output_set(LED_RED_PIN,1); + bl_gpio_output_set(LED_GREEN_PIN,1); + bl_gpio_output_set(LED_BLUE_PIN,1); + +} +void model_gen_cb(uint8_t value) +{ + printf("onff value=%d \n",value); + if(value==1){ + bl_gpio_output_set(LED_RED_PIN,0); + }else if(value==0){ + + borad_rgb_off(); + } +} +static struct bt_mesh_model sig_models[] = { + BT_MESH_MODEL_CFG_SRV(&cfg_srv), + BT_MESH_MODEL_CFG_CLI(&cfg_cli), + BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), + BT_MESH_MODEL_HEALTH_CLI(&health_cli), + BT_MESH_MODEL_GEN_ONOFF(&onoff_srv), +}; + +static struct bt_mesh_elem elements[] = { + BT_MESH_ELEM(0, sig_models, BT_MESH_MODEL_NONE), +}; + +static const struct bt_mesh_comp comp = { + .cid = BL_COMP_ID, + .elem = elements, + .elem_count = ARRAY_SIZE(elements), +}; + +/* Read string from uart */ +static void read_str(char* str, u8_t size) +{ + extern int cli_getchar(char *inbuf); + char* str_s = str; + while(str - str_s <= size){ + while(!cli_getchar(str)); + if(*str == '\r' || *str == '\n'){ + *str = 0; + break; + } + vOutputString("%c", *str); + str++; + } +} + +static void blemesh_init(void) +{ + int err; + + if(blemesh_inited){ + vOutputString("Has initialized \r\n"); + return; + } + + // auto generate device uuid + gen_dev_uuid(); + + err = bt_mesh_init(&prov, &comp); + if(err){ + vOutputString("Failed to init \r\n"); + return; + } + + blemesh_inited = true; + vOutputString("Init successfully \r\n"); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + mesh_set(); + mesh_commit(); + } + + if (bt_mesh_is_provisioned()) { + vOutputString("Mesh network restored from flash\r\n"); + } else { + vOutputString("Use pb-adv or pb-gatt to enable advertising\r\n"); + } + + +} +static const u16_t net_idx = 0x0000; +static const u16_t app_idx = 0x0000; + + +static const char *bearer2str(bt_mesh_prov_bearer_t bearer) +{ + switch (bearer) { + case BT_MESH_PROV_ADV: + return "PB-ADV"; + case BT_MESH_PROV_GATT: + return "PB-GATT"; + default: + return "unknown"; + } +} + +#if defined(CONFIG_BT_MESH_PROV) +static void blemesh_pb_gatt(void) +{ + int err; + err = bt_mesh_prov_enable(BT_MESH_PROV_GATT); + if (err) { + vOutputString("blemesh_pb_gatt Failed to enable\n"); + } else { + vOutputString("blemesh_pb_gatt enable\n"); + } +} +static void blemesh_pb_adv(void) +{ + int err; + + err = bt_mesh_prov_enable(BT_MESH_PROV_ADV); + if (err) { + vOutputString("blemesh_pb_adv Failed to enable\n"); + } else { + vOutputString("blemesh_pb_adv enable\n"); + } +} +#endif + + + +static void link_open(bt_mesh_prov_bearer_t bearer) +{ + vOutputString("Provisioning link opened on %s\r\n", bearer2str(bearer)); +} + +static void link_close(bt_mesh_prov_bearer_t bearer) +{ + vOutputString("Provisioning link closed on %s\r\n", bearer2str(bearer)); +} + +static int output_number(bt_mesh_output_action_t action, u32_t number) +{ + vOutputString("OOB Number: %u\r\n", number); + return 0; +} + +static int output_string(const char *str) +{ + vOutputString("OOB String: %s\r\n", str); + return 0; +} + +static void prov_input_complete(void) +{ + vOutputString("Input complete\r\n"); +} + +static void prov_complete(u16_t net_idx, u16_t addr) +{ + vOutputString("Local node provisioned, net_idx 0x%04x address 0x%04x\r\n", net_idx, addr); + net.net_idx = net_idx, + net.local = addr; + net.dst = addr; +} + +static void prov_reset(void) +{ + vOutputString("The local node has been reset and needs reprovisioning\r\n"); + mesh_node_reset(); +} + +static void gen_dev_uuid(void) +{ +//device uuid: 07af0000-1111-2222-3333-mac address(6 bytes) + + bt_addr_le_t adv_addr; + bt_get_local_public_address(&adv_addr); + u8_t uuid[16] = {0x07,0xaf,0x00,0x00,0x11,0x11,0x22,0x22,0x33,0x33, + adv_addr.a.val[5], + adv_addr.a.val[4], + adv_addr.a.val[3], + adv_addr.a.val[2], + adv_addr.a.val[1], + adv_addr.a.val[0]}; + memcpy(dev_uuid, uuid, 16); + +} + +static int input(bt_mesh_input_action_t act, u8_t size) +{ + char str[20]; + switch (act) { + case BT_MESH_ENTER_NUMBER:{ + vOutputString("Enter a number (max %u digits) with: input-num :", size); + read_str(str, sizeof(str)-1); + u32_t num = strtoul(str, NULL, 10); + vOutputString("Recved num[%d]\n", num); + int err = bt_mesh_input_number(num); + if (err) { + vOutputString("Numeric input failed (err %d)\r\n", err); + } + }break; + case BT_MESH_ENTER_STRING:{ + vOutputString("Enter a string (max %u chars) with: input-str \r\n", size); + read_str(str, sizeof(str)-1); + vOutputString("Recved string[%d]\n", str); + int err = bt_mesh_input_string(str); + if (err) { + vOutputString("String input failed (err %d)\r\n", err); + } + }break; + default: + vOutputString("Unknown input action %u (size %u) requested!\r\n", act, size); + return -EINVAL; + } + + input_act = act; + input_size = size; + return 0; +} + +static void blemesh_reset(void) +{ + if(!blemesh_inited){ + vOutputString("blemesh not init\n"); + return; + } + bt_mesh_reset(); + vOutputString("Local node reset complete\r\n"); + +} + +static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count) +{ + u8_t i, limit = *count; + + for (i = 0U, *count = 0U; i < faults_size && *count < limit; i++) { + if (faults[i]) { + *dst++ = faults[i]; + (*count)++; + } + } +} + +static void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count) +{ + size_t i; + + if (!fault_count) { + vOutputString("Health Test ID 0x%02x Company ID 0x%04x: no faults\r\n", test_id, cid); + return; + } + + vOutputString("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu:\r\n", test_id, cid, fault_count); + + for (i = 0; i < fault_count; i++) { + vOutputString("\t0x%02x", faults[i]); + } +} + +static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr, + u8_t test_id, u16_t cid, u8_t *faults, + size_t fault_count) +{ + vOutputString("Health Current Status from 0x%04x\r\n", addr); + show_faults(test_id, cid, faults, fault_count); +} + +static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id, + u16_t *company_id, u8_t *faults, u8_t *fault_count) +{ + vOutputString("Sending current faults\r\n"); + + *test_id = 0x00; + *company_id = BT_COMP_ID_LF; + + get_faults(cur_faults, sizeof(cur_faults), faults, fault_count); + + return 0; +} + +static int fault_get_reg(struct bt_mesh_model *model, u16_t cid, + u8_t *test_id, u8_t *faults, u8_t *fault_count) +{ + if (cid != BT_COMP_ID_LF) { + vOutputString("Faults requested for unknown Company ID 0x%04x\r\n", cid); + return -EINVAL; + } + + vOutputString("Sending registered faults\r\n"); + + *test_id = 0x00; + + get_faults(reg_faults, sizeof(reg_faults), faults, fault_count); + + return 0; +} + +static int fault_clear(struct bt_mesh_model *model, uint16_t cid) +{ + if (cid != BT_COMP_ID_LF) { + return -EINVAL; + } + + (void)memset(reg_faults, 0, sizeof(reg_faults)); + + return 0; +} + +static int fault_test(struct bt_mesh_model *model, uint8_t test_id, uint16_t cid) +{ + if (cid != BT_COMP_ID_LF) { + return -EINVAL; + } + + if (test_id != 0x00) { + return -EINVAL; + } + + return 0; +} + +static void attn_on(struct bt_mesh_model *model) +{ + + vOutputString("Attention timer on\r\n"); + +} + +static void attn_off(struct bt_mesh_model *model) +{ + vOutputString("Attention timer off\r\n"); +} + +static void bt_enable_cb(int err) +{ + if (!err) { + blemesh_init(); + mesh_gen_srv_callback_register(model_gen_cb); + vTaskDelay(500); + blemesh_pb_gatt(); + } +} +void mesh_node_open(void) +{ + + blemesh_pb_gatt(); + +} +void mesh_node_reset(void) +{ + + blemesh_reset(); + +} +int blemesh_node(void) +{ + borad_rgb_init(); + // Initialize BLE controller + ble_controller_init(configMAX_PRIORITIES - 1); + // Initialize BLE Host stack + hci_driver_init(); + bt_enable(bt_enable_cb); + return 0; +} diff --git a/customer_app/bl602_blemsh_node/bl602_blemesh_node/mesh_node.h b/customer_app/bl602_blemsh_node/bl602_blemesh_node/mesh_node.h new file mode 100644 index 00000000..10c6953e --- /dev/null +++ b/customer_app/bl602_blemsh_node/bl602_blemesh_node/mesh_node.h @@ -0,0 +1,15 @@ +#ifndef __MESH_NODE__ +#define __MESH_NODE__ + +#include +#include +#include + +#define LED_RED_PIN (17) +#define LED_GREEN_PIN (14) +#define LED_BLUE_PIN (11) + +int blemesh_node(void); +void mesh_node_open(void); +void mesh_node_reset(void); +#endif // __ZB_NOTIFY__ \ No newline at end of file diff --git a/customer_app/bl602_blemsh_node/genblemesh b/customer_app/bl602_blemsh_node/genblemesh new file mode 100644 index 00000000..1f08a187 --- /dev/null +++ b/customer_app/bl602_blemsh_node/genblemesh @@ -0,0 +1,3 @@ +#!/bin/sh +make CONFIG_CHIP_NAME=BL602 CONFIG_LINK_ROM=1 CONFIG_BT_MESH=1 CONFIG_BT_MESH_MODEL=0 CONFIG_BT_SETTINGS=1 CONFIG_BT_CONN=1 CONFIG_BLE_TX_BUFF_DATA=2 CONFIG_BT_ALLROLES=0 CONFIG_BT_CENTRAL=0 CONFIG_BT_PERIPHERAL=1 CONFIG_BT_OBSERVER=1 CONFIG_BT_BROADCASTER=0 CONFIG_DISABLE_BT_SMP=1 CONFIG_DISABLE_BT_HOST_PRIVACY=1 -j +exit $? diff --git a/customer_app/bl602_blemsh_node/logo.png b/customer_app/bl602_blemsh_node/logo.png new file mode 100644 index 00000000..859f106d Binary files /dev/null and b/customer_app/bl602_blemsh_node/logo.png differ diff --git a/customer_app/bl602_blemsh_node/proj_config.mk b/customer_app/bl602_blemsh_node/proj_config.mk new file mode 100644 index 00000000..9d628796 --- /dev/null +++ b/customer_app/bl602_blemsh_node/proj_config.mk @@ -0,0 +1,42 @@ +# +#compiler flag config domain +# +#CONFIG_TOOLPREFIX := +#CONFIG_OPTIMIZATION_LEVEL_RELEASE := 1 +#CONFIG_M4_SOFTFP := 1 + +# +#board config domain +# +CONFIG_BOARD_FLASH_SIZE := 2 + +#firmware config domain +# + +#set CONFIG_ENABLE_ACP to 1 to enable ACP, set to 0 or comment this line to disable +#CONFIG_ENABLE_ACP:=1 +CONFIG_BL_IOT_FW_AP:=1 +CONFIG_BL_IOT_FW_AMPDU:=0 +CONFIG_BL_IOT_FW_AMSDU:=0 +CONFIG_BL_IOT_FW_P2P:=0 +CONFIG_ENABLE_PSM_RAM:=1 +#CONFIG_ENABLE_CAMERA:=1 +#CONFIG_ENABLE_BLSYNC:=1 +#CONFIG_ENABLE_VFS_SPI:=1 +CONFIG_ENABLE_VFS_ROMFS:=1 + +# set easyflash env psm size, only support 4K、8K、16K options +CONFIG_ENABLE_PSM_EF_SIZE:=16K + +CONFIG_FREERTOS_TICKLESS_MODE:=1 + +CONFIG_BT:=1 +CONFIG_USE_XTAL32K:=0 + +#blog enable components format :=blog_testc cli vfs helper +LOG_ENABLED_COMPONENTS:=blog_testc hal_drv loopset looprt bloop blestack +ifeq ($(CONFIG_BT_MESH_SYNC),1) +LOG_ENABLED_COMPONENTS += blsync_ble +endif +CONFIG_BL602_USE_ROM_DRIVER:=1 +CONFIG_BT_STACK_PTS:=0