From 0573d641c692dc36a563d7d65944ec040aeeb2cb Mon Sep 17 00:00:00 2001 From: windyyuan <2416560314@qq.com> Date: Fri, 6 Oct 2023 00:00:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E8=B5=9B=E4=BA=8C=E7=BA=A7=E8=B5=9B?= =?UTF-8?q?=E9=A2=98=E7=9B=AE=EF=BC=8CLora=E7=BD=91=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app_test/test_lora_p2p/client_adapter.c | 561 ++++++++++++++++++ .../app_test/test_lora_p2p/gateway_adpater.c | 434 ++++++++++++++ .../app_test/test_lora_p2p/readme.md | 21 + .../0client启动.png | Bin 0 -> 1185 bytes .../10client在断开连接下发送数据.png | Bin 0 -> 2126 bytes .../114514client多次发送数据.png | Bin 0 -> 7955 bytes .../1919810Gateway多次接受数据.png | Bin 0 -> 8445 bytes .../1启动网关.png | Bin 0 -> 3512 bytes .../2client发送连接请求.png | Bin 0 -> 1736 bytes .../3gateway接受并回复join请求.png | Bin 0 -> 3278 bytes .../4client接受gateway-reply,成功连接.png | Bin 0 -> 4088 bytes .../5client发送数据.png | Bin 0 -> 1779 bytes .../6gateway接受数据.png | Bin 0 -> 2648 bytes .../7client发送quit请求.png | Bin 0 -> 1827 bytes .../8gateway接受并回复quit请求.png | Bin 0 -> 3667 bytes .../9client接收gateway-reply并终止连接.png | Bin 0 -> 5230 bytes 16 files changed, 1016 insertions(+) create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/client_adapter.c create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/gateway_adpater.c create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/readme.md create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/0client启动.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/10client在断开连接下发送数据.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/114514client多次发送数据.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/1919810Gateway多次接受数据.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/1启动网关.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/2client发送连接请求.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/3gateway接受并回复join请求.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/4client接受gateway-reply,成功连接.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/5client发送数据.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/6gateway接受数据.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/7client发送quit请求.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/8gateway接受并回复quit请求.png create mode 100644 APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/9client接收gateway-reply并终止连接.png diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/client_adapter.c b/APP_Framework/Applications/app_test/test_lora_p2p/client_adapter.c new file mode 100644 index 000000000..444b419b2 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_lora_p2p/client_adapter.c @@ -0,0 +1,561 @@ +// +// Created by 18363 on 2023/9/17. +// + +#include + +#ifdef ADAPTER_SX1278 +extern AdapterProductInfoType Sx1278Attach(struct Adapter *adapter); +#endif + +#ifdef ADAPTER_E220 +extern AdapterProductInfoType E220Attach(struct Adapter *adapter); +#endif + +#ifdef ADAPTER_E22 +extern AdapterProductInfoType E22Attach(struct Adapter *adapter); +#endif + +/*******************报文宏********************/ +#define ADAPTER_LORA_DATA_LENGTH 112 +#define ADAPTER_LORA_TRANSFER_DATA_LENGTH ADAPTER_LORA_DATA_LENGTH + 16 + +#define ADAPTER_LORA_DATA_HEAD 0x3C +#define ADAPTER_LORA_NET_PANID 0x0102 +#define ADAPTER_LORA_DATA_TYPE_JOIN 0x0A +#define ADAPTER_LORA_DATA_TYPE_QUIT 0x0B +#define ADAPTER_LORA_DATA_TYPE_JOIN_REPLY 0x0C +#define ADAPTER_LORA_DATA_TYPE_QUIT_REPLY 0x0D +#define ADAPTER_LORA_DATA_TYPE_USERDATA 0x0E +#define ADAPTER_LORA_DATA_END 0x5A +/*******************枚举_客户端状态********************/ +enum ClientState +{ + CLIENT_DISCONNECT = 0, + CLIENT_CONNECT, +}; + +/*******************全局变量********************/ +//报文定义 +struct LoraDataFormat +{ + uint16_t flame_head; + uint32_t length; + uint8_t src_id; + uint8_t tar_id; + uint16_t panid; + + uint16_t data_type; + uint8_t data[ADAPTER_LORA_DATA_LENGTH]; + uint16_t crc_data; + + uint16_t flame_end; +}; + +struct ClientParam +{ + uint8_t client_id; + uint16_t panid; + enum ClientState client_state; + + uint8_t gateway_id; +}; + +static sem_t recv_sem; +static pthread_t receive_task; +static pthread_t client_task; +uint8_t recv_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH]; +uint8_t send_buf[ADAPTER_LORA_DATA_LENGTH]; +struct LoraDataFormat recv_data_format; + +/*******************CRC16校验********************/ +static uint16_t Crc16Compute(uint8_t *data, uint16_t length) +{ + int j; + uint16_t crc_data = 0xFFFF; + + while (length--) { + crc_data ^= *data++; + for( j = 0 ; j < 8 ; j ++) { + if(crc_data & 0x01) + crc_data = crc_data >> 1 ^ 0xA001; + else + crc_data = crc_data >> 1; + } + } + + return crc_data; +} + +static int Crc16Check(uint8_t *data, uint16_t length, uint16_t crc_data){ + uint16_t re_crc_data = Crc16Compute(data, length); + if (crc_data == re_crc_data) + return 0; + else + return -1; +} + +/*******************Gateway进程********************/ +//更新连接状态 +static int LoraClientUpdate(struct Adapter *adapter, struct LoraDataFormat *client_recv_data) +{ + struct ClientParam *client = (struct ClientParam *)adapter->adapter_param; + + if (ADAPTER_LORA_DATA_TYPE_JOIN_REPLY == client_recv_data->data_type) { + client->gateway_id = client_recv_data->src_id; + //client->panid = client_recv_data->panid; + client->client_state = CLIENT_CONNECT; + printf("LoraClientUpdate client join panid 0x%x successfully\n", client->panid); + } else if (ADAPTER_LORA_DATA_TYPE_QUIT_REPLY == client_recv_data->data_type) { + client->gateway_id = 0; + //client->panid = 0; + client->client_state = CLIENT_DISCONNECT; + printf("LoraClientUpdate client quit panid 0x%x successfully\n", client->panid); + } + + return 0; +} + +//发送用户数据 +//客户端发送数据,数据类型为UserDate +static int ClientSendData(struct Adapter *adapter, void *send_buf, int length) +{ + struct ClientParam *client = (struct ClientParam *)adapter->adapter_param; + + if (client->client_state != CLIENT_CONNECT) { + printf("Lora client %d does not connect to Lora gateway\n", client->client_id); + return 0; + } + if (length > ADAPTER_LORA_DATA_LENGTH) { + printf("Lora client %d send data %d is larger than max %d \n", client->client_id, length, ADAPTER_LORA_DATA_LENGTH); + return 0; + } + uint16_t client_user_type; + uint32_t client_user_length = ADAPTER_LORA_TRANSFER_DATA_LENGTH; + uint8_t client_user_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH]; + uint16_t crc16=Crc16Compute((uint8_t *)send_buf, ADAPTER_LORA_DATA_LENGTH); + memset(client_user_data, 0, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + client_user_type = ADAPTER_LORA_DATA_TYPE_USERDATA; + + client_user_data[0] = ADAPTER_LORA_DATA_HEAD; + client_user_data[1] = ADAPTER_LORA_DATA_HEAD; + client_user_data[2] = (client_user_length >> 24) & 0xFF; + client_user_data[3] = (client_user_length >> 16) & 0xFF; + client_user_data[4] = (client_user_length >> 8) & 0xFF; + client_user_data[5] = client_user_length & 0xFF; + client_user_data[6] = adapter->net_role_id & 0xFF; + client_user_data[7] = client->gateway_id; + client_user_data[8] = (client->panid>>8) & 0xFF; + client_user_data[9] = client->panid & 0xFF; + client_user_data[10] = ( client_user_type >> 8) & 0xFF; + client_user_data[11] = client_user_type & 0xFF; + memcpy((uint8_t *)(client_user_data + 12), (uint8_t *)send_buf, length); + client_user_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 4] = (crc16>>8)& 0xFF; + client_user_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 3] = crc16& 0xFF; + client_user_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 2] = ADAPTER_LORA_DATA_END; + client_user_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 1] = ADAPTER_LORA_DATA_END; + if (AdapterDeviceSend(adapter, client_user_data, ADAPTER_LORA_TRANSFER_DATA_LENGTH) < 0) { + printf("sending user data fails\n"); + return -1; + } + printf("sending user data is done\n"); + return 0; +} + +//连接或中止请求 +static int ClientJoinNet() +{ + printf("client join starts"); + struct AdapterData priv_lora_net; + struct Adapter *adapter= AdapterDeviceFindByName(ADAPTER_LORA_NAME); + struct ClientParam * client_param=(struct ClientParam * )adapter->adapter_param; + + uint16_t client_join_type; + uint32_t client_join_length = ADAPTER_LORA_TRANSFER_DATA_LENGTH; + uint8_t client_join_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH]; + memset(send_buf, 0, ADAPTER_LORA_DATA_LENGTH); + uint16_t crc16=Crc16Compute((uint8_t *)send_buf, ADAPTER_LORA_DATA_LENGTH); + memset(client_join_data, 0, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + + client_join_type = ADAPTER_LORA_DATA_TYPE_JOIN; + + client_join_data[0] = ADAPTER_LORA_DATA_HEAD; + client_join_data[1] = ADAPTER_LORA_DATA_HEAD; + client_join_data[2] = (client_join_length >> 24) & 0xFF; + client_join_data[3] = (client_join_length >> 16) & 0xFF; + client_join_data[4] = (client_join_length >> 8) & 0xFF; + client_join_data[5] = client_join_length & 0xFF; + client_join_data[6] = adapter->net_role_id & 0xFF; + client_join_data[7] = 0; + client_join_data[8] = (client_param->panid>>8) & 0xFF; + client_join_data[9] = client_param->panid & 0xFF; + client_join_data[10] = ( client_join_type >> 8) & 0xFF; + client_join_data[11] = client_join_type & 0xFF; + + client_join_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 4] = (crc16>>8)& 0xFF; + client_join_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 3] = crc16& 0xFF; + client_join_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 2] = ADAPTER_LORA_DATA_END; + client_join_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 1] = ADAPTER_LORA_DATA_END; + + priv_lora_net.len = ADAPTER_LORA_TRANSFER_DATA_LENGTH; + priv_lora_net.buffer = client_join_data; + + if (AdapterDeviceJoin(adapter, (uint8_t *)&priv_lora_net) < 0) { + printf("sending join message fails\n"); + return -1; + } + + printf("%s:client_join_data panid 0x%x client_id 0x%x\n", __func__, client_param->panid, adapter->net_role_id); + printf("sending join message is done\n"); + return 0; +} + +//终端与目标网关的连接 +static int ClientQuitNet() +{ + printf("client quit starts"); + struct AdapterData priv_lora_net; + struct Adapter *adapter= AdapterDeviceFindByName(ADAPTER_LORA_NAME); + struct ClientParam * client_param=(struct ClientParam * )adapter->adapter_param; + + uint16_t client_quit_type; + uint32_t client_quit_length = ADAPTER_LORA_TRANSFER_DATA_LENGTH; + uint8_t client_quit_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH]; + memset(send_buf, 0, ADAPTER_LORA_DATA_LENGTH); + uint16_t crc16=Crc16Compute((uint8_t *)send_buf, ADAPTER_LORA_DATA_LENGTH); + + memset(client_quit_data, 0, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + + client_quit_type = ADAPTER_LORA_DATA_TYPE_QUIT; + + client_quit_data[0] = ADAPTER_LORA_DATA_HEAD; + client_quit_data[1] = ADAPTER_LORA_DATA_HEAD; + client_quit_data[2] = (client_quit_length >> 24) & 0xFF; + client_quit_data[3] = (client_quit_length >> 16) & 0xFF; + client_quit_data[4] = (client_quit_length >> 8) & 0xFF; + client_quit_data[5] = client_quit_length & 0xFF; + client_quit_data[6] = adapter->net_role_id & 0xFF; + client_quit_data[7] = client_param->gateway_id; + client_quit_data[8] = (client_param->panid>>8) & 0xFF; + client_quit_data[9] = client_param->panid & 0xFF; + client_quit_data[10] = ( client_quit_type >> 8) & 0xFF; + client_quit_data[11] = client_quit_type & 0xFF; + + client_quit_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 4] = (crc16>>8)& 0xFF; + client_quit_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 3] = crc16& 0xFF; + client_quit_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 2] = ADAPTER_LORA_DATA_END; + client_quit_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 1] = ADAPTER_LORA_DATA_END; + + priv_lora_net.len = ADAPTER_LORA_TRANSFER_DATA_LENGTH; + priv_lora_net.buffer = client_quit_data; + + if (AdapterDeviceDisconnect(adapter, (uint8_t *)&priv_lora_net) < 0) { + printf("sending quit message is fails"); + return -1; + } + + printf("%s:client_quit_data panid 0x%x client_id 0x%x\n", __func__, client_param->panid, adapter->net_role_id); + printf("sending quit message is done\n"); + return 0; +} +//打印格式化数据 +static int PrintFormattedData(struct LoraDataFormat formatData){ + printf("HEAD: 0x%x\n",formatData.flame_head); + printf("LENGTH: 0x%x\n",formatData.length); + printf("SRC_ID: 0x%x\n", formatData.src_id); + printf("TAR_ID: 0x%x\n", formatData.tar_id); + printf("PANID: 0x%x", formatData.panid); + printf("DATA_TYPE: 0x%x\n", formatData.data_type); + printf("CRC_DATA: 0x%x\n", formatData.crc_data); + printf("END: 0x%x\n", formatData.flame_end); +} + +//接收数据分析 +static int AnalyzeClientReceiveData(struct Adapter *adapter) +{ + printf("analyze the receivedata\n"); + int ret = 0; + + if (ADAPTER_LORA_NET_PANID == recv_data_format.panid&&adapter->net_role_id==recv_data_format.tar_id) { + + // printf("%s: gateway_recv_data\n", __func__); + + PrintFormattedData(recv_data_format); + + switch (recv_data_format.data_type) + { + //如果从gateway接收的是连接或中止回复 + case ADAPTER_LORA_DATA_TYPE_JOIN_REPLY : + case ADAPTER_LORA_DATA_TYPE_QUIT_REPLY : + printf("The data type is JOIN or REPLY"); + ret = LoraClientUpdate(adapter, &recv_data_format); + break; + default: + break; + } + + //清空 + memset(&recv_data_format, 0 , sizeof(struct LoraDataFormat)); + } else { + printf("target client does not match\n"); + ret = -1; + } + printf("analysis is done\n"); + return ret; +} +//接收数据格式化 +static int FormatReceiveData(struct Adapter *adapter, uint8_t *recv_data, uint16_t length) +{ + printf("Format receive data starts\n"); + if ((ADAPTER_LORA_DATA_HEAD == recv_data[0]) && (ADAPTER_LORA_DATA_HEAD == recv_data[1]) && + (ADAPTER_LORA_DATA_END == recv_data[length - 1]) && (ADAPTER_LORA_DATA_END == recv_data[length - 2])){ + + recv_data_format.flame_head = ((recv_data[0] << 8) & 0xFF00) | recv_data[1]; + recv_data_format.length = ((recv_data[2] << 24) & 0xFF000000) | ((recv_data[3] << 16) & 0xFF0000) | + ((recv_data[4] << 8) & 0xFF00) | (recv_data[5] & 0xFF); + recv_data_format.src_id = recv_data[6]; + recv_data_format.tar_id = recv_data[7]; + recv_data_format.panid = ((recv_data[8] << 8) & 0xFF00) | recv_data[9]; + recv_data_format.data_type = ((recv_data[10] << 8) & 0xFF00) | recv_data[11]; + + recv_data_format.crc_data=((recv_data[length - 4] << 8) & 0xFF00) | recv_data[length - 3]; + recv_data_format.flame_end = ((recv_data[length - 2] << 8) & 0xFF00) | recv_data[length - 1]; + + memcpy(recv_data_format.data, (uint8_t *)(recv_data + 12), ADAPTER_LORA_DATA_LENGTH); + + if(Crc16Check(recv_data_format.data, ADAPTER_LORA_DATA_LENGTH, recv_data_format.crc_data)<0){ + printf("crc16check is fail\n"); + return -1; + } + else return 0; + } + printf("the head or end of the data is wrong\n"); + return -1; +} + +static void *ClientReceiveTask(void *parameter){ + printf("client receive task starts\n"); + int ret = 0; + struct Adapter *lora_adapter = (struct Adapter *)parameter; + + while (1) { + memset(recv_data, 0, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + + ret = AdapterDeviceRecv(lora_adapter, recv_data, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + if (ret <= 0) { + // printf("AdapterDeviceRecv error.Just return\n"); + continue; + } + printf("AdapterDeviceRecv success\n"); + + if(FormatReceiveData(lora_adapter, recv_data, ADAPTER_LORA_TRANSFER_DATA_LENGTH)<0){ + continue; + } + if(AnalyzeClientReceiveData(lora_adapter)){ + continue; + } + } + + return 0; +} + +static void *ClientDataTask(void *parameter) +{ + printf("client data task starts\n"); + //printf("checkpoint10\n"); + //PrivTaskDelay(10000); + + //获取clientparam参数引用 + int i, ret = 0; + struct Adapter *lora_adapter = (struct Adapter *)parameter; + struct ClientParam *client = (struct ClientParam *)lora_adapter->adapter_param; + + //设置发送缓存 + memset(send_buf, 0, ADAPTER_LORA_DATA_LENGTH); + sprintf(send_buf, "Lora client %d adapter test\n", client->client_id); + //printf("checkpoint11\n"); + // PrivTaskDelay(10000); + while (1) { + if (send_buf) { + PrivTaskDelay(2000); + // printf("client is sending test data\n"); + ClientSendData(lora_adapter, (void *)send_buf, strlen(send_buf)); + // printf("sending data is done"); + } + } + + return 0; +} + +static int SendMessageTask(int arg, char* args[]) +{ + printf("client data task starts\n"); + int i, ret = 0; + struct Adapter *lora_adapter= AdapterDeviceFindByName(ADAPTER_LORA_NAME); + struct ClientParam *client = (struct ClientParam *)lora_adapter->adapter_param; + + //设置发送缓存 + memset(send_buf, 0, ADAPTER_LORA_DATA_LENGTH); + sprintf(send_buf, args[1]); + //printf("checkpoint11\n"); + // PrivTaskDelay(10000); + if (send_buf) { + printf("client is sending test data\n"); + ClientSendData(lora_adapter, (void *)send_buf, strlen(send_buf)); + printf("sending data is done"); + } + + return 0; +} + + +int ClientLoraLaunch(void){ + + printf("client is launching\n"); + //获取适配器 + struct Adapter *adapter= AdapterDeviceFindByName(ADAPTER_LORA_NAME); + AdapterDeviceOpen(adapter); + //printf("checkpoint1\n"); + //PrivTaskDelay(10000); + + //配置 +#ifdef ADD_NUTTX_FEATURES + pthread_attr_t lora_client_attr = PTHREAD_ATTR_INITIALIZER; + lora_client_attr.priority = 20; + lora_client_attr.stacksize = 2048; +#else + pthread_attr_t lora_client_attr; + lora_client_attr.schedparam.sched_priority = 20; + lora_client_attr.stacksize = 2048; +#endif + + //启动客户端接收Task:LoraClientDataTask + PrivTaskCreate(&receive_task, &lora_client_attr, &ClientReceiveTask, (void *)adapter); + PrivTaskStartup(&receive_task); + +//#ifdef ADD_NUTTX_FEATURES +// lora_client_attr.priority = 19; +//#else +// lora_client_attr.schedparam.sched_priority = 19; +//#endif +// //printf("checkpoint2\n"); +// //PrivTaskDelay(10000); +// //printf("checkpoint3"); +// //启动客户端Task:LoraClientDataTask +// //create lora client task +// PrivTaskCreate(&client_task, &lora_client_attr, &ClientDataTask, (void *)adapter); +// PrivTaskStartup(&client_task); +// //printf("checkpoint4"); +// //PrivTaskDelay(10000); + return 0; + +} +/*******************设备的初始化和注册********************/ +////注册 +static int ClientAdapterRegister(struct Adapter *adapter){ + int ret = 0; + struct ClientParam *lora_client; + + strncpy(adapter->name, ADAPTER_LORA_NAME, NAME_NUM_MAX); + + adapter->net_protocol = PRIVATE_PROTOCOL; + + + lora_client = PrivMalloc(sizeof(struct ClientParam)); + if (!lora_client) { + printf("creating clientparems is failed\n"); + PrivFree(lora_client); + return -1; + } + + memset(lora_client, 0, sizeof(struct ClientParam)); + + lora_client->client_id = ADAPTER_LORA_NET_ROLE_ID; + lora_client->client_state = CLIENT_DISCONNECT; + lora_client->panid = ADAPTER_LORA_NET_PANID; + lora_client->gateway_id = 0; + printf("creating clientparams is successful\n"); + + memset(&recv_data_format, 0, sizeof(struct LoraDataFormat)); + printf("memestting clientparams is successful\n"); + + adapter->net_role = CLIENT; + adapter->adapter_param = (void *)lora_client; + + adapter->net_role_id = ADAPTER_LORA_NET_ROLE_ID; + + adapter->adapter_status = UNREGISTERED; + + ret = AdapterDeviceRegister(adapter); + printf("setting up the adpater is successful\n"); + if (ret < 0) { + printf("Adapter4G register error\n"); + if (lora_client) + PrivFree(lora_client); + return -1; + } + return ret; +} +//初始化 +int AdapterLoraInit(void){ + printf("init adapter starts\n"); + int ret=0; + struct Adapter *adapter= PrivMalloc(sizeof(struct Adapter)); + if (!adapter) { + PrivFree(adapter); + return -1; + } + memset(adapter, 0, sizeof(struct Adapter)); + //注册adapter + ret=ClientAdapterRegister(adapter); + //根据产品型号进行配置 +#ifdef ADAPTER_SX1278 + AdapterProductInfoType product_info = Sx1278Attach(adapter); + if (!product_info) { + printf("AdapterLoraInit sx1278 attach error\n"); + PrivFree(adapter); + return -1; + } + + adapter->product_info_flag = 1; + adapter->info = product_info; + adapter->done = product_info->model_done; + +#endif + +#ifdef ADAPTER_E220 + AdapterProductInfoType product_info = E220Attach(adapter); + if (!product_info) { + printf("AdapterLoraInit e220 attach error\n"); + PrivFree(adapter); + return -1; + } + + adapter->product_info_flag = 1; + adapter->info = product_info; + adapter->done = product_info->model_done; +#endif + +#ifdef ADAPTER_E22 + AdapterProductInfoType product_info = E22Attach(adapter); + if (!product_info) { + printf("AdapterLoraInit e22 attach error\n"); + PrivFree(adapter); + return -1; + } + + adapter->product_info_flag = 1; + adapter->info = product_info; + adapter->done = product_info->model_done; +#endif + PrivSemaphoreCreate(&adapter->sem, 0 ,0); + PrivSemaphoreCreate(&recv_sem, 0, 0); + PrivMutexCreate(&adapter->lock, 0); + printf("init adapter is completed\n"); + return ret; +} +PRIV_SHELL_CMD_FUNCTION(ClientLoraLaunch, a lora test sample, PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(ClientJoinNet, a lora test sample, PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(ClientQuitNet, a lora test sample, PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(SendMessageTask, a lora test sample, PRIV_SHELL_CMD_MAIN_ATTR); + diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/gateway_adpater.c b/APP_Framework/Applications/app_test/test_lora_p2p/gateway_adpater.c new file mode 100644 index 000000000..c5affd233 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_lora_p2p/gateway_adpater.c @@ -0,0 +1,434 @@ +// +// Created by 18363 on 2023/9/17. +// + +#include + +#ifdef ADAPTER_SX1278 +extern AdapterProductInfoType Sx1278Attach(struct Adapter *adapter); +#endif + +#ifdef ADAPTER_E220 +extern AdapterProductInfoType E220Attach(struct Adapter *adapter); +#endif + +#ifdef ADAPTER_E22 +extern AdapterProductInfoType E22Attach(struct Adapter *adapter); +#endif + +/*******************报文宏********************/ +#define ADAPTER_LORA_DATA_LENGTH 112 +#define ADAPTER_LORA_TRANSFER_DATA_LENGTH ADAPTER_LORA_DATA_LENGTH + 16 + +#define ADAPTER_LORA_DATA_HEAD 0x3C +#define ADAPTER_LORA_NET_PANID 0x0102 +#define ADAPTER_LORA_DATA_TYPE_JOIN 0x0A +#define ADAPTER_LORA_DATA_TYPE_QUIT 0x0B +#define ADAPTER_LORA_DATA_TYPE_JOIN_REPLY 0x0C +#define ADAPTER_LORA_DATA_TYPE_QUIT_REPLY 0x0D +#define ADAPTER_LORA_DATA_TYPE_USERDATA 0x0E +#define ADAPTER_LORA_DATA_END 0x5A + +/*******************枚举_客户端状态********************/ +enum ClientState +{ + CLIENT_DISCONNECT = 0, + CLIENT_CONNECT, +}; + +/*******************全局变量********************/ +//报文定义 +struct LoraDataFormat +{ + uint16_t flame_head; + uint32_t length; + uint8_t src_id; + uint8_t tar_id; + uint16_t panid; + + uint16_t data_type; + uint8_t data[ADAPTER_LORA_DATA_LENGTH]; + uint16_t crc_data; + + uint16_t flame_end; +}; + +struct GatewayParam{ + uint8_t gateway_id; + uint16_t panid; + uint8_t client_id[ADAPTER_LORA_CLIENT_NUM]; + int client_num; +}; + + + +static sem_t recv_sem; +static pthread_t receive_task; +static pthread_t gateway_task; +uint8_t gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH]; +uint8_t send_buff[ADAPTER_LORA_DATA_LENGTH]; +uint8_t recv_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH]; +struct LoraDataFormat recv_data_format; + + +/*******************CRC16校验********************/ +static uint16_t Crc16Compute(uint8_t *data, uint16_t length) +{ + int j; + uint16_t crc_data = 0xFFFF; + + while (length--) { + crc_data ^= *data++; + for( j = 0 ; j < 8 ; j ++) { + if(crc_data & 0x01) + crc_data = crc_data >> 1 ^ 0xA001; + else + crc_data = crc_data >> 1; + } + } + + return crc_data; +} + +static int Crc16Check(uint8_t *data, uint16_t length, uint16_t crc_data){ + uint16_t re_crc_data = Crc16Compute(data, length); + if (crc_data == re_crc_data) + return 0; + else + return -1; +} + +/*******************Gateway进程********************/ +//接收用户数据 +static int GatewayHandleData(struct Adapter *adapter, struct LoraDataFormat *recv_data){ + + /*User needs to handle client data depends on the requirement*/ + printf("Lora Gateway receive Client %d data:\n", recv_data->src_id); + printf("%s\n", recv_data->data); + printf("handling data is done\n"); + return 0; +} +//回复中止或连接请求 +static int GatewayReplyJoin(struct Adapter *adapter, struct LoraDataFormat *recv_data) +{ + printf("reply join\n"); + int i; + int client_join_flag = 0; + uint16_t gateway_data_type; + struct GatewayParam *gateway = (struct GatewayParam *)adapter->adapter_param; + uint32_t gateway_reply_length = ADAPTER_LORA_TRANSFER_DATA_LENGTH; + memset(send_buff, 0, ADAPTER_LORA_DATA_LENGTH); + uint16_t crc16=Crc16Compute((uint8_t *)send_buff, ADAPTER_LORA_DATA_LENGTH); + + memset(gateway_reply_data, 0, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + + for (i = 0; i < gateway->client_num; i ++) { + if (recv_data->src_id == gateway->client_id[i]) { + printf("Lora client_%d 0x%x has already join net 0x%x\n", i, recv_data->src_id, gateway->gateway_id); + client_join_flag = 1; + break; + } + } + if (!client_join_flag) { + if (gateway->client_num > ADAPTER_LORA_CLIENT_NUM) { + printf("Lora gateway only support %u(max) client\n", ADAPTER_LORA_CLIENT_NUM); + gateway->client_num = 0; + } + gateway->client_id[gateway->client_num] = recv_data->src_id; + gateway->client_num++; + } + + + gateway_data_type = ADAPTER_LORA_DATA_TYPE_JOIN_REPLY; + + gateway_reply_data[0] = ADAPTER_LORA_DATA_HEAD; + gateway_reply_data[1] = ADAPTER_LORA_DATA_HEAD; + gateway_reply_data[2] = (gateway_reply_length >> 24) & 0xFF; + gateway_reply_data[3] = (gateway_reply_length >> 16) & 0xFF; + gateway_reply_data[4] = (gateway_reply_length >> 8) & 0xFF; + gateway_reply_data[5] = gateway_reply_length & 0xFF; + gateway_reply_data[6] = recv_data->tar_id; + gateway_reply_data[7] = recv_data->src_id; + gateway_reply_data[8] = (gateway->panid>>8) & 0xFF; + gateway_reply_data[9] = gateway->panid & 0xFF; + gateway_reply_data[10] = (gateway_data_type >> 8) & 0xFF; + gateway_reply_data[11] = gateway_data_type & 0xFF; + + gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 4] = (crc16>>8)& 0xFF; + gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 3] = crc16& 0xFF; + gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 2] = ADAPTER_LORA_DATA_END; + gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 1] = ADAPTER_LORA_DATA_END; + + if (AdapterDeviceSend(adapter, gateway_reply_data, ADAPTER_LORA_TRANSFER_DATA_LENGTH) < 0) { + return -1; + } + printf("Lora gateway 0x%x accept client 0x%x \n", gateway->gateway_id, recv_data->src_id); + printf("replying join is done"); + return 0; +} + +static int GatewayReplyQuit(struct Adapter *adapter, struct LoraDataFormat *recv_data){ + printf("reply quit\n"); + int i; + uint16_t gateway_data_type; + struct GatewayParam *gateway = (struct GatewayParam *)adapter->adapter_param; + uint32_t gateway_reply_length = ADAPTER_LORA_TRANSFER_DATA_LENGTH; + memset(send_buff, 0, ADAPTER_LORA_DATA_LENGTH); + uint16_t crc16=Crc16Compute((uint8_t *)send_buff, ADAPTER_LORA_DATA_LENGTH); + + memset(gateway_reply_data, 0, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + + for (i = 0; i < gateway->client_num; i ++) { + if (gateway->client_id[i] == recv_data->src_id) { + for(int j=i+1;jclient_num;++j){ + gateway->client_id[j-1] = gateway->client_id[j]; + } + gateway->client_num --; + break; + } + } + + gateway_data_type = ADAPTER_LORA_DATA_TYPE_QUIT_REPLY; + + gateway_reply_data[0] = ADAPTER_LORA_DATA_HEAD; + gateway_reply_data[1] = ADAPTER_LORA_DATA_HEAD; + gateway_reply_data[2] = (gateway_reply_length >> 24) & 0xFF; + gateway_reply_data[3] = (gateway_reply_length >> 16) & 0xFF; + gateway_reply_data[4] = (gateway_reply_length >> 8) & 0xFF; + gateway_reply_data[5] = gateway_reply_length & 0xFF; + gateway_reply_data[6] = recv_data->tar_id; + gateway_reply_data[7] = recv_data->src_id; + gateway_reply_data[8] = (gateway->panid>>8) & 0xFF; + gateway_reply_data[9] = gateway->panid & 0xFF; + gateway_reply_data[10] = (gateway_data_type >> 8) & 0xFF; + gateway_reply_data[11] = gateway_data_type & 0xFF; + + gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 4] = (crc16>>8)& 0xFF; + gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 3] = crc16& 0xFF; + gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 2] = ADAPTER_LORA_DATA_END; + gateway_reply_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH - 1] = ADAPTER_LORA_DATA_END; + if (AdapterDeviceSend(adapter, gateway_reply_data, ADAPTER_LORA_TRANSFER_DATA_LENGTH) < 0) { + return -1; + } + printf("Lora gateway 0x%x accept client 0x%x \n", gateway->gateway_id, recv_data->src_id); + printf("replying quit is done"); + return 0; +} +// +//打印格式化数据 +static int PrintFormattedData(struct LoraDataFormat formatData){ + printf("HEAD: 0x%x\n",formatData.flame_head); + printf("LENGTH: 0x%x\n",formatData.length); + printf("SRC_ID: 0x%x\n", formatData.src_id); + printf("TAR_ID: 0x%x\n", formatData.tar_id); + printf("PANID: 0x%x", formatData.panid); + printf("DATA_TYPE: 0x%x\n", formatData.data_type); + printf("CRC_DATA: 0x%x\n", formatData.crc_data); + printf("END: 0x%x\n", formatData.flame_end); +} + +//接收数据分析 +static int AnalyzeGateWayReceiveData(struct Adapter *adapter) +{ + int ret = 0; + + if (ADAPTER_LORA_NET_PANID == recv_data_format.panid) { + + //printf("%s: gateway_recv_data\n", __func__); + PrintFormattedData(recv_data_format); + + switch (recv_data_format.data_type) + { + //如果是连接或中止请求 + case ADAPTER_LORA_DATA_TYPE_JOIN : + ret = GatewayReplyJoin(adapter, &recv_data_format); + break; + case ADAPTER_LORA_DATA_TYPE_QUIT : + ret = GatewayReplyQuit(adapter, &recv_data_format); + break; + //如果是用户数据 + case ADAPTER_LORA_DATA_TYPE_USERDATA : + ret = GatewayHandleData(adapter, &recv_data_format); + break; + default: + break; + } + } else { + ret = -1; + } + + return ret; +} + + + +//接收数据格式化 +static int FormatReceiveData(struct Adapter *adapter, uint8_t *recv_data, uint16_t length) +{ + if ((ADAPTER_LORA_DATA_HEAD == recv_data[0]) && (ADAPTER_LORA_DATA_HEAD == recv_data[1]) && + (ADAPTER_LORA_DATA_END == recv_data[length - 1]) && (ADAPTER_LORA_DATA_END == recv_data[length - 2])){ + + recv_data_format.flame_head = ((recv_data[0] << 8) & 0xFF00) | recv_data[1]; + recv_data_format.length = ((recv_data[2] << 24) & 0xFF000000) | ((recv_data[3] << 16) & 0xFF0000) | + ((recv_data[4] << 8) & 0xFF00) | (recv_data[5] & 0xFF); + recv_data_format.src_id = recv_data[6]; + recv_data_format.tar_id = recv_data[7]; + recv_data_format.panid = ((recv_data[8] << 8) & 0xFF00) | recv_data[9]; + recv_data_format.data_type = ((recv_data[10] << 8) & 0xFF00) | recv_data[11]; + + recv_data_format.crc_data=((recv_data[length - 4] << 8) & 0xFF00) | recv_data[length - 3]; + recv_data_format.flame_end = ((recv_data[length - 2] << 8) & 0xFF00) | recv_data[length - 1]; + + memcpy(recv_data_format.data, (uint8_t *)(recv_data + 12), ADAPTER_LORA_DATA_LENGTH); + + if(Crc16Check(recv_data_format.data, ADAPTER_LORA_DATA_LENGTH, recv_data_format.crc_data)<0){ + printf("crc16check is fail\n"); + return -1; + } + else return 0; + } + return -1; +} + +static void *GatewayReceiveTask(void *parameter){ + int ret = 0; + struct Adapter *lora_adapter = (struct Adapter *)parameter; + + while (1) { + memset(recv_data, 0, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + + ret = AdapterDeviceRecv(lora_adapter, recv_data, ADAPTER_LORA_TRANSFER_DATA_LENGTH); + if (ret <= 0) { + printf("AdapterDeviceRecv error.Just return\n"); + continue; + } + printf("AdapterDeviceRecv success\n"); + if(FormatReceiveData(lora_adapter, recv_data, ADAPTER_LORA_TRANSFER_DATA_LENGTH)<0){ + continue; + } + if(AnalyzeGateWayReceiveData(lora_adapter)){ + continue; + } + } + + return 0; +} + +int GatewayLoraLaunch(void){ + + //获取适配器 + struct Adapter *adapter= AdapterDeviceFindByName(ADAPTER_LORA_NAME); + AdapterDeviceOpen(adapter); + //配置 +#ifdef ADD_NUTTX_FEATURES + pthread_attr_t lora_gateway_attr = PTHREAD_ATTR_INITIALIZER; + lora_gateway_attr.priority = 20; + lora_gateway_attr.stacksize = 2048; +#else + pthread_attr_t lora_gateway_attr; + lora_gateway_attr.schedparam.sched_priority = 20; + lora_gateway_attr.stacksize = 2048; +#endif + //启动网关接收Task:LoraReceiveTask,第四个为传入参数 + PrivTaskCreate(&receive_task, &lora_gateway_attr, &GatewayReceiveTask, (void *)adapter); + PrivTaskStartup(&receive_task); + +} +/*******************设备的初始化和注册********************/ +//注册 +int GatewayAdapterRegister(struct Adapter *adapter){ + int ret = 0; + struct GatewayParam *lora_gateway; + + strncpy(adapter->name, ADAPTER_LORA_NAME, NAME_NUM_MAX); + + adapter->net_protocol = PRIVATE_PROTOCOL; + + + lora_gateway = PrivMalloc(sizeof(struct GatewayParam)); + if (!lora_gateway) { + PrivFree(lora_gateway); + return -1; + } + + memset(lora_gateway, 0, sizeof(struct GatewayParam)); + + lora_gateway->gateway_id = ADAPTER_LORA_NET_ROLE_ID; + lora_gateway->panid = ADAPTER_LORA_NET_PANID; + lora_gateway->client_num=0; + + memset(&recv_data_format, 0, sizeof(struct LoraDataFormat)); + + adapter->net_role = GATEWAY; + adapter->adapter_param = (void *)lora_gateway; + + adapter->net_role_id = ADAPTER_LORA_NET_ROLE_ID; + + adapter->adapter_status = UNREGISTERED; + + ret = AdapterDeviceRegister(adapter); + if (ret < 0) { + printf("Adapter4G register error\n"); + if (lora_gateway) + PrivFree(lora_gateway); + return -1; + } + + return ret; +} +//初始化 +int AdapterLoraInit(void){ + printf("init adapter starts\n"); + int ret=0; + struct Adapter *adapter= PrivMalloc(sizeof(struct Adapter)); + memset(adapter, 0, sizeof(struct Adapter)); + //注册adapter + ret=GatewayAdapterRegister(adapter); + //根据产品型号进行配置 +#ifdef ADAPTER_SX1278 + AdapterProductInfoType product_info = Sx1278Attach(adapter); + if (!product_info) { + printf("AdapterLoraInit sx1278 attach error\n"); + PrivFree(adapter); + return -1; + } + + adapter->product_info_flag = 1; + adapter->info = product_info; + adapter->done = product_info->model_done; + +#endif + +#ifdef ADAPTER_E220 + AdapterProductInfoType product_info = E220Attach(adapter); + if (!product_info) { + printf("AdapterLoraInit e220 attach error\n"); + PrivFree(adapter); + return -1; + } + + adapter->product_info_flag = 1; + adapter->info = product_info; + adapter->done = product_info->model_done; +#endif + +#ifdef ADAPTER_E22 + AdapterProductInfoType product_info = E22Attach(adapter); + if (!product_info) { + printf("AdapterLoraInit e22 attach error\n"); + PrivFree(adapter); + return -1; + } + + adapter->product_info_flag = 1; + adapter->info = product_info; + adapter->done = product_info->model_done; +#endif + PrivSemaphoreCreate(&adapter->sem, 0 ,0); + PrivSemaphoreCreate(&recv_sem, 0, 0); + PrivMutexCreate(&adapter->lock, 0); + printf("init adapter is completed\n"); + return ret; +} + +PRIV_SHELL_CMD_FUNCTION(GatewayLoraLaunch, a lora test sample, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/readme.md b/APP_Framework/Applications/app_test/test_lora_p2p/readme.md new file mode 100644 index 000000000..452bf86bd --- /dev/null +++ b/APP_Framework/Applications/app_test/test_lora_p2p/readme.md @@ -0,0 +1,21 @@ +通信报文定义: +struct LoraDataFormat +{ + uint16_t flame_head;//报文头0x3C3C + uint32_t length;//报文长度 + uint8_t src_id;//源地址 + uint8_t tar_id;//目的地址 + uint16_t panid;//域id 0x0102 + uint16_t data_type;//数据类型join、quit、userdata、join_reply、quit_reply + uint8_t data[ADAPTER_LORA_DATA_LENGTH];//裸数据 + uint16_t crc_data; + +​ uint16_t flame_end;0x5A5A + +}; +通信类型: +JOIN 0x0A +QUIT 0x0B +JOIN_REPLY 0x0C +QUIT_REPLY 0x0D +USERDATA 0x0E diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/0client启动.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/0client启动.png new file mode 100644 index 0000000000000000000000000000000000000000..4cee795c0d85e258e5fd7d886ec46a13c6d09240 GIT binary patch literal 1185 zcmV;S1YY}zP)ZgXgFbngSdJ^%m&Gf6~2RCt{2 zoo$ZeAPhih)vNW?9B%f9vM}Ns)kKGwd6!;E)B#AMq%BA-)#*b^#>t1^`{Zjqf{kH12?4I=# zL3-pBoRCJC(NphKfBM=w;#uo!?o09wz!SGlyiy~LF`7EGwLZW~e5{GR8t>>)aHMXj zevgm*Gk`02Nykd*=1r^Iay*sRIX+Vx1+B+lCEc~ns$9S3wZ^W-PXG@d;qT%Y05*lN zOMuOx69a4xofu$q#7=zI=%PC&cEEQdcH$KiAUy1@xMNHwhck3dr)PD96+55@cfBvT z2JxI&qI9;KmZ#T_v*i3Uc_M+g-5zTGr*)3|(VTNjzLx4sb}ahgd-)$o-AZiG*6U4x zXo=RYRgZN2ssxDAdy9VLyX7Nx+G`~9(%B*(tw#7?vu&wk^^H*$v}~UMAx(WPkN^QY zvvmSQzCIkeYraAP#Bq;zJ^q6}mP>$;@Uq*|b9DlQ^qgxp^3MWHUzj60VPgv^30X{= z!4VVW(1`&yhXe?K&3WaUBY9L+T2?DRu8oSQI>VXcCx9LJwNS1_9!d2|bynGkVFL)c zv$#yBYsWqSFqUG(mNfPBnvzOW`21Qck-}o5SN{sj0e~t;u)Q|fp;T_2e)p7Hk|(_M zud*CKkea+&$^WJ6BR7g>BvRD$vowI!5fdP0bl?!yo3gIv4?s?FW6Ros)Agjblc$0F zyNrUX`2!Gw@|;*xo_^y+dQI9GYW*{i>S&O5$j|(e#2J48MlvPrlHdyfKM1=7*c=id z05*q_7+`aryL{ctOdlV}Q5L_)P>bVSpPh$$(0OXHs<3d|ZY zSJH2ZFtgkjvbMNRr|-7o?3LId>1pZL+OzKVldy6xsu5cUtzSe)>ud9gz0O}}BsA2X zgBSTdq~$p++m^(UmX1`<)rl;YcBt{kvwSLNrhL8cdlL&R`Zddhmfhazam&8uIh5-3 zJa5b2*ZLfK$}P(`PrD<_XNzhi_TtK~Ta}{2yzG`D)VxM$uaSM`NFhCEi%EKIsgtcr>f4Cv`e?lTm8Q^Mv^sijceFn}s5Z8|8oQ)t zMrYF4tR;3xYgUV%T6sPK^iUfOrTgl!afo*!OTPXr>8a_qwzu?|l|${ z2xGnw&ufFgqDRx9EVBvAwAuRHH2&6R54B{EUVkJ%O1d>2SF<5yv746Xe@Cx&IJ!N1 zGksx>>?x~k?5rZQo(Ex<08Y$WBa;9DusMGKM(DTlC=k+?00000NkvXXu0mjf!LLSL literal 0 HcmV?d00001 diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/10client在断开连接下发送数据.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/10client在断开连接下发送数据.png new file mode 100644 index 0000000000000000000000000000000000000000..60606a03bddbdef2699343b14078bd2987fa684a GIT binary patch literal 2126 zcmV-U2(kBxP)ZgXgFbngSdJ^%m*;7LS5RCt{2 zonLO`HVnp@#iDzJwr{!2Tp&TNu^8kaL6B<%$pw6%MUT*Z822ITR8=L4q^WY|*kTCO1U15)r+>z0%$N0|5ZQD17NH0001Tz(D~3h6N4^05B|YPym2oNjj)y zS!h|7)>?KE>(%Jr+Uwco&DI`WEeZQzPhZq(pO@Xy>;Rsx=ku8^mka&)@z-bO>2y*L z@YCre&aX}E95@ZJ#$K9xv$gqJ+YiR%a|ZSI&!0VY6yY3ZIHT1LkNGC@;N)<%q>;E_1)d7GiECv&rDPHd*CctJ~nNxM6@o;BK|%8j?2&4S(b&hsjVZn$E8$xtxm2y_fu;}+8sctgQp!UGcG*X{azi)O@`SFaUbQjO9K}mE<$>~p(3ukBH<7z6O)0xAg zd`XYAk2pJCdbIUorZf&J2j%s6HOnGwZJjy$xdrP~erl25T5k%@KBrUbq*8Xg^l0j} z^e3o?c^{PIxqeT6sa)%gn%9M0U>xz%%>X5eA zsz+icSDv#E8j)KhA1z@~a$kR;|Bz-(sx_#d%(8AZ3YM8F0HZODg93Wsl)&sDSQr2> zEGh?8dLz`6QFY~*O)mgFP&p{>k-=lYwR)95iXAVG+AaXx9`Uf=0RZrZ-3LXa+ou$l z<#zeT$HW^FtsxIwy*c}u_FC+e>`V7-d9=&Y|9Be+x)JY#D(#=i?Wd6*w=hAun!P#} zT@w4=Ww?IOw3%zKR*$Ctv7ZX5XDV(p*mK9s&2Vbpg|%xbHP>)P3##3YPkr{P7XUA+ z?t|)aF~@^m5|iZ-9Lm`lEvQzDHhc&GFN%xgz1|Sjek+*z&QfQ|PVA`S^4>wU-tCgs z3qTES&gb)bxm@V>_Ld$WABkw+UmDcTB64?n%Ogy@;G3GEaErj28I8t{r5{S|&ApH) z=_%ENMRG6_Ne2Z003(1<7XZMpz(D~3h6N4^05B|{4(i*t--?BofrEud2ghUjVBuL_d(Wa1fRQ*vu&|_FiJiE- zMt@wsq*H3ARq*nj{^#-$j12a&64Cnp_PP?y6D+K)S9`oxzgCCUj-(Bic4_rtz721%TU#>g=E78A;8J_+xN|V#$1cn!z%>I0 zH6U1c6%1w+vFYI48+w$i4fQQnoecMcWTrom~HGuOAQnTzRjz zsJ+IEwtx2Q_tWm{v#=87gN3)0+n=*A!N1(`Qu|uF7M+&8M$%(AJs$a7y{R^Gb~OE9 z(Vx?!(dnf>SKiXk+Wu)VUZnlA_jUn^$3XhV7g`Hsjnv~k00yjbjL`dMP%bF4R6 zB)142@ov(Cc{oLa`v_PTKheaI+bPNgUU-YBWvBMvY{T&8%yyoYHpQl zLonh;l2XGt`{5uh}dL-mrgJJx$+kMJ;qCHGj(iA zgS5R{e)v;jzXmH2f`yTgW=gddrAO0)SUdnGq}A+2N-aHbPykFyZ>JPfL(lX($pHYz zrI~~3^_FC$w=)*J^@neMX6~EO-tx|pKO-wq{YCO#i+YlJJhgbYtG2z?{o~n&y}Gn^ zO1q{<&!04Xd}!^UTBR8WU`=hKIw-A^*sD!zXA~!6&7U=?{U#BHT2gEKF#${xHl%&kD5cT!KD`rTqD zPSWzJx-@pJ_1CylYx->~pF2+4KNdaG`aI6>9y_T%9BoE)wKFI#C^dIy_qxN>zEkD& zdzDXN3G%hnk%Bv4shNRCdt*Jh&)hM+$@LFtPx28jH;te9gr%nLp5-}u1^G%saE@|* z!7*X~COH=q_s5v(al-T0z#Oq~T`C0O3 zW+nRXTfEd7MJ~VeET22Zx+WoAFXHOW)yL&&>y_kN^;`PiT3*{f((@**m+K?z^&!>e zab1pE7#27v0Kl-oK>+}U1r7=TFf4FT0Dxin2l^bc#z4*!&j0`b07*qoM6N<$ Ef+6NBX#fBK literal 0 HcmV?d00001 diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/114514client多次发送数据.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/114514client多次发送数据.png new file mode 100644 index 0000000000000000000000000000000000000000..dadf4b1badf33f2b97b5af371a2286a46dc33f94 GIT binary patch literal 7955 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 literal 0 HcmV?d00001 diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/1启动网关.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/1启动网关.png new file mode 100644 index 0000000000000000000000000000000000000000..2f5fa5a352b83965adeb949ae5d87d3a5dde584b GIT binary patch literal 3512 zcmeHK{W}wi7oV4IC=$JxB2*KSw8|Blgds_cQM6k^2%&7+YcJnILvjt5nTm^fS!^*X zsl-=a=55lvOcu**6Ru%nyT14Net-D>51r>Z=kuIj&U2n~&gb(yC&k+fs;Qx`0RR9r z-QAph)^U8@Th)G9j~zqAPwSwX;N%WdTQ`i_)#UXYc+(}|rf+Q6P2}bHP(XN0Y;>q) zLP&gQXiUPj*qgH|Z%?il^Kf@Q1w$2x$Wie;rk3k5U;4{R&Z8OG-p?tWAjjAH+$6Ss zWp%(*Rby+DGAjYTE?P!ca@?dyv;+KTKdhvre_2`i=sZ|yPez*rWq$%22bRvvDQw3q zGFGl}8(VRcxs)!J>Z(*4Z*X8kjjZ?rh|QZDYHDi2bxweHYVLkll2gQSQ4~1y`26De z@v1G}ALEs~Ns)b{uCF#Fae(+l&{jx^ls-Eqg-U_Z_(4Q5x1tmfKF5#9Xyaup%9g=Z zL6Q79R9WghepG>IeVRiD+Hc7|os1n$T>?4hp>vLtEUYG=Yz@ytoQI&39IWaA4tVwU%B{6fOU zg5YM}jy2|ey_{H|hQajv;Z9wNr{Rm?a$*w;loA@$7ms4giF41$4kv0_paLYjX_8)o zctoLipiRubl(MLmM4Jwgu*~ip}&LdSGp=4^6soMw| zo_NhT$+zLU8Ow$0sV%QJ3P42Ud;~tQXt74e1R)Y99K(+{t?qBdnXF+)s2Ir-%HsTz zTXr&>lhT!(2bKef43A#aVJ(W5&ryP_c8JQ+_XgTUnfQ9qEz@~{9fo}JHp13;ML((Q z9zUEu%du^e+TxM&>-nPWd;WG8%=(@>XTq#^DC`CLG@XdSCTIf>xYIxO;lWef=y1Bn z)k81okz5W12?x$$Ak|BEJ**%ce9ry8z61u9A7wBRX{qH$3>nJFsFX^Qhv3n|VcUza z*#<33IgA8#v&wqLeQpwdPDUzOq;kJMiD$pvuSGwRi9&bNY_u}t&wcX!GMhQM)lSqk zgf8apgBq2`P^DxuJXK8eLk@KR?wCq%E1ip(HprM{35vIWtmIZg&`znBHQLQU1$(sjQGX^N1{@WgM=WR|+(B{Hd%<%H*wET|< zQFWC%>$%(w*U72#Jkc?gQp&}ypbRUjKRl=Lqc?#v^dyW

