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..a3c5def56 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_lora_p2p/README.md @@ -0,0 +1,116 @@ +# 基于RISC-V终端,实现LoRa节点和LoRa网关通信私有协议 + +## 1.简介 +在RISC-V终端上实现LoRa节点和LoRa网关私有协议通信功能,客户端可以通过SHELL终端连接\断开网关,并可以向网关发送数据. + +## 2.数据结构设计说明 + +```c +enum ClientState +{ + CLIENT_DISCONNECT = 0, + CLIENT_CONNECT, +}; +struct LoraClientParam +{ + uint8_t client_id; + uint8_t panid; + uint8_t gateway_id; + enum ClientState client_state; + int client_mtx; +}; +``` +Lora客户端基础数据结构,`ClientState`为客户端状态,仅有断开和连接两种状态,`LoraClientParam`为客户端参数数据结构,`client_mtx`是Lora硬件互斥量. +```c +struct LoraGatewayParam +{ + uint8_t gateway_id; + uint8_t panid; + uint8_t client_id[GATEWAY_MAX_CLIENT_NUM]; + int client_num; + int gateway_mtx; +}; +``` +Lora网关参数数据结构,`gateway_mtx`是Lora硬件互斥量. +```c +struct LoraHeaderFormat +{ + uint8_t client_id; //1 + uint8_t panid;//1 + uint8_t gateway_id; //1 + uint8_t lora_data_type; //1 + uint8_t data; //1 + uint8_t crc_lo; + uint8_t crc_hi; //2 +}; +enum LoraDataType +{ + /*****C ---> G*/ + CLIENT_JOIN_NET_REQUEST = 0, + CLIENT_QUIT_NET_REQUEST, + CLIENT_SEND_TEST_DATA_TO_GATEWAY_REQUEST, + /*****G ---> C*/ + GATEWAY_REPLY_CLIENT_RESULT_EXPECTED, + GATEWAY_REPLY_CLIENT_RESULT_UN_EXPECTED, +}; +``` +`LoraHeaderFormat`是主要的数据结构,包含基本参数,数据类型,附带数据,校验信息.`LoraDataType`标识数据报头的类型 + +```c +static int (*gateway_handlers[])(struct Adapter*,struct LoraHeaderFormat*) = +{ + [CLIENT_JOIN_NET_REQUEST] = ClientJoinNetHandler, + [CLIENT_QUIT_NET_REQUEST] = ClientQuitNetHandler, + [CLIENT_SEND_TEST_DATA_TO_GATEWAY_REQUEST] = ClientSendTestDataHandler, +}; +``` +`gateway_handlers`是网关人物处理相关事物的映射表,网关会根据不同的信息类型调用不同的处理函数. + +## 3.测试程序说明 + +1. 第一步: 启动网关任务 + > 网关任务启动后会一直监听信道,在接收到数据后,首先对数据进行过滤,判断是否是发送给当前网关的数据,启动网关的命令: `StartGatewayTask` +2. 第二步: 初始化客户端, + > `ClientInit`命令可以初始化相关参数并打开Lora设备. +3. 第三步:客户端连接网关 + > `ClientConnect`命令可以向客户端配置的网络发送入网请求,当该入网请求被该网络中的网关接受处理后即可完成入网. +4. 第四步:客户端发送数据 + > `ClientSend` 命令在客户端入网后可以向网关发送数据. +5. 第五步:客户端断开连接 + > `ClientDisConnect`命令可以向客户端配置的网络发送退网请求,当该退网请求被指定网关接受处理后即可完成退网. + +## 4. 运行结果(##需结合运行测试截图按步骤说明##) + +1. 修改Lora的初始化和注册函数,将原来的注册函数更换为自定义的初始化函数:
+在文件 `APP_Framework/Framework/framework_init.c` 第 28 行添加 外部函数声明
`extern int UsrAdapterLoraInit(void);`,
+将第170行的`AdapterLoraInit`改为`UsrAdapterLoraInit`. +2. 修改对应的Makefile文件将测试代码加入编译. +3. 在工作区终端进入指定目录并输入命令`make BOARD=edu-riscv64 menuconfig`进入配置模式:
+> (1) 依次进入: `APP_Framework -> Framework `开启 `support connection framework` 并进入;
+![1](images/file_1_1.png)
+> (2) 开启 `Using lora adapter device` 并进入
+![2](images/file_1_2.png)
+> (3) 选择 `Lora device adapter select net role type`,将角色配置为网关角色,其他配置如下图所示
+![3](images/file_1_3.png)
+> (4) 依次进入: `APP_Framework > Applications > test app` 开启 `Enable application test function` 并进入, 开启`Config test lora p2p`选项.
+![4](images/file_1_4.png)
+![5](images/file_1_5.png)
+> (5) 保存配置. +1. 使用命令`make BOARD=edu-riscv64`获得网关服务的运行文件,烧录进一个硬件作为网关 +2. 使用同样的方法配置编译一个客户端可执行文件并烧录(配置的第三步将其配置为客户端角色) +3. 连接两个硬件并开始测试. +4. 开启网关服务 +![6](images/file_2_1.png)
+![7](images/file_2_2.png)
+1. 初始化客户端 +![8](images/file_2_3.png)
+![9](images/file_2_4.png)
+1. 客户端连接网关 +![10](images/file_2_5_1.png)
+![11](images/file_2_5_2.png)
+1. 客户端发送数据到网关 +![12](images/file_2_6_1.png)
+![13](images/file_2_6_2.png)
+1. 客户端断开网关 +![14](images/file_2_7_1.png)
+![15](images/file_2_7_2.png)
diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_1.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_1.png new file mode 100755 index 000000000..7323b07dc Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_1.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_2.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_2.png new file mode 100755 index 000000000..e53805ecf Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_2.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_3.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_3.png new file mode 100755 index 000000000..4db9ee4fe Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_3.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_4.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_4.png new file mode 100755 index 000000000..66c68794c Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_4.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_5.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_5.png new file mode 100755 index 000000000..ca4d6def3 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_5.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_1.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_1.png new file mode 100755 index 000000000..5a257ff01 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_1.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_2.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_2.png new file mode 100755 index 000000000..11cd025be Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_2.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_3.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_3.png new file mode 100755 index 000000000..ad87ad4a9 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_3.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_4.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_4.png new file mode 100755 index 000000000..d05b220f1 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_4.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_5_1.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_5_1.png new file mode 100755 index 000000000..b1bf73305 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_5_1.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_5_2.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_5_2.png new file mode 100755 index 000000000..ef98583d3 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_5_2.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_6_1.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_6_1.png new file mode 100755 index 000000000..bee0b94e0 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_6_1.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_6_2.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_6_2.png new file mode 100755 index 000000000..ba0953a7f Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_6_2.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_7_1.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_7_1.png new file mode 100755 index 000000000..0ef427928 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_7_1.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_7_2.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_7_2.png new file mode 100755 index 000000000..cdd0531fe Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_7_2.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/test_lora_p2p.c b/APP_Framework/Applications/app_test/test_lora_p2p/test_lora_p2p.c new file mode 100644 index 000000000..3e05da386 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_lora_p2p/test_lora_p2p.c @@ -0,0 +1,754 @@ +#include "test_lora_p2p.h" + +/**************************PublicOperations*********************************/ +static const uint8_t table_crc_hi[] = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 +}; + +static const uint8_t table_crc_lo[] = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, + 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, + 0x1E,0xDE, 0xDF, 0x1F,0xDD,0x1D,0x1C,0xDC, 0x14, 0xD4,0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, + 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, + 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, + 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, + 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, + 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, + 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, + 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, + 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, + 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,0x43, 0x83, 0x41, 0x81, 0x80, 0x40 +}; + +void CalCrc(uint8_t const *data_src, uint16_t raw_data_len, uint8_t* crc_lo_dst, uint8_t* crc_hi_dst) +{ + uint8_t crc_hi = 0xFF; + uint8_t crc_lo = 0xFF; + unsigned int i; + + while (raw_data_len--) { + i = crc_hi ^ *data_src++; + crc_hi = crc_lo ^ table_crc_hi[i]; + crc_lo = table_crc_lo[i]; + } + *crc_lo_dst = crc_lo; + *crc_hi_dst = crc_hi; +} + +int CheckCrc(uint8_t const *data_src, uint16_t raw_data_len, uint8_t crc_lo_dst, uint8_t crc_hi_dst) +{ + uint8_t crc_hi = 0xFF; + uint8_t crc_lo = 0xFF; + unsigned int i; + + while (raw_data_len--) { + i = crc_hi ^ *data_src++; + crc_hi = crc_lo ^ table_crc_hi[i]; + crc_lo = table_crc_lo[i]; + } + + if (crc_lo == crc_lo_dst && crc_hi == crc_hi_dst) + { + return 0; + } + return -1; +} + +uint8_t crc_data_buffer[LORA_DATA_MAX_LENGTH]; +uint8_t crc_header_buffer[LORA_HEADER_RAW_LENGTH]; + +void ShowHeader(struct LoraHeaderFormat* header) +{ + printf("Header(client_id: %X panid: %X gateway_id: %X data_type: %d data: %d crc_lo: %X crc_hi: %X)\n",header->client_id,header->panid,header->gateway_id,header->lora_data_type,header->data,header->crc_lo,header->crc_hi); +} + +void CalHeaderCrc(struct LoraHeaderFormat* header) +{ + memcpy(crc_header_buffer,header,LORA_HEADER_RAW_LENGTH); + CalCrc(crc_header_buffer,LORA_HEADER_RAW_LENGTH,&header->crc_lo,&header->crc_hi); + ShowHeader(header); +} + +uint16_t CheckHeaderCrc(struct LoraHeaderFormat* header) +{ + printf("Start the datagram integrity check: "); + ShowHeader(header); + + memcpy(crc_header_buffer,header,LORA_HEADER_RAW_LENGTH); + if (0 == CheckCrc(crc_header_buffer,LORA_HEADER_RAW_LENGTH,header->crc_lo,header->crc_hi)) + { + printf("The datagram integrity check passes\n"); + return 0; + } + printf("Datagram integrity check failed\n"); + return -1; +} + +struct LoraHeaderFormat header_send_buffer; +struct LoraHeaderFormat header_recv_buffer; + +static int LoraRecvHeader(struct Adapter* adapter, struct LoraHeaderFormat* header) +{ + UserTaskDelay(1000); + + if (LORA_HEADER_LENGTH == AdapterDeviceRecv(adapter,header,LORA_HEADER_LENGTH )) + { + if (0 == CheckHeaderCrc(header)) + { + UserTaskDelay(500); + return LORA_HEADER_LENGTH; + } + } + + return -1; +} + +static int LoraSendHeader(struct Adapter* adapter, struct LoraHeaderFormat* header) +{ + UserTaskDelay(500); + + CalHeaderCrc(header); + + if (LORA_HEADER_LENGTH == AdapterDeviceSend(adapter,header,LORA_HEADER_LENGTH )) + { + UserTaskDelay(1000); + return LORA_HEADER_LENGTH; + } + + return -1; +} + +static int LoraSendData(struct Adapter* adapter,uint8_t* src_data, uint16_t raw_data_length) +{ + if (raw_data_length > LORA_DATA_MAX_LENGTH - 2) + { + printf("The amount of data exceeds the limit\n"); + return -1; + } + + UserTaskDelay(500); + + CalCrc(src_data,raw_data_length,src_data + raw_data_length, src_data + raw_data_length + 1); + + if (raw_data_length + 2 == AdapterDeviceSend(adapter,src_data,raw_data_length + 2 )) + { + uint8_t crc_lo = src_data[raw_data_length]; + uint8_t crc_hi = src_data[raw_data_length + 1]; + src_data[raw_data_length] = '\0'; + + printf("Send data : %s crc_lo: %X crc_hi: %X \n",src_data,crc_lo,crc_hi); + + UserTaskDelay(1000); + return raw_data_length + 2; + } + + return -1; +} + +static int LoraRecvData(struct Adapter* adapter, uint8_t* dest_data, uint16_t data_length) +{ + + if (data_length > LORA_DATA_MAX_LENGTH) + { + printf("The amount of data exceeds the limit\n"); + return -1; + } + + UserTaskDelay(1000); + + if (data_length == AdapterDeviceRecv(adapter,dest_data,data_length)) + { + UserTaskDelay(500); + if (0 == CheckCrc(dest_data,data_length -2,dest_data[data_length-2],dest_data[data_length-1])) + { + return data_length; + } + } + return -1; +} + +/**************************ClientOperations*********************************/ +uint8_t client_data_send_buffer[LORA_DATA_MAX_LENGTH]; +static int LoraClientJoinNet() +{ + struct Adapter* adapter = AdapterDeviceFindByName(ADAPTER_LORA_NAME); + if (adapter == NULL) + { + printf("Connection framework fundamental error\n"); + return -1; + } + + struct LoraClientParam* client_param =(struct LoraClientParam*) adapter->adapter_param; + + if (INSTALL != adapter->adapter_status || 0 != AdapterDeviceOpen(adapter)) + { + printf("The Lora device failed to open\n"); + return -1; + } + UserMutexObtain(client_param->client_mtx, -1); + + memset(&header_send_buffer,0,LORA_HEADER_LENGTH); + + header_send_buffer.client_id=client_param->client_id; + header_send_buffer.panid = client_param->panid; + header_send_buffer.lora_data_type = CLIENT_JOIN_NET_REQUEST; + + if (LORA_HEADER_LENGTH != LoraSendHeader(adapter,&header_send_buffer)) + { + printf("The header of the incoming request failed to be sent\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + memset(&header_recv_buffer,0,LORA_HEADER_LENGTH); + + if (LORA_HEADER_LENGTH != LoraRecvHeader(adapter,&header_recv_buffer)) + { + printf("Failed to receive the gateway inbound response data\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + if (header_recv_buffer.lora_data_type == GATEWAY_REPLY_CLIENT_RESULT_UN_EXPECTED) + { + printf("The gateway cannot accept the client from the network\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + client_param->client_state = CLIENT_CONNECT; + client_param->gateway_id = header_recv_buffer.gateway_id; + + printf("The client successfully joins the network through the gateway\n"); + UserMutexAbandon(client_param->client_mtx); + + return 0; +} + +static int LoraClientSendData(void* data, uint16_t raw_data_length) +{ + if (raw_data_length > LORA_DATA_MAX_LENGTH - 2) + { + printf("The data load exceeds the limit\n"); + return -1; + } + + struct Adapter* adapter = AdapterDeviceFindByName(ADAPTER_LORA_NAME); + if (adapter == NULL) + { + printf("Connection framework fundamental error\n"); + return -1; + } + + struct LoraClientParam* client_param =(struct LoraClientParam*) adapter->adapter_param; + + if (INSTALL != adapter->adapter_status || 0 != AdapterDeviceOpen(adapter)) + { + printf("The Lora device failed to open\n"); + return -1; + } + + if (client_param->client_state != CLIENT_CONNECT) + { + printf("This client has not connected to gateway\n"); + return -1; + } + + UserMutexObtain(client_param->client_mtx, -1); + + memset(&header_send_buffer,0,LORA_HEADER_LENGTH); + + header_send_buffer.client_id=client_param->client_id; + header_send_buffer.panid = client_param->panid; + header_send_buffer.gateway_id = client_param->gateway_id; + header_send_buffer.data = raw_data_length + 2; + header_send_buffer.lora_data_type = CLIENT_SEND_TEST_DATA_TO_GATEWAY_REQUEST; + + if (LORA_HEADER_LENGTH != LoraSendHeader(adapter,&header_send_buffer)) + { + printf("The header of the incoming request failed to be sent\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + memset(&header_recv_buffer,0,LORA_HEADER_LENGTH); + + if (LORA_HEADER_LENGTH != LoraRecvHeader(adapter,&header_recv_buffer)) + { + printf("Failed to receive the gateway inbound response data\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + if (header_recv_buffer.lora_data_type == GATEWAY_REPLY_CLIENT_RESULT_UN_EXPECTED) + { + printf("The gateway cannot accept client data\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + if ((raw_data_length + 2)!= LoraSendData(adapter,data,raw_data_length)) + { + printf("The client gets permission to upload the data, but the send fails\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + UserMutexAbandon(client_param->client_mtx); + printf("The client successfully sends the data\n"); + + return 0; +} + +static int LoraClientQuitNet() +{ + struct Adapter* adapter = AdapterDeviceFindByName(ADAPTER_LORA_NAME); + if (adapter == NULL) + { + printf("Connection framework fundamental error\n"); + return -1; + } + + struct LoraClientParam* client_param =(struct LoraClientParam*) adapter->adapter_param; + + if (INSTALL != adapter->adapter_status || 0 != AdapterDeviceOpen(adapter)) + { + printf("The Lora device failed to open\n"); + return -1; + } + + UserMutexObtain(client_param->client_mtx, -1); + memset(&header_send_buffer,0,LORA_HEADER_LENGTH); + + header_send_buffer.client_id=client_param->client_id; + header_send_buffer.panid = client_param->panid; + header_send_buffer.gateway_id = client_param->gateway_id; + header_send_buffer.lora_data_type = CLIENT_QUIT_NET_REQUEST; + + if (LORA_HEADER_LENGTH != LoraSendHeader(adapter,&header_send_buffer)) + { + printf("The header of the incoming request failed to be sent\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + memset(&header_recv_buffer,0,LORA_HEADER_LENGTH); + + if (LORA_HEADER_LENGTH != LoraRecvHeader(adapter,&header_recv_buffer)) + { + printf("Failed to receive the gateway inbound response data\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + if (header_recv_buffer.lora_data_type == GATEWAY_REPLY_CLIENT_RESULT_UN_EXPECTED) + { + printf("Client exit from the network failed\n"); + UserMutexAbandon(client_param->client_mtx); + return -1; + } + + client_param->client_state = CLIENT_DISCONNECT; + client_param->gateway_id = 0; + + printf("The client successfully quit the network through the gateway\n"); + UserMutexAbandon(client_param->client_mtx); + + return 0; +} + +/**************************GatewayOperations*********************************/ +uint8_t gateway_recv_buffer[LORA_DATA_MAX_LENGTH]; + +static int ClientJoinNetHandler(struct Adapter* adapter,struct LoraHeaderFormat* header) +{ + struct LoraGatewayParam* gateway_param = (struct LoraGatewayParam*)adapter->adapter_param; + + header->gateway_id = gateway_param->gateway_id; + + if (gateway_param->client_num == GATEWAY_MAX_CLIENT_NUM) + { + header->lora_data_type = GATEWAY_REPLY_CLIENT_RESULT_UN_EXPECTED; + printf("%X : Clients connected to the gateway have reached the upper limit\n",header->client_id); + + LoraSendHeader(adapter,header); + + return -1; + } + + for (int i = 0; i < gateway_param->client_num; i++) + { + if (gateway_param->client_id[i] == header->client_id) + { + header->lora_data_type = GATEWAY_REPLY_CLIENT_RESULT_EXPECTED; + printf("%X : The client has already connected to this gateway before\n",header->client_id); + + if (LORA_HEADER_LENGTH != LoraSendHeader(adapter,header)) + { + printf("The gateway failed to respond to the client's network connection request\n"); + return -1; + } + return 0; + } + } + + gateway_param->client_id[gateway_param->client_num] = header->client_id; + gateway_param->client_num ++; + header->lora_data_type = GATEWAY_REPLY_CLIENT_RESULT_EXPECTED; + + if (LORA_HEADER_LENGTH != LoraSendHeader(adapter,header)) + { + printf("The gateway failed to respond to the client's network connection request\n"); + return -1; + } + + printf("%X - %X : The client joins the gateway network successfully\n",header->client_id,gateway_param->gateway_id); + + return 0; +} + +static int ClientQuitNetHandler(struct Adapter* adapter,struct LoraHeaderFormat* header) +{ + struct LoraGatewayParam* gateway_param = (struct LoraGatewayParam*)adapter->adapter_param; + + header->gateway_id = gateway_param->gateway_id; + + for (int i = 0; i < gateway_param->client_num; i++) + { + if (gateway_param->client_id[i] == header->client_id) + { + for (int j = i; j < gateway_param->client_num - 1; j++) + { + gateway_param->client_id[j] = gateway_param->client_id[j+1]; + } + gateway_param->client_num --; + + break; + } + } + + header->lora_data_type = GATEWAY_REPLY_CLIENT_RESULT_EXPECTED; + + if (LORA_HEADER_LENGTH != LoraSendHeader(adapter,header)) + { + printf("The gateway failed to respond to the client's decommissioning request\n"); + return -1; + } + + printf("%X - %X : The client quit the gateway network successfully\n",header->client_id,gateway_param->gateway_id); + return 0; +} + +static int ClientSendTestDataHandler(struct Adapter* adapter,struct LoraHeaderFormat* header) +{ + struct LoraGatewayParam* gateway_param = (struct LoraGatewayParam*)adapter->adapter_param; + + int data_length = header->data; + + if (data_length > LORA_DATA_MAX_LENGTH) + { + header->lora_data_type = GATEWAY_REPLY_CLIENT_RESULT_UN_EXPECTED; + LoraSendHeader(adapter,header); + + return -1; + } + + header->lora_data_type = GATEWAY_REPLY_CLIENT_RESULT_EXPECTED; + + if (LORA_HEADER_LENGTH != LoraSendHeader(adapter,header)) + { + printf("The gateway failed to respond to a client data transfer request\n"); + return -1; + } + + memset(gateway_recv_buffer,0,data_length); + + if (data_length != LoraRecvData(adapter,gateway_recv_buffer,data_length)) + { + printf("The gateway failed to receive client data\n"); + return -1; + } + + uint8_t crc_lo = gateway_recv_buffer[data_length - 2]; + uint8_t crc_hi = gateway_recv_buffer[data_length - 1]; + + gateway_recv_buffer[data_length - 2] = '\0'; + gateway_recv_buffer[data_length - 1] = '\0'; + + printf("Receive data: %s crc_lo: %X crc_hi: %X\n",gateway_recv_buffer,crc_lo,crc_hi); + + //todo + return 0; +} + +/*****************************GatewayAutoTask********************************************/ +static void * LoraGatewayAutoTask(void * parameter) +{ + printf("Starting the gateway service...\n"); + struct Adapter* gateway_adapter = (struct Adapter*) parameter; + struct LoraGatewayParam* gateway_param = (struct LoraGatewayParam*)gateway_adapter->adapter_param; + + if (gateway_adapter == NULL || gateway_param == NULL) + { + printf("Connection framework foundation error, task exit!\n"); + goto END; + } + + if (INSTALL != gateway_adapter->adapter_status) + { + if (0 != AdapterDeviceOpen(gateway_adapter)) + { + printf("Open lora device fail, task exit!\n"); + goto END; + } + } + + while (1) + { + UserMutexObtain(gateway_param->gateway_mtx,-1); + memset(&header_recv_buffer, 0, LORA_HEADER_LENGTH); + + if (LORA_HEADER_LENGTH == LoraRecvHeader(gateway_adapter,&header_recv_buffer)) + { + if (header_recv_buffer.panid == gateway_param->panid) + { + if (header_recv_buffer.gateway_id == gateway_param->gateway_id || header_recv_buffer.lora_data_type == CLIENT_JOIN_NET_REQUEST) + { + printf("This header is for the gateway, start processing the data header\n"); + gateway_handlers[header_recv_buffer.lora_data_type](gateway_adapter,&header_recv_buffer); + } + } + } + + UserMutexAbandon(gateway_param->gateway_mtx); + } + +END: + printf("Gateway task end\n"); +} + +/*******************LORA ADAPTER FUNCTION********************/ +static int UsrAdapterLoraRegister(struct Adapter *adapter) +{ + int ret = 0; + struct LoraGatewayParam *lora_gateway; + struct LoraClientParam *lora_client; + + strncpy(adapter->name, ADAPTER_LORA_NAME, NAME_NUM_MAX); + adapter->net_protocol = PRIVATE_PROTOCOL; + +#ifdef AS_LORA_GATEWAY_ROLE + lora_gateway = PrivMalloc(sizeof(struct LoraGatewayParam)); + if (!lora_gateway) { + PrivFree(lora_gateway); + return -1; + } + + memset(lora_gateway, 0, sizeof(struct LoraGatewayParam)); + + lora_gateway->gateway_id = DEAFULT_GATEWAY_ID; + lora_gateway->panid = DEAFULT_PANID; + lora_gateway->gateway_mtx = UserMutexCreate(); + if (lora_gateway->gateway_mtx < 0) + { + printf("create lora gateway mutex fail\n"); + return -1; + } + + adapter->net_role = GATEWAY; + adapter->net_role_id = DEAFULT_GATEWAY_ID; + adapter->adapter_param = (void *)lora_gateway; +#else //AS_LORA_CLIENT_ROLE + lora_client = PrivMalloc(sizeof(struct LoraClientParam)); + if (!lora_client) { + PrivFree(lora_client); + return -1; + } + + memset(lora_client, 0, sizeof(struct LoraClientParam)); + + lora_client->client_id = DEAFULT_CLIENT_ID; + lora_client->client_state = CLIENT_DISCONNECT; + lora_client->panid = DEAFULT_PANID; + lora_client->client_mtx = UserMutexCreate(); + if (lora_client->client_mtx < 0) + { + printf("create lora client mutex fail\n"); + return -1; + } + + adapter->net_role = CLIENT; + adapter->net_role_id = DEAFULT_CLIENT_ID; + adapter->adapter_param = (void *)lora_client; +#endif + adapter->adapter_status = UNREGISTERED; + ret = AdapterDeviceRegister(adapter); + if (ret < 0) { + printf("Adapter4G register error\n"); + if (lora_gateway) + PrivFree(lora_gateway); + if (lora_client) + PrivFree(lora_client); + + return -1; + } + return ret; +} + +int UsrAdapterLoraInit(void) +{ + int ret = 0; + struct Adapter *adapter = PrivMalloc(sizeof(struct Adapter)); + if (!adapter) { + PrivFree(adapter); + return -1; + } + + memset(adapter, 0, sizeof(struct Adapter)); + + ret = UsrAdapterLoraRegister(adapter); + if (ret < 0) { + printf("AdapterLoraInit register lora adapter error\n"); + PrivFree(adapter); + return -1; + } + + 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; + PrivSemaphoreCreate(&adapter->sem, 0, 0); + PrivMutexCreate(&adapter->lock, 0); + return ret; +} + +/**********************************TestFunction***************************/ + +#ifdef AS_LORA_GATEWAY_ROLE +struct Adapter* gateway_adapter = NULL; +UtaskType gateway_task; +int gateway_task_id = -1; + +int StartGatewayTask(void) +{ + gateway_adapter = AdapterDeviceFindByName(ADAPTER_LORA_NAME); + printf("gateway_priv: %d\n", gateway_adapter->net_protocol); + + if (gateway_adapter != NULL) + { + gateway_task.prio = 25; + gateway_task.stack_size = 4096; + gateway_task.func_entry = LoraGatewayAutoTask; + gateway_task.func_param = gateway_adapter; + strncpy(gateway_task.name,"lora_gateway_task",strlen("lora_gateway_task")); + gateway_task_id = UserTaskCreate(gateway_task); + if (gateway_task_id >= 0) + { + if (0 == UserTaskStartup(gateway_task_id)) + { + printf("start gateway task success!\n"); + } + } + } +} +PRIV_SHELL_CMD_FUNCTION(StartGatewayTask, start the lora gateway task, PRIV_SHELL_CMD_MAIN_ATTR); + +int StopLoraGateway(void) +{ + if (gateway_task_id < 0) + { + printf("gateway task not exist!\n"); + } + else + { + UserTaskDelete(gateway_task_id); + gateway_task_id = -1; + printf("delete gateway task success!\n"); + } +} +PRIV_SHELL_CMD_FUNCTION(StopLoraGateway, stop the lora gateway task, PRIV_SHELL_CMD_MAIN_ATTR); + +int ShowGateway(void) +{ + if (gateway_adapter != NULL) + { + struct LoraGatewayParam* gateway_param = (struct LoraGatewayParam*) gateway_adapter->adapter_param; + printf("ROLE: Gateway\n"); + printf("panid: %X, gateway_id:%X, client_num: %X \n", gateway_param->panid, gateway_param->gateway_id,gateway_param->client_num); + printf("clients: \n"); + for (int i = 0; i < gateway_param->client_num; i++) + { + printf("client %d - > %X\t",i,gateway_param->client_id[i]); + } + } +} +PRIV_SHELL_CMD_FUNCTION(ShowGateway, display some info about the gateway after the task started, PRIV_SHELL_CMD_MAIN_ATTR); +#else //AS_LORA_CLIENT_ROLE + +struct Adapter* client_adapter = NULL; +struct LoraClientParam * client_param = NULL; +int client_is_init = -1; + +uint8_t client_input_data_buffer[100]; + +void ClientInit(void) +{ + if (0 != client_is_init) + { + client_adapter = AdapterDeviceFindByName(ADAPTER_LORA_NAME); + client_param =(struct LoraClientParam *) client_adapter->adapter_param; + + if (0 == AdapterDeviceOpen(client_adapter)) + { + client_is_init = 0; + printf("client init success: client_id: %X, panid: %X, gateway_id: %X, client_state: %d \n",client_param->client_id,client_param->panid,client_param->gateway_id,client_param->client_state); + return; + } + } + printf("client init success before: client_id: %X, panid: %X, gateway_id: %X, client_state: %d \n",client_param->client_id,client_param->panid,client_param->gateway_id,client_param->client_state); +} +PRIV_SHELL_CMD_FUNCTION(ClientInit, init the lora client such as open the lora model etc, PRIV_SHELL_CMD_MAIN_ATTR); + +void ShowClient(void) +{ + printf("ROLE: client client_id: %X, panid: %X, gateway_id: %X, client_state: %d \n",client_param->client_id,client_param->panid,client_param->gateway_id,client_param->client_state); +} +PRIV_SHELL_CMD_FUNCTION(ShowClient, show some info about the lora client, PRIV_SHELL_CMD_FUNC_ATTR); + +void ClientConnect() +{ + LoraClientJoinNet(); +} +PRIV_SHELL_CMD_FUNCTION(ClientConnect, connect to the certen vlan, PRIV_SHELL_CMD_FUNC_ATTR); + +void ClientDisConnect() +{ + LoraClientQuitNet(); +} +PRIV_SHELL_CMD_FUNCTION(ClientDisConnect, disconnect to the certen vlan, PRIV_SHELL_CMD_FUNC_ATTR); + +void ClientSend(char *data) +{ + memcpy(client_input_data_buffer,data,strlen(data)); + LoraClientSendData(client_input_data_buffer,strlen(data)); +} +PRIV_SHELL_CMD_FUNCTION(ClientSend, send data to gateway after connected, PRIV_SHELL_CMD_FUNC_ATTR); +#endif \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/test_lora_p2p.h b/APP_Framework/Applications/app_test/test_lora_p2p/test_lora_p2p.h new file mode 100644 index 000000000..49d431865 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_lora_p2p/test_lora_p2p.h @@ -0,0 +1,74 @@ +#include +#include + +#define LORA_DATA_MAX_LENGTH 128 + +#define LORA_HEADER_LENGTH 7 +#define LORA_HEADER_RAW_LENGTH 5 +#define LORA_USER_DATA_MAX_LENGTH LORA_DATA_MAX_LENGTH - LORA_HEADER_LENGTH + +#define GATEWAY_MAX_CLIENT_NUM 20 + +#define DEAFULT_PANID 0XA +#define DEAFULT_CLIENT_ID 0XB +#define DEAFULT_GATEWAY_ID 0XC + +extern AdapterProductInfoType E220Attach(struct Adapter *adapter); + +enum ClientState +{ + CLIENT_DISCONNECT = 0, + CLIENT_CONNECT, +}; + +struct LoraClientParam +{ + uint8_t client_id; + uint8_t panid; + uint8_t gateway_id; + enum ClientState client_state; + int client_mtx; +}; + +struct LoraGatewayParam +{ + uint8_t gateway_id; + uint8_t panid; + uint8_t client_id[GATEWAY_MAX_CLIENT_NUM]; + int client_num; + int gateway_mtx; +}; + +enum LoraDataType +{ + /*****C ---> G*/ + CLIENT_JOIN_NET_REQUEST = 0, + CLIENT_QUIT_NET_REQUEST, + CLIENT_SEND_TEST_DATA_TO_GATEWAY_REQUEST, + /*****G ---> C*/ + GATEWAY_REPLY_CLIENT_RESULT_EXPECTED, + GATEWAY_REPLY_CLIENT_RESULT_UN_EXPECTED, +}; + +struct LoraHeaderFormat +{ + uint8_t client_id; //1 + uint8_t panid;//1 + uint8_t gateway_id; //1 + uint8_t lora_data_type; //1 + uint8_t data; //1 + uint8_t crc_lo; + uint8_t crc_hi; //2 +}; + +/**************************gateway_handlers*********************************/ +static int ClientJoinNetHandler(struct Adapter* adapter,struct LoraHeaderFormat* header); +static int ClientQuitNetHandler(struct Adapter* adapter,struct LoraHeaderFormat* header); +static int ClientSendTestDataHandler(struct Adapter* adapter,struct LoraHeaderFormat* header); + +static int (*gateway_handlers[])(struct Adapter*,struct LoraHeaderFormat*) = +{ + [CLIENT_JOIN_NET_REQUEST] = ClientJoinNetHandler, + [CLIENT_QUIT_NET_REQUEST] = ClientQuitNetHandler, + [CLIENT_SEND_TEST_DATA_TO_GATEWAY_REQUEST] = ClientSendTestDataHandler, +}; \ No newline at end of file