Tange Cloud for Device
 Rev.333
载入中...
搜索中...
未找到
基本代码解读

代码的基本结构

一个设备端程序看起来长下面这个样子

/* 1. 初始一个全局的 TciCB 结构,其成员是一组回调函数的指针 */
static struct TciCB _tci_cb = { ... };
/* 2. 准备一个P2P 命令处理回调函数 */
int _Handle_P2p_Cmd(p2phandle_t handle, int cmd, const void *buf, int size) { ... }
int main() {
/* 3. 设置回调和初始化 */
TciSetCallback(&_tci_cb);
TciSetCmdHandler(Handle_P2p_Cmd);
TciInit("/mnt/flash/"/*一个可写的路径*/, "143S8TTDNJDZ,XXXXXXXXXXXXXX"/*平台分配的UUID和Key*/);
/* 4. 如果需要配网, 调用 TciConfigWifi() */
TciConfigWifi(WM_AP|WM_QRCODE);
/* 5. 启动服务 */
TciStart(...);
while(1) sleep(1000);
}
/* 6. 在外部线程将音视频数据传给 SDK */
while(1) { TciSendFrameEx(...); }
int TciInit(const char *path, const char *uuid)
配置基本参数 在TciStart()之前调用
int TciSetCallback(const struct TciCB *cb)
注册回调 – sdk内部事件
int TciStart(int isBound, unsigned int uCloudBuffSize)
启动服务
int TciConfigWifi(int mode)
开始配置WIFI.
int TciSendFrameEx(int channel, int stream, TCMEDIA mt, const uint8_t *pFrame, int length, uint32_t ts, int uFrameFlags)
发送实时音视频帧.
int TciSetCmdHandler(const TGCMDHANDLER cb)
注册通用命令回调 在回调里处理APP发来的命令请求
void * p2phandle_t
p2p连接句柄.
sdk 回调函数结构

START_HERE.c 解读

源文件START_HERE.c 包含以上所有内容,可以直接加到用户工程,作为设备端程序开发的起点。

文件中注明TODO:的,需要用户实现或修改为用户Prefer的实现。

下面以此文件为例子来对一个设备端程序的基本实现作解读。

包含文件

#include "TgCloudApi.h" // <-- 唯一必须包含的头文件
#include "fplayer.h" // 可选的卡回放功能。如果使用探鸽的回放库, 包含此文件,并把PlaybackSdc.c加到项目。
探鸽云SDK接口申明

关于 fplayer.hPlaybackSdc.c 的信息见 使用卡录像和回放库.

初始化

用户需要实现一系列回调函数,然后调用 TciInit()。回调函数放到后面再解释。

