第三方设备开发指南

功能概述

IntoYun 为智能软硬件整体解决方案服务商,为用户提供开放便捷的物联网云服务。虽然接入物联网的设备丰富多样,但按实现方案可以分为三类,具体如下:

  • 主模式方案

    主模式方案:即用户采取IntoYun提供的硬件开发板/模组作为设备主控,外部连接各类传感器和控制器。 IntoYun为用户提供了完善的SDK功能接口、公共库和跨平台编译环境等。用户可直接便捷的在主控上开发设备软件。
    了解更多请点击主模式设备方案开发指南

  • 从模式方案

    从模式方案:即用户直接使用自选的MCU作为主控,MCU连接各类传感器和控制器,MCU通过串口与IntoYun通讯模组进行通讯, 完成云端通讯。用户将直接在MCU端开发设备软件。
    了解更多请点击从模式设备方案开发指南

  • 第三方设备方案

    第三方设备方案:即用户采取自选硬件方案,用户采取硬件方案商官方提供的SDK进行开发设备软件。

    第三方设备方案,适用于如下使用场景:

    - 设备方案已确定并具备联网能力,需新增云服务器功能。
    - 对硬件方案熟悉,期望使用硬件方案提供的SDK开发设备软件。
    

    IntoYun针对第三方设备方案提供了如下便利:

    - 为部分硬件方案提供离线开发环境(IntoYunIot)
    - 为用户提供第三方设备SDK包,SDK层次清晰,移植到各种硬件平台非常简单。SDK提供的API接口简单明确,使用起来非常简单。
    - 为用户提供自动代码生成工具,有效降低用户设备软件开发工作量。
    

下面我们将详细介绍第三方设备开发的流程步骤

创建产品

登陆IntoYun开发者中心: https://www.intoyun.com/account/login

点击左侧添加框创建新产品

创建产品

选项具体说明如下:

  • 产品名称 :请输入产品的名称。
  • 产品类别 :请选择产品的类别。目前分为工业类消费类其他
  • 数据格式 :请选择产品的数据格式。目前分为数据点-TLV自定义。具体请参考产品数据格式详解
  • 产品描述 :请输入产品的描述信息。
  • 接入方案 :请选择设备的接入方案。目前分为WiFiLoRaGPRS/3G/4G

输入产品相关信息后点击“创建产品”。

数据格式定义

打开创建的产品,选中数据格式定义选项。如果创建产品时,您选择的数据格式为自定义,不需要做其他操作,跳到下章节。 如果选择的数据格式为数据点-TLV,此时你便可以编辑数据点,如下图:

create_product

自动代码生成

自动代码生成功能目前只支持WiFi/GPRS类设备,后续将支持LoRa设备

进入“设备开发”->“第三方设备方案开发”->"设备软件开发"页面,点击“自动生成工程”,如下图所示:

create_product

点击后弹出"自动生成代码"框,如下图所示:

create_product

选项具体说明如下:

  • 基础选项

    • 软件版本号 :设备软件版本号,标明设备软件的版本,设备固件升级有使用。软件版本号格式为<主版本号>.<次版本号>.<修订版本号>,例如1.0.0
    • 硬件平台 :请选择设备采取的硬件平台方案。目前支持桌面PC(Linux/MacOS/Windows)ESP8266ESP32。 后续我们将支持更多的硬件平台,用户也可以自己移植到其他的硬件平台。具体参考第三方设备方案SDK移植教程
  • 高级选项

    • 数据发送 :数据发送类型包括自动处理和用户处理。该选项只对数据格式:数据点-TLV有效。
      自动处理即数据发送由系统控制,只有数据发送变化或者发送时间间隔(默认600秒)到才发送数据。
      用户处理即用户调用数据发送接口立即发送数据。

输入和选择相关信息,点击“生成工程”,完成自动代码生成。现在你可以下载工程开始软件编程开发。

软件编程开发

目录结构

自动生成的工程目录结构如下:

+-- lib                             : 库目录
+-- src                             : 源文件目录
    +-- intoyun-iotkit-sdk          : 第三方设备SDK
    +-- apps                        : 用户应用代码
        +-- inc
            +-- ota_update.h        : OTA升级头文件
            +-- project_config.h    : 项目配置文件
        +-- src
            +-- ota_update.c        : OTA升级源文件
            +-- project.c           : 项目应用源文件
            +-- user_main.c         : 软件入口文件
+-- intoyuniot.ini                  : intoyuniot配置文件
+-- README.md                       : 项目说明文件

