闻而知之谓之圣

经言,望而知之谓之神,闻而知之谓之圣,问而知之谓之工,切脉而知之谓之巧。
在这里插入图片描述

这个是我在小红书分享的视频

阿里云创建产品

阿里云生活物联网平台

  1. 创建项目
    在这里插入图片描述
  2. 在已创项目里创建产品
    在这里插入图片描述
  3. 产品功能定义
    在这里插入图片描述
    在此仅展示简单的开关控制风扇,各位可以根据自己喜好加别的。
    在这里插入图片描述
  4. 设备调试
    人机交互步骤根据自己喜好设置,没有什么特殊要求。在设备调试页面下,新增测试设备然后点击查看设备证书,里边就是所需的设备的三元组。
    在这里插入图片描述
    获取到三元组之后我们就可以开始写自己的代码程序了。

编写代码

tasks.json

在成员里添加以下代码,先前一篇文章编译生成.bin文件的命名处提及的是my_led,可以对比体会一下。

{
    
    
            "label": "fan",
            "type": "shell",
            "command": "aos",
            "args": [
                "make",
                "bluetooth.fan@tc825x"
            ],
            "group": "build",
            "presentation": {
    
    
                "reveal": "silent"
            },
            "problemMatcher": "$msCompile"
        }

完整的内容如下:

{
    
    
    "version": "2.0.0",
    "tasks": [
        {
    
    
            "label": "tc825x",
            "type": "shell",
            "command": "aos",
            "args": [
                "make",
                "bluetooth.light_ctl@tc825x"
            ],
            "group": "build",
            "presentation": {
    
    
                "reveal": "silent"
            },
            "problemMatcher": "$msCompile"
        },
        {
    
    
            "label": "my_led",
            "type": "shell",
            "command": "aos",
            "args": [
                "make",
                "bluetooth.my_led@tc825x"
            ],
            "group": "build",
            "presentation": {
    
    
                "reveal": "silent"
            },
            "problemMatcher": "$msCompile"
        },
        {
    
    
            "label": "fan",
            "type": "shell",
            "command": "aos",
            "args": [
                "make",
                "bluetooth.fan@tc825x"
            ],
            "group": "build",
            "presentation": {
    
    
                "reveal": "silent"
            },
            "problemMatcher": "$msCompile"
        },
        {
    
    
            "label": "max",
            "type": "shell",
            "command": "aos",
            "args": [
                "make",
                "bluetooth.max@tc825x"
            ],
            "group": "build",
            "presentation": {
    
    
                "reveal": "silent"
            },
            "problemMatcher": "$msCompile"
        }
    ]
}

上边的是tasks.json,下边的是settings.json

{
    
    
    "search.exclude": {
    
     //表示搜索区域
        "**/platform/mcu/[a-s]*": true, //[a-s]* 表示a到s字符开头的全部屏蔽,数值也一样,自行体验
        "**/board/bk3435devkit": true,
        "**/board/pca10040": true,
        "**/board/ch6121evb": true,
        "**/board/tg7100b": true,
    },
    "files.exclude": {
    
     //表示显示区域
        "**/.git": true, //true标识改目录不被显示
        "**/.g**": true, //*号标识通配符,.g开头的均屏蔽,根据用途自行配置,多多尝试
        "**/platform/mcu/[a-s]*": true, //[a-s]* 表示a到s字符开头的全部屏蔽,数值也一样,自行体验
        "**/board/bk3435devkit": true,
        "**/board/pca10040": true,
        "**/board/ch6121evb": true,
        "**/board/tg7100b": true,
    },
    "files.associations": {
    
    
        "gpio_8258.h": "c"
    },
    "C_Cpp.errorSquiggles": "Disabled"
}

创建mk文件

复制一份light_ctl的mk文件来修改即可
在这里插入图片描述
这时候就会出现以下这个选项,后续编写好c文件后点击此项编译生成bin文件。
在这里插入图片描述
mk文件内容如下:

NAME := fan

GENIE_MAKE_PATH := app/example/bluetooth/$(NAME)

$(NAME)_COMPONENTS  += genie_app bluetooth.bt_host bluetooth.bt_mesh yloop cli

$(NAME)_INCLUDES += ../ \
					../../../../genie_app \
					../../../../genie_app/base \
					../../../../genie_app/bluetooth/host \
					../../../../genie_app/bluetooth/mesh

