API文档

本章适用的设备:设备的控制逻辑与WiFi联网功能部署在同一个WiFi芯片上,如果您的设备不属于这种情况,请跳转到WiFi设备开发指导-开发环境准备

本章先介绍嵌入式WiFi开发者在使用API时需要掌握的基本概念,然后分功能介绍Ablecloud提供给嵌入式WiFi设备的所有的API。

基本概念

开发者通过调用Ablecloud的API可以实现与云端/移动端之间的消息交互,开发者不需要关心交互的消息的完整格式,只需要掌握如下概念:

(1)消息构成

对开发者来说,设备与云端之间的消息由以下部分构成:

名称 作用
MsgSN 消息的序号(Msg Sequence Number),设备主动上报时填0;设备响应云端指令时必须填写对应的云端指令携带的MsgSN
MsgCode 标识payload的类型
Payloadlen 消息携带的payload的长度,以字节为单位
payload 消息体

(2)MsgCode

MsgCode用来标识设备与云端交互的消息类型,云端和设备端根据对应的MsgCode区分消息携带的payload的类型。

消息类型表(MsgCode)如下:

MsgCode 消息类型 消息类型说明
2 AC_CODE_WIFI_CONNECTED WiFi链接成功通知
3 AC_CODE_WIFI_DISCONNECTED WiFi断链通知
4 AC_CODE_CLOUD_CONNECTED 云端链接成功通知
5 AC_CODE_CLOUD_DISCONNECTED 云端链接断链通知
17 ZC_CODE_OTA_BEGIN MCU OTA开始通知
18 ZC_CODE_OTA_FILE_BEGIN MCU OTA文件传输开始通知
19 ZC_CODE_OTA_FILE_CHUNK MCU OTA文件块到达通知
20 ZC_CODE_OTA_FILE_END MCU OTA文件传输结束通知
21 ZC_CODE_OTA_END MCU OTA结束通知
63 ZC_CODE_SUBSCRIBE_REPORT 请求设备快速上报通知
64 AC_EVENT_BASE 设备自定义控制消息基址
[64,200) AC_EVENT_CONTROL_AND_RESPONSE 设备自定义,由服务或APP发给设备的控制消息以及设备的应答消息
[200,255] AC_EVENT_DEVICE_REPORT 设备自定义,设备上报信息

注意: 小于64的MsgCode是AC使用的消息码,开发者不能占用。[64,255]是提供给开发者的设备自定义消息码,开发者使用时需要遵守表中的规则,且要与移动端及UDS协商一致

(3)payload

是由MsgCode定义的消息类型的具体内容。payload的格式可以是二进制,也可以是JSON。

服务器环境配置接口

Ablecloud为开发者提供了用于开发测试的dev环境,以及用于产品正式生产使用的生产环境。通过在ac_cfg.h中修改CLOUD_ADDR的值,可以选择不同的环境。

CLOUD_ADDR的取值:

AC_DEV_SERVER :测试环境,对应test.ablecloud.cn
AC_CH_SERVER:生产环境-中国,对应device.ablecloud.cn
AC_US_SERVER:生产环境-美洲,对应usdevice.ablecloud.cn
AC_EU_SERVER:生产环境-欧洲,对应eudevice.ablecloud.cn
AC_EA_SERVER:生产环境-东南亚,对应eadevice.ablecloud.cn

WiFi行为控制接口

进入配网状态

  • WiFi设备是通过WiFi模块连接上路由器,再与广域网相连接的,所以WiFi设备要连接到云端,第一步就是连接上路由器。配网即指:利用smartLink、AirKiss等技术,通过路由器、WiFi模块以及连接上路由器的手机APP的协同工作,实现在WiFi模块不知道路由器的SSID和密码的情况下,使WiFi模块获取到路由器的信息、并连接上路由器的过程。
  • 配网状态即WiFi模块进入smartLink或AirKiss等状态,准备好开始配网流程的状态。
  • WiFi模块进入配网状态后,会等待APP在局域网广播的路由器的SSID和密码,获取到密码后,WiFi模块会连接到路由器并通过DHCP获取到IP地址。
  • 配网的功能由WiFi芯片商实现,Ablecloud提供的API会通知WiFi芯片进入配网状态。
  • 配网的具体技术细节请参考“SmartLink”和“AirKiss”等

API:


    void AC_SendRestMsg(void);

