delete p2p
| 
						 | 
					@ -1,154 +0,0 @@
 | 
				
			||||||
# 基于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)、获取使用权后将其配置为传输模式。<br>
 | 
					 | 
				
			||||||
> (2)、构建数据帧并设置好数据帧类型。<br>
 | 
					 | 
				
			||||||
> (3)、监听信道直到信道空闲。<br>
 | 
					 | 
				
			||||||
> (4)、发送数据帧(若是数据传输需要带上数据一起传输),若失败回到第三步。<br>
 | 
					 | 
				
			||||||
> (5)、接收数据帧并对数据帧进行数据过滤,若失败回到第三步。<br>
 | 
					 | 
				
			||||||
> (6)、解析数据帧并得到结果<br>
 | 
					 | 
				
			||||||
### 2、网关后台任务操作
 | 
					 | 
				
			||||||
> (1)、获取使用权后开启数据接收。<br>
 | 
					 | 
				
			||||||
> (2)、根据数据帧结构,监听信道,过滤掉杂乱的信号,在接收到一个完整的数据帧并完整性校验通过后返回继续第三步,否则循环执行第二步。<br>
 | 
					 | 
				
			||||||
> (3)、根据得到的数据帧类型将其交付给对应的处理器处理,处理完毕后返回第二步。<br>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 四、测试程序说明
 | 
					 | 
				
			||||||
在进行测试时,最好先启动网关并开启网关程序,当然后启动网关也一样。
 | 
					 | 
				
			||||||
### 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)` ;
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
2. `APP_Framework > Framework` 开启 `support connection framework (NEW)` ,然后进入其中,开启 `Using lora adapter device (NEW)` ,然后进入其中, 客户端将其配置如下图所示,网关将其配置为下下图所示;
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
3. 将客户端和网关分别编译、烧录到不同的板子并启动后用串口进行连接;
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
4. 启动网关程序;
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
5. 整体测试客户端;
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
6. 测试断网
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
7. 测试联网
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
8. 测试数据发送
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 200 KiB  | 
| 
		 Before Width: | Height: | Size: 160 KiB  | 
| 
		 Before Width: | Height: | Size: 160 KiB  | 
| 
		 Before Width: | Height: | Size: 134 KiB  | 
| 
		 Before Width: | Height: | Size: 158 KiB  | 
| 
		 Before Width: | Height: | Size: 198 KiB  | 
| 
		 Before Width: | Height: | Size: 196 KiB  | 
| 
		 Before Width: | Height: | Size: 196 KiB  | 
| 
		 Before Width: | Height: | Size: 190 KiB  | 
| 
						 | 
					@ -1,826 +0,0 @@
 | 
				
			||||||
#include "test_lora_p2p.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************public_operate*********************************/
 | 
					 | 
				
			||||||
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};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct DataFrameFormat frame_send_buffer;        // 消息发送缓冲区
 | 
					 | 
				
			||||||
struct DataFrameFormat frame_recv_buffer;        // 消息接收缓冲区
 | 
					 | 
				
			||||||
uint8_t data_buffer[LORA_FRAME_USER_MAX_LENGTH]; // 数据发送/接收缓冲区
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 按照要求计算出数据帧的校验值
 | 
					 | 
				
			||||||
static uint8_t CalCrcDataFrameFormat(struct DataFrameFormat *frame)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    uint8_t crc_hi = 0xFF;
 | 
					 | 
				
			||||||
    uint8_t crc_lo = 0xFF;
 | 
					 | 
				
			||||||
    unsigned int temp;
 | 
					 | 
				
			||||||
    uint8_t *bit_arr = (uint8_t *)frame; // 转化为字节的方式进行数据访问
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint8_t *temp_begin = bit_arr + 2; // 指向第二个数据段
 | 
					 | 
				
			||||||
    for (int i = 0; i < 5; i++)        // 计算第二个字段到第六个字段,计算完毕该指针失效
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        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)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            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];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    frame->crc_lo = crc_lo;
 | 
					 | 
				
			||||||
    frame->crc_hi = crc_hi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 按照要求计算出数据帧的校验值
 | 
					 | 
				
			||||||
static uint8_t CheckCrcDataFrameFormat(struct DataFrameFormat *frame)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    uint8_t crc_hi = 0xFF;
 | 
					 | 
				
			||||||
    uint8_t crc_lo = 0xFF;
 | 
					 | 
				
			||||||
    unsigned int temp;
 | 
					 | 
				
			||||||
    uint8_t *bit_arr = (uint8_t *)frame; // 转化为字节的方式进行数据访问
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint8_t *temp_begin = bit_arr + 2; // 指向第二个数据段
 | 
					 | 
				
			||||||
    for (int i = 0; i < 5; i++)        // 计算第二个字段到第六个字段,计算完毕该指针失效
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        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)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            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];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    frame->crc_lo = crc_lo;
 | 
					 | 
				
			||||||
    frame->crc_hi = crc_hi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (frame->crc_hi == crc_hi && frame->crc_lo == crc_lo) ? 0 : -1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 初始化数据帧的头部标识和尾部标识
 | 
					 | 
				
			||||||
