涂鸦智能烧水壶之嵌入式系统创建

Posted 三明治开发社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了涂鸦智能烧水壶之嵌入式系统创建相关的知识,希望对你有一定的参考价值。

前言


现如今,科技快速发展,我们的家里已经布满了各种家电设备;其中烧水壶是我们常用的家用设备之一,传统的烧水壶只有简单的加热功能,不能设定加热温度,也不能远程控制,针对此情景,今天我们将改装家里的烧水壶,为其赋能使其实现智能化,首先我们要创建一个嵌入式软件系统,使我们的手机和烧水壶之前能够进行通信。

创建产品

  • 首先进入 涂鸦智能IoT平台,创建一个烧水壶产品。点击创建产品->“找不到品类”>智能烧水壶。。

在这里插入图片描述

  • 自定义产品名称,通讯协议选择WIFI+蓝牙,点击创建产品。
    在这里插入图片描述

  • 添加DP点,本案例中添加了标准功能:“开关”、“温度设置”、“当前温度”、“保温”、“故障警告”等功能;功能点可以根据需求自行增减,功能点名称以及属性也可根据需求自行修改。
    在这里插入图片描述

  • 选择设备面板,可以选择自己喜欢的模板或者自己自定义面板,调试阶段推荐选择开发调试面板,便于测试
    在这里插入图片描述

  • 选择硬件开发平台,可以根据需要自行选择开发平台。注意,需要选择芯片平台并上传固件后,面板才能够使用;固件标识名要和上传的固件名称需保持一致,否则烧录授权时将无法通过。

在这里插入图片描述

  • 至此,产品创建阶段已经基本完成,此时可以通过“涂鸦智能”app和虚拟设备体验dp数据的接收和发送。
    在这里插入图片描述

烧水壶的嵌入式系统搭建

前面已经创建了产品,app端的控制界面已经有了,为了实现app和烧水壶的智能交互,此时就需要建立热水壶设备的嵌入式系统。

建立嵌入式开发环境

本案例是基于BK7231N平台进行的SOC开发,开发所用的涂鸦通用SDK编译需要linux环境,首先要安装linux开发环境,然后从涂鸦仓库拉取包含SDK环境的demo例程。。

  • 下载Tuya IoTOS Embeded WiFi & BLE sdk

    $ cd "your directory"
    $ git clone https://github.com/tuya/tuya-iotos-embeded-sdk-wifi-ble-bk7231n
    

    在自己建立的目录中git下来demo,里面有附带有SDK环境,同时“apps”目录中也有几个应用案例,我们就使用apps/tuya_demo_template这个demo为开发模板,在此基础上增减代码,实现一个嵌入式系统框架。

搭建一个能够配网连接APP的嵌入式系统框架

实现烧水壶的智能化首先要搭建一个简易的嵌入式框架,可以实现APP和设备之间的连接与通信,之后我们再模块化的实现烧水壶的功能。

  • 在现有的demo基础上搭建系统框架
    当前tuya_demo_template应用程序的文件组成如下:
├── src	
|    └── tuya_device.c            //应用层入口文件
|
├── include				//头文件目录
|    └──  tuya_device.h
|
└── output              //编译产物
  • 将tuya_demo_template文件夹更名为bk7231n_smart_kettle_demo,更改文件中的tuya_device.h代码,按照创建的产品中的PID去填写。主要作用是配网后同步手机端的app界面。
    在这里插入图片描述
    在这里插入图片描述

  • 创建一个C文件,做为烧水壶的主要应用函数
    创建后的demo文件组成如下:

├── src	
|    └── tuya_device.c            //应用层入口文件
|    └── kettle_app.c            //主要应用文件
|
├── include				//头文件目录
|    └──  tuya_device.h
|    └──  kettle_app.h
|
└── output              //编译产物
  • kettle_app.h中定义功能点的DP_ID和不同DP类型的属性结构体,如枚举型、数值型。
