EDP KIT from OneNet

Dependents:   8-0_OneNet_IoT_demo STM32F103C8T6_OneNet_IoT

Files at this revision

API Documentation at this revision

Comitter:
TaylorGy
Date:
Wed Mar 29 03:07:27 2017 +0000
Commit message:
EDP KIT from OneNet

Changed in this revision

EdpKit.cpp Show annotated file Show diff for this revision Revisions of this file
EdpKit.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 79de700849c5 EdpKit.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EdpKit.cpp	Wed Mar 29 03:07:27 2017 +0000
@@ -0,0 +1,1039 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include "EdpKit.h"
+
+#define MKFUN_PACKET_SAVE_DATA(TYPE, NAME)              \
+    EdpPacket* PacketSavedata##NAME(SaveDataType type,          \
+                    const char* dst_devid,      \
+                    const char* ds_id,          \
+                    TYPE value,             \
+                    time_t at,              \
+                    const char* token){         \
+    EdpPacket* pkg = NULL;                      \
+    switch (type){                          \
+    case kTypeFullJson:                     \
+        pkg = PacketSavedataType1##NAME(dst_devid, ds_id,       \
+                        value, at, token);      \
+        break;                          \
+    case kTypeSimpleJsonWithoutTime:                \
+        pkg = PacketSavedataType2##NAME(dst_devid, ds_id,       \
+                        value, at, token);      \
+        break;                          \
+    case kTypeSimpleJsonWithTime:                   \
+        pkg = PacketSavedataType3##NAME(dst_devid, ds_id,       \
+                        value, at, token);      \
+        break;                          \
+    default:                            \
+        break;                          \
+    }                               \
+                                    \
+    return pkg;                             \
+}
+
+#define MKFUN_PACKET_SAVE_DATA_TYPE1(TYPE, NAME, MED)           \
+    static EdpPacket* PacketSavedataType1##NAME(const char* dst_devid,  \
+                        const char* ds_id,  \
+                        TYPE value,     \
+                        time_t at,      \
+                        const char* token){ \
+    cJSON* json_obj = NULL;                     \
+    cJSON* ds_array = NULL;                     \
+    cJSON* json_obj_ds = NULL;                  \
+    cJSON* dp_array = NULL;                     \
+    cJSON* dp_item = NULL;                      \
+    char ss[100] = {0};                     \
+    EdpPacket* pkg = NULL;                      \
+                                    \
+    json_obj = cJSON_CreateObject();                \
+                                    \
+    if(token) {                         \
+        cJSON_AddStringToObject(json_obj, "token", token);      \
+    }                               \
+                                    \
+    ds_array = cJSON_CreateArray();                 \
+    json_obj_ds = cJSON_CreateObject();             \
+                                    \
+    cJSON_AddStringToObject(json_obj_ds, "id", ds_id);      \
+                                    \
+    dp_array = cJSON_CreateArray();                 \
+    dp_item = cJSON_CreateObject();                 \
+                                    \
+    FormatAt(ss, 100, at);                      \
+    cJSON_AddStringToObject(dp_item, "at", ss);         \
+    cJSON_Add##MED##ToObject(dp_item, "value", value);      \
+    cJSON_AddItemToArray(dp_array, dp_item);            \
+                                    \
+    cJSON_AddItemToObject(json_obj_ds, "datapoints", dp_array); \
+    cJSON_AddItemToArray(ds_array, json_obj_ds);            \
+    cJSON_AddItemToObject(json_obj, "datastreams", ds_array);   \
+                                    \
+    pkg = PacketSavedataJson(dst_devid, json_obj,           \
+                        kTypeFullJson);     \
+    cJSON_Delete(json_obj);                     \
+                                    \
+    return pkg;                         \
+}
+
+#define MKFUN_PACKET_SAVE_DATA_TYPE2(TYPE, NAME, MED)           \
+    static EdpPacket* PacketSavedataType2##NAME(const char* dst_devid,  \
+                        const char* ds_id,  \
+                        TYPE value,     \
+                        time_t at,      \
+                        const char* token)  \
+    {                                   \
+    cJSON* json_obj = NULL;                     \
+    EdpPacket* pkg = NULL;                      \
+                                    \
+    json_obj = cJSON_CreateObject();                \
+    cJSON_Add##MED##ToObject(json_obj, ds_id, value);       \
+                                    \
+    pkg = PacketSavedataJson(dst_devid, json_obj,           \
+                        kTypeSimpleJsonWithoutTime); \
+    cJSON_Delete(json_obj);                     \
+                                    \
+    return pkg;                         \
+}
+
+
+#define MKFUN_PACKET_SAVE_DATA_TYPE3(TYPE, NAME, MED)           \
+    static EdpPacket* PacketSavedataType3##NAME(const char* dst_devid,  \
+                        const char* ds_id,  \
+                        TYPE value,     \
+                        time_t at,      \
+                        const char* token){ \
+    cJSON* json_obj = NULL;                     \
+    cJSON* json_obj_ds = NULL;                  \
+    char ss[100] = {0};                     \
+    EdpPacket* pkg = NULL;                      \
+                                    \
+    json_obj = cJSON_CreateObject();                \
+    FormatAt(ss, 100, at);                      \
+    json_obj_ds = cJSON_CreateObject();             \
+    cJSON_Add##MED##ToObject(json_obj_ds, ss, value);       \
+    cJSON_AddItemToObject(json_obj, ds_id, json_obj_ds);        \
+                                    \
+    pkg = PacketSavedataJson(dst_devid, json_obj,           \
+                        kTypeSimpleJsonWithTime);   \
+    cJSON_Delete(json_obj);                     \
+                                    \
+    return pkg;                         \
+}
+
+#define MKFUN_UNPACK_SAVE_DATA(TYPE, NAME)              \
+    int32 UnpackSavedata##NAME(SaveDataType type,           \
+                 EdpPacket* pkg,            \
+                 char** ds_id,              \
+                 TYPE* value)               \
+    {                                   \
+    int ret = -1;                           \
+    switch (type){                          \
+    case kTypeFullJson:                         \
+    ret = UnpackSavedataType1##NAME(pkg, ds_id, value);     \
+    break;                              \
+    case kTypeSimpleJsonWithoutTime:                    \
+    ret = UnpackSavedataType2##NAME(pkg, ds_id, value);     \
+    break;                              \
+    case kTypeSimpleJsonWithTime:                   \
+    ret = UnpackSavedataType3##NAME(pkg, ds_id, value);     \
+    break;                              \
+    default:                                \
+    break;                              \
+    }                                   \
+                                    \
+    return ret;                             \
+}
+
+#define MKFUN_UNPACK_SAVE_DATA_TYPE1(TYPE, NAME, MED)           \
+    static int32 UnpackSavedataType1##NAME(EdpPacket* pkg,      \
+                         char** ds_id,      \
+                         TYPE* value)       \
+    {                                   \
+    cJSON* json_obj = NULL;                     \
+    cJSON* ds_array = NULL;                     \
+    cJSON* ds_item = NULL;                      \
+    char* id = NULL;                            \
+    cJSON* dp_array = NULL;                     \
+    cJSON* dp_item = NULL;                      \
+    char* valuestring = NULL;                       \
+                                    \
+    if(0 != UnpackSavedataJson(pkg, &json_obj))             \
+    return ERR_UNPACK_SAVED_JSON;                   \
+                                    \
+    ds_array = cJSON_GetObjectItem(json_obj, "datastreams");        \
+    if((0 == ds_array) || (1 != cJSON_GetArraySize(ds_array)))      \
+    return ERR_UNPACK_SAVED_JSON;                   \
+                                    \
+    ds_item = cJSON_GetArrayItem(ds_array, 0);              \
+    if(0 == ds_item)                            \
+    return ERR_UNPACK_SAVED_JSON;                   \
+                                    \
+    id = cJSON_GetObjectItem(ds_item, "id")->valuestring;       \
+    *ds_id = (char*)malloc(strlen(id)+1);               \
+    memcpy((char*)(*ds_id), id, strlen(id)+1);              \
+                                        \
+    dp_array = cJSON_GetObjectItem(ds_item, "datapoints");      \
+    if((0 == dp_array) || (1 != cJSON_GetArraySize(dp_array)))      \
+    return ERR_UNPACK_SAVED_JSON;                   \
+                                    \
+    dp_item = cJSON_GetArrayItem(dp_array, 0);              \
+
+
+#define UNPACK_SAVE_DATA_TYPE1_END_STRING               \
+    valuestring = cJSON_GetObjectItem(dp_item, "value")->valuestring;   \
+    *value = (char*)malloc(strlen(valuestring)+1);          \
+    memcpy((char*)(*value), valuestring, strlen(valuestring)+1);    \
+    cJSON_Delete(json_obj);                     \
+    return 0;                               \
+}
+
+#define UNPACK_SAVE_DATA_TYPE1_END_NUMBER(TYPE)         \
+    *value = cJSON_GetObjectItem(dp_item, "value")->value##TYPE;    \
+    cJSON_Delete(json_obj);                     \
+    return 0;                               \
+}
+
+#define MKFUN_UNPACK_SAVE_DATA_TYPE2(TYPE, NAME, MED)           \
+    static int32 UnpackSavedataType2##NAME(EdpPacket* pkg,      \
+                          char** ds_id,     \
+                          TYPE* value)      \
+    {                                   \
+        cJSON* json_obj = NULL;                     \
+    cJSON* json_child = NULL;                   \
+    size_t len = 0;                         \
+    char* valuestring = NULL;                   \
+                                    \
+    if(0 != UnpackSavedataJson(pkg, &json_obj))         \
+        return ERR_UNPACK_SAVED_JSON;               \
+    if (!json_obj->child){                      \
+        cJSON_Delete(json_obj);                 \
+        return ERR_UNPACK_SAVED_JSON;               \
+    }                               \
+    json_child = json_obj->child;                   \
+    len = strlen(json_child->string) + 1;               \
+    *ds_id = (char*)malloc(len);                    \
+    memcpy((char*)(*ds_id), json_child->string, len);       \
+
+#define UNPACK_SAVE_DATA_TYPE23_END_NUMBER(TYPE)            \
+    *value = json_child->value##TYPE;                   \
+    cJSON_Delete(json_obj);                     \
+    return 0;                               \
+}
+
+#define UNPACK_SAVE_DATA_TYPE23_END_STRING()                \
+    valuestring = json_child->valuestring;              \
+    *value = (char*)malloc(strlen(valuestring)+1);          \
+    memcpy((char*)(*value), valuestring, strlen(valuestring)+1);    \
+    cJSON_Delete(json_obj);                     \
+    return 0;                               \
+}
+
+#define MKFUN_UNPACK_SAVE_DATA_TYPE3(TYPE, NAME, MED)           \
+    static int32 UnpackSavedataType3##NAME(EdpPacket* pkg,      \
+                          char** ds_id,     \
+                          TYPE* value)      \
+{                                   \
+        cJSON* json_obj = NULL;                     \
+    cJSON* json_child = NULL;                   \
+    char* valuestring = NULL;                   \
+    size_t len = 0;                         \
+                                    \
+    if(0 != UnpackSavedataJson(pkg, &json_obj))         \
+        return ERR_UNPACK_SAVED_JSON;               \
+                                    \
+    json_child = json_obj->child;                   \
+    if (!json_child || !json_child->string){            \
+        cJSON_Delete(json_obj);                 \
+        return ERR_UNPACK_SAVED_JSON;               \
+    }                               \
+                                    \
+    len = strlen(json_child->string) + 1;               \
+    *ds_id = (char*)malloc(len);                    \
+    memcpy(*ds_id, json_child->string, len);            \
+                                    \
+    json_child = json_child->child;                 \
+    if (!json_child){                       \
+        cJSON_Delete(json_obj);                 \
+        return ERR_UNPACK_SAVED_JSON;               \
+    }
+
+
+static void FormatAt(char* buffer, int len, time_t now)
+{
+    struct tm timinfo;
+
+    if (now == 0){
+    now = 0;  //time(0);
+    }
+
+#if defined(linux) || defined(__linux) || defined(__linux__)
+    strftime(buffer, len, "%F %T", localtime_r(&now, &timinfo));
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+    localtime_s(&timinfo, &now);
+    strftime(buffer, len, "%F %T", &timinfo); 
+#endif
+}
+
+/*---------------------------------------------------------------------------*/
+Buffer* NewBuffer()
+{
+    Buffer* buf = (Buffer*)malloc(sizeof(Buffer));
+    buf->_data = (uint8*)malloc(sizeof(uint8) * BUFFER_SIZE);
+    buf->_write_pos = 0;
+    buf->_read_pos = 0;
+    buf->_capacity = BUFFER_SIZE;
+    return buf;
+}
+
+void DeleteBuffer(Buffer** buf)
+{
+    uint8* pdata = (*buf)->_data;
+    free(pdata);
+    free(*buf);
+    *buf = 0;
+}
+
+int32 CheckCapacity(Buffer* buf, uint32 len)
+{
+    uint32 cap_len = buf->_capacity;
+    int32 flag = 0;
+    uint8* pdata = NULL;
+
+    while (cap_len - buf->_write_pos < len) /* remain len < len */
+    {
+        cap_len = cap_len << 1;
+        if (++flag > 32)
+            break;  /* overflow */
+    }
+    if (flag > 32)
+        return -1;
+    if (cap_len > buf->_capacity)
+    {
+        pdata = (uint8*)malloc(sizeof(uint8) * cap_len);
+        memcpy(pdata, buf->_data, buf->_write_pos);
+        free(buf->_data);
+        buf->_data = pdata;
+        buf->_capacity = cap_len;
+    }
+    return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+int32 ReadByte(EdpPacket* pkg, uint8* val)
+{
+    if (pkg->_read_pos+1 > pkg->_write_pos) 
+        return -1;
+    *val = pkg->_data[pkg->_read_pos];
+    pkg->_read_pos += 1;
+    return 0;
+}
+
+int32 ReadBytes(EdpPacket* pkg, uint8** val, uint32 count)
+{
+    if (pkg->_read_pos+count > pkg->_write_pos) 
+        return -1;
+    *val = (uint8*)malloc(sizeof(uint8) * count);
+    memcpy(*val, pkg->_data + pkg->_read_pos, count);
+    pkg->_read_pos += count;
+    return 0;
+}
+
+int32 ReadUint16(EdpPacket* pkg, uint16* val)
+{
+    uint8 msb, lsb;
+    if (pkg->_read_pos+2 > pkg->_write_pos) 
+        return -1;
+    msb = pkg->_data[pkg->_read_pos];
+    pkg->_read_pos++;
+    lsb = pkg->_data[pkg->_read_pos];
+    pkg->_read_pos++;
+    *val = (msb<<8) + lsb;
+    return 0;
+}
+
+int32 ReadUint32(EdpPacket* pkg, uint32* val)
+{
+    int32 i = 0;
+    uint32 tmpval = 0;
+    if (pkg->_read_pos+4 > pkg->_write_pos) 
+        return -1;
+    while (i++ < 4) {
+        tmpval = (tmpval << 8) | (pkg->_data[pkg->_read_pos]);
+        pkg->_read_pos++;
+    }
+    *val = tmpval;
+    return 0;
+}
+
+int32 ReadStr(EdpPacket* pkg, char** val)
+{
+    uint16 len = 0;
+    int rc = 0;
+    /* read str len */
+    rc = ReadUint16(pkg, &len);
+    if (rc) 
+        return rc;
+    if (pkg->_read_pos+len > pkg->_write_pos) 
+        return -1;
+    /* copy str val */
+    *val = (char*)malloc(sizeof(char) * (len + 1));
+    memset(*val, 0, len+1);
+    strncpy(*val, (const char *)(pkg->_data + pkg->_read_pos), len);
+    pkg->_read_pos += len;
+    return 0;
+}
+
+int32 ReadRemainlen(EdpPacket* pkg, uint32* len_val)
+{
+    uint32 multiplier = 1;
+    uint32 len_len = 0;
+    uint8 onebyte = 0;
+    int32 rc;
+    *len_val = 0;
+    do {
+        rc = ReadByte(pkg, &onebyte);
+        if (rc) 
+            return rc;
+
+        *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 0;
+}
+
+/*---------------------------------------------------------------------------*/
+int32 WriteByte(Buffer* buf, uint8 byte)
+{
+    assert(buf->_read_pos == 0);
+    if (CheckCapacity(buf, 1))
+        return -1;
+    buf->_data[buf->_write_pos] = byte;
+    buf->_write_pos++;
+    return 0;
+}
+
+int32 WriteBytes(Buffer* buf, const void* bytes, uint32 count)
+{
+    assert(buf->_read_pos == 0);
+    if (CheckCapacity(buf, count))
+        return -1;
+    memcpy(buf->_data + buf->_write_pos, bytes, count);
+    buf->_write_pos += count;
+    return 0;
+}
+
+int32 WriteUint16(Buffer* buf, uint16 val)
+{
+    assert(buf->_read_pos == 0);
+    return WriteByte(buf, MOSQ_MSB(val)) 
+        || WriteByte(buf, MOSQ_LSB(val));
+}
+
+int32 WriteUint32(Buffer* buf, uint32 val)
+{
+    assert(buf->_read_pos == 0);
+    return WriteByte(buf, (val >> 24) & 0x00FF) 
+        || WriteByte(buf, (val >> 16) & 0x00FF)
+        || WriteByte(buf, (val >> 8) & 0x00FF) 
+        || WriteByte(buf, (val) & 0x00FF);
+}
+
+int32 WriteStr(Buffer* buf, const char *str)
+{
+    uint16 length = 0;
+    assert(buf->_read_pos == 0);
+    length = strlen(str);
+    return WriteUint16(buf, length) 
+        || WriteBytes(buf, str, length);
+}
+
+int32 WriteRemainlen(Buffer* buf, uint32 len_val)
+{
+    uint32 remaining_length = len_val;
+    int32 remaining_count = 0;
+    uint8 byte = 0;
+
+    assert(buf->_read_pos == 0);
+
+    do {
+        byte = remaining_length % 128;
+        remaining_length = remaining_length / 128;
+        /* If there are more digits to encode, set the top bit of this digit */
+        if (remaining_length > 0) {
+            byte = byte | 0x80;
+        }
+        buf->_data[buf->_write_pos++] = byte;
+        remaining_count++;
+    }while(remaining_length > 0 && remaining_count < 5);
+    assert(remaining_count != 5);
+    return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+/* connect1 (C->S): devid + apikey */
+EdpPacket* PacketConnect1(const char* devid, const char* auth_key)
+{
+    EdpPacket* pkg = NewBuffer();
+    uint32 remainlen;
+    /* msg type */
+    WriteByte(pkg, CONNREQ);
+    /* remain len */
+    remainlen = (2+3)+1+1+2+(2+strlen(devid))+(2+strlen(auth_key));
+    WriteRemainlen(pkg, remainlen);
+    /* protocol desc */
+    WriteStr(pkg, PROTOCOL_NAME);
+    /* protocol version */
+    WriteByte(pkg, PROTOCOL_VERSION);
+    /* connect flag */
+    WriteByte(pkg, 0x40);
+    /* keep time */
+    WriteUint16(pkg, 0x0080);
+    /* DEVID */
+    WriteStr(pkg, devid);
+    /* auth key */
+    WriteStr(pkg, auth_key);
+    return pkg;
+}
+
+/* connect2 (C->S): userid + auth_info */
+EdpPacket* PacketConnect2(const char* userid, const char* auth_info)
+{
+    EdpPacket* pkg = NULL;
+    uint32 remainlen;
+
+    pkg = NewBuffer();
+    /* msg type */
+    WriteByte(pkg, CONNREQ);
+    /* remain len */
+    remainlen = (2+3)+1+1+2+2+(2+strlen(userid))+(2+strlen(auth_info));
+    WriteRemainlen(pkg, remainlen);
+    /* protocol desc */
+    WriteStr(pkg, PROTOCOL_NAME);
+    /* protocol version */
+    WriteByte(pkg, PROTOCOL_VERSION);
+    /* connect flag */
+    WriteByte(pkg, 0xC0);
+    /* keep time */
+    WriteUint16(pkg, 0x0080);
+    /* devid */
+    WriteByte(pkg, 0x00);
+    WriteByte(pkg, 0x00);
+    /* USERID */
+    WriteStr(pkg, userid);
+    /* auth info */
+    WriteStr(pkg, auth_info);
+    return pkg;
+}
+
+/* push_data (C->S) */
+EdpPacket* PacketPushdata(const char* dst_devid, const char* data, uint32 data_len)
+{
+    EdpPacket* pkg = NULL;
+    uint32 remainlen;
+
+    pkg = NewBuffer();
+    /* msg type */
+    WriteByte(pkg, PUSHDATA);
+    /* remain len */
+    remainlen = (2+strlen(dst_devid))+data_len;
+    WriteRemainlen(pkg, remainlen);
+    /* dst devid */
+    WriteStr(pkg, dst_devid);
+    /* data */
+    WriteBytes(pkg, data, data_len);
+    return pkg;
+}
+
+/* sava_data (C->S) */
+EdpPacket* PacketSavedataJson(const char* dst_devid, cJSON* json_obj, int type)
+{
+    EdpPacket* pkg = NULL;
+    uint32 remainlen = 0;
+    char* json_out = NULL;
+    uint32 json_len = 0;
+
+    pkg = NewBuffer();
+    remainlen;
+    json_out = cJSON_Print(json_obj);
+    json_len = strlen(json_out);
+
+    /* msg type */
+    WriteByte(pkg, SAVEDATA);
+    if (dst_devid)
+    {
+        /* remain len */
+        remainlen = 1+(2+strlen(dst_devid))+1+(2+json_len);
+        WriteRemainlen(pkg, remainlen);
+        /* translate address flag */
+        WriteByte(pkg, 0x80);
+        /* dst devid */
+        WriteStr(pkg, dst_devid);
+    }
+    else
+    {
+        /* remain len */
+        remainlen = 1+1+(2+json_len);
+        WriteRemainlen(pkg, remainlen);
+        /* translate address flag */
+        WriteByte(pkg, 0x00);
+    }
+    /* json flag */
+    WriteByte(pkg, type);
+    /* json */ 
+    WriteStr(pkg, json_out);
+    free(json_out);
+    return pkg;
+}
+
+/* 
+ * 定义3种JSON格式的打包和解包函数,
+ * 每种格式都支持int,double和char*三种类型
+ */
+MKFUN_PACKET_SAVE_DATA_TYPE1(int, Int, Number)
+MKFUN_PACKET_SAVE_DATA_TYPE1(double, Double, Number)
+MKFUN_PACKET_SAVE_DATA_TYPE1(const char*, String, String)
+
+MKFUN_PACKET_SAVE_DATA_TYPE2(int, Int, Number)
+MKFUN_PACKET_SAVE_DATA_TYPE2(double, Double, Number)
+MKFUN_PACKET_SAVE_DATA_TYPE2(const char*, String, String)
+
+MKFUN_PACKET_SAVE_DATA_TYPE3(int, Int, Number)
+MKFUN_PACKET_SAVE_DATA_TYPE3(double, Double, Number)
+MKFUN_PACKET_SAVE_DATA_TYPE3(const char*, String, String)
+
+MKFUN_PACKET_SAVE_DATA(int, Int)
+MKFUN_PACKET_SAVE_DATA(double, Double)
+MKFUN_PACKET_SAVE_DATA(const char*, String)
+
+/* 解包函数 */
+MKFUN_UNPACK_SAVE_DATA_TYPE1(int, Int, Number)
+UNPACK_SAVE_DATA_TYPE1_END_NUMBER(int)
+MKFUN_UNPACK_SAVE_DATA_TYPE1(double, Double, Number)
+UNPACK_SAVE_DATA_TYPE1_END_NUMBER(double)
+MKFUN_UNPACK_SAVE_DATA_TYPE1(char*, String, String)
+UNPACK_SAVE_DATA_TYPE1_END_STRING
+
+MKFUN_UNPACK_SAVE_DATA_TYPE2(int, Int, Number)
+UNPACK_SAVE_DATA_TYPE23_END_NUMBER(int)
+MKFUN_UNPACK_SAVE_DATA_TYPE2(double, Double, Number)
+UNPACK_SAVE_DATA_TYPE23_END_NUMBER(double)
+MKFUN_UNPACK_SAVE_DATA_TYPE2(char*, String, String)
+UNPACK_SAVE_DATA_TYPE23_END_STRING()
+
+MKFUN_UNPACK_SAVE_DATA_TYPE3(int, Int, Number)
+UNPACK_SAVE_DATA_TYPE23_END_NUMBER(int)
+MKFUN_UNPACK_SAVE_DATA_TYPE3(double, Double, Number)
+UNPACK_SAVE_DATA_TYPE23_END_NUMBER(double)
+MKFUN_UNPACK_SAVE_DATA_TYPE3(char*, String, String)
+UNPACK_SAVE_DATA_TYPE23_END_STRING()
+
+MKFUN_UNPACK_SAVE_DATA(int, Int)
+MKFUN_UNPACK_SAVE_DATA(double, Double)
+MKFUN_UNPACK_SAVE_DATA(char*, String)
+
+int32 UnpackSavedataAck(EdpPacket* pkg, char** json_ack){
+    uint32 remainlen = 0;
+    uint8 flag = 0;
+    uint16 json_len = 0;
+
+    if (ReadRemainlen(pkg, &remainlen))
+        return ERR_UNPACK_SAVEDATA_ACK;
+
+    if (ReadByte(pkg, &flag))
+    return ERR_UNPACK_SAVEDATA_ACK;
+
+    if (ReadUint16(pkg, &json_len))
+    return ERR_UNPACK_SAVEDATA_ACK;
+
+    if (ReadBytes(pkg, (uint8**)(json_ack), json_len))
+    return ERR_UNPACK_SAVEDATA_ACK;
+
+    return 0;
+}
+
+/* sava_data bin (C->S) */
+EdpPacket* PacketSavedataBin(const char* dst_devid, 
+        cJSON* desc_obj, const uint8* bin_data, uint32 bin_len)
+{
+    EdpPacket* pkg = NULL;
+    uint32 remainlen = 0;
+    char* desc_out = NULL;
+    uint32 desc_len = 0;
+
+    /* check arguments */
+    desc_out = cJSON_Print(desc_obj);
+    desc_len = strlen(desc_out);
+    if (desc_len > (0x01 << 16) || bin_len > (3 * (0x01 << 20)) 
+            /* desc < 2^16 && bin_len < 3M*/
+            || cJSON_GetObjectItem(desc_obj, "ds_id") == 0)  
+            /* desc_obj MUST has ds_id */
+    {
+        free(desc_out);
+        return 0;
+    }
+    pkg = NewBuffer();
+    /* msg type */
+    WriteByte(pkg, SAVEDATA);
+    if (dst_devid)
+    {
+        /* remain len */
+        remainlen = 1+(2+strlen(dst_devid))+1+(2+desc_len)+(4+bin_len);
+        WriteRemainlen(pkg, remainlen);
+        /* translate address flag */
+        WriteByte(pkg, 0x80);
+        /* dst devid */
+        WriteStr(pkg, dst_devid);
+    }
+    else
+    {
+        /* remain len */
+        remainlen = 1+1+(2+desc_len)+(4+bin_len);
+        WriteRemainlen(pkg, remainlen);
+        /* translate address flag */
+        WriteByte(pkg, 0x00);
+    }
+    /* bin flag */
+    WriteByte(pkg, 0x02);
+    /* desc */ 
+    WriteStr(pkg, desc_out);
+    free(desc_out);
+    /* bin data */
+    WriteUint32(pkg, bin_len);
+    WriteBytes(pkg, bin_data, bin_len);
+    return pkg;
+}
+
+EdpPacket* PacketSavedataBinStr(const char* dst_devid, 
+        const char* desc_str, const uint8* bin_data, uint32 bin_len)
+{
+    EdpPacket* pkg = NULL;
+    uint32 remainlen = 0;
+    uint32 desc_len = 0;
+
+    /* check arguments */
+    desc_len = strlen(desc_str);
+    if (desc_len > (0x01 << 16) || bin_len > (3 * (0x01 << 20)))           
+    { /* desc < 2^16 && bin_len < 3M*/
+        return 0;
+    }
+    pkg = NewBuffer();
+    /* msg type */
+    WriteByte(pkg, SAVEDATA);
+    if (dst_devid)
+    {
+        /* remain len */
+        remainlen = 1+(2+strlen(dst_devid))+1+(2+desc_len)+(4+bin_len);
+        WriteRemainlen(pkg, remainlen);
+        /* translate address flag */
+        WriteByte(pkg, 0x80);
+        /* dst devid */
+        WriteStr(pkg, dst_devid);
+    }
+    else
+    {
+        /* remain len */
+        remainlen = 1+1+(2+desc_len)+(4+bin_len);
+        WriteRemainlen(pkg, remainlen);
+        /* translate address flag */
+        WriteByte(pkg, 0x00);
+    }
+    /* bin flag */
+    WriteByte(pkg, 0x02);
+    /* desc */ 
+    WriteStr(pkg, desc_str);
+    /* bin data */
+    WriteUint32(pkg, bin_len);
+    WriteBytes(pkg, bin_data, bin_len);
+    return pkg;
+}
+
+EdpPacket* PacketCmdResp(const char* cmdid, uint16 cmdid_len,
+             const char* resp, uint32 resp_len)
+{
+    EdpPacket* send_pkg = NULL;
+    unsigned remainlen = 0;
+
+    send_pkg = NewBuffer();
+    /* 6 = 2 + 4 = len(cmdid_len) + len(resp_len) */
+    remainlen = cmdid_len + resp_len + (resp_len ? 6 : 2);
+    WriteByte(send_pkg, CMDRESP);
+    WriteRemainlen(send_pkg, remainlen);
+    WriteUint16(send_pkg, cmdid_len);
+    WriteBytes(send_pkg, cmdid, cmdid_len);
+    if (resp_len){
+    WriteUint32(send_pkg, resp_len);
+    WriteBytes(send_pkg, resp, resp_len);
+    }
+    return send_pkg;
+}
+
+/* ping (C->S) */
+EdpPacket* PacketPing(void)
+{
+    EdpPacket* pkg = NULL;
+
+    pkg = NewBuffer();
+    /* msg type */
+    WriteByte(pkg, PINGREQ);
+    /* remain len */
+    WriteRemainlen(pkg, 0);
+    return pkg;
+}
+
+/*---------------------------------------------------------------------------*/
+/* recv stream to a edp packet (S->C) */
+EdpPacket* GetEdpPacket(RecvBuffer* buf)
+{
+    EdpPacket* pkg = NULL;
+    int32 flag = 0;
+
+    assert(buf->_read_pos == 0);
+    flag = IsPkgComplete(buf);  
+    if (flag <= 0)
+ return pkg;
+    pkg = NewBuffer();
+    WriteBytes(pkg, buf->_data, flag);
+    /* shrink buffer */
+    memmove(buf->_data, buf->_data + flag, buf->_write_pos - flag);
+    buf->_write_pos -= flag;
+    return pkg;
+}
+
+/* is the recv buffer has a complete edp packet? */
+int32 IsPkgComplete(RecvBuffer* buf)
+{
+    uint8* data = NULL;
+    uint32 data_len = 0;
+    uint32 multiplier = 1;
+    uint32 len_val = 0;
+    uint32 len_len = 1;
+    uint8* pdigit = NULL;
+    uint32 pkg_total_len = 0;
+    
+    data = buf->_data;
+    data_len = buf->_write_pos;
+
+    if (data_len <= 1) {
+    return 0;   /* continue receive */
+    }
+    /* recevie remaining len */
+    pdigit = data;
+
+    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);
+
+    pkg_total_len = len_len + len_val;
+    /* receive payload */
+    if (pkg_total_len <= (uint32)data_len){
+#ifdef _DEBUG
+    printf("a complete packet len:%d\n", pkg_total_len);
+#endif
+    return pkg_total_len;   /* all data for this pkg is read */
+    }else{
+    return 0;   /* continue receive */
+    }
+}
+
+/* get edp packet type, client should use this type to invoke Unpack??? function */
+uint8 EdpPacketType(EdpPacket* pkg)
+{
+    uint8 mtype = 0x00;
+    ReadByte(pkg, &mtype);
+    return mtype;
+}
+
+/* connect_resp (S->C)*/
+int32 UnpackConnectResp(EdpPacket* pkg)
+{
+    uint8 flag, rtn;
+    uint32 remainlen;
+    if (ReadRemainlen(pkg, &remainlen))
+        return ERR_UNPACK_CONNRESP_REMAIN;
+    if (ReadByte(pkg, &flag))
+        return ERR_UNPACK_CONNRESP_FLAG;
+    if (ReadByte(pkg, &rtn))
+        return ERR_UNPACK_CONNRESP_RTN;
+    assert(pkg->_read_pos == pkg->_write_pos);
+    return (int32)rtn;
+}
+
+/* push_data (S->C) */
+int32 UnpackPushdata(EdpPacket* pkg, char** src_devid, char** data, uint32* data_len)
+{
+    uint32 remainlen;
+    if (ReadRemainlen(pkg, &remainlen))
+        return ERR_UNPACK_PUSHD_REMAIN;
+    if (ReadStr(pkg, src_devid))
+        return ERR_UNPACK_PUSHD_DEVID;
+    remainlen -= (2 + strlen(*src_devid));
+    if (ReadBytes(pkg, (uint8**)data, remainlen))
+        return ERR_UNPACK_PUSHD_DATA;
+    *data_len = remainlen;
+    assert(pkg->_read_pos == pkg->_write_pos);
+    return 0;
+}
+
+/* save_data (S->C) */
+int32 UnpackSavedata(EdpPacket* pkg, char** src_devid, uint8* jb_flag)
+{
+    uint32 remainlen;
+    uint8 ta_flag;
+    if (ReadRemainlen(pkg, &remainlen))
+        return ERR_UNPACK_SAVED_REMAIN;
+    /* translate address flag */
+    if (ReadByte(pkg, &ta_flag)) 
+        return ERR_UNPACK_SAVED_TANSFLAG;
+    if (ta_flag == 0x80)
+    {
+        if (ReadStr(pkg, src_devid))
+            return ERR_UNPACK_SAVED_DEVID;
+    }
+    else
+    {
+        *src_devid = 0;
+    }
+    /* json or bin */
+    if (ReadByte(pkg, jb_flag)) 
+        return ERR_UNPACK_SAVED_DATAFLAG;
+    return 0;
+}
+
+int32 UnpackSavedataJson(EdpPacket* pkg, cJSON** json_obj)
+{
+    char* json_str;
+    if (ReadStr(pkg, &json_str))
+        return ERR_UNPACK_SAVED_JSON;
+    *json_obj = cJSON_Parse(json_str);
+    free(json_str);
+    if (*json_obj == 0)
+        return ERR_UNPACK_SAVED_PARSEJSON;
+    assert(pkg->_read_pos == pkg->_write_pos);
+    return 0;
+}
+
+int32 UnpackSavedataBin(EdpPacket* pkg, cJSON** desc_obj, 
+        uint8** bin_data, uint32* bin_len)
+{
+    char* desc_str;
+    if (ReadStr(pkg, &desc_str))
+        return ERR_UNPACK_SAVED_BIN_DESC;
+    *desc_obj = cJSON_Parse(desc_str); 
+    free(desc_str);
+    if (*desc_obj == 0)
+        return ERR_UNPACK_SAVED_PARSEDESC;
+    if (ReadUint32(pkg, bin_len))
+        return ERR_UNPACK_SAVED_BINLEN;
+    if (ReadBytes(pkg, bin_data, *bin_len))
+        return ERR_UNPACK_SAVED_BINDATA;
+    assert(pkg->_read_pos == pkg->_write_pos);
+    return 0;
+}
+
+int32 UnpackSavedataBinStr(EdpPacket* pkg, char** desc_str, 
+        uint8** bin_data, uint32* bin_len)
+{
+    if (ReadStr(pkg, desc_str))
+        return ERR_UNPACK_SAVED_BIN_DESC;
+    if (ReadUint32(pkg, bin_len))
+        return ERR_UNPACK_SAVED_BINLEN;
+    if (ReadBytes(pkg, bin_data, *bin_len))
+        return ERR_UNPACK_SAVED_BINDATA;
+    assert(pkg->_read_pos == pkg->_write_pos);
+    return 0;
+}
+
+int32 UnpackCmdReq(EdpPacket* pkg, char** cmdid, uint16* cmdid_len, 
+           char** req, uint32* req_len)
+{
+    uint32 remainlen;
+    int rc;
+    if (ReadRemainlen(pkg, &remainlen))
+    return ERR_UNPACK_CMDREQ;
+
+    rc = ReadUint16(pkg, cmdid_len);
+    if (rc) 
+        return rc;
+    if (ReadBytes(pkg, (uint8**)cmdid, *cmdid_len))
+        return ERR_UNPACK_CMDREQ;
+
+    rc = ReadUint32(pkg, req_len);
+    if (rc) 
+        return rc;
+    if (ReadBytes(pkg, (uint8**)req, *req_len))
+        return ERR_UNPACK_CMDREQ;
+
+    assert(pkg->_read_pos == pkg->_write_pos);
+    return 0;
+}
+
+/* ping_resp (S->C) */
+int32 UnpackPingResp(EdpPacket* pkg)
+{
+    uint32 remainlen;
+    if (ReadRemainlen(pkg, &remainlen))
+        return ERR_UNPACK_PING_REMAIN;
+    assert(pkg->_read_pos == pkg->_write_pos);
+    return 0;
+}
+
+/* sava_data (C->S) */
+EdpPacket* PacketSavedataSimpleString(const char* dst_devid, const char* input)
+{
+    EdpPacket* pkg = NULL;
+    uint32 remainlen = 0;
+    uint32 input_len = 0;
+
+    pkg = NewBuffer();
+    input_len = strlen(input);
+    /* msg type */
+    WriteByte(pkg, SAVEDATA);
+    if (dst_devid)
+    {
+        /* remain len */
+        remainlen = 1+(2+strlen(dst_devid))+1+(2+input_len);
+        WriteRemainlen(pkg, remainlen);
+        /* translate address flag */
+        WriteByte(pkg, 0x80);
+        /* dst devid */
+        WriteStr(pkg, dst_devid);
+    }
+    else
+    {
+        /* remain len */
+        remainlen = 1+1+(2+input_len);
+        WriteRemainlen(pkg, remainlen);
+        /* translate address flag */
+        WriteByte(pkg, 0x00);
+    }
+    /* json flag */
+    WriteByte(pkg, kTypeString);
+    /* json */ 
+    WriteStr(pkg, input);
+
+    return pkg;
+}
+
+int32 UnpackSavedataSimpleString(EdpPacket* pkg, char** output)
+{
+    if (ReadStr(pkg, output))
+        return ERR_UNPACK_SAVED_JSON;
+    return 0;
+}
+
diff -r 000000000000 -r 79de700849c5 EdpKit.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EdpKit.h	Wed Mar 29 03:07:27 2017 +0000
@@ -0,0 +1,743 @@
+#ifndef __EDP_KIT_H__
+#define __EDP_KIT_H__
+
+#ifdef EDPKIT_EXPORTS
+    #define EDPKIT_DLL __declspec(dllexport)
+#else
+    #define EDPKIT_DLL
+#endif
+
+#include "Common.h"
+#include "cJSON.h"
+#include "time.h"
+/*
+ * history
+ * 2015-06-01 v1.0.1 wululu fix bug: malloc for string, MUST memset to 0
+ * 2015-07-10 v1.1.0 wusongwei add UnpackCmdReq() and PacketCmdResp()
+ * 2015-07-13 v1.1.1 wululu 增加封装json的接口, windows版本dll
+ * 2015-07-13 v1.1.2 wululu 支持double和string类型的打包函数和解包函数
+ * 2015-07-15 v1.1.3 wusongwei 添加SAVEACK响应
+ * 2015-07-20 v1.1.4 wusongwei 添加/修改SAVEDATA消息的打包/解包函数
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------------------*/
+#define MOSQ_MSB(A)         (uint8)((A & 0xFF00) >> 8)
+#define MOSQ_LSB(A)         (uint8)(A & 0x00FF)
+#define BUFFER_SIZE         (0x100) 
+#define PROTOCOL_NAME       "EDP"
+#define PROTOCOL_VERSION    1
+/*----------------------------错误码-----------------------------------------*/
+#define ERR_UNPACK_CONNRESP_REMAIN              -1000
+#define ERR_UNPACK_CONNRESP_FLAG                -1001
+#define ERR_UNPACK_CONNRESP_RTN                 -1002
+#define ERR_UNPACK_PUSHD_REMAIN                 -1010
+#define ERR_UNPACK_PUSHD_DEVID                  -1011
+#define ERR_UNPACK_PUSHD_DATA                   -1012
+#define ERR_UNPACK_SAVED_REMAIN                 -1020
+#define ERR_UNPACK_SAVED_TANSFLAG               -1021
+#define ERR_UNPACK_SAVED_DEVID                  -1022
+#define ERR_UNPACK_SAVED_DATAFLAG               -1023
+#define ERR_UNPACK_SAVED_JSON                   -1024
+#define ERR_UNPACK_SAVED_PARSEJSON              -1025
+#define ERR_UNPACK_SAVED_BIN_DESC               -1026
+#define ERR_UNPACK_SAVED_PARSEDESC              -1027
+#define ERR_UNPACK_SAVED_BINLEN                 -1028
+#define ERR_UNPACK_SAVED_BINDATA                -1029
+#define ERR_UNPACK_PING_REMAIN                  -1030
+#define ERR_UNPACK_CMDREQ                       -1031
+#define ERR_UNPACK_ENCRYPT_RESP                 -1032
+#define ERR_UNPACK_SAVEDATA_ACK                 -1033
+
+/*----------------------------消息类型---------------------------------------*/
+/* 连接请求 */
+#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
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+/* SAVEDATA消息支持的格式类型 */
+typedef enum {
+    kTypeFullJson = 0x01,
+    kTypeBin = 0x02,
+    kTypeSimpleJsonWithoutTime = 0x03,
+    kTypeSimpleJsonWithTime = 0x04,
+    kTypeString = 0x05
+}SaveDataType;
+
+/*-------------发送buffer, 接收buffer, EDP包结构定义-------------------------*/
+EDPKIT_DLL 
+typedef struct Buffer
+{
+    uint8*  _data;          /* buffer数据 */
+    uint32  _write_pos;     /* buffer写入位置 */
+    uint32  _read_pos;      /* buffer读取位置 */
+    uint32  _capacity;      /* buffer容量 */
+}Buffer, SendBuffer, RecvBuffer, EdpPacket;
+/*-----------------------------操作Buffer的接口------------------------------*/
+/* 
+ * 函数名:  NewBuffer
+ * 功能:    生成Buffer
+ * 说明:    一般情况下, NewBuffer和DeleteBuffer应该成对出现
+ * 参数:    无
+ * 返回值:  类型 (Buffer*)
+ *          返回值非空 生成Buffer成功, 返回这个Buffer的指针
+ *          返回值为空 生成Buffer失败, 内存不够
+ */
+EDPKIT_DLL Buffer* NewBuffer();
+/* 
+ * 函数名:  DeleteBuffer
+ * 功能:    销毁Buffer
+ * 说明:    一般情况下, NewBuffer和DeleteBuffer应该成对出现
+ * 参数:    buf     一个Buffer的指针的指针
+ * 返回值:  无
+ */
+EDPKIT_DLL void DeleteBuffer(Buffer** buf);
+/* 
+ * 函数名:  CheckCapacity
+ * 功能:    检查Buffer是否能够写入长度为len的字节流, 
+ *          如果Buffer的容量不够, 自动成倍扩展Buffer的容量(不影响Buffer数据)
+ * 参数:    buf     需要写入Buffer的指针
+ *          len     期望写入的长度
+ * 返回值:  类型 (int32)
+ *          <0      失败, 内存不够
+ *          =0      成功
+ */
+EDPKIT_DLL int32 CheckCapacity(Buffer* buf, uint32 len);
+
+/*------------------------读取EDP包数据的接口-------------------------------*/
+/* 
+ * 函数名:  ReadByte
+ * 功能:    按EDP协议, 从Buffer(包)中读取一个字节数据
+ * 参数:    pkg     EDP包
+ *          val     数据(一个字节)
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 ReadByte(EdpPacket* pkg, uint8* val);
+/* 
+ * 函数名:  ReadBytes
+ * 功能:    按EDP协议, 从Buffer(包)中读取count个字节数据
+ * 说明:    val是malloc出来的, 需要客户端自己free 
+ * 参数:    pkg     EDP包
+ *          val     数据(count个字节)
+ *          count   字节数
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 ReadBytes(EdpPacket* pkg, uint8** val, uint32 count);
+/* 
+ * 函数名:  ReadUint16
+ * 功能:    按EDP协议, 从Buffer(包)中读取uint16值
+ * 参数:    pkg     EDP包
+ *          val     uint16值
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 ReadUint16(EdpPacket* pkg, uint16* val);
+/* 
+ * 函数名:  ReadUint32
+ * 功能:    按EDP协议, 从Buffer(包)中读取uint32值
+ * 参数:    pkg     EDP包
+ *          val     uint32值
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 ReadUint32(EdpPacket* pkg, uint32* val);
+/* 
+ * 函数名:  ReadStr
+ * 功能:    按EDP协议, 从Buffer(包)中读取字符串, 以\0结尾
+ * 参数:    pkg     EDP包
+ *          val     字符串
+ * 说明:    val是malloc出来的, 需要客户端自己free 
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 ReadStr(EdpPacket* pkg, char** val);
+/* 
+ * 函数名:  ReadRemainlen
+ * 功能:    按EDP协议, 从Buffer(包)中remainlen
+ * 说明:    remainlen是EDP协议中的概念, 是一个EDP包身的长度
+ * 参数:    pkg     EDP包
+ *          len_val remainlen
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 ReadRemainlen(EdpPacket* pkg, uint32* len_val);
+
+/*------------------------数据写入EDP包的接口-------------------------------*/
+/*
+ * 说明:    目前不支持一个包即在写入又在读取, 因此, 只有对于_read_pos为0的包才能被写入
+ */
+/* 
+ * 函数名:  WriteByte
+ * 功能:    按EDP协议, 将一个字节数据写入Buffer(包)中
+ * 参数:    pkg     EDP包
+ *          byte    数据(一个字节)
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 WriteByte(Buffer* buf, uint8 byte);
+/* 
+ * 函数名:  WriteBytes
+ * 功能:    按EDP协议, 将count个字节数据写入Buffer(包)中
+ * 参数:    pkg     EDP包
+ *          bytes   数据
+ *          count   字节数
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 WriteBytes(Buffer* buf, const void* bytes, uint32 count);
+/* 
+ * 函数名:  WriteUint16
+ * 功能:    按EDP协议, 将uint16写入Buffer(包)中
+ * 参数:    pkg     EDP包
+ *          val     uint16数据
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 WriteUint16(Buffer* buf, uint16 val);
+/* 
+ * 函数名:  WriteUint32
+ * 功能:    按EDP协议, 将uint32写入Buffer(包)中
+ * 参数:    pkg     EDP包
+ *          val     uint32数据
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 WriteUint32(Buffer* buf, uint32 val);
+/* 
+ * 函数名:  WriteStr
+ * 功能:    按EDP协议, 将字符串写入Buffer(包)中
+ * 参数:    pkg     EDP包
+ *          val     字符串
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 WriteStr(Buffer* buf, const char *str);
+/* 
+ * 函数名:  WriteRemainlen 
+ * 功能:    按EDP协议, 将remainlen写入Buffer(包)中
+ * 说明:    remainlen是EDP协议中的概念, 是一个EDP包身的长度
+ * 参数:    pkg     EDP包
+ *          len_val remainlen
+ * 返回值:  类型 (int32)
+ *          <0      失败, pkg中无数据
+ *          =0      成功
+ */
+EDPKIT_DLL int32 WriteRemainlen(Buffer* buf, uint32 len_val);
+/* 
+ * 函数名:  IsPkgComplete 
+ * 功能:    判断接收到的Buffer, 是否为一个完整的EDP包
+ * 参数:    buf     接收到的Buffer(二进制流)
+ * 返回值:  类型 (int32)
+ *          =0      数据还未收完, 需要继续接收
+ *          >0      成功
+ *          <0      数据错误, 不符合EDP协议
+ */
+EDPKIT_DLL int32 IsPkgComplete(RecvBuffer* buf);
+
+/*-----------------------------客户端操作的接口------------------------------*/
+/* 
+ * 函数名:  GetEdpPacket 
+ * 功能:    将接收到的二进制流, 分解成一个一个的EDP包
+ * 说明:    返回的EDP包使用后, 需要删除
+ * 相关函数:EdpPacketType, Unpack***类函数
+ * 参数:    buf         接收缓存
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        无完整的EDP协议包
+ */
+EDPKIT_DLL EdpPacket* GetEdpPacket(RecvBuffer* buf);
+
+/* 
+ * 函数名:  EdpPacketType 
+ * 功能:    获取一个EDP包的消息类型, 客户程序根据消息类型做不同的处理
+ * 相关函数:Unpack***类函数
+ * 参数:    pkg         EDP协议包
+ * 返回值:  类型 (uint8) 
+ *          值          消息类型(详细参见本h的消息类型定义)
+ */
+/* 例子:
+ * ...
+ * int8 mtype = EdpPacketType(pkg);
+ * switch(mtype)
+ * {
+ *  case CONNRESP:
+ *      UnpackConnectResp(pkg);
+ *      break;
+ *  case PUSHDATA:
+ *      UnpackPushdata(pkg, src_devid, data, data_len);
+ *      break;
+ *  case SAVEDATA:
+ *      UnpackSavedata(pkg, src_devid, flag, data);
+ *      break;
+ *  case PINGRESP:
+ *      UnpackPingResp(pkg); 
+ *      break;
+ *  ...
+ * }
+ */
+EDPKIT_DLL uint8 EdpPacketType(EdpPacket* pkg);
+
+/* 
+ * 函数名:  PacketConnect1 
+ * 功能:    打包 由设备到设备云的EDP协议包, 连接设备云的请求(登录认证方式1)
+ * 说明:    返回的EDP包发送给设备云后, 需要客户程序删除该包
+ *          设备云会回复连接响应给设备
+ * 相关函数:UnpackConnectResp
+ * 参数:    devid       设备ID, 申请设备时平台返回的ID
+ *          auth_key    鉴权信息(api-key), 在平台申请的可以操作该设备的api-key字符串
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketConnect1(const char* devid, const char* auth_key);
+
+/* 
+ * 函数名:  PacketConnect2 
+ * 功能:    打包 由设备到设备云的EDP协议包, 连接设备云的请求(登录认证方式2)
+ * 说明:    返回的EDP包发送给设备云后, 需要客户程序删除该包
+ *          设备云会回复连接响应给设备
+ * 相关函数:UnpackConnectResp
+ * 参数:    userid      用户ID, 在平台注册账号时平台返回的用户ID
+ *          auth_info   鉴权信息, 在平台申请设备时填写设备的auth_info属性
+ *                      (json对象字符串), 该属性需要具备唯一性
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketConnect2(const char* userid, const char* auth_info);
+
+/* 
+ * 函数名:  UnpackConnectResp
+ * 功能:    解包 由设备云到设备的EDP协议包, 连接响应
+ * 说明:    接收设备云发来的数据, 通过函数GetEdpPacket和EdpPacketType判断出是连接响应后, 
+ *          将整个响应EDP包作为参数, 由该函数进行解析
+ * 相关函数:PacketConnect1, PacketConnect2, GetEdpPacket, EdpPacketType
+ * 参数:    pkg         EDP包, 必须是连接响应包
+ * 返回值:  类型 (int32) 
+ *          =0          连接成功
+ *          >0          连接失败, 具体失败原因见<OneNet接入方案与接口.docx>
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackConnectResp(EdpPacket* pkg);
+
+/* 
+ * 函数名:  PacketPushdata
+ * 功能:    打包 设备到设备云的EDP协议包, 设备与设备之间转发数据
+ * 说明:    返回的EDP包发送给设备云后, 需要删除这个包
+ * 相关函数:UnpackPushdata
+ * 参数:    dst_devid   目的设备ID
+ *          data        数据
+ *          data_len    数据长度
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketPushdata(const char* dst_devid, 
+        const char* data, uint32 data_len);
+
+/* 
+ * 函数名:  UnpackPushdata
+ * 功能:    解包 由设备云到设备的EDP协议包, 设备与设备之间转发数据
+ * 说明:    接收设备云发来的数据, 通过函数GetEdpPacket和EdpPacketType判断出是pushdata后, 
+ *          将整个响应EDP包作为参数, 由该函数进行解析 
+ *          返回的源设备ID(src_devid)和数据(data)都需要客户端释放
+ * 相关函数:PacketPushdata, GetEdpPacket, EdpPacketType
+ * 参数:    pkg         EDP包, 必须是pushdata包
+ *          src_devid   源设备ID
+ *          data        数据
+ *          data_len    数据长度
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackPushdata(EdpPacket* pkg, char** src_devid, 
+        char** data, uint32* data_len);
+
+/* 
+ * 函数名:  PacketSavedataJson
+ * 功能:    打包 设备到设备云的EDP协议包, 存储数据(json格式数据)
+ * 说明:    返回的EDP包发送给设备云后, 需要删除这个包
+ * 相关函数:UnpackSavedata, UnpackSavedataJson
+ * 参数:    dst_devid   目的设备ID
+ *          json_obj    json数据
+ *          type        json的类型         
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EdpPacket* PacketSavedataJson(const char* dst_devid, cJSON* json_obj, int type);
+
+/* 
+ * 函数名:  PacketSavedataInt
+ * 功能:    打包 设备到设备云的EDP协议包, 存储数据(json格式数据)
+ * 说明:    该函数适用于数据点为int类型的数据流
+ *          它把参数封装成EDP协议规定的cJSON对象,
+ *          type类型决定使用哪种JSON格式,具体格式说明见文档《设备终端接入协议2-EDP.docx》
+ * 相关函数:UnPacketSavedataInt
+ * 参数:    type        采用的JSON数据类型,可选类型为:kTypeFullJson, 
+ *                      kTypeSimpleJsonWithoutTime, kTypeSimpleJsonWithTime
+ *          dst_devid   目的设备ID
+ *          ds_id       数据流ID
+ *          value       int型数据点
+ *          at          如果设置为0,则采用系统当前时间,否则采用给定时间。
+ *                      如果type选择为kTypeSimpleJsonWithoutTime,由于这种类型的JSON格式不带时间,
+ *                      服务器端统一采用系统时间,此值将被忽略
+ *          token       当type为kTypeFullJson时,将根据EDP协议封装token字段,
+ *                      为其它类型时将被忽略。
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketSavedataInt(SaveDataType type, const char* dst_devid, 
+                    const char* ds_id, int value, 
+                    time_t at, const char* token);
+
+/* 
+ * 函数名:  PacketSavedataDouble
+ * 功能:    打包 设备到设备云的EDP协议包, 存储数据(json格式数据)
+ * 说明:    该函数适用于数据点为double类型的数据流
+ *          它把参数封装成EDP协议规定的cJSON对象,
+ *          type类型决定使用哪种JSON格式,具体格式说明见文档《设备终端接入协议2-EDP.docx》
+ * 相关函数:UnPacketSavedataDouble
+ * 参数:    type        采用的JSON数据类型,可选类型为:kTypeFullJson, 
+ *                      kTypeSimpleJsonWithoutTime, kTypeSimpleJsonWithTime
+ *          dst_devid   目的设备ID
+ *          ds_id       数据流ID
+ *          value       double型数据点
+ *          at          如果设置为0,则采用系统当前时间,否则采用给定时间。
+ *                      如果type选择为kTypeSimpleJsonWithoutTime,由于这种类型的JSON格式不带时间,
+ *                      服务器端统一采用系统时间,此值将被忽略
+ *          token       当type为kTypeFullJson时,将根据EDP协议封装token字段,
+ *                      为其它类型时将被忽略。
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketSavedataDouble(SaveDataType type, const char* dst_devid, 
+                const char* ds_id, double value, 
+                time_t at, const char* token);
+
+/* 
+ * 函数名:  PacketSavedataString
+ * 功能:    打包 设备到设备云的EDP协议包, 存储数据(json格式数据)
+ * 说明:    该函数适用于数据点为char*类型的数据流
+ *          它把参数封装成EDP协议规定的cJSON对象,
+ *          type类型决定使用哪种JSON格式,具体格式说明见文档《设备终端接入协议2-EDP.docx》
+ * 相关函数:UnPacketSavedataString
+ * 参数:    type        采用的JSON数据类型,可选类型为:kTypeFullJson, 
+ *                      kTypeSimpleJsonWithoutTime, kTypeSimpleJsonWithTime
+ *          dst_devid   目的设备ID
+ *          ds_id       数据流ID
+ *          value       char*型数据点
+ *          at          如果设置为0,则采用系统当前时间,否则采用给定时间。
+ *                      如果type选择为kTypeSimpleJsonWithoutTime,由于这种类型的JSON格式不带时间,
+ *                      服务器端统一采用系统时间,此值将被忽略
+ *          token       当type为kTypeFullJson时,将根据EDP协议封装token字段,
+ *                      为其它类型时将被忽略。
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketSavedataString(SaveDataType type, const char* dst_devid, 
+                const char* ds_id, const char* value, 
+                time_t at, const char* token);
+
+/* 
+ * 函数名:  UnpackSavedataInt
+ * 功能:    解包 由设备云到设备的EDP协议包, 存储数据
+ * 说明:    接收设备云发来的数据,将其中的数据流ID及值解析出来。
+ *
+ * 相关函数:PacketSavedataInt
+ *          
+ * 参数:    type        采用的JSON数据类型,可选类型为:kTypeFullJson, 
+ *                      kTypeSimpleJsonWithoutTime, kTypeSimpleJsonWithTime
+ *          pkg         EDP包, 必须是savedata包
+ *          ds_id       获取数据流ID,使用完后必须释放
+ *          value       数据流对应的值
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, -1 type类型不合法,其它值见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackSavedataInt(SaveDataType type, EdpPacket* pkg,
+                     char** ds_id, int* value);
+
+/* 
+ * 函数名:  UnpackSavedataDouble
+ * 功能:    解包 由设备云到设备的EDP协议包, 存储数据
+ * 说明:    接收设备云发来的数据,将其中的数据流ID及值解析出来。
+ *
+ * 相关函数:PacketSavedataDouble
+ *          
+ * 参数:    type        采用的JSON数据类型,可选类型为:kTypeFullJson, 
+ *                      kTypeSimpleJsonWithoutTime, kTypeSimpleJsonWithTime
+ *          pkg         EDP包, 必须是savedata包
+ *          ds_id       获取数据流ID,使用完后必须释放
+ *          value       数据流对应的值
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, -1 type类型不合法,其它值见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackSavedataDouble(SaveDataType type, EdpPacket* pkg,
+                    char** ds_id, double* value);
+
+/* 
+ * 函数名:  UnpackSavedataString
+ * 功能:    解包 由设备云到设备的EDP协议包, 存储数据
+ * 说明:    接收设备云发来的数据,将其中的数据流ID及值解析出来。
+ *
+ * 相关函数:PacketSavedataString
+ *          
+ * 参数:    type        采用的JSON数据类型,可选类型为:kTypeFullJson, 
+ *                      kTypeSimpleJsonWithoutTime, kTypeSimpleJsonWithTime
+ *          pkg         EDP包, 必须是savedata包
+ *          ds_id       获取数据流ID,使用完后需要释放
+ *          value       数据流对应的值,使用完后需要释放
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, -1 type类型不合法,其它值见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackSavedataString(SaveDataType type, EdpPacket* pkg,
+                    char** ds_id, char** value);
+
+
+/* 
+ * 函数名:  UnpackSavedataAck
+ * 功能:    解包 由设备云到设备的EDP协议包, 存贮(转发)消息的响应
+ * 说明:    当存贮(转发)消息带token时,平台会响应一个SAVE_ACK消息,
+ *          用作存储消息的确认。
+ * 相关函数: PacketSavedataDoubleWithToken PacketSavedataStringWithToken
+ * 参数:    pkg         EDP包, 必须是连接响应包
+ *          json_ack    获取响应的json字符串,使用完后需要释放
+ * 返回值:  类型 (int32) 
+ *          =0          心跳成功
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackSavedataAck(EdpPacket* pkg, char** json_ack);
+
+/* 
+ * 函数名:  PacketSavedataSimpleString
+ * 功能:    打包 设备到设备云的EDP协议包, 存储数据(以分号分隔的简单字符串形式)
+ * 说明:    返回的EDP包发送给设备云后, 需要删除这个包
+ * 相关函数:UnpackSavedataSimpleString
+ * 参数:    dst_devid   目的设备ID
+ *          input       以分号分隔的简单字符串形式,
+ *                      详见《设备终端接入协议2-EDP.docx》
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketSavedataSimpleString(const char* dst_devid, const char* input);
+
+/* 
+ * 函数名:  UnpackSavedataSimpleString
+ * 功能:    解包 由设备云到设备的EDP协议包, 存储数据
+ * 说明:    接收设备云发来的数据, 通过函数GetEdpPacket和EdpPacketType判断出是savedata后,
+ *          将整个响应EDP包作为参数, 由该函数进行解析,
+ *          获取源端发送来的以分号作为分隔符的字符串。
+ * 相关函数: PacketSavedataSimpleString
+ *          
+ * 参数:    pkg         EDP包, 必须是savedata包
+ *          output      存储发送来的字符串
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackSavedataSimpleString(EdpPacket* pkg, char** output);
+
+/* 
+ * 函数名:  PacketSavedataBin
+ * 功能:    打包 设备到设备云的EDP协议包, 存储数据(bin格式数据)
+ * 说明:    返回的EDP包发送给设备云后, 需要删除这个包
+ * 相关函数:UnpackSavedata, UnpackSavedataBin
+ * 参数:    dst_devid   目的设备ID
+ *          desc_obj    数据描述 json格式
+ *          bin_data    二进制数据
+ *          bin_len     二进制数据长度
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EdpPacket* PacketSavedataBin(const char* dst_devid, 
+        cJSON* desc_obj, const uint8* bin_data, uint32 bin_len);
+/* 
+ * 函数名:  PacketSavedataBinStr
+ * 功能:    打包 设备到设备云的EDP协议包, 存储数据(bin格式数据)
+ * 说明:    返回的EDP包发送给设备云后, 需要删除这个包
+ * 相关函数:UnpackSavedata, UnpackSavedataBin
+ * 参数:    dst_devid   目的设备ID
+ *          desc_obj    数据描述 字符串格式
+ *          bin_data    二进制数据
+ *          bin_len     二进制数据长度
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketSavedataBinStr(const char* dst_devid, 
+        const char* desc_str, const uint8* bin_data, uint32 bin_len);
+
+/* 
+ * 函数名:  UnpackSavedata
+ * 功能:    解包 由设备云到设备的EDP协议包, 存储数据
+ * 说明:    接收设备云发来的数据, 通过函数GetEdpPacket和EdpPacketType判断出是savedata后,
+ *          将整个响应EDP包作为参数, 由该函数进行解析 
+ *          然后再根据json和bin的标识(jb_flag), 调用相应的解析函数
+ *          返回的源设备ID(src_devid)需要客户端释放
+ * 相关函数:PacketSavedataJson, PacketSavedataBin, GetEdpPacket, 
+ *          UnpackSavedataJson, UnpackSavedataBin
+ * 参数:    pkg         EDP包, 必须是savedata包
+ *          src_devid   源设备ID
+ *          jb_flag     json or bin数据, 1: json, 2: 二进制
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackSavedata(EdpPacket* pkg, char** src_devid, uint8* jb_flag);
+
+/* 
+ * 函数名:  UnpackSavedataJson
+ * 功能:    解包 由设备云到设备的EDP协议包, 存储数据(json格式数据)
+ * 说明:    返回的json数据(json_obj)需要客户端释放
+ * 相关函数:PacketSavedataJson, GetEdpPacket, EdpPacketType, UnpackSavedata
+ * 参数:    pkg         EDP包, 必须是savedata包的json数据包
+ *          json_obj    json数据 
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+int32 UnpackSavedataJson(EdpPacket* pkg, cJSON** json_obj);
+
+/* 
+ * 函数名:  UnpackSavedataBin
+ * 功能:    解包 由设备云到设备的EDP协议包, 存储数据(bin格式数据)
+ * 说明:    返回的数据描述(desc_obj)和bin数据(bin_data)需要客户端释放
+ * 相关函数:PacketSavedataBin, GetEdpPacket, EdpPacketType, UnpackSavedata
+ * 参数:    pkg         EDP包, 必须是savedata包的bin数据包
+ *          desc_obj    数据描述 json格式
+ *          bin_data    二进制数据
+ *          bin_len     二进制数据长度
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+int32 UnpackSavedataBin(EdpPacket* pkg, cJSON** desc_obj, 
+        uint8** bin_data, uint32* bin_len);
+/* 
+ * 函数名:  UnpackSavedataBinStr
+ * 功能:    解包 由设备云到设备的EDP协议包, 存储数据(bin格式数据)
+ * 说明:    返回的数据描述(desc_obj)和bin数据(bin_data)需要客户端释放
+ * 相关函数:PacketSavedataBin, GetEdpPacket, EdpPacketType, UnpackSavedata
+ * 参数:    pkg         EDP包, 必须是savedata包的bin数据包
+ *          desc_obj    数据描述 string格式
+ *          bin_data    二进制数据
+ *          bin_len     二进制数据长度
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackSavedataBinStr(EdpPacket* pkg, char** desc_str, 
+        uint8** bin_data, uint32* bin_len);
+/* 
+ * 函数名:  PacketCmdResp
+ * 功能:    向接入机发送命令响应
+ * 说明:    返回的EDP包发送给设备云后, 需要客户程序删除该包
+ *          
+ * 相关函数:UnpackCmdReq
+ * 参数:    cmdid       命令id
+ *          cmdid_len   命令id长度
+ *          resp        响应的消息
+ *          resp_len    响应消息长度
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketCmdResp(const char* cmdid, uint16 cmdid_len, 
+        const char* resp, uint32 resp_len);
+
+/* 
+ * 函数名:  UnpackCmdReq
+ * 功能:    解包 由设备云到设备的EDP协议包, 命令请求消息
+ * 说明:    接收设备云发来的数据, 解析命令请求消息包
+ *          获取的cmdid以及req需要在使用后释放。
+ * 相关函数:PacketCmdResp
+ * 参数:    pkg         EDP包
+ *          cmdid       获取命令id
+ *          cmdid_len   cmdid的长度
+ *          req         用户命令的起始位置
+ *          req_len     用户命令的长度
+ * 返回值:  类型 (int32) 
+ *          =0          解析成功
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackCmdReq(EdpPacket* pkg, char** cmdid, uint16* cmdid_len, 
+                  char** req, uint32* req_len);
+
+/* 
+ * 函数名:  PacketPing
+ * 功能:    打包 由设备到设备云的EDP协议包, 心跳
+ * 说明:    返回的EDP包发送给设备云后, 需要客户程序删除该包
+ *          设备云会回复心跳响应给设备
+ * 相关函数:UnpackPingResp
+ * 参数:    无
+ * 返回值:  类型 (EdpPacket*) 
+ *          非空        EDP协议包
+ *          为空        EDP协议包生成失败 
+ */
+EDPKIT_DLL EdpPacket* PacketPing(void);
+
+/* 
+ * 函数名:  UnpackPingResp
+ * 功能:    解包 由设备云到设备的EDP协议包, 心跳响应
+ * 说明:    接收设备云发来的数据, 通过函数GetEdpPacket和EdpPacketType判断出是连接响应后, 
+ *          将整个响应EDP包作为参数, 由该函数进行解析
+ * 相关函数:PacketPing, GetEdpPacket, EdpPacketType
+ * 参数:    pkg         EDP包, 必须是连接响应包
+ * 返回值:  类型 (int32) 
+ *          =0          心跳成功
+ *          >0          心跳失败, 具体失败原因见<OneNet接入方案与接口.docx>
+ *          <0          解析失败, 具体失败原因见本h文件的错误码
+ */
+EDPKIT_DLL int32 UnpackPingResp(EdpPacket* pkg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EDP_KIT_H__ */