diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/README.md b/APP_Framework/Applications/app_test/test_lora_p2p/README.md old mode 100644 new mode 100755 index a3c5def56..f67371cb6 --- a/APP_Framework/Applications/app_test/test_lora_p2p/README.md +++ b/APP_Framework/Applications/app_test/test_lora_p2p/README.md @@ -1,116 +1,151 @@ -# 基于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)
+# 基于RISC-V终端,实现LoRa节点和LoRa网关通信私有协议 + +## 一、简介 +在RISC-V终端上实现LoRa节点和LoRa网关私有协议通信功能,客户端可以通过SHELL终端连接\断开网关,并可以向网关发送数据. + +## 二、数据结构设计说明 +### 1、Lora工作模式枚举 +```c +enum LoraMode +{ + LORA_SLEEP = 0, // 切换至休眠模式 + LORA_WORK = 1 // 切换至工作模式 +}; +``` +在客户端需要传输数据时,Lora会工作在普通模式进行数据传输,在客户端数据传输完毕后,Lora会切换到休眠模式以屏蔽数据。 + +### 2、客户端/网关状态信息 +```c +enum ClientState +{ + CLIENT_DISCONNECT = 0, // 开启但断网 + CLIENT_CONNECT, // 开启且联网 + CLIENT_BROKEN, // 硬件损坏 + CLIENT_CLOSED // 硬件关闭 +}; +enum GatewayState +{ + GATEWAY_ORIGINAL= 0, // 关闭且未开始工作 + GATEWAY_WORKING, // 开启且已经开始工作 + GATEWAY_BROKEN // 模块损坏 +}; +``` +### 3、客户端/网关参数信息 +```c +struct ClientParam +{ + uint8_t client_id; + uint8_t panid; + uint8_t gateway_id; + enum ClientState client_state; + pthread_mutex_t client_mutex; // 互斥量 +}; +struct GatewayParam +{ + uint8_t gateway_id; + uint8_t panid; + uint8_t client_infos[GATEWAY_MAX_CLIENT_NUM]; + uint8_t client_num; + enum GatewayState gateway_state; + pthread_mutex_t gateway_mutex; // 互斥量 +}; +``` +### 4、数据帧类型枚举 +```c +enum FrameType +{ + /*C ---> G*/ + CG_NET_JOIN = 0, // 入网请求 + CG_NET_QUIT, // 退网请求 + CG_DATA_SEND, // 数据传输请求 + /*G ---> C*/ + GC_REPLY_EXPECTED, // 上行请求执行成功 + GC_REPLY_UNEXPECTED, // 上行请求执行失败 +}; +``` +### 5、数据帧结构设计 +```c +struct DataFrameFormat +{ + uint8_t begin_mark_1; // 0XFF + uint8_t begin_mark_2; // 0XAA + uint8_t client_id; // 0 - 127 + uint8_t panid; // 0 - 127 + uint8_t gateway_id; // 0 - 127 + uint8_t frame_type; // 0 - 127 + uint8_t attach_data; // 0 - 127 可以是数据长度,该值的意义视数据帧类型而定 + uint8_t* user_data; // 在有数据携带时才会发送该指针所指缓冲区数据 + uint8_t crc_hi; // 这个字节没有0XFF + uint8_t crc_lo; // 这个字节会出现 0XFF,但是他的下一个字节不可能是00,必然是0XFF + uint8_t end_mark_1; // 0XFF + uint8_t end_mark_2; // 0X00 +}; +``` +## 三、包含以下功能 +### 1、客户端联网/退网/数据传输操作 +> (1)、获取使用权后将其配置为传输模式。
+> (2)、构建数据帧并设置好数据帧类型。
+> (3)、监听信道直到信道空闲。
+> (4)、发送数据帧(若是数据传输需要带上数据一起传输),若失败回到第三步。
+> (5)、接收数据帧并对数据帧进行数据过滤,若失败回到第三步。
+> (6)、解析数据帧并得到结果
+### 2、网关后台任务操作 +> (1)、获取使用权后开启数据接收。
+> (2)、根据数据帧结构,监听信道,过滤掉杂乱的信号,在接收到一个完整的数据帧并完整性校验通过后返回继续第三步,否则循环执行第二步。
+> (3)、根据得到的数据帧类型将其交付给对应的处理器处理,处理完毕后返回第二步。
+ +## 四、测试程序说明 +在进行测试时,最好先启动网关并开启网关程序,当然后启动网关也一样。 +### 1、客户端测试程序 +> (1)、`TestLoraConnectState`命令可以进行网络连接或者断开,`0-CLIENT_DISCONNECT 1-CLIENT_CONNECT`。 +> (2)、`TestLoraSendData`命令可以发送数据(联网状态下),请使用字符串(`void TestLoraSendData(char* data)`)。 +> (3)、`TestLoraClient`命令可以整体测试,先进行联网,再发送数据,再断开连接,最后再联网。 +### 2、网关测试程序 +> (1)、`TestLoraGateway`命令可以启动网关程序。 + +## 五、运行结果(##需结合运行测试截图按步骤说明##) +### 1、修改必要的框架和驱动代码 +#### 修改文件: `xiuos/APP_Framework/Framework/framework_init.c` +1. 在第`28`行添加代码: `extern int UsrAdapterLoraInit(void);`; +2. 将第`170`行代码的`AdapterLoraInit`修改为`UsrAdapterLoraInit`,更换Lora的初始化函数; +#### 修改文件:`xiuos/APP_Framework/Framework/connection/lora/e220/e220.c` +1. 将第`429`行代码修改为`cfg.serial_timeout = 5000;`,更改客户端超时时间; +2. 为第`478`行的`E220Ioctl`添加函数体: +```c +static int E220Ioctl(struct Adapter *adapter, int cmd, void *args) +{ + switch (cmd) + { + case 0: // LORA_SLEEP + E220LoraModeConfig(CONFIGURE_MODE_MODE); // 切换至休眠模式 + break; + case 1: // LORA_WORK + E220LoraModeConfig(DATA_TRANSFER_MODE); // 切换至传输模式 + break; + default: + break; + } + + return 0; +} +``` +### 2、修改Makefile +#### 修改文件: `xiuos/APP_Framework/Applications/app_test/Makefile` 第 `137` 行为 `SRC_FILES += test_lora_p2p/test_lora_p2p.c` +### 3、menuconfig配置 +1. `APP_Framework > Applications > test app` 开启 `Enable application test function` ,然后进入其中,开启 `Config test lora p2p (NEW)` ; +![image](images/5-3-1.png) +2. `APP_Framework > Framework` 开启 `support connection framework (NEW)` ,然后进入其中,开启 `Using lora adapter device (NEW)` ,然后进入其中, 客户端将其配置如下图所示,网关将其配置为下下图所示; +![image](images/5-3-2-1.png) +![image](images/5-3-2-2.png) +3. 将客户端和网关分别编译、烧录到不同的板子并启动后用串口进行连接; +![image](images/5-3-3.png) +4. 启动网关程序; +![image](images/5-3-4.png) +5. 整体测试客户端; +![image](images/5-3-5.png) +6. 测试断网 +![image](images/5-3-6.png) +7. 测试联网 +![image](images/5-3-7.png) +8. 测试数据发送 +![image](images/5-3-8.png) \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-1.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-1.png new file mode 100755 index 000000000..cd4f859f9 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-1.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-2-1.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-2-1.png new file mode 100755 index 000000000..aedf8eaf2 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-2-1.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-2-2.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-2-2.png new file mode 100755 index 000000000..18cd03d99 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-2-2.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-3.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-3.png new file mode 100755 index 000000000..181d471c0 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-3.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-4.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-4.png new file mode 100755 index 000000000..71673186c Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-4.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-5.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-5.png new file mode 100755 index 000000000..8a73cc1eb Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-5.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-6.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-6.png new file mode 100755 index 000000000..29ccfa34d Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-6.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-7.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-7.png new file mode 100755 index 000000000..2605a964e Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-7.png differ diff --git a/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-8.png b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-8.png new file mode 100755 index 000000000..1aa130aa5 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_lora_p2p/images/5-3-8.png differ 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 deleted file mode 100755 index 7323b07dc..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_1.png and /dev/null 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 deleted file mode 100755 index e53805ecf..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_2.png and /dev/null 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 deleted file mode 100755 index 4db9ee4fe..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_3.png and /dev/null 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 deleted file mode 100755 index 66c68794c..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_4.png and /dev/null 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 deleted file mode 100755 index ca4d6def3..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_1_5.png and /dev/null 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 deleted file mode 100755 index 5a257ff01..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_1.png and /dev/null 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 deleted file mode 100755 index 11cd025be..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_2.png and /dev/null 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 deleted file mode 100755 index ad87ad4a9..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_3.png and /dev/null 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 deleted file mode 100755 index d05b220f1..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_4.png and /dev/null 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 deleted file mode 100755 index b1bf73305..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_5_1.png and /dev/null 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 deleted file mode 100755 index ef98583d3..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_5_2.png and /dev/null 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 deleted file mode 100755 index bee0b94e0..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_6_1.png and /dev/null 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 deleted file mode 100755 index ba0953a7f..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_6_2.png and /dev/null 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 deleted file mode 100755 index 0ef427928..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_7_1.png and /dev/null 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 deleted file mode 100755 index cdd0531fe..000000000 Binary files a/APP_Framework/Applications/app_test/test_lora_p2p/images/file_2_7_2.png and /dev/null 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 index efb31ab33..9e9ac72f1 100644 --- 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 @@ -1,627 +1,793 @@ -/* -* Copyright (c) 2023 AIIT XUOS Lab -* XiUOS is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* See the Mulan PSL v2 for more details. -*/ - -/** -* @file: test_lora_p2p.c -* @brief: a application of lora function -* @version: 1.0 -* @author: Chu yunfei -* @date: 2023/8/22 -*/ - #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) +/******************************public_operate*********************************/ +static const uint8_t table_crc_hi[] = { - return 0; - } - return -1; -} + 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}; -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)) +static const uint8_t table_crc_lo[] = { - printf("The datagram integrity check passes\n"); - return 0; - } - printf("Datagram integrity check failed\n"); - return -1; -} + 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}; -struct LoraHeaderFormat header_send_buffer; -struct LoraHeaderFormat header_recv_buffer; +struct DataFrameFormat frame_send_buffer; // 消息发送缓冲区 +struct DataFrameFormat frame_recv_buffer; // 消息接收缓冲区 +uint8_t data_buffer[LORA_FRAME_USER_MAX_LENGTH]; // 数据发送/接收缓冲区 -static int LoraRecvHeader(struct Adapter* adapter, struct LoraHeaderFormat* header) +// 按照要求计算出数据帧的校验值 +static uint8_t CalCrcDataFrameFormat(struct DataFrameFormat *frame) { - PrivTaskDelay(1000); + uint8_t crc_hi = 0xFF; + uint8_t crc_lo = 0xFF; + unsigned int temp; + uint8_t *bit_arr = (uint8_t *)frame; // 转化为字节的方式进行数据访问 - if (LORA_HEADER_LENGTH == AdapterDeviceRecv(adapter,header,LORA_HEADER_LENGTH )) + uint8_t *temp_begin = bit_arr + 2; // 指向第二个数据段 + for (int i = 0; i < 5; i++) // 计算第二个字段到第六个字段,计算完毕该指针失效 { - if (0 == CheckHeaderCrc(header)) + temp = crc_hi ^ *temp_begin++; + crc_hi = crc_lo ^ table_crc_hi[temp]; + crc_lo = table_crc_lo[temp]; + } + + if (CG_DATA_SEND == frame->frame_type) // 是否携带了上传数据 + { + if (NULL == frame->user_data) { - PrivTaskDelay(500); - return LORA_HEADER_LENGTH; + printf("CalCrcDataFrameFormat: User data is null\n"); + return -1; + } + uint8_t data_length = frame->attach_data; + temp_begin = frame->user_data; + for (int i = 0; i < data_length; i++) // 计算上传数据的校验值 + { + temp = crc_hi ^ *temp_begin++; + crc_hi = crc_lo ^ table_crc_hi[temp]; + crc_lo = table_crc_lo[temp]; } } - return -1; + frame->crc_lo = crc_lo; + frame->crc_hi = crc_hi; + + return 0; } -static int LoraSendHeader(struct Adapter* adapter, struct LoraHeaderFormat* header) +// 按照要求计算出数据帧的校验值 +static uint8_t CheckCrcDataFrameFormat(struct DataFrameFormat *frame) { - PrivTaskDelay(500); + uint8_t crc_hi = 0xFF; + uint8_t crc_lo = 0xFF; + unsigned int temp; + uint8_t *bit_arr = (uint8_t *)frame; // 转化为字节的方式进行数据访问 - CalHeaderCrc(header); - - if (LORA_HEADER_LENGTH == AdapterDeviceSend(adapter,header,LORA_HEADER_LENGTH )) + uint8_t *temp_begin = bit_arr + 2; // 指向第二个数据段 + for (int i = 0; i < 5; i++) // 计算第二个字段到第六个字段,计算完毕该指针失效 { - PrivTaskDelay(1000); - return LORA_HEADER_LENGTH; + temp = crc_hi ^ *temp_begin++; + crc_hi = crc_lo ^ table_crc_hi[temp]; + crc_lo = table_crc_lo[temp]; } - 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) + if (CG_DATA_SEND == frame->frame_type) // 是否携带了上传数据 { - printf("The amount of data exceeds the limit\n"); - return -1; - } - - PrivTaskDelay(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); - - PrivTaskDelay(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; - } - - PrivTaskDelay(1000); - - if (data_length == AdapterDeviceRecv(adapter,dest_data,data_length)) - { - PrivTaskDelay(500); - if (0 == CheckCrc(dest_data,data_length -2,dest_data[data_length-2],dest_data[data_length-1])) + if (NULL == frame->user_data) { - return data_length; + printf("CheckCrcDataFrameFormat: User data is null\n"); + return -1; + } + uint8_t data_length = frame->attach_data; + temp_begin = frame->user_data; + for (int i = 0; i < data_length; i++) // 计算上传数据的校验值 + { + temp = crc_hi ^ *temp_begin++; + crc_hi = crc_lo ^ table_crc_hi[temp]; + crc_lo = table_crc_lo[temp]; } } - return -1; + + frame->crc_lo = crc_lo; + frame->crc_hi = crc_hi; + + return (frame->crc_hi == crc_hi && frame->crc_lo == crc_lo) ? 0 : -1; } -/**************************ClientOperations*********************************/ -uint8_t client_data_send_buffer[LORA_DATA_MAX_LENGTH]; -static int LoraClientJoinNet() +// 初始化数据帧的头部标识和尾部标识 +static void InitFrame(struct DataFrameFormat *frame) { - struct Adapter* adapter = AdapterDeviceFindByName(ADAPTER_LORA_NAME); - if (adapter == NULL) + memset(frame, 0, sizeof(struct DataFrameFormat)); + frame->begin_mark_1 = LORA_FRAME_BEGIN_MARK_1; + frame->begin_mark_2 = LORA_FRAME_BEGIN_MARK_2; + frame->end_mark_1 = LORA_FRAME_END_MARK_1; + frame->end_mark_2 = LORA_FRAME_END_MARK_2; +} + +// 空中信号探测器,用于简易的信道碰撞检测,当一个周期未能收到数据时判定为信道空闲 +static uint8_t SignalDetector(struct Adapter *adapter) +{ + uint8_t temp_dst; + while (1 == AdapterDeviceRecv(adapter, &temp_dst, 1)) // 当读取数据超时时假定为信道空闲 { - printf("Connection framework fundamental error\n"); - return -1; + printf("SignalDetector: Channel Occupied\n"); } - - 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; - } - PrivMutexObtain(&client_param->client_mtx); - - 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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&client_param->client_mtx); - + printf("SignalDetector: Channel Idle\n"); return 0; } -static int LoraClientSendData(void* data, uint16_t raw_data_length) +// 打印消息头数据 +static void PrintFrame(struct DataFrameFormat *frame, char *prefix) { - if (raw_data_length > LORA_DATA_MAX_LENGTH - 2) + printf("%s: ", prefix); + printf("client: %X, pan: %X, gateway: %X, frame_type: ", frame->client_id, frame->panid, frame->gateway_id); + switch (frame->frame_type) { - printf("The data load exceeds the limit\n"); - return -1; + case CG_NET_JOIN: + printf(" - CG_NET_JOIN- "); + break; + case CG_NET_QUIT: + printf(" - CG_NET_QUIT- "); + break; + case CG_DATA_SEND: + printf(" - CG_DATA_SEND- "); + break; + case GC_REPLY_EXPECTED: + printf(" - GC_REPLY_EXPECTED- "); + break; + case GC_REPLY_UNEXPECTED: + printf(" - GC_REPLY_UNEXPECTED- "); + break; + default: + break; } - - struct Adapter* adapter = AdapterDeviceFindByName(ADAPTER_LORA_NAME); - if (adapter == NULL) + printf("attach_data: %X, crc: %X %X ", frame->attach_data, frame->crc_hi, frame->crc_lo); + if (frame->frame_type == CG_DATA_SEND) { - printf("Connection framework fundamental error\n"); - return -1; + frame->user_data[frame->attach_data] = '\0'; + printf("user_data: %s \n", frame->user_data); } - - struct LoraClientParam* client_param =(struct LoraClientParam*) adapter->adapter_param; - - if (INSTALL != adapter->adapter_status || 0 != AdapterDeviceOpen(adapter)) + else { - printf("The Lora device failed to open\n"); - return -1; + printf("\n"); } - - if (client_param->client_state != CLIENT_CONNECT) - { - printf("This client has not connected to gateway\n"); - return -1; - } - - PrivMutexObtain(&client_param->client_mtx); - - 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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&client_param->client_mtx); - return -1; - } - - PrivMutexAbandon(&client_param->client_mtx); - printf("The client successfully sends the data\n"); - - return 0; } -static int LoraClientQuitNet() +// 接收直到一个完整的数据帧并校验其完整性,不完整的数据会被丢弃 +static uint8_t RecvFrame(struct Adapter *adapter, struct DataFrameFormat *frame) { - struct Adapter* adapter = AdapterDeviceFindByName(ADAPTER_LORA_NAME); - if (adapter == NULL) + memset(frame, 0, sizeof(struct DataFrameFormat)); // 缓冲区数据初始化 + uint8_t header_temp[2] = {0, 0}; // 头部数据查找缓冲区,一个用于接收数据,一个用于存储上一次接收到的数据 + + while (1 == AdapterDeviceRecv(adapter, &header_temp[1], 1)) // 查找开始标志 { - 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; - } - - PrivMutexObtain(&client_param->client_mtx); - 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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&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"); - PrivMutexAbandon(&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)) + if (LORA_FRAME_BEGIN_MARK_2 == header_temp[1]) // 查找到了第二个标志 + { + if (LORA_FRAME_BEGIN_MARK_1 == header_temp[0]) // 查看上一次的数据是不是第一个标识 { - 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) - { - PrivMutexObtain(&gateway_param->gateway_mtx); - 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) + frame->begin_mark_1 = header_temp[0]; + frame->begin_mark_2 = header_temp[1]; + // 开始按照结构读取数据 + if (LORA_FRAME_NECK_LENGTH == AdapterDeviceRecv(adapter, &frame->client_id, LORA_FRAME_NECK_LENGTH)) // 接收除可能的用户数据以外的数据 { - 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); + // 判断是否有用户数据 + if (CG_DATA_SEND == frame->frame_type) // 存在用户数据 + { + frame->user_data = data_buffer; // 关联数据缓冲区用于接收数据 + if (frame->attach_data != AdapterDeviceRecv(adapter, data_buffer, frame->attach_data)) // 接收数据 + { + printf("RecvFrame: Timeout or Failed 5\n"); + break; // 接收用户数据失败或者超时 + } + } + // 继续接收接下来的数据 + if (LORA_FRAME_CRC_LENGTH + LORA_FRAME_MARK_LENGTH == AdapterDeviceRecv(adapter, &frame->crc_hi, LORA_FRAME_CRC_LENGTH + LORA_FRAME_MARK_LENGTH)) + { + // 判断数据帧的完善性,看是否有尾巴 + if (LORA_FRAME_END_MARK_1 == frame->end_mark_1 && LORA_FRAME_END_MARK_2 == frame->end_mark_2) + { + // 进行数据完整性校验 + if (0 == CheckCrcDataFrameFormat(frame)) + { + return 0; // 成功接收了一帧数据 + } + printf("RecvFrame: CRC ERROR!\n"); + break; + } + printf("RecvFrame: End ERROR!\n"); + break; + } + printf("RecvFrame: Timeout or Failed 4\n"); + break; + } + printf("RecvFrame: Timeout or Failed 3\n"); + break; // 找到了头数据,却没能收到完整数据的全部失败 + } + else + { + header_temp[0] = header_temp[1]; // 记录这一次的数据 + } + } + else + { + header_temp[0] = header_temp[1]; // 记录这一次的数据 + } + } + + return -1; +} + +// 计算消息头校验并发送出去 +static uint8_t SendFrame(struct Adapter *adapter, struct DataFrameFormat *frame) +{ + // 校验数据 + if (0 == CalCrcDataFrameFormat(frame)) + { + // 发送公共信息 + if (LORA_FRAME_MARK_LENGTH + LORA_FRAME_NECK_LENGTH == AdapterDeviceSend(adapter, frame, LORA_FRAME_MARK_LENGTH + LORA_FRAME_NECK_LENGTH)) + { + // 判断是否有需要发送的用户数据 + if (CG_DATA_SEND == frame->frame_type) + { + if (frame->attach_data != AdapterDeviceSend(adapter, frame->user_data, frame->attach_data)) + { + return -1; } } + // 发送剩下的数据 + if (LORA_FRAME_MARK_LENGTH + LORA_FRAME_CRC_LENGTH == AdapterDeviceSend(adapter, &frame->crc_hi, LORA_FRAME_MARK_LENGTH + LORA_FRAME_CRC_LENGTH)) + { + return 0; + } } - - PrivMutexAbandon(&gateway_param->gateway_mtx); } - -END: - printf("Gateway task end\n"); + return -1; } +// 切换Lora的工作模式 +static void LoraModeConfig(struct Adapter *adapter, enum LoraMode mode) +{ + if (adapter->net_protocol == PRIVATE_PROTOCOL) + { + struct PrivProtocolDone *done = (struct PrivProtocolDone *)adapter->done; + done->ioctl(adapter, mode, NULL); + + printf("LoraModeConfig: Config Lora %s\n", mode == LORA_WORK ? "Working" : "Sleeping"); + } + else + { + printf("LoraModeConfig: Config Lora Fail\n"); + } +} + +// 客户端数据帧过滤器 +static uint8_t LoraClientFrameFilter(struct ClientParam *client_param, struct DataFrameFormat *frame) +{ + if (client_param->panid != frame->panid) // 是否是同一个网络 + { + printf("LoraFrameFilter: Different Networks\n"); + return -1; + } + + if (client_param->gateway_id != 0 && client_param->gateway_id != frame->gateway_id) // 不是该客户端所连接的网关 + { + printf("LoraFrameFilter: Different Gateway\n"); + return -1; + } + + if (client_param->client_id != frame->client_id) // 不是该客户端所连接的网关 + { + printf("LoraFrameFilter: Not For This Client\n"); + return -1; + } + + return 0; +} + +// 网关数据帧过滤器 +static uint8_t LoraGatewayFrameFilter(struct GatewayParam *gateway_param, struct DataFrameFormat *frame) +{ + if (gateway_param->panid != frame->panid) // 是否是同一个网络 + { + printf("LoraFrameFilter: Different Networks\n"); + return -1; + } + + if (frame->gateway_id == 0 && frame->frame_type == CG_NET_JOIN) // 入网请求 + { + return 0; + } + + if (frame->gateway_id != gateway_param->gateway_id) // 不是该网关所连接的客户端 + { + printf("LoraFrameFilter: Different Gateway\n"); + return -1; + } + + return 0; +} + +/******************************client_operate*********************************/ +static uint8_t LoraClientConnectState(struct Adapter *adapter, enum ClientState aim_state) +{ + if (aim_state == CLIENT_CONNECT || aim_state == CLIENT_DISCONNECT) // 只支持联网和退网 + { + struct ClientParam *client_param = (struct ClientParam *)adapter->adapter_param; + + if (client_param->client_state == aim_state) // 已经处于目标状态 + { + printf("LoraClientConnectState: Client %s Before\n", aim_state == CLIENT_CONNECT ? "Connect" : "Disconnect"); + return 0; + } + + PrivMutexObtain(&client_param->client_mutex); // 获取lora的使用权 + LoraModeConfig(adapter, LORA_WORK); // 切换Lora到普通接收模式 + + InitFrame(&frame_send_buffer); // 准备数据帧 + frame_send_buffer.client_id = client_param->client_id; + frame_send_buffer.panid = client_param->panid; + frame_send_buffer.gateway_id = client_param->gateway_id; + frame_send_buffer.frame_type = aim_state == CLIENT_CONNECT ? CG_NET_JOIN : CG_NET_QUIT; + + while (1) // 不停的发送信息直到收到正确的响应 + { + SignalDetector(adapter); // 监听信道直到信道空闲 + + if (0 == SendFrame(adapter, &frame_send_buffer)) + { + printf("LoraClientConnectState: Send Frame Success\n"); + PrintFrame(&frame_send_buffer, "LoraClientConnectState Send"); + if (0 == RecvFrame(adapter, &frame_recv_buffer)) // 成功接收到了一个数据帧 + { + printf("LoraClientConnectState: Recv Frame Success\n"); + PrintFrame(&frame_recv_buffer, "LoraClientConnectState Recv"); + if (0 == LoraClientFrameFilter(client_param, &frame_recv_buffer)) // 判断这个数据帧是不是自己 + { + if (frame_recv_buffer.frame_type == GC_REPLY_EXPECTED) // 请求成功 + { + client_param->gateway_id = aim_state == CLIENT_CONNECT ? frame_recv_buffer.gateway_id : 0; + client_param->client_state = aim_state; + + printf("LoraClientConnectState: Success - > Client(%X) Gateway(%X) %s\n", client_param->client_id, client_param->gateway_id, aim_state == CLIENT_CONNECT ? "Connect" : "Disconnect"); + break; + } + else + { + printf("LoraClientConnectState: Fail And Try Again\n"); + } + } + } + else + { + printf("LoraClientConnectState: Recv Frame Failed\n"); + } + } + else + { + printf("LoraClientConnectState: Send Frame Failed\n"); + } + } + + LoraModeConfig(adapter, LORA_SLEEP); // 切换Lora到休眠状态 + PrivMutexAbandon(&client_param->client_mutex); // 释放Lora + + return 0; + } + else + { + printf("LoraClientConnectState: Not Supported!\n"); + return -1; + } +} + +static uint8_t LoraClientSendData(struct Adapter *adapter, uint8_t *data_buffer, uint8_t data_length) +{ + struct ClientParam *client_param = (struct ClientParam *)adapter->adapter_param; + + if (client_param->client_state == CLIENT_CONNECT) // 只有处于联网状态的客户端才可以进行数据传输任务 + { + PrivMutexObtain(&client_param->client_mutex); // 拿到控制权 + LoraModeConfig(adapter, LORA_WORK); // 切换Lora为工作模式 + + InitFrame(&frame_send_buffer); // 准备消息头 + frame_send_buffer.client_id = client_param->client_id; + frame_send_buffer.panid = client_param->panid; + frame_send_buffer.gateway_id = client_param->gateway_id; + frame_send_buffer.frame_type = CG_DATA_SEND; + frame_send_buffer.user_data = data_buffer; // 关联数据缓冲区 + frame_send_buffer.attach_data = data_length; // 数据长度 + + while (1) // 不停的发送信息直到收到正确的响应 + { + SignalDetector(adapter); // 监听信道直到信道空闲 + + if (0 == SendFrame(adapter, &frame_send_buffer)) + { + printf("LoraClientSendData: Send Frame Success\n"); + PrintFrame(&frame_send_buffer, "LoraClientSendData Send"); + if (0 == RecvFrame(adapter, &frame_recv_buffer)) // 成功接收到了一个数据帧 + { + printf("LoraClientSendData: Recv Frame Success\n"); + PrintFrame(&frame_recv_buffer, "LoraClientSendData Recv"); + if (0 == LoraClientFrameFilter(client_param, &frame_recv_buffer)) // 判断这个数据帧是不是自己 + { + if (frame_recv_buffer.frame_type == GC_REPLY_EXPECTED) // 发送成功 + { + printf("LoraClientSendData: Send Data Success\n"); + break; + } + else + { + printf("LoraClientSendData: Fail And Try Again\n"); + } + } + } + else + { + printf("LoraClientSendData: Recv Frame Failed\n"); + } + } + else + { + printf("LoraClientSendData: Send Frame Failed\n"); + } + } + + LoraModeConfig(adapter, LORA_SLEEP); // 切换Lora到睡眠模式 + PrivMutexAbandon(&client_param->client_mutex); // 释放Lora + + return 0; + } + else + { + printf("LoraClientSendData: Client Is Disconnect\n"); + return -1; + } +} + +/**************************gateway_handlers*********************************/ + +// 网关处理客户端入网请求 +static uint8_t GatewayJoinNetHandler(struct Adapter *adapter, struct DataFrameFormat *frame) +{ + PrintFrame(frame, "GatewayJoinNetHandler Recv"); + + struct GatewayParam *gateway_param = (struct GatewayParam *)adapter->adapter_param; + + frame->gateway_id = gateway_param->gateway_id; // 确保网关设备参数正确传递 + + if (gateway_param->client_num == GATEWAY_MAX_CLIENT_NUM) // 判断网关连接的客户端是否达到上限 + { + printf("GatewayJoinNetHandler: Too much client\n"); + frame->frame_type = GC_REPLY_UNEXPECTED; + if (0 != SendFrame(adapter, frame)) + { + printf("GatewayJoinNetHandler: Client(%X) Join Gateway(%X) Failed 1 !\n", frame->client_id, gateway_param->gateway_id); + return -1; + } + PrintFrame(frame, "GatewayJoinNetHandler Send"); + printf("GatewayJoinNetHandler: Client(%X) Join Gateway(%X) Failed (MAX)!\n", frame->client_id, gateway_param->gateway_id); + return -1; + } + + for (int i = 0; i < gateway_param->client_num; i++) // 判断该客户端是否已经连接过了 + { + if (gateway_param->client_infos[i] == frame->client_id) + { + printf("GatewayJoinNetHandler: Joined before\n"); + frame->frame_type = GC_REPLY_EXPECTED; + if (0 != SendFrame(adapter, frame)) + { + printf("GatewayJoinNetHandler: Client(%X) Join Gateway(%X) Failed 2 !\n", frame->client_id, gateway_param->gateway_id); + return -1; + } + PrintFrame(frame, "GatewayJoinNetHandler Send"); + printf("GatewayJoinNetHandler: Client(%X) Join Gateway(%X) Success!\n", frame->client_id, gateway_param->gateway_id); + return 0; + } + } + + gateway_param->client_infos[gateway_param->client_num] = frame->client_id; + gateway_param->client_num++; + frame->frame_type = GC_REPLY_EXPECTED; // 成功连接到网关 + frame->gateway_id = gateway_param->gateway_id; + if (0 != SendFrame(adapter, frame)) + { + printf("GatewayJoinNetHandler: Client(%X) Join Gateway(%X) Failed 3 !\n", frame->client_id, gateway_param->gateway_id); + return -1; + } + PrintFrame(frame, "GatewayJoinNetHandler Send"); + printf("GatewayJoinNetHandler: Client(%X) Join Gateway(%X) Success!\n", frame->client_id, gateway_param->gateway_id); + return 0; +} + +// 网关处理客户端退网请求 +static uint8_t GatewayQuitNetHandler(struct Adapter *adapter, struct DataFrameFormat *frame) +{ + PrintFrame(frame, "GatewayQuitNetHandler Recv"); + + struct GatewayParam *gateway_param = (struct GatewayParam *)adapter->adapter_param; + + for (int i = 0; i < gateway_param->client_num; i++) + { + // 移除这个客户端的信息 + if (gateway_param->client_infos[i] == frame->client_id) + { + for (int j = i; j < gateway_param->client_num - 1; j++) + { + gateway_param->client_infos[j] = gateway_param->client_infos[j + 1]; + } + gateway_param->client_num--; + break; + } + } + + frame->frame_type = GC_REPLY_EXPECTED; + if (0 != SendFrame(adapter, frame)) + { + printf("GatewayQuitNetHandler: Client(%X) Quit Gateway(%X) Failed!\n", frame->client_id, gateway_param->gateway_id); + return -1; + } + PrintFrame(frame, "GatewayQuitNetHandler Send"); + printf("GatewayQuitNetHandler: Client(%X) Quit Gateway(%X) Success!\n", frame->client_id, gateway_param->gateway_id); + return 0; +} + +// 网关处理客户端的数据传输请求 +static uint8_t GatewayDataSendHandler(struct Adapter *adapter, struct DataFrameFormat *frame) +{ + PrintFrame(frame, "GatewayDataSendHandler Recv"); + + frame->frame_type = GC_REPLY_EXPECTED; + + if (0 != SendFrame(adapter, frame)) + { + printf("GatewayDataSendHandler: Client(%X) Send Data To Gateway(%X) Failed!\n", frame->client_id, frame->gateway_id); + return -1; + } + PrintFrame(frame, "GatewayDataSendHandler Send"); + printf("GatewayDataSendHandler: Client(%X) Send Data To Gateway(%X) Success!\n", frame->client_id, frame->gateway_id); + return 0; +} + +// 网关自动程序 +static void *GatewayDaemonTask(void *param) +{ + struct Adapter *gateway_adapter = (struct Adapter *)param; + if (gateway_adapter == NULL) // 判断参数合法性 + { + return NULL; + } + + struct GatewayParam *gateway_param = (struct GatewayParam *)gateway_adapter->adapter_param; + if (gateway_param->gateway_state != GATEWAY_WORKING) + { + if (0 != AdapterDeviceOpen(gateway_adapter)) // 开启Lora模块以接收消息 + { + return NULL; + } + gateway_param->gateway_state = GATEWAY_WORKING; + } + + PrivMutexObtain(&gateway_param->gateway_mutex); // 获取Lora控制权 + + while (1) // 内部业务大循环 + { + if (0 == RecvFrame(gateway_adapter, &frame_recv_buffer) && 0 == LoraGatewayFrameFilter(gateway_param, &frame_recv_buffer)) // 是否接收成功且是发给自己的 + { + gateway_handlers[frame_recv_buffer.frame_type](gateway_adapter, &frame_recv_buffer); // 根据消息类型,调用指定处理函数 + } + else + { + printf("GatewayDaemonTask: Recv No Frame\n"); + } + } + + PrivMutexAbandon(&gateway_param->gateway_mutex); // 释放Lora + + printf("GatewayDaemonTask: Exit!\n"); + return NULL; +} + +/**************************test_funcations*********************************/ +#ifdef AS_LORA_GATEWAY_ROLE + +void TestLoraGateway(void) +{ + struct Adapter *gateway_adapter = (struct Adapter *)AdapterDeviceFindByName(ADAPTER_LORA_NAME); + + UtaskType gateway_task; + gateway_task.prio = 24; + gateway_task.stack_size = 2048; + gateway_task.func_param = gateway_adapter; + gateway_task.func_entry = GatewayDaemonTask; + strncpy(gateway_task.name, "lora_gateway_task", strlen("lora_gateway_task")); + + int32_t gateway_task_id = UserTaskCreate(gateway_task); + + if (gateway_task_id > 0) + { + printf("TestLoraGateway: Create Gateway Task Success\n"); + if (0 == UserTaskStartup(gateway_task_id)) + { + printf("TestLoraGateway: Start Gateway Task Success\n"); + } + else + { + printf("TestLoraGateway: Start Gateway Task Failed\n"); + } + } + else + { + printf("TestLoraGateway: Create Gateway Task Failed\n"); + } +} +PRIV_SHELL_CMD_FUNCTION(TestLoraGateway, TestLoraGateway No Param, PRIV_SHELL_CMD_MAIN_ATTR); + +#else +void TestLoraConnectState(int user_state) +{ + enum ClientState state; + if (user_state == 0) + { + state = CLIENT_DISCONNECT; + printf("TestLoraConnectState: Config Lora Disconnect\n"); + } + else if (user_state == 1) + { + state = CLIENT_CONNECT; + printf("TestLoraConnectState: Config Lora Connect\n"); + } + else + { + printf("TestLoraConnectState: Not Suport 0-CLIENT_DISCONNECT 1-CLIENT_CONNECT\n"); + } + + struct Adapter *client_adapter = (struct Adapter *)AdapterDeviceFindByName(ADAPTER_LORA_NAME); + if (0 == AdapterDeviceOpen(client_adapter)) + { + if (0 == LoraClientConnectState(client_adapter, state)) + { + printf("TestLoraConnectState: Config Lora Connect State Success\n"); + } + else + { + printf("TestLoraConnectState: Config Lora Connect State Failed\n"); + } + } + else + { + printf("TestLoraConnectState: Lora Open Failed\n"); + } +} +PRIV_SHELL_CMD_FUNCTION(TestLoraConnectState, Only Suport 0-CLIENT_DISCONNECT 1-CLIENT_CONNECT, PRIV_SHELL_CMD_FUNC_ATTR); + +void TestLoraSendData(char* data) +{ + struct Adapter *client_adapter = (struct Adapter *)AdapterDeviceFindByName(ADAPTER_LORA_NAME); + if (0 == AdapterDeviceOpen(client_adapter)) + { + if (0 == LoraClientSendData(client_adapter, data,strlen(data))) + { + printf("TestLoraSendData: Send Data Success\n"); + } + else + { + printf("TestLoraSendData: Send Data Failed\n"); + } + } + else + { + printf("TestLoraSendData: Lora Open Failed\n"); + } +} +PRIV_SHELL_CMD_FUNCTION(TestLoraSendData, char* data param, PRIV_SHELL_CMD_FUNC_ATTR); + +void TestLoraClient(void) +{ + struct Adapter *client_adapter = (struct Adapter *)AdapterDeviceFindByName(ADAPTER_LORA_NAME); + if (0 == AdapterDeviceOpen(client_adapter)) + { + printf("TestLoraClient: Open Lora Success!\n"); + if (0 == LoraClientConnectState(client_adapter, CLIENT_CONNECT)) + { + printf("TestLoraClient: Client Join Net Success!\n"); + if (0 == LoraClientSendData(client_adapter, "Hello,Gateway!", strlen("Hello,Gateway!"))) + { + printf("TestLoraClient: Client Send Data Success!\n"); + if (0 == LoraClientConnectState(client_adapter, CLIENT_DISCONNECT)) + { + printf("TestLoraClient: Client Quit Net Success!\n"); + if (0 == LoraClientConnectState(client_adapter, CLIENT_CONNECT)) + { + printf("TestLoraClient: Client Join Net Success!\n"); + } + else + { + printf("TestLoraClient: Client Join Net Failed!\n"); + } + } + else + { + printf("TestLoraClient: Client Quit Net Failed!\n"); + } + } + else + { + printf("TestLoraClient: Client Send Data Fail!\n"); + } + } + else + { + printf("TestLoraClient: Client Join Net Fail!\n"); + } + } + else + { + printf("TestLoraClient: Open Lora Failed!\n"); + } +} +PRIV_SHELL_CMD_FUNCTION(TestLoraClient, TestLoraClient No Param, PRIV_SHELL_CMD_MAIN_ATTR); + +#endif /*******************LORA ADAPTER FUNCTION********************/ static int UsrAdapterLoraRegister(struct Adapter *adapter) { int ret = 0; - struct LoraGatewayParam *lora_gateway; - struct LoraClientParam *lora_client; - + struct GatewayParam *gateway_param; + struct ClientParam *client_param; 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 (PrivMutexCreate(&lora_gateway->gateway_mtx,0) < 0) + gateway_param = PrivMalloc(sizeof(struct GatewayParam)); + if (!gateway_param) { - printf("create lora gateway mutex fail\n"); + PrivFree(gateway_param); return -1; } - + memset(gateway_param, 0, sizeof(struct GatewayParam)); + gateway_param->gateway_id = DEAFULT_GATEWAY_ID; + gateway_param->panid = DEAFULT_PANID; + gateway_param->gateway_state = GATEWAY_ORIGINAL; + PrivMutexCreate(&gateway_param->gateway_mutex, 0); 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; - if (PrivMutexCreate(&lora_client->client_mtx,0)< 0) + adapter->adapter_param = (void *)gateway_param; +#else // AS_LORA_CLIENT_ROLE + client_param = PrivMalloc(sizeof(struct ClientParam)); + if (!client_param) { - printf("create lora client mutex fail\n"); + PrivFree(client_param); return -1; } - + memset(client_param, 0, sizeof(struct ClientParam)); + client_param->client_id = DEAFULT_CLIENT_ID; + client_param->panid = DEAFULT_PANID; + client_param->gateway_id = 0; + client_param->client_state = CLIENT_DISCONNECT; + PrivMutexCreate(&client_param->client_mutex, 0); adapter->net_role = CLIENT; adapter->net_role_id = DEAFULT_CLIENT_ID; - adapter->adapter_param = (void *)lora_client; + adapter->adapter_param = (void *)client_param; #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); - + if (ret < 0) + { + printf("Adapter lora register error\n"); + if (gateway_param) + PrivFree(gateway_param); + if (client_param) + PrivFree(client_param); return -1; } return ret; @@ -631,22 +797,22 @@ int UsrAdapterLoraInit(void) { int ret = 0; struct Adapter *adapter = PrivMalloc(sizeof(struct Adapter)); - if (!adapter) { + if (!adapter) + { PrivFree(adapter); return -1; } - memset(adapter, 0, sizeof(struct Adapter)); - ret = UsrAdapterLoraRegister(adapter); - if (ret < 0) { + if (ret < 0) + { printf("AdapterLoraInit register lora adapter error\n"); PrivFree(adapter); return -1; } - AdapterProductInfoType product_info = E220Attach(adapter); - if (!product_info) { + if (!product_info) + { printf("AdapterLoraInit e220 attach error\n"); PrivFree(adapter); return -1; @@ -658,116 +824,3 @@ int UsrAdapterLoraInit(void) 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 index 515a79f55..7e4d690aa 100644 --- 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 @@ -15,84 +15,143 @@ * @brief: a head file of lora structure * @version: 1.0 * @author: Chu yunfei -* @date: 2023/8/22 +* @date: 2023/8/30 */ #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 LORA_FRAME_MAX_LENGTH 128 +#define LORA_FRAME_USER_MAX_LENGTH LORA_FRAME_MAX_LENGTH - 11 +#define LORA_FRAME_BEGIN_MARK_1 0XFF +#define LORA_FRAME_BEGIN_MARK_2 0XAA +#define LORA_FRAME_END_MARK_1 0XFF +#define LORA_FRAME_END_MARK_2 0X00 +#define LORA_FRAME_MARK_LENGTH 2 +#define LORA_FRAME_NECK_LENGTH 5 +#define LORA_FRAME_CRC_LENGTH 2 +#define LORA_FRAME_SEND_INTERVAL 500 #define GATEWAY_MAX_CLIENT_NUM 20 +#define DEFAULT_ID_MAX 125 +#define DEFAULT_ID_MIN 1 #define DEAFULT_PANID 0XA #define DEAFULT_CLIENT_ID 0XB #define DEAFULT_GATEWAY_ID 0XC extern AdapterProductInfoType E220Attach(struct Adapter *adapter); -enum ClientState +// Lora工作模式枚举 +enum LoraMode { - CLIENT_DISCONNECT = 0, - CLIENT_CONNECT, + LORA_SLEEP = 0, // 切换至休眠模式 + LORA_WORK = 1 // 切换至工作模式 }; -struct LoraClientParam +// 客户端状态 +enum ClientState +{ + CLIENT_DISCONNECT = 0, // 开启但断网 + CLIENT_CONNECT, // 开启且联网 + CLIENT_BROKEN, // 硬件损坏 + CLIENT_CLOSED // 硬件关闭 +}; + +// 客户端参数 +struct ClientParam { uint8_t client_id; uint8_t panid; uint8_t gateway_id; enum ClientState client_state; - pthread_mutex_t client_mtx; + pthread_mutex_t client_mutex; // 互斥量 }; -struct LoraGatewayParam +// 网关状态 +enum GatewayState +{ + GATEWAY_ORIGINAL= 0, // 关闭且未开始工作 + GATEWAY_WORKING, // 开启且已经开始工作 + GATEWAY_BROKEN // 模块损坏 +}; + +// 网关参数 +struct GatewayParam { uint8_t gateway_id; uint8_t panid; - uint8_t client_id[GATEWAY_MAX_CLIENT_NUM]; - int client_num; - pthread_mutex_t gateway_mtx; + uint8_t client_infos[GATEWAY_MAX_CLIENT_NUM]; + uint8_t client_num; + enum GatewayState gateway_state; + pthread_mutex_t gateway_mutex; // 互斥量 }; -enum LoraDataType +// 消息类型 +enum FrameType { - /*****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, + /*C ---> G*/ + CG_NET_JOIN = 0, // 入网请求 + CG_NET_QUIT, // 退网请求 + CG_DATA_SEND, // 数据传输请求 + /*G ---> C*/ + GC_REPLY_EXPECTED, // 上行请求执行成功 + GC_REPLY_UNEXPECTED, // 上行请求执行失败 +}; +// 消息数据帧格式 +struct DataFrameFormat +{ + uint8_t begin_mark_1; // 0XFF + uint8_t begin_mark_2; // 0XAA + uint8_t client_id; // 0 - 127 + uint8_t panid; // 0 - 127 + uint8_t gateway_id; // 0 - 127 + uint8_t frame_type; // 0 - 127 + uint8_t attach_data; // 0 - 127 + uint8_t* user_data; // 在有数据携带时才会发送该指针所指缓冲区数据 + uint8_t crc_hi; // 这个字节没有0XFF + uint8_t crc_lo; // 这个字节会出现 0XFF,但是他的下一个字节不可能是00,必然是0XFF + uint8_t end_mark_1; // 0XFF + uint8_t end_mark_2; // 0X00 +}; +/******************************client_operate*********************************/ +/** + * @description: 将客户端网络状态切换为联网状态或者离线状态 + * @param adapter - 需要是一个已经打开的设备 + * @param aim_state - 需要转换的状态: CLIENT_CONNECT OR CLIENT_DISCONNECT + * @return success: 0, failure: -1 + */ +static uint8_t LoraClientConnectState(struct Adapter *adapter, enum ClientState aim_state); + +/** + * @description: 在联网状态下向网关发送数据 + * @param adapter - 需要是一个已经打开的设备 + * @param data_buffer - 数据缓冲区地址 + * @param data_length - 数据长度 + * @return success: 0, failure: -1 + */ +static uint8_t LoraClientSendData(struct Adapter *adapter, uint8_t *data_buffer, uint8_t data_length); + +/*****************************gateway_handlers*********************************/ +// 网关处理客户端入网请求 +static uint8_t GatewayJoinNetHandler(struct Adapter* adapter,struct DataFrameFormat* frame); +// 网关处理客户端退网请求 +static uint8_t GatewayQuitNetHandler(struct Adapter* adapter,struct DataFrameFormat* frame); +// 网关处理客户端的数据传输请求 +static uint8_t GatewayDataSendHandler(struct Adapter* adapter,struct DataFrameFormat* frame); +// 网关自动化处理程序任务,需要启动 +static void *GatewayDaemonTask(void *param); + +// 网关处理程序与消息类型的对照表 +static uint8_t (*gateway_handlers[])(struct Adapter*,struct DataFrameFormat*) = +{ + [CG_NET_JOIN] = GatewayJoinNetHandler, + [CG_NET_QUIT] = GatewayQuitNetHandler, + [CG_DATA_SEND] = GatewayDataSendHandler }; -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 -}; - -static int LoraClientJoinNet(); -static int LoraClientSendData(void* data, uint16_t raw_data_length); -static int LoraClientQuitNet(); - -/**************************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 +/************************lora adapter function*********************************/ +// 自定义注册函数 +static int UserAdapterLoraRegister(struct Adapter *adapter); +// 自定义初始化函数 +int UserAdapterLoraInit(void); \ No newline at end of file