Add LoRa module

This commit is contained in:
yudongdong
2021-04-30 21:16:42 +08:00
parent 18da044bb7
commit 849f5d7dd5
61 changed files with 15109 additions and 15 deletions

View File

@@ -1,7 +1,13 @@
menuconfig CONNECTION_COMMUNICATION_WIFI
bool "Enable Wifi"
default n
menuconfig CONNECTION_COMMUNICATION_LORA
bool "Enable LORA"
default n
if CONNECTION_COMMUNICATION_LORA
source "$KERNEL_DIR/framework/connection/Adapter/lora/Kconfig"
endif
menuconfig CONNECTION_COMMUNICATION_ETHERNET
bool "Enable Ethernet"

View File

@@ -1,9 +1,9 @@
SRC_DIR := src
# ifeq ($(CONFIG_CONNECTION_COMMUNICATION_LORA), y)
# SRC_DIR += lora
# endif
ifeq ($(CONFIG_CONNECTION_COMMUNICATION_LORA), y)
SRC_DIR += lora
endif
ifeq ($(CONFIG_CONNECTION_COMMUNICATION_ETHERNET), y)
SRC_DIR += ethernet

View File

@@ -0,0 +1,184 @@
/*
* Copyright (c) 2020 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 xs_adapterLora.h
* @brief lora adhoc logic
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.04.22
*/
#ifndef XS_ADAPTER_LORA_H
#define XS_ADAPTER_LORA_H
#include "xs_adapter.h"
#define DEVNAME_LEN_MAX 32
#define NETNAME_LEN_MAX 32
#define CONNECTED_CLIENTS_MAX 512
#define CLIENT_SEND_CELL_LEN 120
struct AdapterLora {
struct Adapter parent; /* inherit from Adapter */
const char * name; /* name of the adapter instance */
const char *deve_ui; /* Lora specific value */
const char *app_key; /* Lora specific value */
int spi_lora_fd;
};
typedef struct AdapterLora *AdapterLoraT;
int LoraAdapterOpen(adapter_t padapter);
void LoraAdapterCose(struct Adapter *padapter);
int LoraAdapterSend(struct Adapter *padapter, const char* data, int len, bool block, int time_out, int delay, void *p);
int LoraAdapterReceive(adapter_t padapter, char* rev_buffer, int buffer_len,int time_out, bool block, void *p);
int LoraAdapterJoin(adapter_t sadapter, int dev_type, char* net_id);
int LoraAdapterSendc2g(adapter_t padapter, const char *data, int len, bool block, int time_out, int delay, send_success cb, void* param, void *p);
// Client state machine
enum LoraClientStatus
{
LORA_CLIENT_IDLE = 0,
LORA_CLIENT_LOOKING4GATEWAY,
LORA_CLIENT_CONNECTING2GATEWAY,
LORA_CLIENT_CONNECTED,
LORA_CLIENT_WAITTING_FOR_DISCONNECTED,
LORA_CLIENT_DISCONNECTED,
};
struct LoraClientStatusInfo
{
enum LoraClientStatus status;
int user_id;
char gateway_name[DEVNAME_LEN_MAX];
char client_name[DEVNAME_LEN_MAX];
};
enum LoraOpcode
{
LORA_OPCODE_START = 0xFFF0,
LORA_JOIN_REQ = 0xFFF1,
LORA_JOIN_RSP = 0xFFF2,
LORA_HANDSHAKE_REQ = 0xFFF3,
LORA_HANDSHAKE_RSP = 0xFFF4,
LORA_C2G_DATA_REQ = 0xFFF5,
LORA_C2G_DATA_RSP = 0xFFF6,
LORA_CLOSE_REQ = 0xFFF7,
LORA_CLOSE_RSP = 0xFFF8,
LORA_OPCODE_END,
};
enum WorkThreadStatus
{
WORK_THREAD_RX = 1,
WORK_THREAD_TX,
};
// pkg header
typedef struct
{
int op_code;
int length;
}LoraHeader;
// Network access, handshake function protocol
typedef struct
{
char net_id[NETNAME_LEN_MAX];
}LoraProtoJoinReq;
typedef struct
{
char net_id[NETNAME_LEN_MAX];
char gateway_name[DEVNAME_LEN_MAX];
int signal_strength;
int error_code;
}LoraProtoJoinRsp;
typedef struct
{
char client_name[DEVNAME_LEN_MAX];
char gateway_name[DEVNAME_LEN_MAX];
}LoraProtoHandshakeReq;
typedef struct
{
char client_name[DEVNAME_LEN_MAX];
char gateway_name[DEVNAME_LEN_MAX];
int user_id;
int error_code;
}LoraProtoHandshakeRsp;
// Data transmission protocol
typedef struct
{
int user_id;
int pkg_id;
int data_len;
int crc;
}LoraProtoC2GDataReq;
typedef struct
{
int user_id;
int ack_id;
int data_len;
int crc;
}LoraProtoC2GDataRsp;
// Client active disconnect
typedef struct
{
int user_id;
}LoraProtoCloseReq;
typedef struct
{
int user_id;
int error_code;
}LoraProtoCloseRsp;
typedef struct
{
char* data;
int len;
bool* prsp_flag;
adapter_t padapter;
}CheckRspParam;
typedef void(*send_success)(void* param);
typedef struct
{
bool has_data;
int crc;
int pkg_id;
char data[CLIENT_SEND_CELL_LEN];
int data_len;
send_success callback;
void* param;
}ClientSendCell;
typedef struct
{
char user_name[DEVNAME_LEN_MAX];
int user_id;
DoubleLinklistType link;
}OnlineUser;
#endif