static void InitFrame(struct DataFrameFormat *frame)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    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("SignalDetector: Channel Occupied\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    printf("SignalDetector: Channel Idle\n");
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 打印消息头数据
 | 
					 | 
				
			||||||
static void PrintFrame(struct DataFrameFormat *frame, char *prefix)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    printf("%s: ", prefix);
 | 
					 | 
				
			||||||
    printf("client: %X, pan: %X, gateway: %X, frame_type: ", frame->client_id, frame->panid, frame->gateway_id);
 | 
					 | 
				
			||||||
    switch (frame->frame_type)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    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;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    printf("attach_data: %X, crc: %X %X ", frame->attach_data, frame->crc_hi, frame->crc_lo);
 | 
					 | 
				
			||||||
    if (frame->frame_type == CG_DATA_SEND)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        frame->user_data[frame->attach_data] = '\0';
 | 
					 | 
				
			||||||
        printf("user_data: %s \n", frame->user_data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        printf("\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 接收直到一个完整的数据帧并校验其完整性,不完整的数据会被丢弃
 | 
					 | 
				
			||||||
static uint8_t RecvFrame(struct Adapter *adapter, struct DataFrameFormat *frame)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    memset(frame, 0, sizeof(struct DataFrameFormat)); // 缓冲区数据初始化
 | 
					 | 
				
			||||||
    uint8_t header_temp[2] = {0, 0};                  // 头部数据查找缓冲区,一个用于接收数据,一个用于存储上一次接收到的数据
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while (1 == AdapterDeviceRecv(adapter, &header_temp[1], 1)) // 查找开始标志
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (LORA_FRAME_BEGIN_MARK_2 == header_temp[1]) // 查找到了第二个标志
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (LORA_FRAME_BEGIN_MARK_1 == header_temp[0]) // 查看上一次的数据是不是第一个标识
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                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)) // 接收除可能的用户数据以外的数据
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    // 判断是否有用户数据
 | 
					 | 
				
			||||||
                    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;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    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 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
 | 
					 | 
				
			||||||
    gateway_param = PrivMalloc(sizeof(struct GatewayParam));
 | 
					 | 
				
			||||||
    if (!gateway_param)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        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 *)gateway_param;
 | 
					 | 
				
			||||||
#else // AS_LORA_CLIENT_ROLE
 | 
					 | 
				
			||||||
    client_param = PrivMalloc(sizeof(struct ClientParam));
 | 
					 | 
				
			||||||
    if (!client_param)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        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 *)client_param;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    adapter->adapter_status = UNREGISTERED;
 | 
					 | 
				
			||||||
    ret = AdapterDeviceRegister(adapter);
 | 
					 | 
				
			||||||
    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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,157 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
* 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.h
 | 
					 | 
				
			||||||
* @brief:   a head file of lora structure
 | 
					 | 
				
			||||||
* @version: 1.0
 | 
					 | 
				
			||||||
* @author:  Chu yunfei
 | 
					 | 
				
			||||||
* @date:    2023/8/30
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include<adapter.h>
 | 
					 | 
				
			||||||
#include<transform.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Lora工作模式枚举
 | 
					 | 
				
			||||||
enum LoraMode
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    LORA_SLEEP = 0, // 切换至休眠模式
 | 
					 | 
				
			||||||
    LORA_WORK = 1 // 切换至工作模式
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 客户端状态
 | 
					 | 
				
			||||||
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_mutex; // 互斥量
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 网关状态
 | 
					 | 
				
			||||||
enum GatewayState
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    GATEWAY_ORIGINAL= 0, // 关闭且未开始工作
 | 
					 | 
				
			||||||
    GATEWAY_WORKING, // 开启且已经开始工作
 | 
					 | 
				
			||||||
    GATEWAY_BROKEN // 模块损坏
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 网关参数
 | 
					 | 
				
			||||||
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; // 互斥量
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 消息类型
 | 
					 | 
				
			||||||
enum FrameType
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /*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
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/************************lora adapter function*********************************/
 | 
					 | 
				
			||||||
// 自定义注册函数
 | 
					 | 
				
			||||||
static int UserAdapterLoraRegister(struct Adapter *adapter);
 | 
					 | 
				
			||||||
// 自定义初始化函数
 | 
					 | 
				
			||||||
int UserAdapterLoraInit(void);
 | 
					 | 
				
			||||||