API行为:
- 清除WiFi模块存储的上次连接的路由器的信息
- 重启设备,设备重启后进入配网状态

触发设备进入AP模式

通常WiFi芯片支持Sta模式和AP模式。
AP模式: Access Point,提供无线接入服务,允许其它无线设备接入,提供数据访问。AP和AP之间允许相互连接
Sta模式: Station, 类似于无线终端,Sta本身并不接受无线的接入,它可以连接到AP,通过AP接入广域网或其他网络。

通常,WiFi模块的AP模式用于AP配网:由于部分路由器不支持广播,导致WiFi模块在Sta模式下无法完成配网。转为AP模式,手机APP可以先接入WiFi模块,然后将要连接的路由器的SSID和密码发送给WiFi模块,之后WiFi模块再切换为Sta模式,连接路由器,完成配网流程。

API:


    ZC_ErrorCode AC_SendSetApMsg(u8 *pu8ApName,u8 u8Len)

参数

字段 类型 说明
pu8ApName u8 * 存储WiFi模块进入AP模式后的SSID的字符串的首地址
u8Len u8 WiFi模块进入AP模式后的SSID的长度,不能超过27个字节(超出的部分会被截掉)

返回值

意义
ZC_RET_OK 配置AP模式成功
ZC_PARA_ERROR 配置AP模式失败,入参无效或内存分配失败

API行为:
- 重启WiFi模块 - 重启后,WiFi模块进入AP模式,AP的SSID为入参 pu8ApName 指向的字符串+Mac地址的后四位,密码固定为123456789

重启WiFi模块

API:


    void AC_SendRebootMsg(void);

API行为:
- 重启WiFi芯片。重启后,如果Flash中存储了上次连接的路由器的信息,则WiFi模块会直接连接路由器,否则等待APP进行配网

休眠唤醒

如果WiFi芯片具有休眠功能,则这组API会使WiFi芯片进入/切出休眠状态。不同的WiFi芯片,其休眠状态的行为不完全一致。通常来讲,进入休眠状态的WiFi芯片,其射频部分会被关闭,此时设备无法再与外界进行通信。在不需要与外界通信时进入休眠状态,可以降低设备的功耗。

API:


    void AC_SendSleepMsg(void);  
    void AC_SendWakeUpMsg(void);

API行为:
- 第一个API关闭WiFi芯片的射频部分,使设备进入低功耗状态
- 第二个API打开WiFi芯片的射频部分,使设备进入正常工作模式

注意:
如果开启低功耗模式,设备的数据收发会受到影响,使用时请注意。

局域网通信接口

局域网通信加密方式配置接口

接口定义


    void AC_SetLocalLevel(PCT_LOCAL_LEVEL Etoken);

参数

字段 类型 说明
Etoken PCT_LOCAL_LEVEL 局域网通信加密方式

    typedef enum
    {
        PCT_LOCAL_NONE_TOKEN = 0,  /*不加密*/
        PCT_LOCAL_STATIC_TOKEN = 1,  /*静态加密*/
        PCT_LOCAL_DYNAMIC_TOKEN = 2  /*动态加密*/
    }PCT_LOCAL_LEVEL;

注意:
一般不建议开发者使用无加密的方式。AC联网SDK默认采用动态加密的方式,如果开发者要使用静态加密,可以在ac_cfg.h中添加预定义宏LOCAL_STATIC_TOKEN。所以开发者一般不需要关心这个API。

通知类型消息处理接口

当设备的网络连接状态发生变化,如连接上路由器、连接上云端等,Ablecloud联网模块会通过函数接口通知开发者,开发者可以在该函数接口中添加自己的处理逻辑,如点亮相应的灯,显示WiFi连接状态。

所在文件

ac_hal.c

接口定义


    void AC_DealNotifyMessage(ZC_MessageHead *pstruMsg, AC_OptList *pstruOptList, u8 *pu8Playload);

参数

字段 类型 说明
pstruMsg ZC_MessageHead * 收到的数据
pstruOptList AC_OptList * 解析后的option项
pu8Playload u8 * 指向Playload数据起始位置