View File

@@ -0,0 +1,30 @@
#LORA adhoc configuration
#Set same netID, and then join one adhoc net.
menuconfig CONNECTION_COMMUNICATION_BOOTSTART_LORA_NET_SAMPLE
bool "use bootstart lora net sample"
default n
if CONNECTION_COMMUNICATION_BOOTSTART_LORA_NET_SAMPLE
menuconfig CONNECTION_COMMUNICATION_SET_AS_LORA_CLIENT
bool "set this as lora client "
default n
if CONNECTION_COMMUNICATION_SET_AS_LORA_CLIENT
config CONNECTION_COMMUNICATION_LORA_CLIENT_NAME
string "config lora net client name"
default "lora_client_name0"
config CONNECTION_COMMUNICATION_LORA_CLIENT_PKG_COUNT
int "config lora send pkg count"
default 1000
endif
menuconfig CONNECTION_COMMUNICATION_SET_AS_LORA_GATEWAY
bool "set this as lora gateway"
default n
config CONNECTION_COMMUNICATION_LORA_NET_ID
string "config lora net ID"
default "intelligence grain"
endif

View File

@@ -0,0 +1,3 @@
SRC_FILES := xs_adapter_lora.c
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,849 @@
/*
* Copyright (c) 2020 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 xs_AdapterLora.c
* @brief lora adhoc logic
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.04.22
*/
#include <xs_adapter_lora.h>
#include "spi_lora_sx12xx.h"
#include "radio.h"
#include "sx1276-LoRa.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <user_api.h>
#define SLEEP_MS 50
enum NetRoleType _role_type = ROLE_TYPE_NONE;
bool gateway_listening = false;
bool client_work_thread_running = false;
char gateway_net_id[NETNAME_LEN_MAX];
char client_net_id[NETNAME_LEN_MAX];
struct LoraClientStatusInfo g_client_status_info;
int pkg_id_c2g;
#define BUFFER_LEN_MAX 120
char rec_buffer[BUFFER_LEN_MAX] = {0};
char client_rec_buffer[BUFFER_LEN_MAX] = {0};
char send_buffer[BUFFER_LEN_MAX] = {0};
DoubleLinklistType online_user_head = {&online_user_head, &online_user_head};
// Client send buffer. Only one element is set temporarily
ClientSendCell client_send_buffer;
int pclient_send_buffer_mutex = -1;
enum WorkThreadStatus g_work_thread_status;
bool need_send_data = false;
int32 ServerTask = NONE;
int32 ClientTask = NONE;
static int spi_lora_fd_intern = -1;
extern tRadioDriver *Radio;
/**
* @description: open lora adapter
* @param padapter - lora adapter pointer
*/
int LoraAdapterOpen(adapter_t padapter)
{
int fd = ((AdapterLoraT)padapter)->spi_lora_fd;
if (fd < 0){
fd = open(LORA_SPI_NAME,O_RDWR);
}
if(fd < 0){
printf("LoRa check failed!\n!");
return ERROR;
} else {
((AdapterLoraT)padapter)->spi_lora_fd = fd;
spi_lora_fd_intern = fd;
memset(&g_client_status_info, 0, sizeof(g_client_status_info));
g_client_status_info.status = LORA_CLIENT_IDLE;
pkg_id_c2g = 1;
_role_type = ROLE_TYPE_NONE;
printf("LoRa check ok!\nNote: The length of the message that can be sent in a single time is 120 characters\n");
}
return 0;
}
/**
* @description: close lora adapter
* @param padapter - lora adapter pointer
*/
void LoraAdapterCose(struct Adapter *padapter)
{
if (((AdapterLoraT)padapter)->spi_lora_fd < 0){
printf("LoRa device not found! close failed!\n");
} else {
// Disconnect
int count = 10;
g_client_status_info.status = LORA_CLIENT_WAITTING_FOR_DISCONNECTED;
need_send_data = true;
while (count > 0 && g_client_status_info.status == LORA_CLIENT_WAITTING_FOR_DISCONNECTED)
{
printf("lora client waitting for rsp, count(%d)\n", count);
UserTaskDelay(1000);
count--;
}
if (g_client_status_info.status != LORA_CLIENT_DISCONNECTED){
printf("lora send close pkg failed!\n");
}
gateway_listening = false;
client_work_thread_running = false;
// Release thread
if (NONE != ServerTask){
UserTaskDelete(ServerTask);
ServerTask = NONE;
}
if (NONE != ClientTask){
UserTaskDelete(ClientTask);
ClientTask = NONE;
}
// Release the lock
if (pclient_send_buffer_mutex != NONE) {
UserMutexDelete(pclient_send_buffer_mutex);
pclient_send_buffer_mutex = NONE;
}
// Driver
((AdapterLoraT)padapter)->spi_lora_fd = NONE;
}
}
bool lora_channel_avtive()
{
return Radio->ChannelEmpty() == 0;
}
int LoraAdapterSend(struct Adapter *padapter, const char *data, int len, bool block, int time_out, int delay, void *p)
{
if (len > 120){
printf("ERROR:The message is too long!\n");
return ERROR;
}
if (((AdapterLoraT)padapter)->spi_lora_fd == NONE){
printf("LoRa device not found!\n");
return ERROR;
} else {
int time_counter = 0;
int time_sleep_gap = 500;
while (false == lora_channel_avtive()) {
if (time_counter * time_sleep_gap > time_out) {
printf("LoRa_adapter_send failed! time_out!\n");
return ERROR;
}
UserTaskDelay(time_sleep_gap);
time_counter++;
}
char Msg[120] = {0};
memcpy(Msg, data, len);
Radio->SetTxPacket(Msg, len);
while (Radio->Process() != RF_TX_DONE)
;
}
}
int lora_send(const char *data, int len)
{
if (len > 120) {
printf("ERROR:The message is too long!\n");
return ERROR;
}
int time_counter = 0;
int time_sleep_gap = 500;
int time_out = 10000;
while (false == lora_channel_avtive()) {
if (time_counter * time_sleep_gap > time_out) {
printf("LoRa send failed! time_out!\n");
return ERROR;
}
UserTaskDelay(time_sleep_gap);
time_counter++;
}
char Msg[120] = {0};
memcpy(Msg, data, len);
Radio->SetTxPacket(Msg, len);
while (Radio->Process() != RF_TX_DONE)
;
}
int LoraAdapterSendc2g(adapter_t padapter, const char *data, int len, bool block, int time_out, int delay, send_success cb, void *param, void *p)
{
if (_role_type == ROLE_TYPE_SLAVE && g_client_status_info.status == LORA_CLIENT_CONNECTED) {
LoraHeader header;
memset(&header, 0, sizeof(header));
header.op_code = LORA_C2G_DATA_REQ;
header.length = sizeof(LoraHeader) + sizeof(LoraProtoC2GDataReq) + len;
if (header.length > 120) {
printf("Send failed, LoRa send max length is 120.\n");
return ERROR;
}
if (client_send_buffer.has_data == true){
printf("Send failed, last pakage is resending\n");
return ERROR;
}
LoraProtoC2GDataReq req;
req.user_id = g_client_status_info.user_id;
req.pkg_id = pkg_id_c2g;
req.data_len = len;
req.crc = 0xFFFF;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), &req, sizeof(req));
memcpy(send_buffer + sizeof(header) + sizeof(req), data, len);
// Write data to buffer (lock)
UserMutexObtain(pclient_send_buffer_mutex, WAITING_FOREVER);
client_send_buffer.has_data = true;
client_send_buffer.pkg_id = pkg_id_c2g;
client_send_buffer.crc = 0xFFFF;
memcpy(client_send_buffer.data, send_buffer, header.length);
client_send_buffer.data_len = header.length;
client_send_buffer.callback = cb;
client_send_buffer.param = param;
UserMutexAbandon(pclient_send_buffer_mutex);
// printf("copy to send buffer. len = %d\n", header.length);
// Switch worker thread state
need_send_data = true;
return ERROR;
} else {
printf("LoRa client is unconnected! can not send data!\n");
}
}
OnlineUser *find_user_by_name(char *name)
{
DoubleLinklistType *pLink;
DOUBLE_LINKLIST_FOR_EACH(pLink, &online_user_head)
{
OnlineUser *pUer =CONTAINER_OF(pLink, OnlineUser, link);
if (strcmp(pUer->user_name, name) == 0) {
return pUer;
}
}
return NONE;
}
OnlineUser *find_user_by_id(int id)
{
DoubleLinklistType *pLink;
DOUBLE_LINKLIST_FOR_EACH(pLink, &online_user_head)
{
OnlineUser *pUer =CONTAINER_OF(pLink, OnlineUser, link);
if (pUer->user_id == id) {
return pUer;
}
}
return NONE;
}
int insert_connected_clients(char *name, int user_id)
{
OnlineUser *pUser = malloc(sizeof(OnlineUser));
if (NONE == pUser)
return ERROR;
pUser->user_id = user_id;
strcpy(pUser->user_name, name);
DoubleLinkListInsertNodeAfter(&online_user_head, &pUser->link);
return EOK;
}
void CheckSendBuffer()
{
UserMutexObtain(pclient_send_buffer_mutex, WAITING_FOREVER);
if (client_send_buffer.has_data == true)
{
//Sending or packet loss retransmission
lora_send(client_send_buffer.data, client_send_buffer.data_len);
// printf("client check and send. len = %d\n", client_send_buffer.data_len);
}
UserMutexAbandon(pclient_send_buffer_mutex);
}
int LoraAdapterReceive(adapter_t padapter, char *rev_buffer, int buffer_len, int time_out, bool block, void *p)
{
uint16 BufferSize = buffer_len;
memset(rev_buffer, 0, buffer_len);
if (((AdapterLoraT)padapter)->spi_lora_fd == NONE)
{
printf("LoRa device not found!\n");
}
else
{
Radio->StartRx();
printf("Ready!\n");
while (Radio->Process() != RF_RX_DONE)
{
// if (time_out < 0)
// {
// printf("LoRa device receive failed! Timeout!\n");
// return ERROR;
// }
// UserTaskDelay(SLEEP_MS);
// time_out -= SLEEP_MS;
}
Radio->GetRxPacket(rev_buffer, (uint16 *)&BufferSize);
if (BufferSize == buffer_len)
{
printf("rev_buffer is too small!\n");
}
printf("RX : %s\n", rev_buffer);
return BufferSize;
}
}
int LoraGatewayProcess(adapter_t padapter, char *pkg, int rec_len)
{
struct AdapterLora* lora_adapter = (struct AdapterLora*)padapter;
if (rec_len > 0)
{
LoraHeader header;
memset(&header, 0, sizeof(header));
char *start = (char *)pkg;
LoraHeader *pheader = (LoraHeader *)start;
char *req = start + sizeof(LoraHeader);
if (pheader->op_code < LORA_OPCODE_START || pheader->op_code > LORA_OPCODE_END)
{
printf("Illegal opcode, discard data!\n");
return ERROR;
}
if (rec_len != pheader->length)
{
printf("pkg is not complete!, discard data!\n");
return ERROR;
}
printf("gateway receive pkg opcode(%4x)\n", pheader->op_code);
switch (pheader->op_code)
{
case LORA_JOIN_REQ: // There is a client request to join the network segment
if (strcmp(((LoraProtoJoinReq *)req)->net_id, gateway_net_id) == 0) // The request is really this network segment
{
LoraProtoJoinReq *req = (LoraProtoJoinReq *)(start + sizeof(LoraHeader));
header.op_code = LORA_JOIN_RSP;
header.length = sizeof(LoraHeader) + sizeof(LoraProtoJoinRsp);
LoraProtoJoinRsp rsp;
memset(&rsp, 0, sizeof(rsp));
rsp.error_code = 0;
rsp.signal_strength = 0; // signal intensity
printf(" 11aa strlen(lora_adapter->name) = %d\n", strlen(lora_adapter->name));
printf(" 11aa lora_adapter->name = %s\n", lora_adapter->name);
strcpy(rsp.gateway_name, lora_adapter->name);
strcpy(rsp.net_id, gateway_net_id);
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), &rsp, sizeof(rsp));
printf("LoraProtoJoinRsp rsp.gateway_name = %s rsp.net_id = %s\n", rsp.gateway_name, rsp.net_id);
lora_send(send_buffer, header.length);
printf("gateway send pkg opcode(%4x)\n", header.op_code);
}
break;
case LORA_HANDSHAKE_REQ:
if (strcmp(((LoraProtoHandshakeReq *)req)->gateway_name, lora_adapter->name) == 0) //The other party really wants to connect themselves
{
// Construction reply, connection confirmation
LoraProtoHandshakeReq *req = (LoraProtoHandshakeReq *)(start + sizeof(LoraHeader));
int user_id = 0;
// If it can be found, it will prove that it is connected. It may be packet loss, so normal retransmission is good
OnlineUser *pUser = find_user_by_name(req->client_name);
if (NONE == pUser)
{
// New virtual connection
user_id = rand() % UINT32_SIZE_MAX;
if (ERROR == insert_connected_clients(req->client_name, user_id))
{
return ERROR;
}
}
else
{
// Packet loss
user_id = pUser->user_id;
}
header.op_code = LORA_HANDSHAKE_RSP;
header.length = sizeof(LoraHeader) + sizeof(LoraProtoHandshakeRsp);
LoraProtoHandshakeRsp rsp;
memset(&rsp, 0, sizeof(rsp));
strcpy(rsp.client_name, req->client_name);
strcpy(rsp.gateway_name, req->gateway_name);
rsp.user_id = user_id;
rsp.error_code = 0;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), &rsp, sizeof(rsp));
printf("LoraProtoHandshakeRsp, rsp.client_name = %s, rsp.gateway_name = %s\n", rsp.client_name, rsp.gateway_name);
lora_send(send_buffer, header.length);
printf("gateway send pkg opcode(%4x)\n", header.op_code);
}
break;
case LORA_C2G_DATA_REQ:
{
OnlineUser *pUser = find_user_by_id(((LoraProtoC2GDataReq *)req)->user_id);
if (pUser) //What the other party wants to send is really himself
{
LoraProtoC2GDataReq *req = (LoraProtoC2GDataReq *)(start + sizeof(LoraHeader));
char *data = start + sizeof(LoraHeader) + sizeof(LoraProtoC2GDataReq);
// printf("receive data from client(%s), content(%s)", pUser->user_name, data);
printf(" receive data from \033[0;31m client(%s)\033[0m \n, content(%s). ", pUser->user_name, data);
// Logic layer to deal with
// CRC calculation for data and reply to client
header.op_code = LORA_C2G_DATA_RSP;
header.length = sizeof(LoraHeader) + sizeof(LoraProtoC2GDataRsp);
LoraProtoC2GDataRsp rsp;
memset(&rsp, 0, sizeof(rsp));
rsp.user_id = req->user_id;
rsp.crc = 0xFFFF;
rsp.data_len = rec_len;
rsp.ack_id = req->pkg_id;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), &rsp, sizeof(rsp));
lora_send(send_buffer, header.length);
printf("gateway send pkg opcode(%4x), ack_id(%d)\n", header.op_code, rsp.ack_id);
}
else
{
printf("user unconnected, discard data.\n");
return ERROR;
}
break;
}
case LORA_CLOSE_REQ:
{
LoraProtoCloseReq *req = (LoraProtoCloseReq *)(start + sizeof(LoraHeader));
//log
DoubleLinklistType *pNode;
printf("******** connected users *********\n");
DOUBLE_LINKLIST_FOR_EACH(pNode, &online_user_head)
{
OnlineUser *pUser =CONTAINER_OF(pNode, OnlineUser, link);
printf("pUser->user_name %s\n", pUser->user_name);
printf("pUser->user_id %d\n", pUser->user_id);
}
printf("*********************************\n");
printf("req->user_id = %d\n", req->user_id);
OnlineUser *pUser = find_user_by_id(req->user_id);
if (pUser)
{
DoubleLinkListRmNode(&pUser->link);
header.op_code = LORA_CLOSE_RSP;
header.length = sizeof(LoraHeader) + sizeof(LoraProtoCloseRsp);
LoraProtoCloseRsp rsp;
rsp.error_code = 0;
rsp.user_id = req->user_id;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), &rsp, sizeof(rsp));
lora_send(send_buffer, header.length);
}
else
{
printf("find user failed!\n");
}
}
default:
break;
}
}
}
// Gateway receives requests from clients in a loop
static void LoraGateWayListen(void *parameter)
{
// adapter_t padapter = (adapter_t)malloc(sizeof(struct Adapter));
adapter_t padapter = parameter;
while (gateway_listening)
{
printf("444x(0x%x), %d, %d \n", ((AdapterLoraT)padapter)->spi_lora_fd, sizeof(rec_buffer), BUFFER_LEN_MAX);
int rec_len = LoraAdapterReceive(padapter, rec_buffer, BUFFER_LEN_MAX, 10000, true, NULL);
UserTaskDelay(50); //Afraid the other party hasn't entered reception mode yet
LoraGatewayProcess(padapter, rec_buffer, rec_len);
}
}
// All client packets received are processed here
int LoraClientProcess(adapter_t padapter, char *pkg, int pkg_len)
{
struct AdapterLora* lora_adapter = (struct AdapterLora*)padapter;
LoraHeader *pheader = (LoraHeader *)pkg;
LoraHeader header;
memset(&header, 0, sizeof(header));
char *data_start = pkg + sizeof(LoraHeader);
switch (pheader->op_code)
{
case LORA_JOIN_RSP:
if (g_client_status_info.status == LORA_CLIENT_LOOKING4GATEWAY)
{
LoraProtoJoinRsp *data = (LoraProtoJoinRsp *)data_start;
if (strcmp(data->net_id, client_net_id) != 0)
break;
strcpy(g_client_status_info.gateway_name, data->gateway_name);
strcpy(g_client_status_info.client_name, lora_adapter->name);
g_client_status_info.status = LORA_CLIENT_CONNECTING2GATEWAY;
break;
}
case LORA_HANDSHAKE_RSP:
if (strcmp(((LoraProtoHandshakeRsp *)data_start)->client_name, lora_adapter->name) == 0) // Confirm that it was sent to yourself
{
LoraProtoHandshakeRsp *data = (LoraProtoHandshakeRsp *)data_start;
printf("get LoraProtoHandshakeRsp data->client_name = %s, data->gateway_name = %s\n", data->client_name, data->gateway_name);
// Confirm the connection and record the status information
g_client_status_info.status = LORA_CLIENT_CONNECTED;
g_client_status_info.user_id = data->user_id;
strcpy(g_client_status_info.gateway_name, data->gateway_name);
printf("client is connected to gateway(%s)\n", g_client_status_info.gateway_name);
}
break;
case LORA_C2G_DATA_RSP:
if (((LoraProtoC2GDataRsp *)data_start)->user_id == g_client_status_info.user_id) // Confirm that it was sent to yourself
{
LoraProtoC2GDataRsp *data = (LoraProtoC2GDataRsp *)data_start;
UserMutexObtain(pclient_send_buffer_mutex, WAITING_FOREVER);
if (data->ack_id == client_send_buffer.pkg_id)
{
if (data->crc == client_send_buffer.crc)
{
// Send successfully, execute external callback
if (client_send_buffer.callback)
{
client_send_buffer.callback(client_send_buffer.param);
}
//Reset buffer
memset(&client_send_buffer, 0, sizeof(client_send_buffer));
client_send_buffer.has_data = false;
// printf("pkg_id(%d) get ack. send success. send buffer clear.\n", data->ack_id);
pkg_id_c2g++;
}
else
{
// Then do nothing and wait for the retransmission
printf("client send failed.crc check failed.\n");
}
}
UserMutexAbandon(pclient_send_buffer_mutex);
}
break;
case LORA_CLOSE_RSP:
{
LoraProtoCloseRsp *rsp = (LoraProtoCloseRsp *)data_start;
printf("case LORA_CLOSE_RSP rsp->user_id(%d)\n", rsp->user_id);
printf("case LORA_CLOSE_RSP g_client_status_info.user_id(%d)\n", g_client_status_info.user_id);
if (rsp->user_id == g_client_status_info.user_id)
{
g_client_status_info.status = LORA_CLIENT_DISCONNECTED;
printf("client close success.\n");
}
}
break;
default:
break;
}
}
// The client requests the gateway to disconnect
int SendCloseReq()
{
LoraHeader header;
memset(&header, 0, sizeof(header));
header.op_code = LORA_CLOSE_REQ;
header.length = sizeof(LoraHeader) + sizeof(LoraProtoCloseReq);
LoraProtoCloseReq req;
req.user_id = g_client_status_info.user_id;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), &req, sizeof(req));
printf("client send close req");
lora_send(send_buffer, header.length);
}
// The client broadcasts the name of the network segment that it wants to join
int SendJoinReq(char *net_id)
{
LoraHeader header;
memset(&header, 0, sizeof(header));
header.op_code = LORA_JOIN_REQ;
header.length = sizeof(LoraHeader) + sizeof(LoraProtoJoinReq);
LoraProtoJoinReq req;
memcpy(req.net_id, net_id, strlen(net_id) + 1);
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), &req, sizeof(req));
lora_send(send_buffer, header.length);
}
// Client requests connection from gateway
int SendHandShakeReq(char *client_name, char *gateway_name)
{
LoraHeader header;
header.op_code = LORA_HANDSHAKE_REQ;
header.length = sizeof(LoraHeader) + sizeof(LoraProtoHandshakeReq);
LoraProtoHandshakeReq req;
memset(&req, 0, sizeof(req));
strcpy(req.client_name, client_name);
strcpy(req.gateway_name, gateway_name);
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), &req, sizeof(req));
printf("LoraProtoHandshakeReq, req.client_name = %s req.gateway_name = %s\n", req.client_name, req.gateway_name);
lora_send(send_buffer, header.length);
}
void work_thread_process(adapter_t padapter)
{
if (g_work_thread_status == WORK_THREAD_RX)
{
// printf("client start receiving \n");
uint16 len;
int counter = 0;
Radio->StartRx();
while (Radio->Process() != RF_RX_DONE)
{
// Receive external signal, check buffer
if (need_send_data)
{
g_work_thread_status = WORK_THREAD_TX;
need_send_data = false;
return;
}
//Jump out of the monitoring cycle regularly to see if there is anything that needs to be retransmitted
if (counter > 100000)
{
if (g_client_status_info.status == LORA_CLIENT_CONNECTED)
{
//printf("check send buffer.\n");
}
if (g_client_status_info.status >= LORA_CLIENT_LOOKING4GATEWAY &&
g_client_status_info.status <= LORA_CLIENT_CONNECTING2GATEWAY)
{
printf("retry to handshake.\n");
}
g_work_thread_status = WORK_THREAD_TX;
// printf("client end receiving.\n");
return;
}
counter++;
}
enum LoraClientStatus old = g_client_status_info.status;
Radio->GetRxPacket(rec_buffer, (uint16 *)&len);
LoraClientProcess(padapter, rec_buffer, len);
//If the client state machine changes, there is something to send to the other party, and it will be switched to the sending mode immediately
if (old != g_client_status_info.status)
{
g_work_thread_status = WORK_THREAD_TX;
UserTaskDelay(50); //Afraid the other party hasn't entered reception mode yet
}
}
else if (g_work_thread_status == WORK_THREAD_TX)
{
// Temporarily designed not to be interrupted
switch (g_client_status_info.status)
{
case LORA_CLIENT_LOOKING4GATEWAY:
SendJoinReq(client_net_id);
break;
case LORA_CLIENT_CONNECTING2GATEWAY:
SendHandShakeReq(g_client_status_info.client_name, g_client_status_info.gateway_name);
break;
case LORA_CLIENT_CONNECTED:
CheckSendBuffer();
break;
case LORA_CLIENT_WAITTING_FOR_DISCONNECTED:
SendCloseReq(g_client_status_info.user_id);
break;
default:
break;
}
g_work_thread_status = WORK_THREAD_RX;
}
}
void static work_thread_func(void *parameter)
{
adapter_t padapter = (adapter_t)parameter;
while (client_work_thread_running)
{
work_thread_process(padapter);
}
}
int LoraAdapterJoin(adapter_t padapter, int net_role_type, char *net_id)
{
UtaskType lora_utask_master;
UtaskType lora_utask_slave;
do
{
_role_type = net_role_type;
x_err_t err;
if (_role_type == ROLE_TYPE_MASTER)
{
strcpy(gateway_net_id, net_id);
//Single child thread gateway loop monitoring req
gateway_listening = true;
printf("GateWayListen thread create...");
strncpy(lora_utask_master.name,"GateWayListen",strlen("GateWayListen"));
lora_utask_master.func_entry = LoraGateWayListen;
lora_utask_master.func_param = padapter;
lora_utask_master.prio = 10;
lora_utask_master.stack_size = 2048;
ServerTask = UserTaskCreate(lora_utask_master);
err = UserTaskStartup(ServerTask);
if (err != EOK)
{
break;
}
}
else if (_role_type == ROLE_TYPE_SLAVE)
{
strcpy(client_net_id, net_id);
// Create lock
if (pclient_send_buffer_mutex < 0)
{
pclient_send_buffer_mutex = UserMutexCreate();
}
// Update state machine
g_client_status_info.status = LORA_CLIENT_LOOKING4GATEWAY;
// Start single child thread client loop to listen for RSP
client_send_buffer.has_data = false;
memset(&client_send_buffer, 0, sizeof(client_send_buffer));
client_work_thread_running = true;
g_work_thread_status = WORK_THREAD_TX;
strncpy(lora_utask_slave.name,"ClientWorkThread",strlen("ClientWorkThread"));
lora_utask_slave.func_entry = work_thread_func;
lora_utask_slave.func_param = padapter;
lora_utask_slave.prio = 10;
lora_utask_slave.stack_size = 2048;
ClientTask = UserTaskCreate(lora_utask_slave);
err = UserTaskStartup(ClientTask);
if (err != EOK)
{
break;
}
// Block detection for a period of time
int counter = 100;
while (counter > 0)
{
if (g_client_status_info.status == LORA_CLIENT_CONNECTED)
{
break; // Successful connection
}
else
{
UserTaskDelay(300);
}
counter--;
}
return (counter > 0) ? 0 : ERROR;
}
return EOK;
} while (false);
// Exception handling, releasing resources
LoraAdapterCose(padapter);
return ERROR;
}