$(NAME)_SOURCES  := fan.c

ble = 1
bt_mesh = 1
en_bt_smp = 1

bt_host_tinycrypt = 1

# Host configurations
GLOBAL_DEFINES += CONFIG_BLUETOOTH
GLOBAL_DEFINES += CONFIG_BT_CONN
#GLOBAL_DEFINES += CONFIG_BT_CENTRAL
GLOBAL_DEFINES += CONFIG_BT_PERIPHERAL
#GLOBAL_DEFINES += CONFIG_BLE_50


# Mesh function select
GLOBAL_DEFINES += CONFIG_BT_MESH
GLOBAL_DEFINES += CONFIG_BT_MESH_PROV
GLOBAL_DEFINES += CONFIG_BT_MESH_PB_ADV
GLOBAL_DEFINES += CONFIG_BT_MESH_PB_GATT
GLOBAL_DEFINES += CONFIG_BT_MESH_PROXY
GLOBAL_DEFINES += CONFIG_BT_MESH_GATT_PROXY
GLOBAL_DEFINES += CONFIG_BT_MESH_RELAY
#GLOBAL_DEFINES += CONFIG_BT_MESH_FRIEND
#GLOBAL_DEFINES += CONFIG_BT_MESH_LOW_POWER
#GLOBAL_DEFINES += CONFIG_BT_MESH_SHELL

# Mesh foundation model select
GLOBAL_DEFINES += CONFIG_BT_MESH_CFG_SRV
GLOBAL_DEFINES += CONFIG_BT_MESH_HEALTH_SRV
MESH_MODEL_GEN_ONOFF_SRV = 1
#MESH_MODEL_DIABLE_TRANS = 1
MESH_MODEL_LIGHTNESS_SRV = 1
MESH_MODEL_CTL_SRV = 1
MESH_MODEL_VENDOR_SRV = 1
ALI_SIMPLE_MODLE = 1


GLOBAL_DEFINES += CONFIG_BT_DEVICE_NAME=\"light\"

GLOBAL_DEFINES += PROJECT_SW_VERSION=0x00010102
GLOBAL_DEFINES += PROJECT_SECRET_KEY=\"00112233445566770011223344556677\"

# Feature configurations
GLOBAL_DEFINES += GENIE_OLD_AUTH
GLOBAL_DEFINES += CONIFG_OLD_FLASH_PARA
#GLOBAL_DEFINES += GENIE_ULTRA_PROV

genie_ota = 1
#genie_vendor_timer = 1


# Host configurations
GLOBAL_DEFINES += CONFIG_BT_SMP
GLOBAL_DEFINES += CONFIG_BT_HCI_VS_EXT

GLOBAL_DEFINES += CONFIG_BT_RX_BUF_LEN=151
GLOBAL_DEFINES += CONFIG_BT_L2CAP_TX_MTU=143

# project configurations
#GLOBAL_DEFINES += CONIFG_LIGHT_HONGYAN

genie_vendor_timer = 0

tc825x_debug_mode = 1

GLOBAL_DEFINES += CONFIG_BT_DEBUG_LOG
ifeq ($(tc825x_debug_mode),1)
GLOBAL_DEFINES += CONFIG_GENIE_DEBUG_CMD

############### debug ###############
## BLE debug log general control macro (Note: still to be affected by DEBUG)
## Enable below macros if BLE stack debug needed

# Mesh debug message enable
GLOBAL_DEFINES += GENIE_DEBUG_COLOR
GLOBAL_DEFINES += MESH_DEBUG_RX
GLOBAL_DEFINES += MESH_DEBUG_TX
GLOBAL_DEFINES += MESH_DEBUG_PROV
#GLOBAL_DEFINES += CONFIG_INIT_STACKS
#GLOBAL_DEFINES += CONFIG_PRINTK

## BLE subsystem debug log control macro
## Enable below macros if component-specific debug needed
#GLOBAL_DEFINES += CONFIG_BT_DEBUG_L2CAP
#GLOBAL_DEFINES += CONFIG_BT_DEBUG_CONN
#GLOBAL_DEFINES += CONFIG_BT_DEBUG_ATT
#GLOBAL_DEFINES += CONFIG_BT_DEBUG_GATT
#GLOBAL_DEFINES += CONFIG_BT_DEBUG_HCI_DRIVER
#GLOBAL_DEFINES += CONFIG_BT_DEBUG_HCI_CORE
#GLOBAL_DEFINES += CONFIG_BT_DEBUG_CORE