int main()
{
TciSetCallback(&_tci_cb); //注册sdk内部回调
TciSetCmdHandler(Handle_P2p_Cmd); //注册p2p命令回调
PlayerSetCallbacks(GetFileList, GetPathFromFileItem); //注册卡录像回放需要的回调(可选)
ret = TciInit(_cwd/*可写目录*/, _uuid_/*平台分配的设备uuid和token字符串*/);
if(ret) {
_err("TciInit retur %d\n", ret);
return 1;
}

TciInit() 需要一个可写目录的路径作参数。SDK运行期间的配置/数据文件会保存在这个目录里。

上面例子中还通过 PlayerSetCallbacks()注册了卡录像回放的回调。这个一个可选的功能,使用方式见 使用卡录像和回放库.

配网和绑定

一般的对接方式,设备需要有一个绑定到用户的过程(非一般的对接方式是预绑定)。

对wifi设备,这个过程是在配网时完成。对有线(调用SDK前就完成网络配置的,包括4G和应用配网的WiFi)设备,不用配网,但仍需用户在APP上执行添加设备的操作。

下面的代码在 TciInit() 之后:

//in main()
if(IsRegistered() && is_wifi) //未注册的wifi设备,启动Qrcode和AP模式配网
{
//TODO: 启动AP
TciConfigWifi(GWM_QRCODE|GWM_AP); //在set_wifi()回调里配网
_info("Got wifi configuration, let's go ....\n");
}
#define GWM_AP
AP或蓝牙模式
#define GWM_QRCODE
二维码

设备在在本地记录是否绑定的标志。上面的IsRegistered()是需要自己实现的返回这个标志的函数。

初始时或复位后是未绑定(IsRegistered()==0)的。如果是Wifi设备,则要调用 TciConfigWifi() 开启配网过程。

上面的代码同时开启了AP和设备扫二维码的配网过程。

获取到配网信息后,应用会收到 .set_wifi 回调。

int set_wifi(int is_switching, const char *ssid, const char *key)
{
_info("is_switching:%d. ssid:%s, key:%s", is_switching, ssid, key);
//TODO:
//1. 如果 is_switching=0, 意味设备处在AP配网状态,先切到STA模式。
//2. 配置wifi
//3. 获取IP配置
//4. 上述操作都成功后才返回0,否则返回非0
return 0;
}

set_wifi() 回调返回0后, TciConfigWifi() 才会退出。

启动服务

//in main()
ret = TciStart(IsRegistered(), (1<<20)); //第二个参数云存预录缓冲区大小
if(ret) return ret; //如果返回非0,意味着有不可恢复错

TciStart()的第一个参数为前面提到的本地保存的是否绑定的标志。对未绑定的设备:

  • 如果是wifi设备,配网后在 TciStart() 里完成绑定操作
  • 如果是有线设备,TciStart() 会阻塞直到用户在App上完成添加操作。

服务启动后,TciStart() 会返回。

完成绑定操作后,应用要修改本地保存的绑定标志。保存的时机可是在 TciStart() 返回0之后,或者在 .on_status回调里收到上线通知。

上线和删除通知

在启动中或启动后,设备会通过 .on_status回调收到在线/绑定状态变化通知。

可以在添加设备操作收到上线通知(STATUS_LOGON) 时修改本地保存的绑定标志(SetRegistered())。

任何时间收到 STATUS_DELETED, 表示用户在App上删除了设备,设备要清除绑定标志,并复位重启。

int on_status(int status, const void *pData, int len)
{
switch(status)
{
if(!IsRegistered())
SetRegistered(1);
break;
SetRegistered(0);
//需要复位启
break;
....
}
}
#define STATUS_LOGON
设备上线. data: NULL.
#define STATUS_DELETED
设备被删除. data: NULL.

退出

//可以在main(), 也可以在别的线程
_info("Stop tci service and cleanup...\n");
return 0;
}
int TciCleanup(void)
释放资源
int TciStop(void)
停止服务

回调函数

上面的 _tci_cb 是一个全局的函数指针结构:

static TciCB _tci_cb = {
//获取设备基本&配置信息
.get_info = get_info;
.get_feature = get_device_feature;
.request_iframe_ex = request_iframe_ex; //请求I帧
.set_timezone = set_timezone;
.set_time = set_time;
.snapshot = snapshot;
.set_wifi = set_wifi;
.on_status = on_status;
//.get_state = get_device_state,
//.on_apmode_login = on_apmode_login;
//二维码配网
.qrcode_start = on_qrcode_start;
.qrcode_get_y_data = on_get_y_data;
.qrcode_end = on_qrcode_end;
//OTA
.on_ota_download_start = on_ota_download_start;
.on_ota_download_data = on_ota_download_data;
.on_ota_download_finished = on_ota_download_finished;
//对讲
.on_talkback_start = on_talkback_start;
.talkback = talkback;
.on_talkback_stop = on_talkback_stop;
.log = on_log; //获取设备日志
.switch_quality = switch_quality;
.trans_stat = transfer_stat; //传输统计
};

视开发者的选择,不是每一个回调功能都必要。但前面3组都应该实现。

START_HERE.c 里大部分都是这些回调函数的实现代码。从名字可以看出回调的大体功能。此处不再赘述。开发者可自行参看源文件和手册 TciCB.

发送音视频

在初始化完成后,就可以调用 TciSendFrameEx() 发送音视频。如果设备准备支持云存功能,应用就需要一直保持调用。SDK内部会按需要将数据上传云端和发送到App。

要注意的是,设备需要保存音视频的时间戳正确和同步,否则会引起App播放异常。

其它

  • 调用 TciSetEventEx() 发送事件

    大多数事件都需要在上报的时候提供一张图片。本调用是异步的,图片和事件在别的线程上报。因为应用无法知道图片空间何时使用完,所以需要为每一张图片独立分配内存,并在传递参数时通知SDK在使用完成后释放图片空间。