bCkriO04fYiBzlUx6{ z3{r5<0U5b2260f1!V<-U@7}2I&lziZWqzKu>@CXrGx;%0x1z3=x>=YQMq7>1ebJY* zhNQvF?4}!egpVTrtP(}hZD^i8>4TlV^Nrf{GU&srqij;zV4TaZ@#?|AbH8Rh4nRsS z+V~&@@DqbGrC}93f2_mW!0OB8z(8@D>0ng9O$epjhM^YvMkCMMb&sL$M_1P^XvUwt z^T6AIsWr1sd>21skB6+{Z?;9qP4e&d&YwcSB74)^f$n8fbJ^<-D%4;G-SM@s%=XUj zd?6l`T_w1fusg$wGyX;UT8;f@j7(R8}S)%KW zR#~85$Mg?X;uz#FOW2D5c=2DB=ScO~z_B4=bej)r!r}orqV!EJ98H-L((4U0XBBN) zH+GbsZKggVyQ|E$Jk3AcH~I;^bAb_J#uIOZf7Q19?%C{suIZ072^a>>h=Tqm0~ALr(*v_ z`NE8t99yOx)P3lND2($9ewepRl+e|ArbNU24tOxh^LXh&`BhT$7&D1C zT{U}|GKIlnOE@{Jm5qi+tQkMRN)Fu_JA=YrKvNk@Ss};WYeg(+%>eDkf_P=7x3>9J zi|N{K?~CX&ryhfZy+}4SF>I1E#SU)WC1PdK(kOf57A7JT!T>5hecy)gASa?y@XP%o zW;HGqv>6Ygr)Bp43HebRGW!noN;74&t z0sqA5)L&x6PY|O@a((5ZtzrTo&8XGu#xZRs zh>u-`lTuC>Td|nb>JOe6*VDu*g5K~YuF4f5LOaBiLs<+dM||avF2GxcxJIp746p^1 z7!3(i0IlnkuUu~#+FQXiZk6bI89_VtJs-jn7lOjwdYij~=PT?8db@sh{&VI(ujMC0 he`?GBsbZ!=$=)($vn(cV`}*qzaCh-?u6FwE?%#7HD!~8% literal 0 HcmV?d00001 diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/2client发送连接请求.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/2client发送连接请求.png new file mode 100644 index 0000000000000000000000000000000000000000..e0df27cbb0674bcc19362c61da35d297653dd1f7 GIT binary patch literal 1736 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 literal 0 HcmV?d00001 diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/4client接受gateway-reply,成功连接.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/4client接受gateway-reply,成功连接.png new file mode 100644 index 0000000000000000000000000000000000000000..ed21ef53bd6e419fe84bb495d148dd024f2aa956 GIT binary patch literal 4088 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 CNG`+x literal 0 HcmV?d00001 diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/5client发送数据.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/5client发送数据.png new file mode 100644 index 0000000000000000000000000000000000000000..88dd2f486bb90eb9d8506f0a2613917e856f875d GIT binary patch literal 1779 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 R!h`?-002ovPDHLkV1imEhynlr literal 0 HcmV?d00001 diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/8gateway接受并回复quit请求.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/8gateway接受并回复quit请求.png new file mode 100644 index 0000000000000000000000000000000000000000..661ae00f6385c0e25ee21859a6d2c73d91dd8902 GIT binary patch literal 3667 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 literal 0 HcmV?d00001 diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/9client接收gateway-reply并终止连接.png b/APP_Framework/Applications/app_test/test_lora_p2p/连接、断开、发送数据、打开连接下发送数据/9client接收gateway-reply并终止连接.png new file mode 100644 index 0000000000000000000000000000000000000000..d1f3de45a9c9ce556a329d6993e51d3ec9bce8e8 GIT binary patch literal 5230 zcmYjVdpMK*|No4l6so6Eb4=w>4)J8k!w`xb%P|a3MLEoQ6vNWNDWQo_R75G8^R!{p z!SRvW%+y-zNe;6{4#OP3w|?L2d;Rvu?!$Fo_w~L%pV#UAPIGcNB`pP)0su(cSX-V2 z0LFvPt2RkM|GD8Q=b*!es1r6Wo1hWik^bOPXc*dGJL*ED zzkg`d<*?{UaVipkoxsM@+~vvx0mnXrUmZuAQrD%hIf6?~f+rmAFvrgDPy2626!zTj zeP|VPO?2d%nfRp~%H|EPw^`rc+%=-JwEeWH1tplp`|hXA-rsds>r?lSHF3R~($3nM zCpp@DURtLW0A`VkD0ir!XCJM_LAC}w5P%(4`=x=|liQiI=WDWuBR{#Jk_}7x+WlE9 z3R0OZ!seZ1Bj<+IQ4zw;uarPx(|vm6D=lpzi%*{pCG{vP z%Sig~tzhsN8|FQi zQRr!sQE-mv4V!7!DG8;W!LUEoqIIhm;3X?`rj`4h&^0>|YJjaoQWN$+KTKUryfNro zA_U)h2CXYJgwAQtS+XG9gfM{&gqs0cRTH`RC;+7I<8gEVzDNnQJ!VAS64%X<;UR_! z-90_F8Lkw2Z-xZesd?#mLEq@Z-s-#GL+sJau7JO4_&X|>cXChdNV6oDzvYG6&W6GO zdJEj|f_}ke@sQgm_YY~I5Z5$Z(&yFPXHr_%m^;Dikwk9>vcGCxy8mwqiaU+zFuiC3 z`;W_1t|~j(7n%m-yEzInp~zHqBC%6RAH}cB!s_$8&5SidbD>lfoKA7WNOH z73qF1Uv`=alf$^)u}v(&Z6i;kM)+#mHiE$!BaUJ+uRm7fvFd)_^mw_L^v7RKO3Ece zydB$Ae=J$4NP%knTbdq2Hu0y=bN-?eTiW&3`0*mN8*vLoL9!&F(x;Tb)&aC5LxWgk zK8xi(oM9*4QRz^DzkRY4d(MD%nkkP_G%SzT`QvbSa?p~!MfcQdc!XOj$SYb|2f)M;&3w&i|rrjg70M*xZ#6&20j*kS$kl{0Q3gN z(}_f)h&RED_GIIW?bM*trKP2_jz*MIpBqOjqzum}x&$z?`4TbA;RbE)Qw5e#b=cgS zIaKcD?%sNcI^Mt>3h0&vsik#5zSZP10HIbDXR4c?N&;YV!c`0s-T(!0pmL_&tJ=rc zcV?IwbWm4Ux7LT~e`HUm-;rzxtt*MXtx0Reqw$a+rlh1`U+wWIW$_J=Rh)~nBp!w! zf`QA|BlGYgtdFP8dk71?|AsfEb`C>QTHk8O_P`fZM%P__)r@dUgjl7TbE3kpf|7wR za0zSEuW7kgF?cEsQp}Z-Ljh>#5{f)s-FUJ7@|(&6QqG%cqd( zVEQ`^4}uFm@~Ec8F^s>#Sr^n!P4+SXZ!docM{ex5T5i>SUou`{|xD<2k!gvw9teW8wORztNok`GZF7o&|5$c~<@ zvGFm&U+$+8io_ysY{kKVncYLjE!}2X0Q4J$mB9ecbCk7yfM-H#lU6HJo%3M6DpfLTm*gFunCFdRFqfwDUzav1t(;_ zK{7`AQIMNHGpaR2;+dY)R`8+0jcCIdg8@I?)B6*Wl9Wq5wx`Kuzo}3F;JkkEgpby4 zeFd3yKtRHspD(vPVoS9iJTrIRW@$`SC55p57=`?b5~u}RSKW0d58W6Q`#)FrHwh1c z_}V!N$2RtLf*vBxx-%P?stDUzj06{TLP#UxMS=K zfjq!@J!w%}SzN4aR?|LP{LkB?IX0K|)-jL`AEMQK3du9|sd5u(PF7T?L;7(>)sLCB z%TFBO`mdBstWFK3G`Ft}SP+saUPe zc9^DiL1GDg>~=k_x}vQ-3;}?3n=1-`XRqJ&^)lf@UpRzxe8JmIt~NMnK+~QID$6)i zo!&lF(@dp$NyBHX)^At+3M#7$rmIf#3TNNExsJtREz!?lplRb7f(@6;^@X4Yz*z>5 zrpGj^{%+(tzn%6Sm?cvmv`11 z!!NJ%GY#2Ox&y6<@TE-HUQ7}q69cdDA-yy1!b zY&jH}RxrbZcl=mP-v(J7Y=_j5b^x}fLl%2LH6N0u!XNPsp2Jxf7(yn+qSafvI>P87 z(q5t1Q$^bKI1@`Ab;;r&v)u`h5k3Emi$7Mn#$xdA`4* zE5?5Q=29wV83yK(eemzgH=++cHG`9`972pt^(jT^8iD>lza}?$XhCuXiK(`$CdUl^ z+}D&Tcrji`4ovuGC@iW<3H-{a$tms)=oXTJyef5cBJ@y$8C++$31M6#e+boLzl8rh zC5iLeX-sQ(|MB@l)7(zpIWge!WaHrFN`V=i92wf6ZmseM81tD8G`C9Rs-w`$=}DMt zM?>J&Y%@4hqLhp-3MRk9k{5k5$nnoEC?vtrpjys^c8lmGXbU*ui1=Q&;)PrV*~u5> z*O93B|43`FOk5M0iWtgk*~EpuwN>tNM1($Gi`EX|sLd~%tG=?ZaDUWPL54m#|CGgN z-uX3g$jnNy#7vP%ZpwYr;0thRk!QnDxJ+Rj%9F|#{5IR2EO+scXJ_+ahwOwAoBRLu zOe$L0mjijL&D(vnTm1S*=kA|&e=P1&zf0o;#@B!(4+Dh@bXM5~$@E{Ew!1u%aen}? zi`ZqC9u=FkwrUdnFgZ<8Cv(}o;M?oP!r7pP#rlbYd3kQsMdwC6_=m6`gJ?r6%9?Z4F zl@(p68FBF8=D^4V@}Yw{!B+f#N_d|FDfWLeVLJ?Q;_pX!^2~1}GAx4GjI#TBR`EEo zGJfi~bE0d4ee8y}Urmc(Y3RVk)$(5nKfgC|jPhwG_aPlCh2+VP?%$RQ5DpV9-a58D ze4$bIf$w_Bfp2vx_-MJF%DmvZkhlb|C0{wagE6avORlk4i+)?zTY@=M_w6&WT=ZL` zP;|fPFjqN$o)cqQNi`^sEKCe_c4(!N9!!LOa$o8@Vo<*HlTA3)iPfOw4dr>76b*D3 zfV=jxi@U`&Up32q{qqi*Hlwu>|5Ff;!@iCoJt6Ux^eMkBwhg^ts=7PTN=LjY^1S3s-!aM#5&ATzmR_F8rBv zeSGjnBGns7DjyoLjaBfbDkHh-j0h(taiZ4crI1W!d*|uLG`Ln!T&K$Bq4epCG7crl`ZeyWr6@{5aypRSePo-&{=544L0OIc``lO4u3^pn9=D(-xg%A@iYL zyMi}a(HnMW+>qbsMfy5AxIwyFPbo`2{|qOGtlJ!%$Tk|>B=mnKU$eZc!Qi`5{hkt1 zW$vA{K4|wHneMFi(dxql>Xw=$Q$BopJjQ~h{+U)YG&R_?l_BXUe9$M^u;AM#!VY}h z@hG0q)%b!~rOFh@X0lI-YvX6yPxJtD)C))VdA>z^jXi|~d4dvAH?RwCl z#XqD>F5{+Fevc#nSW#vOiGBH=7yt(AV-;rt%RT_Qc>V8syOt(3U_Cj%M2}4EvV-2? zKMOgt_0HdkC7o`agvGwq*bQ(+J6`6zADKvmIs~Xaae5~P!s~)2@w>N+L^GEHR|4v` zZ_j~bm%cc4MN3vzb{}67(0Zj1+GB~-{H}|4b(OO^K3jW0Ga=ovFPwKy_a013fJb}R zvq82-Xqy<+pHv;CS1@cKt&%Sqx6|8g0KmR_x^>pcQa}HjL0bb|VBk50%-}#%ADesP zz)Z`6fzNn%;?|qTTP4H`94b^*p_XP?Bs$l~u9{s+xQfO8GefyOu|9OURomqKbJ%Uh zg;g+J)Tmgiz*zi_NenGKy3toI?zvQ1Ik7S`7I0%;}qzrKS zxE?LN1M1GTHhWgx-YA%l-<#DTsbrK3<5Y6JsnCfDcn&II}7+@L@j<8XcxBCV@Jw4E2Dk RIA}fxY^)qC2`BuL{{zDEL5ctX literal 0 HcmV?d00001