用户应用代码存放在src/apps/目录,项目编译和下载教程请参考项目工程内文档。

项目说明

下面我们以数据格式为数据点-TLV为例介绍应用代码, 自定义数据格式类似:

project_config.h 为项目配置文件,主要定义产品的相关信息。包括产品标识、产品密钥、产品硬件版本号、产品软件版本号。

#ifndef PROJECT_CONFIG_H_
#define PROJECT_CONFIG_H_

//产品ID
//产品ID是一个16个字节的字符串,为一个产品的标识符。设备通过上送产品ID可以把设备归属到该类产品中。
//产品ID属于绝密信息,请防止泄露。
#define PRODUCT_ID_DEF                           "b0e2547500000305"

//产品密钥
//产品密钥是一个32个字节的字符串,通过产品密钥可以完成设备的自动注册。产品密钥在任何时候不传输。
//产品密钥属于绝密信息,请防止泄露。
#define PRODUCT_SECRET_DEF                       "31efe19957a95501b92b6b3fa905c6ab"

//硬件版本号
//硬件版本号,为设备的硬件版本号。该版本号将上送至服务器。
#define HARDWARE_VERSION_DEF                     "1.0.0"

//软件版本号
//软件版本号,为设备当前软件的版本号。该版本号将上送至服务器。
#define SOFTWARE_VERSION_DEF                     "1.0.0"

#endif

project.c 为项目主源文件,主要分成几部分:

  • 应用初始化
#define DEVICE_ID_DEF                             "*"         //设备标识 24个字节
#define DEVICE_SECRET_DEF                         "*"         //设备密钥 32个字节

void userInit(void)
{
    //初始设备信息
    System.init();
    System.setDeviceInfo(DEVICE_ID_DEF, DEVICE_SECRET_DEF, PRODUCT_ID_DEF, PRODUCT_SECRET_DEF, HARDWARE_VERSION_DEF, SOFTWARE_VERSION_DEF);
    System.setEventCallback(eventProcess);
    //定义产品数据点
    Cloud.defineDatapointBool(DPID_BOOL_SWITCH, DP_PERMISSION_UP_DOWN, false);                            //开关
    Cloud.defineDatapointNumber(DPID_DOUBLE_TEMPERATURE, DP_PERMISSION_UP_DOWN, 0, 100, 1, 0);            //温度
    Cloud.defineDatapointNumber(DPID_INT32_HUMIDITY, DP_PERMISSION_UP_DOWN, 0, 100, 0, 0);                //湿度
    Cloud.defineDatapointEnum(DPID_ENUM_COLOR, DP_PERMISSION_UP_DOWN, 1);                                 //颜色模式
    Cloud.defineDatapointString(DPID_STRING_DISPLAY, DP_PERMISSION_UP_DOWN, 255, "hello! intoyun!");      //显示字符串
    Cloud.defineDatapointBinary(DPID_BINARY_LOCATION, DP_PERMISSION_UP_DOWN, 255, "\x12\x34\x56\x78", 4); //位置信息
    /*************此处修改和添加用户初始化代码**************/
    Cloud.connect();
    timerID = timerGetId();
    /*******************************************************/
}

这段代码功能: 初始化设备信息和定义产品数据点。用户可以在该函数添加用户的初始代码

DEVICE_ID_DEF 和 DEVICE_SECRET_DEF 定义设备标识和设备密钥。设备凭借这两个参数连接平台,每个设备参数都不同。

获取和使用方法请参考第三方设备使用设备密钥教程

  • 应用处理
void userHandle(void)
{
    if(Cloud.connected()) {
        if(timerIsEnd(timerID, 10000)) {
            timerID = timerGetId();

            //更新数据点数据(数据点具备:上送属性)
            Cloud.writeDatapointBool(DPID_BOOL_SWITCH, dpBoolSwitch);
            Cloud.writeDatapointNumberDouble(DPID_DOUBLE_TEMPERATURE, dpDoubleTemperature);
            Cloud.writeDatapointNumberInt32(DPID_INT32_HUMIDITY, dpInt32Humidity);
            Cloud.writeDatapointEnum(DPID_ENUM_COLOR, dpEnumColor);
            Cloud.writeDatapointString(DPID_STRING_DISPLAY, "hello! intoyun!");
            Cloud.writeDatapointBinary(DPID_BINARY_LOCATION, "\x12\x34\x56\x78", 4);
        }
    }
}

您可以在userHandle()函数中处理自己的逻辑,通过Cloud.writeDatapoint()函数往模块内部数据点缓冲区中写数据。系统默认会自动发送数据,当数据点数据变化或者发送间隔时间到时,模块会自动上送数据。

  • 应用事件处理