默认实现


    void AC_DealNotifyMessage(ZC_MessageHead *pstruMsg, AC_OptList *pstruOptList, u8 *pu8Playload)
    {
        //deal notify message about state of WiFi connection and cloud connection
        switch(pstruMsg->MsgCode)
        {
            case ZC_CODE_WIFI_CONNECTED://WiFi module disconnect with AP
            {
                AC_SendDeviceRegsiter(g_u8EqVersion,g_u8ModuleKey,(u8*)&g_u64Domain,g_u8DeviceId);
                break;
            }
            case ZC_CODE_WIFI_DISCONNECTED://WiFi module disconnect with AP
            {
                ZC_Printf(eLL_Info, eMT_Tbc, "AC_DealNotifyMessage WiFi disconnect\n");
                break;
            }
            case ZC_CODE_CLOUD_CONNECTED://WiFi module connect with cloud
            {
    #if defined(DEMO_REPORT)
                UserCallback_CloudConnect();
    #endif
                AC_StoreStatus(CLOUDSTATUS,CLOUDCONNECT);
                break;
            }
            case ZC_CODE_CLOUD_DISCONNECTED://WiFi module disconnect with cloud
            {
    #if defined(DEMO_REPORT)
                UserCallback_CloudDisconnect();
    #endif
                AC_StoreStatus(CLOUDSTATUS,CLOUDDISCONNECT);
                break;
            }
            case ZC_CODE_NTP:
            {
                AC_HandleNtp((ZC_NTP_TIME*)pu8Playload);
                break;
            }
            case ZC_CODE_LQ://ntp timer
            {
                AC_HandleLinkQuality((s8)pu8Playload[0]);
                break;
            }
            case ZC_CODE_SUBSCRIBE_REPORT:
            {
                AC_SendDeviceStatus(pstruOptList);
                break;
            }
            default:
            {
                ZC_Printf(eLL_Err, eMT_Prot, "AC_DealNotifyMessage error\n");
                break;
            }
        }
    }

网络连接状态事件通知

ZC_CODE_WIFI_CONNECTEDZC_CODE_WIFI_DISCONNECTEDZC_CODE_CLOUD_CONNECTEDZC_CODE_CLOUD_DISCONNECTED分别是WiFi连接上路由器,WiFi与路由器连接断开,WiFI连接上云端,WiFi与云端连接断开的事件通知。 开发者可以在此添加自己的控制逻辑,如点亮LED指示灯。

设备注册接口

设备进行联网注册的逻辑已经由AC联网模块完成,开发者只需要关心是使用MAC地址还是使用自定义ID作为设备的物理ID。

1.如果要使用WiFi模块的MAC作为物理ID,则需要在ZC_CODE_WIFI_CONNECTED事件中调用APIAC_SendDeviceRegsiter时,将最后一个参数置位NULL
2.如果要使用自定义ID作为物理ID,则需要在ZC_CODE_WIFI_CONNECTED事件中调用APIAC_SendDeviceRegsiter时,将最后一个参数改为g_u8DeviceId 3.如果使用自定义ID作为物理ID,开发者可以修改ac_cfg.h中的预定义宏DEVICE_ID,也可以在调用ZC_Init之前自行为数组g_u8DeviceId赋值,作为设备的物理ID

设备属性快速上报请求通知

Ablecloud提供了设备属性快速上报的功能,主要针对以下两种场景:

1.通过云端快速上报设备属性
当有APP打开时,用户有可能想更实时的查看到设备的状态变化,此时需要设备提高上报频率;而当没有APP打开时,设备的上报频率可以降低

2.局域网内快速上报设备属性
在局域网内,当有APP打开时,用户有可能想更实时的收到设备状态的上报消息。

对于场景1,设备上报的频率及持续时间是由APP开发者配置的,对于场景2,设备上报的频率是默认的(3秒一次)。
当需要设备上报属性时,AC联网模块会发送事件ZC_CODE_SUBSCRIBE_REPORT给UserApp,UserApp需要在该事件通知中构造并上报设备的全量信息。开发示例如下:


    void AC_DealNotifyMessage(ZC_MessageHead *pstruMsg, AC_OptList *pstruOptList, u8 *pu8Playload)
    {
        //deal notify message about state of WiFi connection and cloud connection
        switch(pstruMsg->MsgCode)
        {
                                    .
                                    .
                                    .
                                    .
            case ZC_CODE_SUBSCRIBE_REPORT:
            {
                AC_SendDeviceStatus(pstruOptList);
                break;
            }
            default:
            {
                ZC_Printf(eLL_Err, eMT_Prot, "AC_DealNotifyMessage error\n");
                break;
            }
        }
    }

    void AC_SendDeviceStatus(AC_OptList *pstruOptList)
    {
        u8 DeviceStatus[100] = {0};
        /*开发者需要自行构造上报消息的内容*/
        AC_SendMessage(MSG_SERVER_CLIENT_GET_LED_STATUS_RSP,0,
                        (u8*)&DeviceStatus, sizeof(DeviceStatus),
                        pstruOptList);
    }