View File

@@ -26,6 +26,9 @@
#ifdef CONNECTION_COMMUNICATION_ZIGBEE
#include <xs_adapter_zigbee.h>
#endif
#ifdef CONNECTION_COMMUNICATION_LORA
#include <xs_adapter_lora.h>
#endif
// Zigbee Adapter List
@@ -48,8 +51,7 @@ void* ZigbeeAdapterFind(char* name)
DoubleLinklistType* phead = &zigbee_adapter_list;
struct AdapterZigbee* padapter = NONE;
for(pnode = phead->node_next; pnode != phead; pnode = pnode->node_next)
{
for(pnode = phead->node_next; pnode != phead; pnode = pnode->node_next) {
padapter = (struct AdapterZigbee*)SYS_DOUBLE_LINKLIST_ENTRY(pnode, struct Adapter, link);
// KPrintf("ZigbeeReceiveDemo bbb\n");
if (0 == strcmp(padapter->name, name)){
@@ -61,7 +63,37 @@ void* ZigbeeAdapterFind(char* name)
}
#endif
// Lora Adapter List
#ifdef CONNECTION_COMMUNICATION_LORA
static DoubleLinklistType lora_adapter_list;
void LoraAdapterInit()
{
InitDoubleLinkList(&lora_adapter_list);
}
void LoraAdapterRegister(adapter_t padapter)
{
DoubleLinkListInsertNodeAfter(&lora_adapter_list, &(padapter->link));
}
void* LoraAdapterFind(char* name)
{
DoubleLinklistType* pnode = NONE;
DoubleLinklistType* phead = &lora_adapter_list;
struct AdapterLora* padapter = NONE;
for(pnode = phead->node_next; pnode != phead; pnode = pnode->node_next) {
padapter = (struct AdapterLora*)SYS_DOUBLE_LINKLIST_ENTRY(pnode, struct Adapter, link);
if (0 == strcmp(padapter->name, name)) {
return padapter;
}
}
return padapter;
}
#endif
// AT Adapter List
static DoubleLinklistType at_adapter_list;
@@ -86,8 +118,7 @@ void* ATAdapterFind(uint32 adapter_id)
struct AdapterAT* padapter = NONE;
for(pnode = phead->node_next; pnode != phead; pnode = pnode->node_next)
{
for(pnode = phead->node_next; pnode != phead; pnode = pnode->node_next) {
padapter = (struct AdapterAT*)SYS_DOUBLE_LINKLIST_ENTRY(pnode, struct AdapterAT, link);
if (padapter->at_adapter_id == adapter_id){