代码的基本结构
一个设备端程序看起来长下面这个样子
static struct TciCB _tci_cb = { ... };
int _Handle_P2p_Cmd(
p2phandle_t handle,
int cmd,
const void *buf,
int size) { ... }
int main() {
TciInit(
"/mnt/flash/",
"143S8TTDNJDZ,XXXXXXXXXXXXXX");
while(1) sleep(1000);
}
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连接句柄.
START_HERE.c 解读
源文件START_HERE.c
包含以上所有内容,可以直接加到用户工程,作为设备端程序开发的起点。
文件中注明TODO:
的,需要用户实现或修改为用户Prefer的实现。
下面以此文件为例子来对一个设备端程序的基本实现作解读。
包含文件
关于 fplayer.h
和PlaybackSdc.c
的信息见 使用卡录像和回放库.
初始化
用户需要实现一系列回调函数,然后调用 TciInit()。回调函数放到后面再解释。
int main()
{
PlayerSetCallbacks(GetFileList, GetPathFromFileItem);
if(ret) {
_err("TciInit retur %d\n", ret);
return 1;
}
TciInit() 需要一个可写目录的路径作参数。SDK运行期间的配置/数据文件会保存在这个目录里。
上面例子中还通过 PlayerSetCallbacks()
注册了卡录像回放的回调。这个一个可选的功能,使用方式见 使用卡录像和回放库.
配网和绑定
一般的对接方式,设备需要有一个绑定到用户的过程(非一般的对接方式是预绑定)。
对wifi设备,这个过程是在配网时完成。对有线(调用SDK前就完成网络配置的,包括4G和应用配网的WiFi)设备,不用配网,但仍需用户在APP上执行添加设备的操作。
下面的代码在 TciInit() 之后:
if(IsRegistered() && is_wifi)
{
_info("Got wifi configuration, let's go ....\n");
}
设备在在本地记录是否绑定的标志。上面的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);
return 0;
}
set_wifi() 回调返回0后, TciConfigWifi() 才会退出。
启动服务
ret =
TciStart(IsRegistered(), (1<<20));
if(ret) return ret;
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.
退出
_info("Stop tci service and cleanup...\n");
return 0;
}
回调函数
上面的 _tci_cb 是一个全局的函数指针结构:
.get_info = get_info;
.get_feature = get_device_feature;
.request_iframe_ex = request_iframe_ex;
.set_timezone = set_timezone;
.set_time = set_time;
.snapshot = snapshot;
.set_wifi = set_wifi;
.on_status = on_status;
.qrcode_start = on_qrcode_start;
.qrcode_get_y_data = on_get_y_data;
.qrcode_end = on_qrcode_end;
.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播放异常。
其它