注意

1.无论是云端快速上报请求还是局域网快速上报请求,AC联网模块都是通过上述接口通知开发者的,开发者可以通过入参pstruOptList是否为空来判断本次上报是发送给云端还是局域网。如果pstruOptList为空,则本次上报是发送给云端(UDS)的;如果pstruOptList不为空,则本次上报是发送给局域网内的APP的。
2.对于局域网快速上报,WiFi是通过局域网UDP广播发送给局域网内的所有APP的。
3.上报消息的MsgCode必须不小于200

设备控制消息处理接口

当WiFi模块接收相关的设备自定义控制消息后,会调用该接口。自定义消息的MsgCode必须大于等于64。

所在文件

ac_hal.c

接口定义


    void AC_DealEvent(ZC_MessageHead *pstruMsg, AC_OptList *pstruOptList , u8 *pu8Payload, u16 u16PayloadLen);

参数

字段 类型 说明
pstruMsg ZC_MessageHead * 收到的数据的协议头
pstruOptList AC_OptList * 解析后的option项。如果该参数为空,则表明是云端发送来的消息;如果该参数不为空,则表明是局域网APP发送来的消息
pu8Payload u8 * 指向Payload数据起始位置
u16PayloadLen u16 Payload的长度,单位为Byte

开发示例


    void AC_DealEvent(ZC_MessageHead *pstruMsg, AC_OptList *pstruOptList, u8 *pu8Payload, u16 u16PayloadLen)
    {   
        //处理设备自定义控制消息
        switch(pstruMsg->MsgCode)
        {
            case MSG_SERVER_CLIENT_SET_LED_ONOFF_REQ:
            {
                AC_DealLed(pstruMsg, pstruOptList, pu8Payload, u16PayloadLen);
            }
            break;
        }
    }

注意:
1.为了更好的体验,我们建议消息处理接口中,开发者在处理完控制逻辑后,将最新的设备状态作为响应信息返回给云端。
2. 开发者在处理完云端下发的指令后,如果要回复响应消息,请在调用 AC_BuildMessage API时,将 AC_DealEvent 的入参pstruOptList传递给AC_BuildMessage函数。
3.开发者可以通过参数pstruOptList是否为NULL来判断消息来源是云端还是局域网。如果pstruOptList为NULL,则表明是云端消息;如果不为NULL,则表明是局域网消息

OTA接口

对于SoC方案,AC联网模块已经集成了OTA功能,开发者不需要做额外的开发,也不建议开发者修改OTA的流程。
如果开发者希望自行处理OTA的事件通知和数据包,AC联网模块也提供了相关的接口(但是强烈不建议开发者自行修改),在ac_hal.c文件中的函数AC_DealEvent中,AC_DealEvent的接口描述参见上一小节。


    void AC_DealEvent(ZC_MessageHead *pstruMsg, AC_OptList *pstruOptList,u8 *pu8Payload, u16 u16PayloadLen)
    {
        /*deal with message defined by device.*/
        switch(pstruMsg->MsgCode)
        {
                                .
                                .
                                .
            case ZC_CODE_OTA_BEGIN:
            {
                AC_DealEvent_OtaBegin(pstruMsg, pu8Payload, u16PayloadLen);
                break;
            }
            case ZC_CODE_OTA_FILE_BEGIN:
            {
                AC_DealEvent_OtaFileBegin(pstruMsg, pu8Payload, u16PayloadLen);
                break;
            }
            case ZC_CODE_OTA_FILE_CHUNK:
            {
                AC_DealEvent_OtaFileChunk(pstruMsg, pu8Payload, u16PayloadLen);
                break;
            }
            case ZC_CODE_OTA_FILE_END:
            {
                AC_DealEvent_OtaFileEnd(pstruMsg, pu8Payload, u16PayloadLen);
                break;
            }
            case ZC_CODE_OTA_END:
            {
                AC_DealEvent_OtaEnd(pstruMsg, pu8Payload, u16PayloadLen);
                break;
            }
                                .
                                .
                                .
        }

    }

OTA开始事件处理接口

所在文件

ac_hal.c

