這篇文章主要介紹Linux下UVC免驅攝像頭操作流程,介紹V4L2框架、完成攝像頭拍照保存為BMP圖像到本地,最后貼出了利用CJSON庫解析天氣預報、北京時間接口返回的數據例子代碼(上篇文章的案例補充)。
任務1:攝像頭操作方式
(1)攝像頭框架介紹
Linux、windows這些系統下很多攝像頭都是免驅(UVC)。
v4l2 :免驅攝像頭框架----一堆結構體。
Linux下開發攝像頭的不同角度問題:(嵌入式開發)
【1】上層軟件系統開發(系統編程),控制驅動提供的接口使用攝像頭。
【2】底層硬件系統開發(驅動編程),直接控制攝像頭采集數據。
攝像頭功能:將采集到的圖像數據轉為二進制數據返回。
驅動的代碼集成在操作系統里。
在操作系統里使用攝像頭步驟:學習接口函數的調用。
fread(); read();
Linux下是一切設備皆文件: 攝像頭、網卡、聲卡、鼠標、鍵盤………………….
Linux下設備文件存放的位置: /dev目錄下。
在虛擬機跑Linux,使用外設設備都需要單獨掛載才可以使用。
掛載攝像頭:
查看攝像頭的設備節點:
[root@wbyq /]# ls /dev/video*
/dev/video0 /dev/video1
(2)運行網頁監控項目代碼
遠程網頁視頻監控示例
第一步:編譯libjpeg-turbo
?
1. 解壓:libjpeg-turbo-1.2.1.tar.gz
?
2. 生成Makefile(如果報錯,就安裝報錯提示安裝包):./configure
?
3. 編譯安裝:make && make install
?
4. 將生成lib和include目錄下的文件拷貝到/usr目錄下的對應文件夾
?
第二步:編譯mjpg-streamer-r63
?
1.直接make進行編譯
?
2.運行程序:./mjpg_streamer -i "/work/mjpeg/mjpg-streamer-r63/input_uvc.so -f 10 -r 800*480 -y" -o "/work/mjpeg/mjpg-streamer-r63/output_http.so -w www"
?
注意: 可以使用電腦自帶的攝像頭。在虛擬機的右下角進行將windows系統的攝像頭掛載到Linux系統
?
3. 在瀏覽器里輸入地址進行查看攝像頭:
?
例如:192.168.11.123:8080
復制代碼
將遠程攝像頭監控的代碼編譯運行實現效果。
(1) 修改端口號,8080不能作為公網的端口訪問。
(2) 修改線程數量。
(3) 分析下線程的函數實現原理。
(4) 使用花生殼軟件實現公網監控。
花生殼: 將本地IP地址映射為一個域名。
外網想要訪問本地電腦IP就直接訪問域名。
(3)攝像頭編程,實現拍照功能
學習攝像頭的使用
(1)攝像頭實現拍照源程序流程:(50%程序學過的)
(2)打開攝像頭的設備文件 open(“/dev/xxx”);
(3)獲取攝像頭參數。判斷攝像頭是否支持一些特有的操作。read
(4)配置攝像頭的參數。(1) 輸出的源數據格式RGB888 (2) 輸出的圖像尺寸
RGB888:數字數據格式
其他格式: YUV 模擬數據格式
(5)判斷攝像頭的參數是否設置成功。
(6)讀取攝像頭的數據。 隊列的形式。
(7)將讀取的YUV格式數據轉為RGB格式
(8)將RGB格式數據編碼為BMP格式的圖片存放到電腦上
安裝rpm軟件包:rpm -ivh xxxxx.rpm
Linux下安裝軟件有兩種方式:
【1】rpm軟件安裝包(已經編譯好的二進制文件的集合),使用rpm -ivh xxx.rpm
【2】直接下載源碼包自己編譯安裝。libjpeg-turbo-1.2.1.tar.gz
(1) 沒有makefile文件,就有: configure文件,用來生成makefile文件
示例: ./configure
(2) make 編譯源碼
(3) make install 安裝源碼。(會將編譯好的文件拷貝到指定的目錄下)
void *memset(void *s, int c, size_t count) //給指定地址的空間填入指定大小的數據
參數:
*s :起始地址
c :填入的數據
count :填入的數量
RGB888 : 000 FFF
復制代碼
攝像頭拍照示例代碼:
#include "camera_bmp.h"
?
T_PixelDatas Pixedata; //存放實際的圖像數據
?
/*
USB攝像頭相關參數定義
*/
struct v4l2_buffer tV4l2Buf;
int iFd;
int ListNum;
unsigned char* pucVideBuf[4]; // 視頻BUFF空間地址
?
int main(int argc ,char *argv[])
{
if(argc!=2)
{
printf("./app /dev/videoX\n");
return -1;
}
camera_init(argv[1]); //攝像頭設備初始化
?
//開始采集攝像頭數據,并編碼保存為BMP圖片
camera_pthread();
return 0;
}
?
?
//YUV轉RGB實現
unsigned int Pyuv422torgb32(unsigned char * ptr,unsigned int width, unsigned int height)
{
unsigned int i, size;
unsigned char Y, Y1, U, V;
unsigned char *buff = ptr; //源數據
unsigned char *output_pt=Pixedata.VideoBuf; //存放轉換之后的數據
unsigned char r, g, b;
size = width * height /2;
for (i = size; i > 0; i--)
{
Y = buff[0];
U = buff[1];
Y1= buff[2];
V = buff[3];
buff += 4;
r = R_FROMYV(Y,V);
g = G_FROMYUV(Y,U,V); //b
b = B_FROMYU(Y,U); //v
*output_pt++ = b;
*output_pt++ = g;
*output_pt++ = r;
r = R_FROMYV(Y1,V);
g = G_FROMYUV(Y1,U,V); //b
b = B_FROMYU(Y1,U); //v
*output_pt++ = b;
*output_pt++ = g;
*output_pt++ = r;
}
return 0;
}
?
//攝像頭設備的初始化
int camera_init(char *video)
{
int i=0;
int cnt=0;
//定義攝像頭驅動的BUF的功能捕獲視頻
int iType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
/* 1、打開視頻設備 */
iFd = open(video,O_RDWR);
if(iFd < 0)
? {
? printf("攝像頭設備打開失敗!\n");
? return 0;
? }
?
? struct v4l2_format ?tV4l2Fmt;
?
? /* 2、 VIDIOC_S_FMT 設置攝像頭使用哪種格式 */
? memset(&tV4l2Fmt, 0, sizeof(struct v4l2_format));
? tV4l2Fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //視頻捕獲
??
? //設置攝像頭輸出的圖像格式
? ? ?tV4l2Fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
??
? /*設置輸出的尺寸*/
? tV4l2Fmt.fmt.pix.width ? ? ? = 640;
? tV4l2Fmt.fmt.pix.height ? ? ?= 480;
? tV4l2Fmt.fmt.pix.field ? ? ? = V4L2_FIELD_ANY;
?
? ? ?//VIDIOC_S_FMT 設置攝像頭的輸出參數
? ? ?ioctl(iFd, VIDIOC_S_FMT, &tV4l2Fmt);
??
? //打印攝像頭實際的輸出參數
? printf("Support Format:%d\n",tV4l2Fmt.fmt.pix.pixelformat);
? printf("Support width:%d\n",tV4l2Fmt.fmt.pix.width);
? printf("Support height:%d\n",tV4l2Fmt.fmt.pix.height);
??
? /* 初始化Pixedata結構體,為轉化做準備 */
? Pixedata.iBpp =24;
? //高度 和寬度的賦值
? Pixedata.iHeight = tV4l2Fmt.fmt.pix.height;
? Pixedata.iWidth = tV4l2Fmt.fmt.pix.width;
??
? //一行所需要的字節數
? Pixedata.iLineBytes = Pixedata.iWidth*Pixedata.iBpp/8;
? //一幀圖像的字節數
? Pixedata.iTotalBytes = Pixedata.iLineBytes * Pixedata.iHeight;
? Pixedata.VideoBuf=malloc(Pixedata.iTotalBytes); //申請存放圖片數據空間
??
? //v412請求命令
? struct v4l2_requestbuffers tV4l2ReqBuffs;
?
? /* 3、VIDIOC_REQBUFS 申請buffer */
? memset(&tV4l2ReqBuffs, 0, sizeof(struct v4l2_requestbuffers));
??
? /* 分配4個buffer:實際上由VIDIOC_REQBUFS獲取到的信息來決定 */
? tV4l2ReqBuffs.count ? = 4;
?
? /*支持視頻捕獲功能*/
? tV4l2ReqBuffs.type ? ?= V4L2_BUF_TYPE_VIDEO_CAPTURE;
?
? /* 表示申請的緩沖是支持MMAP */
? tV4l2ReqBuffs.memory ?= V4L2_MEMORY_MMAP;
?
? /* 為分配buffer做準備 */
? ioctl(iFd, VIDIOC_REQBUFS, &tV4l2ReqBuffs);
?
? for (i = 0; i < tV4l2ReqBuffs.count; i++)
? {
? memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
? tV4l2Buf.index = i;
? tV4l2Buf.type ? = V4L2_BUF_TYPE_VIDEO_CAPTURE;
? tV4l2Buf.memory = V4L2_MEMORY_MMAP;
??
? /* 6、VIDIOC_QUERYBUF 確定每一個buffer的信息 并且 mmap */
? ioctl(iFd, VIDIOC_QUERYBUF, &tV4l2Buf);
? //映射空間地址
? pucVideBuf[i] = mmap(0 /* start anywhere */ ,
? ?tV4l2Buf.length, PROT_READ, MAP_SHARED, iFd,
? ?tV4l2Buf.m.offset);
? printf("mmap %d addr:%p\n",i,pucVideBuf[i]);
? }
??
? /* 4、VIDIOC_QBUF 放入隊列*/
? ? ?for (i = 0; i 在LCD上顯示:rgb888 */
? initLut();
? printf("開始采集數據.......\n");
? FD_ZERO(&readfds);
? FD_SET(iFd,&readfds);
? select(iFd+1,&readfds,NULL,NULL,NULL);
? ?
? memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
? tV4l2Buf.type ? ?= V4L2_BUF_TYPE_VIDEO_CAPTURE; //類型
? tV4l2Buf.memory ?= V4L2_MEMORY_MMAP; //存儲空間類型
??
? /* 9、VIDIOC_DQBUF ? 從隊列中取出 */
? error = ioctl(iFd, VIDIOC_DQBUF, &tV4l2Buf); //取出一幀數據
? ListNum = tV4l2Buf.index; //索引編號
?
? //將YUV轉換為RGB
? Pyuv422torgb32(pucVideBuf[ListNum],Pixedata.iWidth,Pixedata.iHeight);
?
? //保存BMP
? save_bmp(Pixedata.VideoBuf);
? memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
? tV4l2Buf.index ?= ListNum;
? tV4l2Buf.type ? = V4L2_BUF_TYPE_VIDEO_CAPTURE;
? tV4l2Buf.memory = V4L2_MEMORY_MMAP;
? error = ioctl(iFd, VIDIOC_QBUF, &tV4l2Buf);
?}
??
??
?/*-----------------保存為BMP格式的圖片------------------*/
?typedef unsigned char ?BYTE;
?typedef unsigned short WORD;
?typedef unsigned long ?DWORD;
??
?#pragma pack(1)
?typedef struct tagBITMAPFILEHEADER{
? ? ? WORD ?bfType; ? ? ? ? ? ? ? ?// the flag of bmp, value is "BM"
? ? ? DWORD ? ?bfSize; ? ? ? ? ? ? ? ?// size BMP file ,unit is bytes
? ? ? DWORD ? ?bfReserved; ? ? ? ? ? ?// 0
? ? ? DWORD ? ?bfOffBits; ? ? ? ? ? ? // must be 54 RGB數據存放位置
?}BITMAPFILEHEADER;
??
?typedef struct tagBITMAPINFOHEADER{
? ? ? DWORD ? ?biSize; ? ? ? ? ? ?// must be 0x28
? ? ? DWORD ? ?biWidth; ? ? ? ? ? // 寬度
? ? ? DWORD ? ?biHeight; ? ? ? ? ?// 高度
? ? ? WORD ? ? biPlanes; ? ? ? ? ?// must be 1
? ? ? WORD ?biBitCount; ? ? ? ? ? ?// 像素位數
? ? ? DWORD ? ?biCompression; ? ? ? ? //
? ? ? DWORD ? ?biSizeImage; ? ? ? //
? ? ? DWORD ? ?biXPelsPerMeter; ? //
? ? ? DWORD ? ?biYPelsPerMeter; ? //
? ? ? DWORD ? ?biClrUsed; ? ? ? ? ? ? //
? ? ? DWORD ? ?biClrImportant; ? ? ? ?//
?}BITMAPINFOHEADER;
??
??
?//保存為BMP格式的文件
?void save_bmp(char *src)
?{
? /*-----------------------------------------------------------
? 獲取時間參數,用來給圖片命名
? -------------------------------------------------------------*/
? time_t t;
? ? ?struct tm *tmp;
? ? ?char buffer[1024] = {0};
? ? ?t = time(NULL);
? ? ?tmp=localtime(&t);
? ? ?if(strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S_", tmp) == 0)
? ? {
? ? printf("timer error\n");
? ? }
?
? static int cnt=0; ? ? ?//靜態變量存放總數量
? cnt++;
? if(cnt>=20)cnt=0; //清理計數器
char str[10];
sprintf(str,"%d",cnt); //整數轉為字符串
strcat(buffer,str);
strcat(buffer,".bmp");
printf("%s\n",buffer); //打印圖片的名稱
/*-----------------------------------------------------------
獲取圖片數據,用來保存為BMP圖片格式
-------------------------------------------------------------*/
FILE * fp;
int i;
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
memset(&bf ,0 ,sizeof(BITMAPFILEHEADER));
memset(&bi ,0 ,sizeof(BITMAPINFOHEADER));
?
fp = fopen(buffer, "wb");
if(!fp)
{
printf("open %s error\n",buffer);
return ;
}
?
//Set BITMAPINFOHEADER 設置BMP信息頭
bi.biSize = sizeof(BITMAPINFOHEADER);//40;
bi.biWidth = Pixedata.iWidth;//IMAGEWIDTH;
bi.biHeight = Pixedata.iHeight;//IMAGEHEIGHT;
bi.biPlanes = 1;
bi.biBitCount = 24;//8;
bi.biCompression = 0;
bi.biSizeImage =Pixedata.iHeight*Pixedata.iWidth*3; //;0
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;// 1<<(bi.biBitCount)
? bi.biClrImportant = 0;
??
? ? ?//Set BITMAPFILEHEADER
? ? ?bf.bfType = 0x4d42; //'B''M'
? ? ?bf.bfSize = 54 + bi.biSizeImage;// sizeof(BITMAPFILEHEADER); ? ?
? ? ?bf.bfReserved = 0;
? ? ?bf.bfOffBits = 54;
? ? ? ?
? ? ?fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, fp);
? ? ?fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, fp); ? ?
? ? ?fwrite(src, Pixedata.iWidth*Pixedata.iHeight*3,1,fp);
? ? ?fclose(fp);
?}
??
?/*----------------------YUV轉RGB算法-------------------*/
??
?static int *LutYr = NULL;
?static int *LutYg = NULL;;
?static int *LutYb = NULL;;
?static int *LutVr = NULL;;
?static int *LutVrY = NULL;;
?static int *LutUb = NULL;;
?static int *LutUbY = NULL;;
?static int *LutRv = NULL;
?static int *LutGu = NULL;
?static int *LutGv = NULL;
?static int *LutBu = NULL;
??
??
?unsigned char RGB24_TO_Y(unsigned char r, unsigned char g, unsigned char b)
?{
? return (LutYr[(r)] + LutYg[(g)] + LutYb[(b)]);
?}
??
?unsigned char YR_TO_V(unsigned char r, unsigned char y)
?{
? return (LutVr[(r)] + LutVrY[(y)]);
?}
??
?unsigned char YB_TO_U(unsigned char b, unsigned char y)
?{
? return (LutUb[(b)] + LutUbY[(y)]);
?}
??
?unsigned char R_FROMYV(unsigned char y, unsigned char v)
?{
? return CLIP((y) + LutRv[(v)]);
?}
??
?unsigned char G_FROMYUV(unsigned char y, unsigned char u, unsigned char v)
?{
? return CLIP((y) + LutGu[(u)] + LutGv[(v)]);
?}
??
?unsigned char B_FROMYU(unsigned char y, unsigned char u)
?{
? return CLIP((y) + LutBu[(u)]);
?}
??
?void initLut(void)
?{
? int i;
? #define Rcoef 299
? #define Gcoef 587
? #define Bcoef 114
? #define Vrcoef 711 //656 //877
? #define Ubcoef 560 //500 //493 564
?
? #define CoefRv 1402
? #define CoefGu 714 // 344
? #define CoefGv 344 // 714
? #define CoefBu 1772
?
? LutYr = malloc(256*sizeof(int));
? LutYg = malloc(256*sizeof(int));
? LutYb = malloc(256*sizeof(int));
? LutVr = malloc(256*sizeof(int));
? LutVrY = malloc(256*sizeof(int));
? LutUb = malloc(256*sizeof(int));
? LutUbY = malloc(256*sizeof(int));
?
? LutRv = malloc(256*sizeof(int));
? LutGu = malloc(256*sizeof(int));
? LutGv = malloc(256*sizeof(int));
? LutBu = malloc(256*sizeof(int));
? for (i= 0;i < 256;i++)
? {
? ? ?LutYr[i] = i*Rcoef/1000 ;
? ? ?LutYg[i] = i*Gcoef/1000 ;
? ? ?LutYb[i] = i*Bcoef/1000 ;
? ? ?LutVr[i] = i*Vrcoef/1000;
? ? ?LutUb[i] = i*Ubcoef/1000;
? ? ?LutVrY[i] = 128 -(i*Vrcoef/1000);
? ? ?LutUbY[i] = 128 -(i*Ubcoef/1000);
? ? ?LutRv[i] = (i-128)*CoefRv/1000;
? ? ?LutBu[i] = (i-128)*CoefBu/1000;
? ? ?LutGu[i] = (128-i)*CoefGu/1000;
? ? ?LutGv[i] = (128-i)*CoefGv/1000;
? }
?}
??
??
?void freeLut(void)
?{
? free(LutYr);
? free(LutYg);
? free(LutYb);
? free(LutVr);
? free(LutVrY);
? free(LutUb);
? free(LutUbY);
?
? free(LutRv);
? free(LutGu);
? free(LutGv);
? free(LutBu);
?}
復制代碼;>
(4)解析北京時間
#include
#include
#include
#include "cJSON.h"
#include
#include
#include
?
/*
標準時間運行格式: ./app
*/
int GetData(char *src);
int main(int argc,char **argv)
{
/*1. 拼接訪問的鏈接路徑*/
char src[200];
char str[]="http://api.k780.com:88/?app=life.time'&'appkey=10003'&'sign=b59bc3ef6191eb9f747dd4e83c99f2a4'&'format=json >data.txt";
strcpy(src,"curl ");
strcat(src,str);
system(src); //執行瀏覽器數據
/*2. 讀取源數據*/
FILE *file=fopen("data.txt","rb");
if(file==NULL)
{
printf("文件打開失敗!\n");
exit(-1);
}
struct stat file_stat_buf;
stat("data.txt",&file_stat_buf); //獲取文件的狀態
char *src_data=malloc(file_stat_buf.st_size);
if(src_data==NULL)
{
printf("%s文件第%d行,出現錯誤:空間失敗!\n",__FILE__,__LINE__);
exit(-1);
}
fread(src_data,1,file_stat_buf.st_size,file); //讀取源數據到緩沖區
/*3. 數據解析*/
GetData(src_data);
/*4. 釋放空間*/
free(src_data);
return 0;
}
?
/*
函數功能:獲取具體的數據
函數形參:保存json的源數據首地址
*/
int GetData(char *src)
{
/*1. 載入源數據,獲取根對象*/
cJSON *root=cJSON_Parse(src);
if(root==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取根對象失敗!\n",__FILE__,__LINE__);
return -1;
}
/*2. 獲取對象中的值*/
cJSON *json=cJSON_GetObjectItem(root,"success");
if(json==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
//判斷獲取的值是否成功
if(strcmp(json->valuestring,"1")!=0)
{
printf("%s文件第%d行,出現錯誤:時間獲取失敗!\n",__FILE__,__LINE__);
return -1;
}
//獲取結果
json=cJSON_GetObjectItem(root,"result");
if(json==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
//獲取秒單位時間
cJSON *data=cJSON_GetObjectItem(json,"timestamp");
if(data==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
printf("秒單位的時間:%s\n",data->valuestring);
data=cJSON_GetObjectItem(json,"datetime_1");
if(data==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
printf("datetime_1:%s\n",data->valuestring);
data=cJSON_GetObjectItem(json,"datetime_2");
if(data==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
printf("datetime_2:%s\n",data->valuestring);
data=cJSON_GetObjectItem(json,"week_1");
if(data==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
printf("week_1:%s\n",data->valuestring);
data=cJSON_GetObjectItem(json,"week_2");
if(data==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
printf("week_2:%s\n",data->valuestring);
data=cJSON_GetObjectItem(json,"week_3");
if(data==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
printf("week_3:%s\n",data->valuestring);
data=cJSON_GetObjectItem(json,"week_4");
if(data==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
printf("week_4:%s\n",data->valuestring);
/* */
cJSON_Delete(root);
}
復制代碼
(5)解析天氣預報
#include
#include
#include
#include "cJSON.h"
#include
#include
#include
?
/*
標準時間運行格式: ./app
*/
int GetData(char *src);
int main(int argc,char **argv)
{
if(argc!=2)
{
printf("參數格式: ./app <城市名稱>\n");
return 0;
}
/*1. 拼接訪問的鏈接路徑*/
char src[200];
char str1[]="http://api.k780.com:88/?app=weather.future'&'weaid=";
char str2[]="'&&'appkey=10003'&'sign=b59bc3ef6191eb9f747dd4e83c99f2a4'&'format=json >data.txt";
strcpy(src,"curl ");
strcat(src,str1);
strcat(src,argv[1]);
strcat(src,str2);
system(src); //執行瀏覽器數據
/*2. 讀取源數據*/
FILE *file=fopen("data.txt","rb");
if(file==NULL)
{
printf("文件打開失敗!\n");
exit(-1);
}
struct stat file_stat_buf;
stat("data.txt",&file_stat_buf); //獲取文件的狀態
char *src_data=malloc(file_stat_buf.st_size);
if(src_data==NULL)
{
printf("%s文件第%d行,出現錯誤:空間失敗!\n",__FILE__,__LINE__);
exit(-1);
}
fread(src_data,1,file_stat_buf.st_size,file); //讀取源數據到緩沖區
/*3. 數據解析*/
GetData(src_data);
/*4. 釋放空間*/
free(src_data);
return 0;
}
?
/*
函數功能:獲取具體的數據
函數形參:保存json的源數據首地址
*/
int GetData(char *src)
{
/*1. 載入源數據,獲取根對象*/
cJSON *root=cJSON_Parse(src);
if(root==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取根對象失敗!\n",__FILE__,__LINE__);
return -1;
}
/*2. 獲取對象中的值*/
cJSON *json=cJSON_GetObjectItem(root,"success");
if(json==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
//判斷獲取的值是否成功
if(strcmp(json->valuestring,"1")!=0)
{
printf("%s文件第%d行,出現錯誤:時間獲取失敗!\n",__FILE__,__LINE__);
return -1;
}
//獲取結果
json=cJSON_GetObjectItem(root,"result");
if(json==NULL)
{
printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
return -1;
}
?
//獲取數組大小
int cnt=cJSON_GetArraySize(json);
printf("cnt=%d\n",cnt);
int i;
for(i=0;ivaluestring);
p=cJSON_GetObjectItem(data,"days");
printf("days=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"week");
printf("week=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"cityno");
printf("cityno=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"citynm");
printf("citynm=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"cityid");
printf("cityid=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"temperature");
printf("temperature=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"humidity");
printf("humidity=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"weather");
printf("weather=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"wind");
printf("wind=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"winp");
printf("winp=%s\n",p->valuestring);
p=cJSON_GetObjectItem(data,"winp");
printf("winp=%s\n",p->valuestring);
printf("\n\n");
}
cJSON_Delete(root);
}
-
Linux
+關注
關注
87文章
11304瀏覽量
209483 -
攝像頭
+關注
關注
60文章
4841瀏覽量
95691 -
編程
+關注
關注
88文章
3615瀏覽量
93732
發布評論請先 登錄
相關推薦
評論