## MESH debug log control macro
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_ADV
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_BEACON
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_PROXY
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_PROV
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_NET
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_CRYPTO
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_TRANS
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_FRIEND
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_LOW_POWER
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_ACCESS
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_FLASH
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_MODEL
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_VENDOR_MODEL
#GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_FACTORY
GLOBAL_DEFINES += CONFIG_BT_MESH_DEBUG_OTA
else
GLOBAL_DEFINES += CONFIG_INFO_DISABLE
endif



编写fan.c文件(重点)

内容比较简单,初始化PB4引脚,通过该引脚的电平高低来实现风扇开关
在这里插入图片描述
然后配置组播地址,设置通用开关模型
在这里插入图片描述
接着就是user_event部分了,这部分参照genie_event来自定义,在天猫精灵成功触发的地方添加自己的事件
在这里插入图片描述
完整代码:


#include "drivers/8258/gpio_8258.h"
#include "vendor/common/alios_app_config.h"

#include "common/log.h"

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <aos/aos.h>
#include <aos/kernel.h>

#include <misc/printk.h>
#include <misc/byteorder.h>
#include <hal/soc/gpio.h>

#include <bluetooth.h>
#include <soc.h>
#include <api/mesh.h>
#include "genie_app.h"

// #ifndef CONFIG_INFO_DISABLE
// #define LIGHT_DBG(fmt, ...)  printf("[%s]"fmt"\n", __func__, ##__VA_ARGS__)
// #else
// #define LIGHT_DBG(fmt, ...)
// #endif

// #define LIGHT_CTL_TEMP_MIN            (0x0320)    // 800
// #define LIGHT_CTL_TEMP_MAX            (0x4E20)    // 20000

// #define LED_FLASH_CYCLE MESH_TRNSATION_CYCLE

#define FAN_GPIO TC825X_GET_PIN_NUM(GPIO_PB4)

gpio_dev_t fan_gpio;

//配置初始化引脚
void my_fan_init(void)
{
    
    
    fan_gpio.config = OUTPUT_PUSH_PULL;
    fan_gpio.port = FAN_GPIO;

    hal_gpio_init(&fan_gpio);
}

void fan_gpio_on(void)
{
    
    
    hal_gpio_output_high(&fan_gpio);
}

void fan_gpio_off(void)
{
    
    
    hal_gpio_output_low(&fan_gpio);
}



/* unprovision device beacon adv time */
#define MESH_PBADV_TIME 600 //unit:s

#define DEFAULT_MESH_GROUP1 0xC007
#define DEFAULT_MESH_GROUP2 0xCFFF

uint32_t get_mesh_pbadv_time(void)
{
    
    
    return MESH_PBADV_TIME * 1000; //ms
}

/* element configuration start */
#define MESH_ELEM_COUNT 1
#define MESH_ELEM_STATE_COUNT MESH_ELEM_COUNT

elem_state_t g_elem_state[MESH_ELEM_STATE_COUNT];
model_powerup_t g_powerup[MESH_ELEM_STATE_COUNT];

static struct bt_mesh_model element_models[] = {
    
    
    BT_MESH_MODEL_CFG_SRV(),
    BT_MESH_MODEL_HEALTH_SRV(),
    /*代码添加*/
    MESH_MODEL_GEN_ONOFF_SRV(&g_elem_state[0]), //通用开关模型

};

static struct bt_mesh_model g_element_vendor_models[] = {
    
    
    MESH_MODEL_VENDOR_SRV(&g_elem_state[0]), //厂商自定义模型
};

struct bt_mesh_elem elements[] = {
    
    
    BT_MESH_ELEM(0, element_models, g_element_vendor_models, 0),
};

uint8_t get_vendor_element_num(void)
{
    
    
    return MESH_ELEM_COUNT;
}
/* element configuration end */

void mesh_sub_init(u16_t *p_sub)
{
    
    
    memset(p_sub, 0, CONFIG_BT_MESH_MODEL_GROUP_COUNT << 1);

    p_sub[0] = DEFAULT_MESH_GROUP1;
    p_sub[1] = DEFAULT_MESH_GROUP2;
}