接口定义


    void AC_DealEvent_OtaBegin(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen);

参数

字段 类型 说明
pstruMsg ZC_MessageHead * 收到数据的协议头
pu8Payload u8 * 指向Payload数据起始位置
u16PayloadLen u16 Payload数据的长度(单位为byte)

其中payload是一个ZC_OtaBeginReq类型的报文,定义如下:


    typedef struct
    {
        u8 u8FileNum;
        u8 u8Pad[3];

    }ZC_OtaBeginReq;
字段 类型 说明
u8FileNum u8 OTA文件数目
u8Pad u8 padding,补齐用

默认实现


    void AC_DealEvent_OtaBegin(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen)
    {
        ZC_OtaBeginReq struOtaBegin;
        if (u16PayloadLen != sizeof(ZC_OtaBeginReq))
        {
            ZC_Printf(eLL_Err, eMT_OTA, "AC_DealEvent_OtaBegin Err! payload len is invalid %d\n", u16PayloadLen);
            ZC_CheckResponse(ZC_CODE_ERR, pstruMsg->MsgSN);
            return;
        }
        memcpy(&struOtaBegin, pu8Payload, sizeof(ZC_OtaBeginReq));
        ZC_Printf(eLL_Info, eMT_OTA, "AC_DealEvent_OtaBegin, file num is %d\n", struOtaBegin.u8FileNum);
        ZC_CheckResponse(ZC_CODE_ACK, pstruMsg->MsgSN);
        return;
    }

OTA文件传输开始事件处理接口

所在文件

ac_hal.c

接口定义


    void AC_DealEvent_OtaFileBegin(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen);

参数

字段 类型 说明
pstruMsg ZC_MessageHead * 收到数据的协议头
pu8Payload u8 * 指向Payload数据起始位置
u16PayloadLen u16 Payload数据的长度(单位为byte)

其中payload是一个ZC_OtaFileBeginReq类型的报文,定义如下:


    typedef struct
    {
        u8 u8FileType;
        u8 u8FileVersion;
        u8  u8TotalFileCrc[2];

        u32 u32FileTotalLen;
    }ZC_OtaFileBeginReq;
字段 类型 说明
u8FileType u8 OTA文件类型
u8FileVersion u8 OTA版本号
u8TotalFileCrc u8 OTA文件CRC值
u32FileTotalLen u8 OTA文件总长度(单位为byte)

默认实现


    void AC_DealEvent_OtaFileBegin(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen)
    {
        ZC_OtaFileBeginReq struFileBegin;
        if (u16PayloadLen != sizeof(ZC_OtaFileBeginReq))
        {
            ZC_Printf(eLL_Err, eMT_OTA, "AC_DealEvent_OtaFileBegin Err! payload len is invalid %d\n", u16PayloadLen);
            ZC_CheckResponse(ZC_CODE_ERR, pstruMsg->MsgSN);
            return;
        }

        if (NULL != gpFdFirmware)
        {
            //fclose(gpFdFirmware);
            gpFdFirmware = NULL;
        }
        //gpFdFirmware = fopen(OtaFileLocalPath, "wb");  /* open the file */
        if (NULL == gpFdFirmware)
        {
            ZC_Printf(eLL_Err, eMT_OTA, "AC_DealEvent_OtaFileBegin open file failed\n");
            ZC_CheckResponse(ZC_CODE_ERR, pstruMsg->MsgSN);
            return;
        }

        OtaFileCrcLocal = 0;
        memcpy(&struFileBegin, pu8Payload, sizeof(ZC_OtaFileBeginReq));
        OtaFileCrcRemote = struFileBegin.u8TotalFileCrc[0]*256+struFileBegin.u8TotalFileCrc[1];
        ZC_Printf(eLL_Info, eMT_OTA, "AC_DealEvent_OtaFileBegin: \nfileType:\t%d\nfileVersion:\t%d\nCRC:\t%x %x\nfiltLen:\t%d\n",
                  struFileBegin.u8FileType, struFileBegin.u8FileVersion, struFileBegin.u8TotalFileCrc[0],
                  struFileBegin.u8TotalFileCrc[1], struFileBegin.u32FileTotalLen);
        ZC_CheckResponse(ZC_CODE_ACK, pstruMsg->MsgSN);
        return;
    }

OTA文件块到达处理接口

所在文件

ac_hal.c

接口定义


    void AC_DealEvent_OtaFileChunk(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen);

