OneNET定位为PaaS服务,即在物联网应用和真实设备之间搭建高效、稳定、安全的应用平台:面向设备,适配多种网络环境和常见传输协议,提供各类硬件终端的快速接入方案和设备管理服务;面向应用层,提供丰富的API和数据分发能力以满足各类行业应用系统的开发需求,使物联网企业可以更加专注于自身应用的开发,而不用将工作重心放在设备接入层的环境搭建上,从而缩短物联网系统的形成周期,降低企业研发、运营和运维成本。
物联网是把生活中各种物品通过各种元器件,传感器等连接在一起的网络。这个网络具备观察性和可控性,我们可以通过这个网络知道其中各个物品的状态,同时可以控制他们。
物联网可以分为三层,感知层、网络层、应用层。其中感知层可以通过传感器,执行器等元器件与环境进行互动。网络层指起到数据存储于管理功能的那一部分,其可以把各种数据按照特定标准进行存储,便于应用层调取。应用层是用户与网络层的接口,一方面把数据以特定形式展现给用户,一方面存储用户的指令,以备感知层调用。
OneNET平台具备网络层和应用层的功能,它可以把Arduino传感器采集的数据存储在自己的服务器上,同时可以在设计应用的时候调用这些数据。
OneNET平台是中国移动开发的物联网平台,稳定性非常好,上手容易。
使用方法:
1)进入OneNET官网(“https://open.iot.10086.cn/”)注册账号
2)注册完成后在首页右上角点击「开发者中心」进入产品开发界面
小提示:零基础入,建议先别去网络上找找乱七八糟的文章学习,直接参考官方文档一步一步走就没那么多问题了。遇到实际问题后首先根据官方文档以及网上资料去解决。官方文档:【首页】-【服务与支持】- 【开发文档】- 【快速入门】
2.1 创建产品
进入产品开发界面后,选择左侧菜单栏中【全部产品】-【基础服务】。基础服务中有:
【多协议接入】-【HTTP】-【添加产品】
2.2 创建设备
创建产品后,点击左上角 【OneNet】 回到首页,单击进入产品 【HTTP】
OneNet上在项目下还有设备的概念,一个设备就相当于一块Arduino板。单击【设备列表】-【添加备】,在弹出的设备信息里可以随便填,对后面没有影响,唯一需要注意的是数据保密性这里,建议选择私有,如果选择公开,那后面你把这个项目发布的时候别人就能看的你的数据了。填完后单击添加即可完成创建。
选择【设备列表】-【添加设备】
【添加新设备】 - 设置设备名称、设备编号后,点击确认即可。
2.3 新建数据流
Arduino发送给OneNET平台的数据可能有很多种,比如温度,湿度,光照强度等等。我们需要在OneNET上建立「变量」来存储这些数据,在OneNET上我们把这种变量叫做“ 数据流 ”。单击【数据流模板】-【添加数据流模板】,填入数据流名称即可得到一个存储数据的数据流。
2.4 创建应用
有了数据之后,我们需要把数据以一种特定形式呈现出来,比如用一个温度计显示实时温度,以一个折线图显示一段时间的温度趋势。肩负展示数据功能的是“应用”,就像我们平时在手机的“应用商店”里下载的那种应用一样,上面会有图标,图片等等。我们依次单击选择【应用管理】-【添加应用】
设置应用相关信息:名称、logo等。
添加应用后,进入编辑应用界面如下:
参考资料
1.1 硬件
ESP8266-01S | Arduno Uno |
---|---|
VCC&EN | 3.3V |
GND | GND |
RX | TX (D1) |
TX | RX(D0) |
DHT11 | Arduno Uno |
---|---|
VCC | 3.3V /5V |
GND | GND |
OUT | D3 |
1.2 软件
Arduino 通过 ESP8266-01S 发送数据给 OneNet 平台的数据。ESP8266-01S 属于 安信可公司的产品,我们需要下载官网的安信可串口调试助手 查看返回的数据。
1.3 平台
OneNet服务器里有很多项目很多设备,具体把数据发到拿呢?
实际上OneNet平台对于发送过来的Json数据是有一定格式要求的,其中除了要传输的数据,还包含了设备ID、密匙,这样就可以保证数据发送到正确的设备。
在正式开始前,我们需要记录设备的ID和密匙。设备ID可通过单击【设备列表】可在设备前面看到设备ID、密匙,在APIKey这一列的就是密匙。
597420765
vutzlt=cl9B99vnsozQcKSRSkNs=
(进入【设备列表】- 【设备详情】路径添加APIKey)另外,还需要自家的WiFi账号与密码接入网络。
补充:按照前文的方法对 OneNet平台设置:创建产品(多协议接入 - edp)、创建设备、新建数据流(数据流的名称要与程序中的一致)、添加应用(注意开关控件的属性设置"switch:{V}")
2.1 ESP8266-01S AT指令手动联网
/***************************************************
*
* 名称:ESP8266 01S AT指令手动联网
* 作者:Naiva
* 日期:2020/05/17
* 接线:
* Arduino nano ESP8266 01S
* D2(RX) ——— TX
* D3(TX) ——— RX
* VCC(3.3) ——— VCC(&EN)
* GND ——— GND
*
****************************************************/
#include
SoftwareSerial mySerial(2,3);//RX ,TX wifiSerial
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial)
{
;
}
Serial.println("ok");
mySerial.begin(115200);
mySerial.println("ready");
}
void loop() {
// put your main code here, to run repeatedly:
if(mySerial.available())
Serial.write(mySerial.read());
if(Serial.available())
mySerial.write(Serial.read());
}
2.2 自动联网及接入设备
把AT指令写进程序让程序自动帮我们发送,并且链接到云平台,还要再实现设备和脚本的关联。
while (!doCmdOk("AT+CWMODE=3", "OK")); //工作模式
while (!doCmdOk("AT+CWJAP=\"CMCC-R6Qs\",\"qmt2fx3q\"", "OK"));//WiFi账号与WiFi密码
while (!doCmdOk("AT+CIPSTART=\"TCP\",\"jjfaedp.hedevice.com\",876", "OK"));//链接到云平台,三个参数分别是接入协议,服务器地址和端口号
while (!doCmdOk("AT+CIPMODE=1", "OK")); //透传模式
while (!doCmdOk("AT+CIPSEND", ">")); //开始发送
程序讲解参考一下视频连接,代码见文末附录。
https://www.bilibili.com/video/BV1CE411h7hP?p=4
安信可串口调试助手
实验过程中,一开始用的Arduino Nano 开发板,但后来可能因为开发板质量或接线的把板子烧坏了,电脑识别不了设备,于是我换了一块官网的Arduino Uno 正版开发板!
OneNet 移动终端「设备云」效果界面展示,实现温湿度显示、开关控件控制pin13 板载 LED 的亮灭。
参考资料
附代码
ESP8266_EDP.ino
/***********************************************************
File name: ESP8266_EDP.ino
Description: ESP8266 realizes remote control via ONENet
Author: Naiva
Date: 2020/05/17
***********************************************************/
#include "edp.c"
#include "DHT11.h"
DHT11 dht11;
#define DHT11PIN 3 //pin3
#define KEY "24eV33JUKr8dj=XGpckVygdFyJQ=" //APIkey
#define ID "598229651" //设备ID
//#define PUSH_ID "680788"
#define PUSH_ID NULL
String comdata = "";
// 串口
#define _baudrate 115200
#define WIFI_UART Serial
int DHT11 = 0;
const int stbPin = 7; //the segment display module STB pin connected to digital pin 7
const int clkPin = 9; //the segment display module CLK pin connected to digital pin 9
const int dioPin = 8; //the segment display module DIO pin connected to digital pin 8
uint8_t digits[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };
edp_pkt *pkt;
/*
* doCmdOk
* 发送命令至模块,从回复中获取期待的关键字
* keyword: 所期待的关键字
* 成功找到关键字返回true,否则返回false
*/
bool doCmdOk(String data, char *keyword)
{
bool result = false;
if (data != "") //对于tcp连接命令,直接等待第二次回复
{
WIFI_UART.println(data); //发送AT指令
}
if (data == "AT") //检查模块存在
delay(2000);
else
while (!WIFI_UART.available()); // 等待模块回复
delay(200);
if (WIFI_UART.find(keyword)) //返回值判断
{
result = true;
}
else
{
result = false;
}
while (WIFI_UART.available()) WIFI_UART.read(); //清空串口接收缓存
delay(500); //指令时间间隔
return result;
}
void sendCommand(uint8_t value)
{
digitalWrite(stbPin, LOW); //pin low. To begin receiving data
shiftOut(dioPin, clkPin, LSBFIRST, value); //send data(value) to the segment display module
digitalWrite(stbPin, HIGH); //pin high. Stop receiving data
}
void setup()
{
char buf[100] = {0};
int tmp;
pinMode(13, OUTPUT); //WIFI模块指示灯
pinMode(8, OUTPUT); //用于连接EDP控制的发光二极管
WIFI_UART.begin( _baudrate );
pinMode(stbPin, OUTPUT); //initialize the stbPin as an output 数码管
pinMode(clkPin, OUTPUT); //initialize the clkPin as an output
pinMode(dioPin, OUTPUT); //initialize the dioPin as an output
sendCommand(0x8f); //activate
WIFI_UART.setTimeout(3000); //设置find超时时间
delay(3000);
Serial.setTimeout(100);
delay(2000);
while (!doCmdOk("AT", "OK"));
digitalWrite(13, HIGH); // 使Led亮
while (!doCmdOk("AT+CWMODE=3", "OK")); //工作模式
while (!doCmdOk("AT+CWJAP=\"CMCC-R6Qs\",\"qmt2fx3q\"", "OK"));//WiFi账号与WiFi密码
while (!doCmdOk("AT+CIPSTART=\"TCP\",\"jjfaedp.hedevice.com\",876", "OK"));
while (!doCmdOk("AT+CIPMODE=1", "OK")); //透传模式
while (!doCmdOk("AT+CIPSEND", ">")); //开始发送
}
int dht_flag = 1;
void loop()
{
static int edp_connect = 0;
bool trigger = false;
edp_pkt rcv_pkt;
unsigned char pkt_type;
int i = 0, tmp;
char num[10];
int wd,sd;
char wd1[20],sd1[20];
/* EDP 连接 */
if (!edp_connect)
{
while (WIFI_UART.available()) WIFI_UART.read(); //清空串口接收缓存
packetSend(packetConnect(ID, KEY)); //发送EPD连接包
while (!WIFI_UART.available()); //等待EDP连接应答
if ((tmp = WIFI_UART.readBytes(rcv_pkt.data, sizeof(rcv_pkt.data))) > 0 )
{
rcvDebug(rcv_pkt.data, tmp);
if (rcv_pkt.data[0] == 0x20 && rcv_pkt.data[2] == 0x00 && rcv_pkt.data[3] == 0x00)
{
edp_connect = 1;
digitalWrite(13, LOW); // 使Led灭
}
else
;
}
packetClear(&rcv_pkt);
}
if(dht_flag == 1)
{
dht_flag = 0;
dht11.read(DHT11PIN);//温湿度
wd = dht11.temperature;
sd = dht11.humidity;
sprintf(wd1,"%d",wd); //int型转换char型
sprintf(sd1,"%d",sd); //int型转换char型
DHT11 = 0;
delay(500);
packetSend(packetDataSaveTrans(NULL, "WD", wd1)); //将新数据值上传至数据流 WD是上传的地方 wd1是上传的数据
delay(500);
packetSend(packetDataSaveTrans(NULL, "SD", sd1)); //将新数据值上传至数据流
delay(500);
}
DHT11++;
if(DHT11 > 150&&edp_connect)
{
dht11.read(DHT11PIN);
wd = dht11.temperature;
sd = dht11.humidity;
sprintf(wd1,"%d",wd); //int型转换char型
sprintf(sd1,"%d",sd); //int型转换char型
DHT11 = 0;
delay(500);
packetSend(packetDataSaveTrans(NULL, "WD", wd1)); //将新数据值上传至数据流
delay(500);
packetSend(packetDataSaveTrans(NULL, "SD", sd1)); //将新数据值上传至数据流
delay(500);
}
while (WIFI_UART.available())
{
readEdpPkt(&rcv_pkt);
if (isEdpPkt(&rcv_pkt))
{
pkt_type = rcv_pkt.data[0];
switch (pkt_type)
{
case CMDREQ:
char edp_command[50];
char edp_cmd_id[40];
long id_len, cmd_len, rm_len;
char datastr[20];
char val[10];
memset(edp_command, 0, sizeof(edp_command));
memset(edp_cmd_id, 0, sizeof(edp_cmd_id));
edpCommandReqParse(&rcv_pkt, edp_cmd_id, edp_command, &rm_len, &id_len, &cmd_len);
//数据处理与应用中EDP命令内容对应
//本例中格式为 datastream:[1/0]
sscanf(edp_command, "%[^:]:%s", datastr, val);
if (atoi(val) == 1)
// 使Led亮
digitalWrite(13, HIGH);
//digitalWrite(8, HIGH);
else
digitalWrite(13, LOW); // 使Led灭
//digitalWrite(8, HIGH);
if(atoi(val) > 1)
{
sendCommand(0x40); //setting the Write Data Command,using automatic address genuine.
digitalWrite(stbPin, LOW); //pin low. To begin receiving data
shiftOut(dioPin, clkPin, LSBFIRST, 0xc0); //Set the start address 0C0H
if(atoi(val) >= 100 && atoi(val) <=1000)
{
shiftOut(dioPin, clkPin, LSBFIRST, digits[0]);//thousand data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[atoi(val)/100%10]); //hundred data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[atoi(val)/10%10]); //ten data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[atoi(val)%10]); //bit data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
}
else if(atoi(val) >= 10 && atoi(val) <=100)
{
shiftOut(dioPin, clkPin, LSBFIRST, digits[0]);//thousand data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[0]); //hundred data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[atoi(val)/10%10]); //ten data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[atoi(val)%10]); //bit data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
}
else if(atoi(val) > 0 && atoi(val) <=10)
{
shiftOut(dioPin, clkPin, LSBFIRST, digits[0]);//thousand data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[0]); //hundred data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[0]); //ten data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
shiftOut(dioPin, clkPin, LSBFIRST, digits[atoi(val)%10]); //bit data
shiftOut(dioPin, clkPin, LSBFIRST, 0x00); //filling high 8-bit data
}
digitalWrite(stbPin, HIGH);
delay(500);
}
//pin high. Stop receiving data
packetSend(packetDataSaveTrans(NULL, datastr, val)); //将新数据值上传至数据流
break;
default:
;
break;
}
}
//delay(4);
}
if (rcv_pkt.len > 0)
packetClear(&rcv_pkt);
delay(150);
}
/*
* readEdpPkt
* 从串口缓存中读数据到接收缓存
*/
bool readEdpPkt(edp_pkt *p)
{
int tmp;
if ((tmp = WIFI_UART.readBytes(p->data + p->len, sizeof(p->data))) > 0 )
{
rcvDebug(p->data + p->len, tmp);
p->len += tmp;
}
return true;
}
/*
* packetSend
* 将待发数据发送至串口,并释放到动态分配的内存
*/
void packetSend(edp_pkt* pkt)
{
if (pkt != NULL)
{
WIFI_UART.write(pkt->data, pkt->len); //串口发送
WIFI_UART.flush();
free(pkt); //回收内存
}
}
void rcvDebug(unsigned char *rcv, int len)
{
int i;
}
EHT11.cpp
/*
File name: EHT11.cpp
*/
#include "DHT11.h"
// Return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int DHT11::read(int pin)
{
// BUFFER TO RECEIVE
uint8_t bits[5];
uint8_t cnt = 7;
uint8_t idx = 0;
// EMPTY BUFFER
for (int i=0; i< 5; i++) bits[i] = 0;
// REQUEST SAMPLE
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
delay(18);
digitalWrite(pin, HIGH);
delayMicroseconds(40);
pinMode(pin, INPUT);
// ACKNOWLEDGE or TIMEOUT
unsigned int loopCnt = 10000;
while(digitalRead(pin) == LOW)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
loopCnt = 10000;
while(digitalRead(pin) == HIGH)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
// READ OUTPUT - 40 BITS => 5 BYTES or TIMEOUT
for (int i=0; i<40; i++)
{
loopCnt = 10000;
while(digitalRead(pin) == LOW)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
unsigned long t = micros();
loopCnt = 10000;
while(digitalRead(pin) == HIGH)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
if ((micros() - t) > 40) bits[idx] |= (1 << cnt);
if (cnt == 0) // next byte?
{
cnt = 7; // restart at MSB
idx++; // next byte!
}
else cnt--;
}
// WRITE TO RIGHT VARS
// as bits[1] and bits[3] are allways zero they are omitted in formulas.
humidity = bits[0];
temperature = bits[2];
uint8_t sum = bits[0] + bits[2];
if (bits[4] != sum) return DHTLIB_ERROR_CHECKSUM;
return DHTLIB_OK;
}
EHT11.h
/*
/*
File name: EHT11.h
*/
*/
#ifndef DHT11_H
#define DHT11_H
#if defined(ARDUINO) && (ARDUINO >= 100)
#include
#else
#include
#endif
#define DHT11LIB_VERSION "V1.0"
#define DHTLIB_OK 0
#define DHTLIB_ERROR_CHECKSUM -1
#define DHTLIB_ERROR_TIMEOUT -2
class DHT11
{
public:
int read(int pin);
int humidity;
int temperature;
};
#endif
edp.c
/*
File name: edp.c
*/
#include
#include
#include
#define CONNREQ 0x10
#define CONNRESP 0x20
#define PUSHDATA 0x30
#define SAVEDATA 0x80
#define SAVEACK 0x90
#define CMDREQ 0xA0
#define CMDRESP 0xB0
#define PINGREQ 0xC0
#define PINGRESP 0xD0
#define ENCRYPTREQ 0xE0
#define ENCRYPTRESP 0xF0
#define MAX_LEN 200
#define PROTOCOL_NAME "EDP"
#define PROTOCOL_VERSION 1
typedef unsigned char uint8;
typedef char int8;
typedef unsigned int uint16;
typedef int int16;
typedef unsigned long uint32;
typedef long int32;
typedef struct
{
uint8 data[MAX_LEN];
int16 len;
int16 read_p;
} edp_pkt;
/*
* packetCreate
* 创建一个EDP包缓存空间
*/
edp_pkt *packetCreate(void)
{
edp_pkt *p;
if((p = (edp_pkt *)malloc(sizeof(edp_pkt))) != NULL)
memset(p, 0, sizeof(edp_pkt));
return p;
}
/*
* writeRemainlen
* 向EDP包中写入剩余长度字段
* len_val: 剩余长度的值
*/
int8 writeRemainlen(edp_pkt* pkt, int16 len_val)
{
int8 remaining_count = 0;
int8 tmp = 0;
do {
tmp = len_val % 128;
len_val = len_val / 128;
/* If there are more digits to encode, set the top bit of this digit */
if (len_val > 0) {
tmp = tmp | 0x80;
}
pkt->data[pkt->len++] = tmp;
remaining_count++;
} while (len_val > 0 && remaining_count < 5);
return remaining_count;
}
/*
* writeByte
* 向EDP包中写入一个字节
*/
int16 writeByte(edp_pkt* pkt, int8 byte)
{
pkt->data[pkt->len++] = byte;
return 0;
}
/*
* writeBytes
* 向EDP包中写入多个字节
*/
int16 writeBytes(edp_pkt* pkt, const void* bytes, int16 count)
{
memcpy(pkt->data + pkt->len, bytes, count);
pkt->len += count;
return 0;
}
/*
* writeStr
* 向EDP包中写入字符串字段
* 首先写入两个字节的长度,随后紧跟字符串内容
*/
int16 writeStr(edp_pkt* pkt, const int8* str)
{
short len = strlen(str);
writeByte(pkt, len >> 8);
writeByte(pkt, len & 0x00ff);
memcpy(pkt->data + pkt->len, str, len);
pkt->len += len;
return 0;
}
/*---------------------------------------------------------------------------*/
/*
* readUint8
* 从EDP包中读出一个字节
*/
uint8 readUint8(edp_pkt* pkt)
{
return pkt->data[pkt->read_p++];
}
/*
* readUint16
* 从EDP包中读出16bit的字段
*/
uint16 readUint16(edp_pkt* pkt)
{
uint16 tmp;
uint8 msb, lsb;
msb = readUint8(pkt);
lsb = readUint8(pkt);
tmp = (msb<<8) | lsb;
return tmp;
}
/*
* readUint32
* 从EDP包中读出4个字节的字段
*/
uint32 readUint32(edp_pkt* pkt)
{
uint32 tmp = 0;
int i = 4;
while (--i >= 0)
{
tmp <<= 8;
tmp |= readUint8(pkt);
}
return tmp;
}
/*
* readStr
* 根据长度,从EDP包中读出字符串数据
* len : 字符串的长度
*/
void readStr(edp_pkt* pkt, char* str, uint16 len)
{
memcpy(str, pkt->data + pkt->read_p, len);
pkt->read_p += len;
}
/*
* readRemainlen
* 从EDP包中读出剩余长度
*/
int32 readRemainlen(edp_pkt* pkt)
{
uint32 multiplier = 1;
uint32 len_len = 0;
uint8 onebyte = 0;
int32 len_val = 0;
do
{
onebyte = readUint8(pkt);
len_val += (onebyte & 0x7f) * multiplier;
multiplier *= 0x80;
len_len++;
if (len_len > 4)
{
return -1; /*len of len more than 4;*/
}
} while((onebyte & 0x80) != 0);
return len_val;
}
/*
* packetConnect:组EDP连接包
* 首先创建EDP缓存空间,按照EDP协议组EDP连接包
* 分配的内存需要在发送之后free掉
* devid: 设备id
* key:APIKey
*/
edp_pkt *packetConnect(const int8* devid, const int8* key)
{
int32 remainlen;
edp_pkt* pkt;
if((pkt = packetCreate()) == NULL)
return NULL;
/* msg type */
writeByte(pkt, CONNREQ);
/* remain len */
remainlen = (2 + 3) + 1 + 1 + 2 + (2 + strlen(devid)) + (2 + strlen(key));
writeRemainlen(pkt, remainlen);
/* protocol desc */
writeStr(pkt, PROTOCOL_NAME);
/* protocol version */
writeByte(pkt, PROTOCOL_VERSION);
/* connect flag */
writeByte(pkt, 0x40);
/* keep time */
writeByte(pkt, 0);
writeByte(pkt, 0x80);
/* DEVID */
writeStr(pkt, devid);
/* auth key */
writeStr(pkt, key);
return pkt;
}
/*
* packetDataSaveTrans:组EDP数据存储转发包
* 首先创建EDP缓存空间,按照EDP协议组EDP数据存储转发包
* 分配的内存需要在发送之后free掉
* devid: 设备id
* streamId:数据流ID,即数据流名
* val: 字符串形式的数据值
*/
edp_pkt *packetDataSaveTrans(const int8* destId, const int8* streamId, const int8 *val)
{
int32 remainlen;
int8 tmp[200];
int16 str_len;
edp_pkt *pkt;
if((pkt = packetCreate()) == NULL)
return pkt;
/* 生成数据类型格式5的数据类型 */
sprintf(tmp, ",;%s,%s", streamId, val);
str_len = strlen(tmp);
/* msg type */
writeByte(pkt, SAVEDATA);
if (destId != NULL)
{
/* remain len */
remainlen = 1 + (2 + strlen(destId)) + 1 + (2 + str_len);
writeRemainlen(pkt, remainlen);
/* translate address flag */
writeByte(pkt, 0x80);
/* dst devid */
writeStr(pkt, destId);
}
else
{
/* remain len */
remainlen = 1 + 1 + (2 + str_len);
writeRemainlen(pkt, remainlen);
/* translate address flag */
writeByte(pkt, 0x00);
}
/* json flag */
writeByte(pkt, 5);
/* json */
writeStr(pkt, tmp);
return pkt;
}
void packetClear(edp_pkt* pkt)
{
memset(pkt, 0, sizeof(edp_pkt));
}
/*
* isEdpPkt
* 按照EDP数据格式,判断是否是完整数据包
*/
int16 isEdpPkt(edp_pkt* pkt)
{
uint32 data_len = 0;
uint32 multiplier = 1;
uint32 len_val = 0;
uint32 len_len = 1;
uint32 pkt_total_len = 0;
uint8* pdigit;
pdigit = pkt->data;
data_len = pkt->len;
if (data_len <= 1)
{
return 0; /* continue receive */
}
do {
if (len_len > 4)
{
return -1; /* protocol error; */
}
if (len_len > data_len - 1)
{
return 0; /* continue receive */
}
len_len++;
pdigit++;
len_val += ((*pdigit) & 0x7f) * multiplier;
multiplier *= 0x80;
} while (((*pdigit) & 0x80) != 0);
pkt_total_len = len_len + len_val;
/* receive payload */
if (pkt_total_len == data_len)
{
return 1; /* all data for this pkt is read */
}
else
{
return 0; /* continue receive */
}
}
/*
* edpCommandReqParse
* 按照EDP命令请求协议,解析数据
*/
int edpCommandReqParse(edp_pkt* pkt, char *id, char *cmd, int32 *rmlen, int32 *id_len, int32 *cmd_len)
{
readUint8(pkt); /* 包类型 */
*rmlen = readRemainlen(pkt); /* 剩余长度 */
*id_len = readUint16(pkt); /* ID长度 */
readStr(pkt, id, *id_len); /* 命令ID */
*cmd_len = readUint32(pkt); /* 命令长度 */
readStr(pkt, cmd, *cmd_len); /* 命令内容 */
}
/*
* edpPushDataParse
* 按照EDP透传数据格式,解析数据
*/
int edpPushDataParse(edp_pkt* pkt, char *srcId, char *data)
{
uint32 remain_len;
uint16 id_len;
readUint8(pkt); /* 包类型 */
remain_len = readRemainlen(pkt); /* 剩余长度 */
id_len = readUint16(pkt); /* 源ID长度 */
readStr(pkt, srcId, id_len); /* 源ID */
readStr(pkt, data, remain_len - 2 - id_len); /* 数据内容 */
}