#ifndef __KETTLE_APP_H__
#define __KETTLE_APP_H__
/* Includes ------------------------------------------------------------------*/
#include "tuya_cloud_types.h"
#include "tuya_iot_com_api.h"
#ifdef __cplusplus
    extern "C" {
#endif /* __cplusplus */

/* Exported types ------------------------------------------------------------*/

typedef UINT8_T DP_ID_T;

typedef struct {
    DP_ID_T dp_id;
    
    bool power;
}DP_BOOL_T;

typedef struct {
    DP_ID_T dp_id;
    
    INT_T value;
}DP_VALUE_T;


/* Exported constants --------------------------------------------------------*/         
/* Exported macro ------------------------------------------------------------*/

#define DP_SWITCH           101
#define DP_TEMPER           102
#define DP_TEMP_SET         103
#define DP_KEEP_WARM        104
#define DP_WORK_TYPE        105
#define DP_FAULT            106
/* Exported functions ------------------------------------------------------- */
VOID_T deal_dp_proc(IN CONST TY_OBJ_DP_S *root);
VOID_T report_one_dp_status(int dp_id);
VOID_T kettle_init();
#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /*__KETTLE_APP_H__ */
  • kettle_app.c中实现deal_dp_proc函数,用于实现设备接收到不同dp数据后的动作。实现report_one_dp_status函数,用于dp数据的上报。
//根据下发的不同命令执行相应的动作
VOID_T deal_dp_proc(IN CONST TY_OBJ_DP_S *root)
{
    UCHAR_T dpid;
    dpid = root->dpid;
    
    switch (dpid){
    
    case DP_SWITCH: {
        PR_DEBUG("switch on/off");
        }
        break;

    case DP_TEMP_SET: {
		PR_DEBUG("temperature set");
        }
        break;

    case DP_KEEP_WARM: {

		PR_DEBUG("keep_warm on/off");
        }
        break;

    case DP_WORK_TYPE: {
		PR_DEBUG("work_type set");
        }
        break;
    default:
        break;
    }

}
//dp数据上报函数,判断已经连接网络后,执行此函数,根据所传入的DP_ID,上传相应DP_ID的状态数据
VOID_T report_one_dp_status(int dp_id)
{
    
    OPERATE_RET op_ret = OPRT_OK;
    GW_WIFI_NW_STAT_E wifi_state = 0xFF;
    op_ret = get_wf_gw_nw_status(&wifi_state);
    if (OPRT_OK != op_ret) {
        PR_ERR("get wifi state err");
        return;
    }
    if (wifi_state <= STAT_AP_STA_DISC || wifi_state == STAT_STA_DISC) {
        return;
    }
    TY_OBJ_DP_S *dp_arr = (TY_OBJ_DP_S *)Malloc(SIZEOF(TY_OBJ_DP_S));
    if(NULL == dp_arr) {
        PR_ERR("malloc failed");
        return;
    }
    memset(dp_arr, 0, SIZEOF(TY_OBJ_DP_S));

    switch (dp_id){
    case DP_SWITCH: {
        dp_arr[0].dpid = switch_s.dp_id;
        dp_arr[0].type = PROP_BOOL;
        dp_arr[0].time_stamp = 0;
        dp_arr[0].value.dp_bool = switch_s.power;

        }
        break;

    case DP_TEMPER: {
        dp_arr[0].dpid = temper_s.dp_id;
        dp_arr[0].type = PROP_VALUE;
        dp_arr[0].time_stamp = 0;
        dp_arr[0].value.dp_value = temper_s.value;
        }
        break;

    case DP_TEMP_SET: {
        dp_arr[0].dpid = temp_set_s.dp_id;
        dp_arr[0].type = PROP_VALUE;
        dp_arr[0].time_stamp = 0;
        dp_arr[0].value.dp_bool = temp_set_s.value;
        }
        break;

    case DP_KEEP_WARM: {
        dp_arr[0].dpid = keep_warm_s.dp_id;
        dp_arr[0].type = PROP_BOOL;
        dp_arr[0].time_stamp = 0;
        dp_arr[0].value.dp_enum = keep_warm_s.power;
        }
        break;

    case DP_WORK_TYPE : {
        dp_arr[0].dpid = work_type_s.dp_id;
        dp_arr[0].type = PROP_ENUM;
        dp_arr[0].time_stamp = 0;
        dp_arr[0].value.dp_enum = work_type_s.value;
        }
        break;

    case DP_FAULT: {
        dp_arr[0].dpid = fault_s.dp_id;
        dp_arr[0].type = PROP_ENUM;
        dp_arr[0].time_stamp = 0;
        dp_arr[0].value.dp_bool = fault_s.value;
        }
        break;
    default:
    
        break;
    }

    op_ret = dev_report_dp_json_async(NULL , dp_arr, 1);
    Free(dp_arr);
    dp_arr = NULL;
    if(OPRT_OK != op_ret) {
        PR_ERR("dev_report_dp_json_async relay_config data error,err_num",op_ret);
    }
}
  • 更改tuya_device.c中代码。

调用dp点执行函数,用于app端下发dp数据后,设备端的动作响应处理,配网成功后将调用hw_report_all_dp_status(VOID_T)函数,将本地的设备信息上报到云端。

/**
 * @Function: dev_obj_dp_cb
 * @Description: obj dp info cmd callback, tuya cloud dp(data point) received
 * @Input: dp:obj dp info
 * @Output: none
 * @Return: none
 * @Others: app send data by dpid  control device stat
 */
VOID dev_obj_dp_cb(IN CONST TY_RECV_OBJ_DP_S *dp)
{
    PR_DEBUG("dp->cid:%s dp->dps_cnt:%d",dp->cid,dp->dps_cnt);
    UCHAR_T i = 8;

    for(i = 0;i < dp->dps_cnt;i++) {
        deal_dp_proc(&(dp->dps[i]));
    }
}
/**
 * @Function: hw_report_all_dp_status
 * @Description: update all dp data
 * @Input: none
 * @Output: none
 * @Return: none
 * @Others: 
 */

VOID_T hw_report_all_dp_status(VOID_T)
{
    report_one_dp_status(DP_BOIL);
    report_one_dp_status(DP_TEMPER);
    report_one_dp_status(DP_TEMP_SET);
    report_one_dp_status(DP_KEEP_WARM);
    report_one_dp_status(DP_WATER_TYPE);
    report_one_dp_status(DP_FAULT);
}

此时一个简单的软件框架就搭建好了,软件思想是app下发dp数据,设备端会有对应的打印信息,接下来是编译及烧录。

程序的编译和烧录

  • 在SDK根目录下执行以下命令开始编译:

    sh build_app.sh apps/bk7231n_smart_kettle_demo bk7231n_smart_kettle_demo 1.0.0 
    
  • 固件烧录授权相关信息请参考:Wi-Fi + BLE 系列模组烧录授权

  • 设备连接与实验
    烧录后打开涂鸦智能app搜索设备进行连接,设备名称是创建产品时的产品名称。连接成功后app端发送dp数据,设备的串口2将打印对应的输出信息。

系统框架建立完成

此时设备已经和app端进行了连接实现了通信,后面就可以逐个实现智能烧水壶的各个功能。
具体的功能实现过程将在后续的文章详细介绍。

技术支持

您可以通过以下方法获得涂鸦的支持:

以上是关于涂鸦智能烧水壶之嵌入式系统创建的主要内容,如果未能解决你的问题,请参考以下文章

涂鸦智能烧水壶软件实现之水温调节和灯光提示

涂鸦智能烧水壶软件实现之温度采集和过温报警功能

涂鸦智能烧水壶软件实现之云端控制(完结)

智能烧水壶 (Bluetooth 版)02——系统创建篇

智能烧水壶 (Bluetooth版)03——离线控制功能实现篇

智能烧水壶-FAQ