参数

字段 类型 说明
pstruMsg ZC_MessageHead * 收到数据的协议头
pu8Payload u8 * 指向Payload数据起始位置
u16PayloadLen u16 Payload数据的长度(单位为byte)

其中payload是一个ZC_OtaFileChunkReq类型的报文,定义如下:


    typedef struct
    {
        u32 u32Offset;
    }ZC_OtaFileChunkReq;
字段 类型 说明
u32Offset u32 OTA文件块偏移(单位为byte)

默认实现


    void AC_DealEvent_OtaFileChunk(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen)
    {
        ZC_OtaFileChunkReq struOtaFileChunkReq;
        u8 *pOtaFileSegment = NULL;
        size_t written = 0;
        u16 OtaFileSegmentSize = 0;
        if (u16PayloadLen <= sizeof(ZC_OtaFileChunkReq))
        {
            ZC_Printf(eLL_Err, eMT_OTA, "AC_DealEvent_OtaFileChunk Err! payload len is invalid %d\n", u16PayloadLen);
            ZC_CheckResponse(ZC_CODE_ERR, pstruMsg->MsgSN);
            return;
        }

        memcpy(&struOtaFileChunkReq, pu8Payload, sizeof(ZC_OtaFileChunkReq));
        pOtaFileSegment = pu8Payload + sizeof(ZC_OtaFileChunkReq);
        ZC_Printf(eLL_Info, eMT_OTA, "AC_DealEvent_OtaFileChunk, offset is %d\n", ZC_HTONL(struOtaFileChunkReq.u32Offset));

        if (NULL == gpFdFirmware)
        {
            ZC_Printf(eLL_Err, eMT_OTA, "AC_DealEvent_OtaFileChunk Err! Firmware file not exist\n");
            ZC_CheckResponse(ZC_CODE_ERR, pstruMsg->MsgSN);
            return;
        }
        OtaFileSegmentSize = u16PayloadLen - sizeof(ZC_OtaFileChunkReq);
       // written = fwrite(pOtaFileSegment, sizeof(char), OtaFileSegmentSize, gpFdFirmware);
        ZC_Printf(eLL_Info, eMT_OTA, "AC_DealEvent_OtaFileChunk wrtten block num: %d\n", written);
        OtaFileCrcLocal = crc16_ccitt_segment(OtaFileCrcLocal, (const u8*)pOtaFileSegment, OtaFileSegmentSize);

        ZC_CheckResponse(ZC_CODE_ACK, pstruMsg->MsgSN);

        return;
    }

OTA文件传输结束处理接口

所在文件

ac_hal.c

接口定义


    void AC_DealEvent_OtaFileEnd(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen);

参数

字段 类型 说明
pstruMsg ZC_MessageHead * 收到数据的协议头
pu8Payload u8 * 指向Payload数据起始位置
u16PayloadLen u16 Payload数据的长度(单位为byte)

默认实现


    void AC_DealEvent_OtaFileEnd(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen)
    {
        if (u16PayloadLen != 0)
        {
            ZC_Printf(eLL_Err, eMT_OTA, "AC_DealEvent_OtaFileEnd Err! payload len is invalid %d\n", u16PayloadLen);
            ZC_CheckResponse(ZC_CODE_ERR, pstruMsg->MsgSN);
            return;
        }

        if (OtaFileCrcRemote != OtaFileCrcLocal)
        {
            ZC_Printf(eLL_Err, eMT_OTA, "AC_DealEvent_OtaFileEnd err! CRC failed! local crc is %x, remote crc is %x\n", OtaFileCrcLocal, OtaFileCrcRemote);
            ZC_CheckResponse(ZC_CODE_ERR, pstruMsg->MsgSN);
        }

        ZC_Printf(eLL_Info, eMT_OTA, "AC_DealEvent_OtaFileEnd OK\n");

        /*todo write OTA segment to local file*/
        ZC_CheckResponse(ZC_CODE_ACK, pstruMsg->MsgSN);
        return;
    }

OTA结束事件处理接口

所在文件

ac_hal.c

接口定义


    void AC_DealEvent_OtaEnd(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen);

参数

字段 类型 说明
pstruMsg ZC_MessageHead * 收到数据的协议头
pu8Payload u8 * 指向Payload数据起始位置
u16PayloadLen u16 Payload数据的长度(单位为byte)

