全志V821对接录风者app-3
·
概要
基于thttpd对接录风者app基础指令。
实现app预览实时画面的基础功能。
为实现这一目标我们要实现如下三条HTTP请求
- 获取产品信息
http://192.168.169.1/app/getproductinfo
返回参数示例
{
"result": 0,
"info": {
"model": "x1",
"company": "alibaba",
"soc": " eeasytech ",
"sp": "FH"
}
}
| 参数名 | 类型 | 描述 |
|---|---|---|
| model | string | 该产品的型号,比如”iphone 11 pro“; |
| company | string | 该产品对应的生产商,比如”Apple“;如果是方案商的公版,就写和下面的sp 一样; |
| soc | string | 对应的芯片平台,比如: “eeasy”、“sigmstar”等 |
| sp | string | 对应方案商的名称或代号,比如:烽航“FH” |
- 获取设备信息
http://192.168.169.1/app/getdeviceattr
返回参数示例
{
"result": 0,
"info": {
"uuid": "12ad3f5b8c9d",
"softver": "v1.2.3",
"otaver": "v1.20230312.1",
"hwver": "v1.2",
"ssid": "cardv-12ad4f",
"bssid": "12ad3f5b8c9d",
"camnum":2,
"curcamid":0,
"wifireboot":0
}
}
| 参数名 | 类型 | 描述 |
|---|---|---|
| uuid | string | 设备的唯一标志,设备端可以用mac 地址或是sn |
| softver | string | 当前固件的版本号 |
| otaver | string | 用来专门升级用的ota 版本号,需要满足版本号的定义规范,如果softver 满足ota 版本号规范,可以不用此字段,具体规范参考第7 章OTA; |
| hwver | string | 当前设备的硬件版本 |
| ssid | string | WiFi 的ssid |
| bssid | string | WiFi 的mac 地址 |
| camnum | int | 摄像头的个数 |
| curcamid | int | 当前摄像头的id,front:0,rear:1,如果只有一个摄像头,则为0 |
| wifireboot | int | 更改WiFi 名、密码、恢复出厂设置后是否需要App下发重启WiFi:0-不需要,1-需要 |
- 获取媒体信息
http://192.168.169.1/app/getmediainfo
返回参数示例
{
"result": 0,
"info": {
"rtsp": "rtsp://192.168.169.1/stream.mp4",
"transport":"tcp"
"port": 6035
"rtsps": ["rtsp://192.168.169.1/stream.mp4",
"rtsp://192.168.169.1/stream1.mp4"]
"page": 1,
"rectime": 1
}
}
| 参数名 | 类型 | 描述 |
|---|---|---|
| rtsp | string | 用来播放RTSP 的地址 |
| transport | string | RTSP 的传输协议,“tcp” 、“udp” |
| port | int | 推送消息设备端的tcp socket server 的监听端口 |
| rtsps | array | 非必选;多路设备,当各路播流地址不同时,通过此字段返回每一路的播流地址 |
| page | int | 非必选;App 默认一次性查询所有文件,如果设备支持分页查询,此字段返回1 |
| rectime | int | 非必选;支持通过getrecduration 接口查询当前录像时间 |
技术细节
- HTTP请求流程

