php onenet 设备 互联,手把手教你在OneNet上实现设备的批量创建

本帖最后由 shuxulala 于 2015-7-8 13:29 编辑

如题,为了方便大家实现批量设备的快速创建,在此教大家在设备终端上运用RestFul API实现设备的批量创建,下面来看看本次实验用到的设备终端,如下图,本次实验用到的是一款STM32F103的简易开发板,前段时间有坛友用过,该开发板提供USB(USB模拟串口)、以太网口、JTAG等接口。

104314og91xjshxkhchpwb.png

下面看看代码实现,本实例代码是在UCOSII下开发的,运用Lwip实现网络通信,由于代码比较多,这里只贴出主要流程代码,重点展示运用RestFul API实现平台设备批量创建的过程和原理,对于设备硬件设置和初始化、Lwip移植不做详细说明,首先看看几个重要的宏定义和变量:

#define DEV_NAME "My_Dev" //设备名

#define DEV_CNT 10 //要创建的设备数量

#define API_KEY "your ApiKey" //ApiKey

#define SERVER_ADDR "api.heclouds.com" //服务器地址

#define SERVER_PORT 80 //服务器端口号

unsigned int sys_timer = 0; //系统时间Tick

char send_buf[512]; //HTTP数据包存储buff

unsigned int dev_num = 0; //设备计数复制代码

入口函数:

int main(void)

{

CPU_INT08U os_err;

/* 禁止所有中断 */

CPU_IntDis();

/* ucosII 初始化 */

OSInit();

/* 硬件平台初始化 */

BSP_Init();

/*初始化ucosII时钟节拍*/

OS_CPU_SysTickInit();

/*初始化Lwip*/

lwip_init_task();

/*建立主任务,该任务执行函数为App_TaskStart */

os_err = OSTaskCreate((void (*)(void *)) App_TaskStart, //指向任务代码的指针

(void *) 0, //任务开始执行时,传递给任务的参数的指针

(OS_STK *) &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1],

(INT8U) 1); //分配给任务的优先级

OSTimeSet(0); //ucosII的节拍计数器清0 节拍计数器是0-4294967295

OSStart(); //启动ucosII内核

return 0;

}复制代码

主函数创建一个任务,该任务的执行入口函数为App_TaskStart,下面我们看该函数的实现:

void App_TaskStart(void* p_arg)

{

unsigned int count = 0;

/*创建新线程执行数据上传任务,线程的执行入口函数mkdev_demo*/

sys_thread_new("mkdev_demo", mkdev_demo, 0, 512, TCPIP_THREAD_PRIO + 1);

while(1)

{

/*use process_mac() to query netif packages*/

process_mac();

count++;

if(count % 10 == 0)

{

/*给其他任务留出执行时间*/

OSTimeDly(1);

}

}

}复制代码

App_TaskStart最主要的作用是新建了一个线程,该线程的执行入口为mkdev_demo函数,具体实现如下:

void mkdev_demo(void * arg)

{复制代码

int sockfd, ret;

EdpPacket* send_pkg;

/*初始化内存*/

uMEM_Init();

sys_timer = sys_now();

while(1)

{

/* 与服务器创建TCP连接 */

sockfd = Open(SERVER_ADDR, SERVER_PORT);

if(sockfd < 0)

{

Close(sockfd);

continue;

}

/*发送数据包和接收服务器响应*/

client_process_func(&sockfd);

Close(sockfd);

}复制代码

}

mkdev_demo首先初始化内存,和服务器创建TCP连接,最后调用client_process_func发送HTTP数据包并接收来自服务器的响应信息,client_process_func函数实现如下:

int client_process_func(void* arg)

{

int sockfd = *(int*)arg;

fd_set readset;

fd_set writeset;

int i, maxfdp1;

for(;;)

{

maxfdp1 = sockfd+1;

/*套节字集合清空 */

FD_ZERO(&readset);

FD_ZERO(&writeset);

/*加入读写套接字集合*/

FD_SET(sockfd, &readset);

FD_SET(sockfd, &writeset);

/*检测套接字是否可读可写*/

i = select(maxfdp1, &readset, &writeset, 0, 0);

/*套接字不可读不可写*/

if(i == 0)

continue;

/*检测sockfd是否在读套接字集合里面*/

if(FD_ISSET(sockfd, &readset))

{

/*如果可读,接收网络数据*/

if(recv_func(sockfd) < 0)

break;

}

/*如果socket 准备好可写,调用write_func函数发送数据到远程终端*/

if(FD_ISSET(sockfd, &writeset))

{

if(write_func(sockfd) < 0)

break;

}

}

return -1;

}复制代码

client_process_func函数实现socket的读写监听设置,当检测到有网络数据的时候调用recv_func接收数据,当检测到可以发送数据的时候调用write_func发送创建设备的数据包,write_func实现如下:

int write_func(int arg)

{

int sockfd = arg;

unsigned int now = sys_now();

int32 ret = 0;

char *pJson;

char tmp[50];

/*控制发送HTTP包间隔,如果检测到设备已经创建设备个数已经达到设置值,不再创建*/

if(now - sys_timer < 2000 && dev_num < DEV_CNT)

{

return 0;

}

if(dev_num < DEV_CNT)

{

sys_timer = now;

/*创建HTTP请求内容,即描述创建设备相关信息的JSON串*/

pJson = makeJson();

/*HTTP包头封装*/

send_buf[0] = 0;

strcat(send_buf,"POST /devices HTTP/1.1\r\n");

strcat(send_buf,"api-key:");

strcat(send_buf,API_KEY);

strcat(send_buf,"\r\n");

strcat(send_buf,"Host:");

strcat(send_buf,SERVER_ADDR);

strcat(send_buf,"\r\n");

sprintf(tmp,"Content-Length:%d\r\n\r\n", strlen(pJson));

strcat(send_buf,tmp);

strcat(send_buf,pJson);

/*释放产生JSON字符串所分配的内存*/

uMEM_Free(pJson);

/*发送数据包*/

ret = DoSend(sockfd, send_buf, strlen(send_buf));

/*创建设备计数*/

dev_num ++;

return ret;

}

}复制代码

函数write_func实现HTTP包的封装并发送,其中makeJson创建HTTP包中的HTTP请求内容,makeJson中主要调用JSON的C语言库函数进行数据封装:

char* makeJson(void)

{

cJSON * pJsonRoot = NULL;

char buff[50] = {0};

char * p = NULL;

cJSON * pSubJson = NULL;

/*创建JSON对象*/

pJsonRoot = cJSON_CreateObject();

if(NULL == pJsonRoot)

{

return NULL;

}

sprintf(buff, "%s%d", DEV_NAME,dev_num);

/*添加JSON对象中设备相关的描述信息,设备的名字*/

cJSON_AddStringToObject(pJsonRoot, "title", buff);

/*添加JSON对象中设备相关的描述信息,设备的描述信息*/

cJSON_AddStringToObject(pJsonRoot, "desc", "my device test");

/*JSON子对象*/

pSubJson = cJSON_CreateObject();

if(NULL == pSubJson)

{

cJSON_Delete(pJsonRoot);

return NULL;

}

/*添加设备的地图位置信息*/

cJSON_AddNumberToObject(pSubJson, "ele", 37000);

cJSON_AddNumberToObject(pSubJson, "lat", 17.609997);

cJSON_AddNumberToObject(pSubJson, "lon", 177.03403);

/*子对象添加到跟对象中*/

cJSON_AddItemToObject(pJsonRoot, "location", pSubJson);

/*设备的属性,私有设备*/

cJSON_AddBoolToObject(pJsonRoot, "private", 1);

/*添加设备的默认路由信息*/

cJSON_AddStringToObject(pJsonRoot, "route_to", "2113");

/*分配内存并输出JSON串到内存中*/

p = cJSON_Print(pJsonRoot);

if(NULL == p)

{

cJSON_Delete(pJsonRoot);

return NULL;

}

cJSON_Delete(pJsonRoot);

/*返回JSON字符串指针,该指针指向的内存需要在使用完JSON串后释放*/

return p;

}复制代码

makeJson函数实现HTTP请求内容的封装,封装后输出的信息格式类似于:

{

"title":"My_Dev0",//用户范围内唯一

"desc":"my device test",

"location":{//可选

"ele":370000,

"lat":17,

"lon":177

},复制代码

"private":true,

"route_to":"2113",//socket接口发送数据的默认路由地址(设备ID号)

}

recv_func函数主要作用是接收服务的响应信息:

int recv_func(int arg)

{

int sockfd = arg;

int n, rtn, error;

int ret = 0;

do

{

/*接收网络数据*/

n = Recv(sockfd, buffer, 512, 0);

if(n <= 0)

{

Printf("recv error, bytes: %d\n", n);

error = -1;

break;

}

/*打印网络数据*/

Printf("recv from server, bytes: %d\n", n);

Printf("*****return result******\n%s\n\n", buffer);

}

while(0);

return error;

}复制代码

以上就是在设备终端上运用RestFul API实现平台设备批量创建的全过程,将代码编译下载(借助JTAG)到设备终端,运行,可以在平台的设备管理页面查看设备的批量创建具体情况,例如,我们使用以上代码在平台相应账户下批量创建10个设备,设备管理界面显示如下:

115805c77f7j99q9q0qonn.png

可以看到,我们在平台的响应账户下创建了名为My_DevX的10个设备(X表示设备的创建序号0-9),设备批量创建成功。与之类似,运用RestFul API的其他接口可以实现设备资源的批量操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值