默认实现


    void AC_DealEvent_OtaEnd(ZC_MessageHead *pstruMsg, u8 *pu8Payload, u16 u16PayloadLen)
    {
        char cpCmd[200] = {0};
        if (u16PayloadLen != 0)
        {
            ZC_Printf(eLL_Err, eMT_OTA, "AC_DealEvent_OtaEnd Err! payload len is invalid %d\n", u16PayloadLen);
            ZC_CheckResponse(ZC_CODE_ERR, pstruMsg->MsgSN);
            return;
        }

        /*todo write OTA segment to local file*/
        ZC_CheckResponse(ZC_CODE_ACK, pstruMsg->MsgSN);
        ZC_Printf(eLL_Info, eMT_OTA, "AC_DealEvent_OtaEnd OTA chunk finished\n");

        /*resource free begin*/
        g_struProtocolController.pstruMoudleFun->pfunReleaseSource();
        /*resource free end*/

        /*todo @developer: developer should add itself code here to release source.*/

        ZC_Printf(eLL_Info, eMT_OTA, "WRTnode_FirmwareUpdateFinish Err! TCP OTA should not be executed\n");

        sprintf(cpCmd, "mv %s /tmp/AbcloudFirmware.tar.gz", OtaFileLocalPath);
       // if (-1 == system(cpCmd))
        {
            ZC_Printf(eLL_Err, eMT_OTA, "system cmd mv failed\n");
            return;
        }

       // exit(0);

        return;
    }

强制解绑设备接口

设备与APP用户绑定后,开发者在需要时可以调用API强制解除该绑定关系。

API:


    void AC_SendUbindMsg(void);

API行为:
通知Ablecloud联网模块发起设备绑定关系强制解除操作

与云端通信接口

设备与云端的交互流程及代码开发框架具体流程参见WiFi设备开发指导中的“接收云端消息”和“处理云端消息”的描述。这里只描述相关API的具体信息及开发示例。

数据组包发送接口

开发者调用 AC_BuildMessage API按云端协议格式组包后,调用该API将数据交给Ablecloude的联网模块,Ablecloud会将其发送给云端。

API:


    ZC_ErrorCode AC_SendMessage(
        u8 u8MsgCode, 
        u8 u8MsgSN, 
        u8 *pu8Payload, 
        u16 u16PayloadLen, 
        AC_OptList *pstruOptList
    )

参数

字段 类型 说明
u8MsgCode u8 消息类型
u8MsgSN u8 消息序列号,设备主动上报时填0,响应时填写对应的云端下发指令的u8MsgSN
pu8Payload u8 * 消息体,设备发送的消息的实际内容。如果不需要发送payload,该参数填NULL
u16PayloadLen u16 消息实际长度
pstruOptList AC_OptList * Option项列表,设备主动上报时填NULL,响应时直接将下行控制消息中的pstruOptList填在该处

返回值

意义
ZC_RET_OK 发送成功(不代表已经被接收端成功接收)
ZC_PAYLOAD_LEN_OVERFLOW 发送失败,发送的消息过长
ZC_RET_ERROR 发送失败,其他原因

API行为:
- Ablelcoude联网模块会将数据发送给云端

开发示例


    /*上报数据包=code:203 + req:{1,0,0,0}*/

    typedef struct tag_STRU_LED_ONOFF
    {       
        u8       u8LedOnOff ; // 0:关,1:开
        u8       u8ControlStatus;//0为APP控制开关,1为按键控制开关   
        u8       u8Pad[2];       
    }STRU_LED_ONOFF;

    void AC_SendStatus2Server(u8 u8control)
    {
        ZC_ErrorCode ret;

        /*上报demo灯的状态*/
        STRU_LED_ONOFF struReport;
        u16 u16DataLen;

        /*读取demo灯状态*/
        struReport.u8LedOnOff = GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2);
        struReport.u8LedOnOff = struRsp.u8LedOnOff>>2;
        struReport.u8ControlStatus = u8control;

        /*构造并发送消息*/
        ret = AC_SendMessage(203, 0, (u8*)&struReport, sizeof(STRU_LED_ONOFF), NULL);
        if (ZC_RET_OK != ret) 
        {
            ZC_Printf("AC_SendStatus2Server Err, AC_SendMessage failed\n");
            return;
        }     
    }

JSON格式