#ifdef CONFIG_GENIE_OTA
bool ota_check_reboot(void)
{
    
    
    // the device will reboot when it is off
    if (g_elem_state[0].state.onoff[T_CUR] == 0)
    {
    
    
        // save light para, always off
        g_powerup[0].last_onoff = 0;
        genie_flash_write_userdata(GFI_MESH_POWERUP, (uint8_t *)g_powerup, sizeof(g_powerup));
        BT_DBG("reboot!");
        return true;
    }
    BT_DBG("no reboot!");
    return false;
}
#endif

static void _init_fan_para(void)
{
    
    
    uint8_t i = 0;
    E_GENIE_FLASH_ERRCODE ret;
    // init element state
    memset(g_elem_state, 0, sizeof(g_elem_state));
    elem_state_init(MESH_ELEM_STATE_COUNT, g_elem_state);

    // load light para
    ret = genie_flash_read_userdata(GFI_MESH_POWERUP, (uint8_t *)g_powerup, sizeof(g_powerup));

    if (ret == GENIE_FLASH_SUCCESS)
    {
    
    
        while (i < MESH_ELEM_STATE_COUNT)
        {
    
    
#ifdef CONFIG_GENIE_OTA
            // if the device reboot by ota, it must be off.
            if (g_powerup[0].last_onoff == 0)
            {
    
    
                g_elem_state[0].state.onoff[T_TAR] = 0;
                // load lightness
                if (g_powerup[0].last_actual)
                {
    
    
                    g_elem_state[0].state.actual[T_TAR] = g_powerup[0].last_actual;
                    g_elem_state[0].powerup.last_actual = g_powerup[0].last_actual;
                }
                // load temperature
                if (g_powerup[0].last_temp)
                {
    
    
                    g_elem_state[0].state.temp[T_TAR] = g_powerup[0].last_temp;
                    g_elem_state[0].powerup.last_temp = g_powerup[0].last_temp;
                }
                clear_trans_para(&g_elem_state[0]);
            }
            else
#endif
            {
    
    
                memcpy(&g_elem_state[0].powerup, &g_powerup[0], sizeof(model_powerup_t));
                // load lightness
                if (g_powerup[0].last_actual)
                {
    
    
                    g_elem_state[0].state.actual[T_TAR] = g_powerup[0].last_actual;
                }
                // load temperature
                if (g_powerup[0].last_temp)
                {
    
    
                    g_elem_state[0].state.temp[T_TAR] = g_powerup[0].last_temp;
                }
                //LIGHT_DBG("l:%d t:%d", g_powerup[0].last_actual, g_powerup[0].last_temp);
                if (g_elem_state[0].state.onoff[T_TAR] == 1)
                {
    
    
                    g_elem_state[0].state.trans_start_time = k_uptime_get() + g_elem_state[0].state.delay * 5;
                    g_elem_state[0].state.trans_end_time = g_elem_state[0].state.trans_start_time + get_transition_time(g_elem_state[0].state.trans);
                }
            }
            g_elem_state[0].state.temp[T_CUR] = g_elem_state[0].state.temp[T_TAR];

            i++;
        }
    }
}

static void _reset_fan_para(void)
{
    
    
    uint8_t i = 0;
    while (i < MESH_ELEM_STATE_COUNT)
    {
    
    
        g_elem_state[i].state.onoff[T_CUR] = GEN_ONOFF_DEFAULT;
        g_elem_state[i].state.actual[T_CUR] = LIGHTNESS_DEFAULT;
        g_elem_state[i].state.temp[T_CUR] = CTL_TEMP_DEFAULT;
        g_elem_state[i].state.onoff[T_TAR] = GEN_ONOFF_DEFAULT;
        g_elem_state[i].state.actual[T_TAR] = LIGHTNESS_DEFAULT;
        g_elem_state[i].state.temp[T_TAR] = CTL_TEMP_DEFAULT;
        g_elem_state[i].state.trans = 0;
        g_elem_state[i].state.delay = 0;
        g_elem_state[i].state.trans_start_time = 0;
        g_elem_state[i].state.trans_end_time = 0;

        g_elem_state[i].powerup.last_actual = LIGHTNESS_DEFAULT;
        g_elem_state[i].powerup.last_temp = CTL_TEMP_DEFAULT;

        g_powerup[i].last_onoff = GEN_ONOFF_DEFAULT;
        g_powerup[i].last_actual = LIGHTNESS_DEFAULT;
        g_powerup[i].last_temp = CTL_TEMP_DEFAULT;
        i++;
    }
    genie_flash_write_userdata(GFI_MESH_POWERUP, (uint8_t *)g_powerup, sizeof(g_powerup));

    //LIGHT_DBG("done");
}