- 录风者app应注意V821wifi配成AP模式且IP要固定为:192.168.169.1
因为app那边的http请求的IP都是192.168.169.1
修改固定IP
源文件路径:
tina-v821-release\platform\allwinner\wireless\wifimanager\demo\wifi_test_tool\wifi_daemon.c
static wmg_status_t open_ap_mode(char *p)
- 以ap模式开启WiFi(V821 SDK默认是以station模式开启的WiFi)
wifi -o ap v821 12345678
- 基于thttpd实现设备端的HTTP server
关于在全志V821上如何安装thttpd前文《全志V821对接录风者app》中已经有详细描述,这边不再赘述,这边只阐述基于thttpd实现目标功能。
下面以伪代码形式描述基本流程
//注册用户操作回调函数
app_ezCam_http_property_json_info_reg(app_ezCam_http_get_property, app_ezCam_http_set_property);
//thttpd_start_main 和 app_viidure_service_reg_distriblink需要自己在thttpd的源码中改造
//(附件资源包中已经有改造好的源码欢迎大家下载使用)。
//注册http请求调度器
app_viidure_service_reg_distriblink(app_viidure_msg_dispatcher);
//启动thttpd服务
pthread_create(&g_webserver_pid, NULL, thttpd_start_main, args);
- 以http://192.168.169.1/app/getproductinfo请求为例,主要实现函数如下
void app_ezCam_http_get_property(char *devPropCode, void *data)
{
EZ_U32 i,ret;
if(strcmp(devPropCode, EZCAM_CGI_GET_DEVICE_ATTR) == 0) {
EZ_U32 *dat = (EZ_U32 *)data;
EZCAM_HTTP_DBG("data[0]: %d\n",dat[0]);
if(dat[0] == DEV_GET_UUID) {
memcpy(dat,WIFI_DEV_UUID,strlen(WIFI_DEV_UUID));
dat[strlen(WIFI_DEV_UUID)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_UUID));
}
else if(dat[0] == DEV_GET_SOFT_VER) {
memcpy(dat,WIFI_DEV_SOFT_VER,strlen(WIFI_DEV_SOFT_VER));
dat[strlen(WIFI_DEV_SOFT_VER)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_SOFT_VER));
}
else if(dat[0] == DEV_GET_OTA_VER) {
memcpy(dat,WIFI_DEV_OTA_VER,strlen(WIFI_DEV_OTA_VER));
dat[strlen(WIFI_DEV_OTA_VER)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_OTA_VER));
}
else if(dat[0] == DEV_GET_HW_VER) {
memcpy(dat,WIFI_DEV_HW_VER,strlen(WIFI_DEV_HW_VER));
dat[strlen(WIFI_DEV_HW_VER)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_HW_VER));
}
else if(dat[0] == DEV_GET_SSID) {
memcpy(dat,WIFI_DEV_SSID,strlen(WIFI_DEV_SSID));
dat[strlen(WIFI_DEV_SSID)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_SSID));
}
else if(dat[0] == DEV_GET_BSSID) {
memcpy(dat,WIFI_DEV_BSSID,strlen(WIFI_DEV_BSSID));
dat[strlen(WIFI_DEV_BSSID)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_BSSID));
}
else if(dat[0] == DEV_GET_CAM_NUM) {
*dat = WIFI_DEV_CAM_NUM;
}
else if(dat[0] == DEV_GET_CUR_CAM_ID) {
*dat = WIFI_DEV_CUR_CAM_ID;
}
else if(dat[0] == DEV_GET_WIFI_REBOOT) {
*dat = WIFI_DEV_WIFI_REBOOT;
}
}
else if(strcmp(devPropCode, EZCAM_CGI_CAPABILITY) == 0) {
EZ_U32 *dat = (EZ_U32 *)data;
EZCAM_HTTP_DBG("data[0]: %d\n",dat[0]);
/* capability_t. */
if(dat[0] == CAPABILITY_OPTION_GPS) {
*dat = 0;
}
else if(dat[0] == CAPABILITY_OPTION_CAMERA_TYPE) {
*dat = 1;
}
else if(dat[0] == CAPABILITY_OPTION_PARK_MONITOR) {
*dat = 0;
}
else if(dat[0] == CAPABILITY_OPTION_FILE_LOCK) {
*dat = 1;
}
else if(dat[0] == CAPABILITY_OPTION_DEL_LOCK_FILE) {
*dat = 0;
}
else if(dat[0] == CAPABILITY_OPTION_SUPPORT_CAP_MODE) {
*dat = 0;
}
else if(dat[0] == CAPABILITY_OPTION_PB_USE_RTSP) {
*dat = 0;
}
else if(dat[0] == CAPABILITY_OPTION_SUPPORT_CAP_FUNCTION) {
*dat = 0;
}
else if(dat[0] == CAPABILITY_OPTION_SUPPORT_CHANGE_WIFI_NAME_PWD) {
*dat = 0;
}
else if(dat[0] == CAPABILITY_OPTION_SUPPORT_FILE_COPY) {
*dat = 0;
}
}
else if(strcmp(devPropCode, EZCAM_CGI_GET_PRODUCT_INFO) == 0) {
EZ_U32 *dat = (EZ_U32 *)data;
EZCAM_HTTP_DBG("data[0]: %d\n",dat[0]);
/* PRODUCT_MODEL */
if(dat[0] == PRODUCT_MODEL) {
memcpy(dat,WIFI_DEV_PRODUCT_MODEL,strlen(WIFI_DEV_PRODUCT_MODEL));
dat[strlen(WIFI_DEV_PRODUCT_MODEL)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_PRODUCT_MODEL));
}
/* PRODUCT_COMPANY */
else if(dat[0] == PRODUCT_COMPANY) {
memcpy(dat,WIFI_DEV_PRODUCT_COMPANY,strlen(WIFI_DEV_PRODUCT_COMPANY));
dat[strlen(WIFI_DEV_PRODUCT_COMPANY)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_PRODUCT_COMPANY));
}
/* PRODUCT_SOC */
else if(dat[0] == PRODUCT_SOC) {
memcpy(dat,WIFI_DEV_PRODUCT_SOC,strlen(WIFI_DEV_PRODUCT_SOC));
dat[strlen(WIFI_DEV_PRODUCT_SOC)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_PRODUCT_SOC));
}
/* PRODUCT_SP */
else if(dat[0] == PRODUCT_SP) {
memcpy(dat,WIFI_DEV_PRODUCT_SP,strlen(WIFI_DEV_PRODUCT_SP));
dat[strlen(WIFI_DEV_PRODUCT_SP)] = '\0';
EZCAM_HTTP_DBG("data => %s/%d\n",dat,strlen(WIFI_DEV_PRODUCT_SP));
}
}
else if(strcmp(devPropCode, EZCAM_CGI_GET_MEDIA_INFO) == 0) {
EZ_U32 *dat = (EZ_U32 *)data;
EZCAM_HTTP_DBG("data[0]: %d\n",dat[0]);
/* RTSP_URL */
if(dat[0] == MEDIA_INFO_RTSP_URL) {
memcpy(dat,WIFI_DEV_MEDIA_INFO_RTSP_URL,strlen(WIFI_DEV_MEDIA_INFO_RTSP_URL));
}
/* TRANSPORT */
else if(dat[0] == MEDIA_INFO_TRANSPORT) {
memcpy(dat,WIFI_DEV_MEDIA_INFO_TRANSPORT,strlen(WIFI_DEV_MEDIA_INFO_TRANSPORT));
}
/* PORT */
else if(dat[0] == MEDIA_INFO_PORT) {
memcpy(dat,WIFI_DEV_MEDIA_INFO_PORT,strlen(WIFI_DEV_MEDIA_INFO_PORT));
}
}
}
static void ezCam_http_json_get_productInfo(char *jsonStr)
{
int dev_product_info[32];
cJSON *cgiItem = cJSON_CreateObject();
cJSON *cgiAddItem = cJSON_CreateObject();
cJSON_AddNumberToObject(cgiItem,"result",0);
/* model */
memset(dev_product_info,0x0,sizeof(dev_product_info));
dev_product_info[0] = PRODUCT_MODEL;
fp_json_httpdGetCamProperty((char *)EZCAM_CGI_GET_PRODUCT_INFO,(int *)dev_product_info);
cJSON_AddStringToObject(cgiAddItem,"model",(char *)dev_product_info);
/* company */
memset(dev_product_info,0x0,sizeof(dev_product_info));
dev_product_info[0] = PRODUCT_COMPANY;
fp_json_httpdGetCamProperty((char *)EZCAM_CGI_GET_PRODUCT_INFO,(int *)dev_product_info);
cJSON_AddStringToObject(cgiAddItem,"company",(char *)dev_product_info);
/* soc */
memset(dev_product_info,0x0,sizeof(dev_product_info));
dev_product_info[0] = PRODUCT_SOC;
fp_json_httpdGetCamProperty((char *)EZCAM_CGI_GET_PRODUCT_INFO,(int *)dev_product_info);
cJSON_AddStringToObject(cgiAddItem,"soc",(char *)dev_product_info);
/* sp */
memset(dev_product_info,0x0,sizeof(dev_product_info));
dev_product_info[0] = PRODUCT_SP;
fp_json_httpdGetCamProperty((char *)EZCAM_CGI_GET_PRODUCT_INFO,(int *)dev_product_info);
cJSON_AddStringToObject(cgiAddItem,"sp",(char *)dev_product_info);
cJSON_AddItemToObject(cgiItem,"info",cgiAddItem);
char *json_data = cJSON_Print(cgiItem);
if(json_data == NULL){
EZCAM_HTTP_DBG("json print malloc error");
}
memcpy(jsonStr,json_data,strlen(json_data));
jsonStr[strlen(json_data)] = '\0';
cJSON_Delete(cgiItem);
free(json_data);
}
EZ_S32 app_ezCam_http_get_productInfo(EZ_S32 socket, EZ_CHAR *request, EZ_U32 req_len)
{
int ret = EZ_SUCCESS;
EZ_S32 body_len = 0, head_len = 0;
char *json_data;
EZ_CHAR *buf;
EZCAM_HTTP_DBG("%s %d S\n",__FUNCTION__,__LINE__);
json_data = malloc(JSON_DATA_BUFFER);
if(json_data == NULL){
EZCAM_HTTP_DBG("json_data malloc error");
}
buf = malloc(HTTP_RESPONSE_BUF);
if(buf == NULL){
EZCAM_HTTP_DBG("buf malloc error");
}
ezCam_http_json_get_productInfo(json_data);
if(strlen(json_data) >= JSON_DATA_BUFFER - 1){
EZCAM_HTTP_DBG("Array out of bounds, please increase the size of JSON_DATA_BUFFER \n");
}
body_len = strlen(json_data);
head_len = app_ezCam_package_http_header(buf, body_len, 200, TRUE);
if (body_len > 0)
memcpy(buf + head_len, json_data, body_len);
EZCAM_HTTP_DBG("http response: \n %s \n", buf);
if (app_ezCam_send_data(socket, buf, strlen(buf)) != strlen(buf)) {
EZCAM_HTTP_DBG("xcam_send_data() failed\n");
return EZ_FAILURE;
}
if(json_data != NULL){
free(json_data);
json_data = NULL;
}
if(buf != NULL){
free(buf);
buf = NULL;
}
EZCAM_HTTP_DBG("%s %d E\n",__FUNCTION__,__LINE__);
return ret;
}
HTTP请求测试方法:手机/电脑连接v821wifi打开网页输入请求指令
http://192.168.169.1/app/getproductinfo
得到如下反馈,代表基于thttpd的HTTP Server实现正常

其它两条请求类似添加,添加成功后手机端安装《录风者》APP。连接设备WiFi,打开APP应能正常出图,至此我们就成功实现了关键指令的对接。

其它诸如设置项管理,文件管理(在线回放/下载设备端视频)的功能大家有兴趣可以自己完善。
后续我也会慢慢完善到我们的ezCam上
小结
1.录风者APP是公版免费的且兼容多平台,可以助力我们快速完成自己的项目。
2.请期待下期,接入大模型
更多推荐



所有评论(0)