用户可调用第三方源码构造JSON格式的消息体。


    //请求数据包
    { 203 :[
         //关灯
         {"switch", 0}
         //开灯
         {"switch", 1}
    ]
    [
         //APP控制开关
         {"controltype", 0},
         //按键控制开关  
         {"controltype", 1}
    ]}

    void AC_SendLedStatus2Server(u8 controltype)
    {
        ZC_ErrorCode ret;

        /*上报demo灯的状态*/
        cJSON *root;
        char *out;
        u8 u8LedOnOff;
        u16 u16DataLen;
         /*JSON协议内存分配*/
        root=cJSON_CreateObject();
        u8LedOnOff = GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2);
        u8LedOnOff = u8LedOnOff>>2;
         /*构造JSON消息体*/
        cJSON_AddNumberToObject(root,"action",      u8LedOnOff);
        cJSON_AddNumberToObject(root,"controltype",     controltype);
        out=cJSON_Print(root);  
        cJSON_Delete(root);

        /*发送消息*/
        ret = AC_SendMessage(203, 0, (u8*)&out, strlen(out), NULL);
        if (ZC_RET_OK != ret) 
        {
            /*释放JSON消息*/
            free(out);   
            ZC_Printf("AC_SendLedStatus2Server Err, AC_SendMessage failed\n");
            return;
        }     

        /*JSON协议内存释放*/
        free(out);
    }

NTP时间获取接口

触发获取NTP时间接口

API:


    void AC_GetNtpTime(void);

API行为: - 触发AC联网模块到云端服务器获取NTP时间

注意:
获取NTP时间的前提是WiFi模块已经连接上外网

处理NTP结果的接口

开发者调用APIAC_GetNtpTime触发AC联网模块获取NTP时间后,得到的结果会通过函数AC_HandleNtp反馈给开发者。开发者可以在该函数中添加自己的处理逻辑。

API:


    void AC_HandleNtp(ZC_NTP_TIME* ntp);

参数


    typedef struct
    {
        u16 year;
        u8 month;
        u8 day;    
        u8 weekday;
        u8 hour;
        u8 min;
        u8 sec;
        u32 ntp_sec;
    }ZC_NTP_TIME;
字段 类型 说明
year u16 年(UTC时间)
month u8 月(UTC时间)
day u8 日(UTC时间)
weekday u8 星期(UTC时间)
hour u8 时(UTC时间)
min u8 分(UTC时间)
sec u8 秒(UTC时间)
ntp_sec u32 当前时间距1970年1月1日00:00:00的描述(UTC时间)

注意:
通过NTP获取到的时间是UTC时间,开发者如果需要本地时间,需要根据所在时区自行进行转换。

开发示例


    void AC_HandleNtp(ZC_NTP_TIME* ntp)
    {
        ZC_Printf("ntp time is %d-%d-%d %d:%d:%d weekday is %d\n",ZC_HTONS(ntp->year),
                                                                     ntp->month,
                                                                     ntp->day,
                                                                     ntp->hour,
                                                                     ntp->min,
                                                                     ntp->sec,
                                                                     ntp->weekday);
}

获取信号质量接口

触发获取信号质量接口

API:

    void AC_GetLinkQuality(void);

API行为:

  • 触发AC联网模块到获取信号质量

处理获取信号的接口

开发者调用APIAC_GetLinkQuality触发AC联网模块获取获取信号质量,如果模块联网得到的结果会通过函数AC_HandleLinkQuality反馈给开发者。开发者可以在该函数中添加自己的处理逻辑;如果模块处在断网状态会收到在AC_DealNotifyMessage收到断网通知消息

API:

    void AC_HandleLinkQuality(s8 s8LinkQuality);

参数 取值范围[0,100],该值表征的是当前信号质量在信号质量范围内的百分比。该值越大信号质量最好

开发示例


    void AC_HandleLinkQuality(s8 s8LinkQuality)
    {
        ZC_Printf("Link quality is %d\n",s8LinkQuality);
    }

产测接口

Ablecloud针对开发者的产测需求提供了产测服务,具体流程请参见产测服务
要触发进入产测模式,需要调用APIAC_SetProductTest

API:

    void AC_SetProductTest();

API行为:
- 触发WiFi扫频,并连接产测路由器(SSID固定为AC_PRODUCT_TEST1或者AC_PRODUCT_TEST2),期间WiFi会自动重启。如果没有SSID为AC_PRODUCT_TEST1或者AC_PRODUCT_TEST2的路由器,则WiFi不会执行任何操作。