static void _save_light_state(elem_state_t *p_elem)
{
    
    
    uint8_t *p_read = aos_malloc(sizeof(g_powerup));

    if (p_elem->state.actual[T_CUR] != 0)
    {
    
    
        p_elem->powerup.last_actual = p_elem->state.actual[T_CUR];
        g_powerup[p_elem->elem_index].last_actual = p_elem->state.actual[T_CUR];
    }

    p_elem->powerup.last_temp = p_elem->state.temp[T_CUR];
    g_powerup[p_elem->elem_index].last_temp = p_elem->state.temp[T_CUR];
    // always on
    g_powerup[p_elem->elem_index].last_onoff = 1;

    genie_flash_read_userdata(GFI_MESH_POWERUP, p_read, sizeof(g_powerup));

    if (memcmp(g_powerup, p_read, sizeof(g_powerup)))
    {
    
    
        LIGHT_DBG("save %d %d", g_powerup[p_elem->elem_index].last_actual, g_powerup[p_elem->elem_index].last_temp);
        genie_flash_write_userdata(GFI_MESH_POWERUP, (uint8_t *)g_powerup, sizeof(g_powerup));
    }
    aos_free(p_read);
}

static void _user_init(void)
{
    
    
    my_fan_init();  //初始化
    fan_gpio_off(); //初始化时灯灭
#ifdef CONFIG_GENIE_OTA
    // check ota flag
    if (ais_get_ota_indicat())
    {
    
    
        g_indication_flag |= INDICATION_FLAG_VERSION;
    }
#endif
}


void user_event(E_GENIE_EVENT event, void *p_arg)
{
    
    
    E_GENIE_EVENT next_event = event;
    switch (event)
    {
    
    
    case GENIE_EVT_SW_RESET:
    case GENIE_EVT_HW_RESET_START:

        break;
    case GENIE_EVT_HW_RESET_DONE:
        _reset_fan_para();

        break;
    case GENIE_EVT_SDK_MESH_INIT:
        _init_fan_para();
        _user_init();
        if (!genie_reset_get_flag())
        {
    
    
            next_event = GENIE_EVT_SDK_ANALYZE_MSG;
        }
        break;
    case GENIE_EVT_SDK_MESH_PROV_SUCCESS:

        break;
    case GENIE_EVT_SDK_TRANS_CYCLE:
    case GENIE_EVT_SDK_ACTION_DONE:
    {
    
    
        //添加自己事件
        printf("GENIE_EVT_SDK_ACTION_DONE   \r\n");
        elem_state_t *user_state = (elem_state_t *)p_arg; //获取状态,把user_event参数 p_arg 传进来
        /********通用开关********/
        if (user_state->state.onoff[TYPE_NUM]) //elem_state_t->model_state_t->onoff[TYPE_NUM],0关闭1打开
        {
    
    
            fan_gpio_on();
        }
        else
        {
    
    
            fan_gpio_off();
        }
    }

    break;
    case GENIE_EVT_SDK_INDICATE:
        break;
    case GENIE_EVT_SDK_VENDOR_MSG:
        printf("GENIE_EVT_SDK_VENDOR_MSG    \r\n");
        {
    
    
            vnd_model_msg *my_vnd_msg = (vnd_model_msg *)p_arg;
            printf("opcode = %x\r\n", my_vnd_msg->opid);
            int i = 0;
            for (; i < my_vnd_msg->len; i++)
            {
    
    
                printf("%x ", my_vnd_msg->data[i]);
            }
        }

        break;
    default:
        break;
    }
    if (next_event != event)
    {
    
    
        genie_event(next_event, p_arg);
    }
}

int application_start(int argc, char **argv)
{
    
    

    genie_init();
    return 0;
}

编译

在这里插入图片描述
在这里插入图片描述

烧录

找到生成的bin文件烧录即可
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44035986/article/details/120112097