void eventProcess(int event, int param, uint8_t *data, uint32_t datalen)
{
    if(event == event_cloud_comm) {
        switch(param){
            case ep_cloud_comm_data:
                //开关
                if(RESULT_DATAPOINT_NEW == Cloud.readDatapointBool(DPID_BOOL_SWITCH, &dpBoolSwitch)) {
                    MOLMC_LOGI(TAG, "dpBoolSwitch = %d", dpBoolSwitch);
                }
                //温度
                if(RESULT_DATAPOINT_NEW == Cloud.readDatapointNumberDouble(DPID_DOUBLE_TEMPERATURE, &dpDoubleTemperature)) {
                    MOLMC_LOGI(TAG, "dpDoubleTemperature = %f", dpDoubleTemperature);
                }
                //湿度
                if(RESULT_DATAPOINT_NEW == Cloud.readDatapointNumberInt32(DPID_INT32_HUMIDITY, &dpInt32Humidity)) {
                    MOLMC_LOGI(TAG, "dpInt32Humidity = %d", dpInt32Humidity);
                }
                // 颜色模式
                if (RESULT_DATAPOINT_NEW == Cloud.readDatapointEnum(DPID_ENUM_COLOR, &dpEnumColor)) {
                    MOLMC_LOGI(TAG, "dpEnumColor = %d", dpEnumColor);
                }
                // 显示字符串
                if (RESULT_DATAPOINT_NEW == Cloud.readDatapointString(DPID_STRING_DISPLAY, &dpStringDisplay)) {
                    MOLMC_LOGI(TAG, "dpStringDisplay = %s", dpStringDisplay);
                }
                // 位置信息
                if (RESULT_DATAPOINT_NEW == Cloud.readDatapointBinary(DPID_BINARY_LOCATION, &dpBinaryLocation, &dpBinaryLocationLen)) {
                    MOLMC_LOGI(TAG, "dpBinaryLocationLen = %d", dpBinaryLocationLen);
                    MOLMC_LOG_BUFFER_HEX(TAG, dpBinaryLocation, dpBinaryLocationLen);
                }
                break;
            case ep_cloud_comm_ota:
                otaUpdate(data, datalen);
                break;
            default:
                break;
        }
    } else if(event == event_network_status) {
        switch(param){
            case ep_network_status_disconnected:  //模组已断开路由器
                MOLMC_LOGI(TAG, "event network disconnect router");
                break;
            case ep_network_status_connected:     //模组已连接路由器
                MOLMC_LOGI(TAG, "event network connect router");
                break;
            default:
                break;
        }
    } else if(event == event_cloud_status) {
        switch(param){
            case ep_cloud_status_disconnected:    //模组已断开平台
                MOLMC_LOGI(TAG, "event cloud disconnect server");
                break;
            case ep_cloud_status_connected:       //模组已连接平台
                MOLMC_LOGI(TAG, "event cloud connect server");
                break;
            default:
                break;
        }
    }
}

当模块从服务接受数据后,会调用之前定义的事件回调函数,通过Cloud.readDatapoint()函数的返回值可以获知是否有平台下发的数据。具体如下:
RESULT_DATAPOINT_NEW: 表示收到平台下发的数据。读取一次数据后,返回值会变成RESULT_DATAPOINT_OLD。
RESULT_DATAPOINT_OLD: 表示没有平台下发的数据,读取的数据是上次的数据或者自己通过Cloud.writeDatapoint()写入的数据。
RESULT_DATAPOINT_NONE: 数据点不存在。

第三方设备SDK为用户提供了丰富的SDK接口,相关函数接口请参考第三方设备SDK API接口

设备联网调试

代码开发完毕后,烧写代码到模块后,我们将进入设备调试阶段,如果您已经根据教程开发了手机app软件,您可以使用您开发的app进行调试。如果您没有开发手机app, 您可以选择IntoYun app iPhone | Android 进行调试。 除了手机app,我们还提供web控制端用于设备调试。

接下来我们将讲解设备调试的步骤:

a. 添加设备

您也可以通过web端添加设备, 点击“我的设备”左侧的“添加设备”

add_device_step1

点击“手工输入”,输入设备标识和相关信息,完成添加设备。

b. 设备控制

添加设备成功后,设备页面将出现新的设备,点击设备页面, 您便可以通过控制和读取数据来调试数据了。

App设备调试页面如下:

web端设备调试页面如下:

device_develop