#include "../../../User/includes.h" #include "device.h" #include "net_proc.h" #include "radio.h" #include "project_config.h" #include "stdio.h" #include "stm32f10x_it.h" #include "delay.h" #include "string.h" #include "../../gateway_collect/gateway_collect.h" #include "../../globalDef.h" #include "lora.h" #include "../../toolkit/CH455G.h" #include "../../ota/ota.h" #include "../net_ctrl.h" uint8_t AIR_MQTT_PUB(char * topic, char *data, uint32_t len); extern volatile uint32_t TickCounter; loraParam g_loraPa[4]; #define RADIO_RX_TIMEOUT_VALUE 0 //uint8_t cmpBuf[256] ; uint8_t lora_state = 0; OS_Q lora_q; system_lora_t sys_loraTX; system_lora_t sys_loraRx; uint8_t g_loraCadStatus = 0; uint8_t g_loraCadCount = 0; uint32_t g_cadTick = 0; uint32_t g_cadTickTime = 0; timeout_t g_loraRcvTime; // lora接收超时时间 默认为60分钟 /*! * Radio events function pointer * 这个是传参进入其他函数中了,所以用全局变量(局部变量使用完了内存释放可能导致异常) */ static RadioEvents_t RadioEventsObj; static void SX126xOnCadDone( bool channelActivityDetected ); static void SX126xConfigureCad( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin , uint32_t cadTimeout); void init_lora_param(void) { volatile uint8_t i=0; g_loraPa[0].freq = 486300000; g_loraPa[0].power = 20; g_loraPa[0].bandwidth = 1; g_loraPa[0].spreadingFactor = 7; g_loraPa[0].codingrate = 2; g_loraPa[0].preambleLen = 8; g_loraPa[1].freq = 489300000; g_loraPa[1].power = 20; g_loraPa[1].bandwidth = 1; g_loraPa[1].spreadingFactor = 7; g_loraPa[1].codingrate = 2; g_loraPa[1].preambleLen = 8; g_loraPa[2].freq = 509700000; g_loraPa[2].power = 20; g_loraPa[2].bandwidth = 2; g_loraPa[2].spreadingFactor = 8; g_loraPa[2].codingrate = 3; g_loraPa[2].preambleLen = 8; g_loraPa[3].freq = 470300000; g_loraPa[3].power = 20; g_loraPa[3].bandwidth = 2; g_loraPa[3].spreadingFactor = 8; g_loraPa[3].codingrate = 3; g_loraPa[3].preambleLen = 8; } void * lora_queue_mem_calloc_must(void) { OS_ERR err; void * p_msg = NULL; OSSemPend(&sys_loraTX.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); p_msg = OSMemGet(&sys_loraTX.lora_m, &err); // printf("\r\n~~~~~~~~~~~~~~~err = %d\r\n",err); OSSemPost(&sys_loraTX.sem, OS_OPT_POST_ALL, &err); // printf("\r\n~~~~~~~~~~~~~~~err = %d end \r\n",err); return p_msg; } int lora_queue_mem_free(void * p_msg) { OS_ERR err; OSSemPend(&sys_loraTX.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); OSMemPut(&sys_loraTX.lora_m, p_msg, &err); OSSemPost(&sys_loraTX.sem, OS_OPT_POST_ALL, &err); return err; } void lora_queue_insert(char *p_msg, uint32_t msg_len) { OS_ERR err; OSSemPend(&sys_loraTX.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); OS_QPost(&sys_loraTX.lora_q, p_msg, msg_len, OS_OPT_POST_FIFO, 0, &err); OSSemPost(&sys_loraTX.sem, OS_OPT_POST_ALL, &err); //printf("net_queue_insert %p %d\r\n", p_msg, msg_len); } void * lora_queue_mem_calloc_mustRx(void) { OS_ERR err; void * p_msg = NULL; OSSemPend(&sys_loraRx.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); p_msg = OSMemGet(&sys_loraRx.lora_m, &err); OSSemPost(&sys_loraRx.sem, OS_OPT_POST_ALL, &err); return p_msg; } int lora_queue_mem_freeRx(void * p_msg) { OS_ERR err; OSSemPend(&sys_loraRx.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); OSMemPut(&sys_loraRx.lora_m, p_msg, &err); OSSemPost(&sys_loraRx.sem, OS_OPT_POST_ALL, &err); return err; } void lora_queue_insertRx(char *p_msg, uint32_t msg_len) { OS_ERR err; OSSemPend(&sys_loraRx.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); OS_QPost(&sys_loraRx.lora_q, p_msg, msg_len, OS_OPT_POST_FIFO, 0, &err); OSSemPost(&sys_loraRx.sem, OS_OPT_POST_ALL, &err); //printf("net_queue_insert %p %d\r\n", p_msg, msg_len); } static void SX126xOnTxDone( void ) { //printf("TxDone\r\n"); Radio.Standby(); lora_state = lora_state_idle; g_loraCadStatus = 0; //Radio.Rx( RADIO_RX_TIMEOUT_VALUE ); } /*lora数据接收 2021.11.08*/ static void SX126xOnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { // OS_ERR err; // inner_msg_format_t *p_msg = NULL; char *p_msg = NULL; // rssi:信号强度 // printf("RxDone size:%d \r\n",size, rssi, snr); Radio.Standby(); // p_msg = (gateway_collect_com_t *)payload; g_runData.rssi_lora = rssi+1000; memcpy(payload+size,(uint8_t*)&g_runData.rssi_lora,2); p_msg = lora_queue_mem_calloc_mustRx(); if(p_msg) { timeout_start(&g_loraRcvTime); if(size) //和上次数据不同,数据有效 { //data_dump("LORA Rx", (uint8_t *)payload, size); memcpy(p_msg, payload, size+2);//&&memcmp(cmpBuf, payload, size) lora_queue_insertRx((char *)p_msg, size+2); } else { lora_queue_mem_freeRx(p_msg); } // printf("lora rcv\r\n"); } g_loraCadStatus = 0; // OS_QPost(&lora_q, payload, size, OS_OPT_POST_FIFO, 0, &err); // data_dump("LORA Rx", payload, size); #if 0 if(((p_msg->type <= net_msg_type_debug)|| (p_msg->type == net_msg_type_bind_req)|| (p_msg->type == net_msg_type_node_echo))&& (device_type_get() != DEV_TYPE_GATEWAY)) {/* 节点丢弃 */ //drop packets; } else if(((p_msg->type == net_msg_type_bind_rsp)|| (p_msg->type == net_msg_type_gw_echo))&& (device_type_get() == DEV_TYPE_GATEWAY)) { //drop packets; } else { data_dump("LORA Rx", payload, size); //Radio.Rx( RADIO_RX_TIMEOUT_VALUE ); if(((p_msg->type&0x10) == 0x10)|| ((p_msg->type&0x20) == 0x20)) { p_msg = (inner_msg_format_t *)net_queue_mem_calloc_must(); } else { p_msg = (inner_msg_format_t *)net_queue_mem_calloc(); } if(p_msg) { if(size) {//和上次数据不同,数据有效 // data_dump("LORA Rxtx", (uint8_t *)p_msg, size); memcpy(p_msg, payload, size);//&&memcmp(cmpBuf, payload, size) net_queue_insert((char *)p_msg, size); } else { net_queue_mem_free(p_msg); } } } #endif lora_state = lora_state_idle; } static void SX126xOnCadDone( bool channelActivityDetected ) { // inner_msg_format_t *p_msg = NULL; // OS_MSG_SIZE msg_len = 0; // OS_ERR err; int a = 0; // __disable_irq(); Radio.Standby(); // printf("cadDone %d\r\n", channelActivityDetected); if(channelActivityDetected==true){ // lora_state = lora_state_idle; g_loraCadStatus = 0; g_loraCadCount++; srand(TickCounter); a = rand() % 50; if((g_runData.bUpdateHost == 0) )g_cadTickTime = 300+a; else if(g_runData.bUpdateHost == 2) g_cadTickTime = 120 +a; else { if(g_runData.bUpdate != 0) { g_cadTickTime = 700; } else g_cadTickTime = 300+a; } g_cadTick = TickCounter; lora_state = lora_state_sendRept; } else { lora_queue_proc_testTx(); g_loraCadCount = 0; g_cadTick = TickCounter; } // __enable_irq(); return ; } static void SX126xOnTxTimeout( void ) { printf("TxTimeout\r\n"); Radio.Standby(); lora_state = lora_state_idle; } static void SX126xOnRxTimeout( void ) { printf("RxTimeout retry recive\r\n"); Radio.Standby(); //Radio.Rx( LORA_RX_TIMEOUT_VALUE ); lora_state = lora_state_idle; } static void SX126xOnRxError( void ) { printf("RxError retry recive\r\n"); Radio.Standby(); //Radio.Rx(LORA_RX_TIMEOUT_VALUE); lora_state = lora_state_idle; } static void SX126xConfigureCad( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin , uint32_t cadTimeout) { SX126xSetDioIrqParams( IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); SX126xSetCadParams( cadSymbolNum, cadDetPeak, cadDetMin, LORA_CAD_ONLY, ((cadTimeout * 1000) / 15.625 )); } void lora_send(char *tx_data, uint32_t tx_len) { char *p_msg = NULL; // OS_ERR err; p_msg = (char *)lora_queue_mem_calloc_must(); if(p_msg) { memcpy(p_msg, tx_data, tx_len); lora_queue_insert((char *)p_msg, tx_len); } else { lora_queue_mem_free(p_msg); } // char *p_msg = NULL; // OS_ERR err; // /* 接受消息, 发往net_proc模块统一处理 */ // p_msg = (char *)net_queue_mem_calloc_must(); // if(p_msg) { // memcpy(p_msg, tx_data, tx_len); // OS_QPost(&lora_q, p_msg, tx_len, OS_OPT_POST_FIFO, 0, &err); // } } void lora_net_send_test(uint8_t *tx_data, uint8_t tx_len) { if(tx_data[tx_len-2]==0x0d && tx_data[tx_len-1]==0x0a) { tx_data[tx_len-2]='\0'; tx_data[tx_len-1]='\0'; tx_len-=2; data_dump("lora tx:", tx_data, tx_len); } AIR_MQTT_PUB((char*)g_upLinkTopic,(char*)tx_data,0); } /*lora 发送消息 */ void lora_send_test(uint8_t *buf, uint8_t size) { gateway_collect_com_t *msg = (gateway_collect_com_t*)msg; if(msg->type==0x56){ downlink_config.collect_conf[msg->taxinfo.comdata.coll_no].coll_send_num++; } if(g_runData.bUpdate==0){ set_led_status(msg->taxinfo.info[4],0); } Radio.Send(buf, size); } void lora_queue_proc_test(void) { OS_ERR err; gateway_collect_com_t *p_msg; OS_MSG_SIZE msg_len; uint32_t a = 0,*sn = NULL; uint16_t crc = 0, fcrc = 0; uint8_t i = 0,flag = 0; OSSemPend(&sys_loraRx.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); p_msg = (gateway_collect_com_t *)OSQPend(&sys_loraRx.lora_q, 0, OS_OPT_PEND_NON_BLOCKING, &msg_len, NULL, &err); /* blocking. */ OSSemPost(&sys_loraRx.sem, OS_OPT_POST_ALL, &err); if(p_msg&&msg_len) { if(p_msg->frame_header != 0xfefe){ lora_queue_mem_freeRx(p_msg); up_send_log_err(GATEWAY_UP_LOG_CMD2001,LOG_LORA_ERROR,0,0,0,0,0,LOG_LORA_HEADERROR); return; } if((p_msg->type & 0x60) == 0x60) { sn = (uint32_t*)((p_msg->taxinfo.info)); for (i=0;i=0xFFFF) g_runData.collerr = 0; up_send_log_err(GATEWAY_UP_LOG_CMD2001,LOG_TAX_COLLSN,0,0,0,*sn,0,0); lora_queue_mem_freeRx(p_msg); return; } } crc = _crc16_get((uint8_t*)p_msg,p_msg->len+GATE_COLL_HEAD_LEN-2);// len-2); fcrc = p_msg->taxinfo.info[p_msg->len-1];// data[p_tax_tx->len+GATE_COLL_HEAD_LEN-1]; fcrc = (fcrc<<8)| p_msg->taxinfo.info[p_msg->len-2];//data[p_tax_tx->len+GATE_COLL_HEAD_LEN-2]; if(fcrc != crc ){//校验位不对则返回 /* printf("lora_queue_proc: crc error\r\n"); lora_queue_mem_freeRx(p_msg); return;*/ up_send_log_err(GATEWAY_UP_LOG_CMD2001,LOG_LORA_ERROR,0,0,0,0,0,LOG_CRC1); } switch(p_msg->type){ case COLL_GATE_TAX_QUERY: //0x67业务数据接收接收消息 set_led_status(p_msg->taxinfo.data.coll_no,1); collect_rcv_analyze0x67((uint8_t *)p_msg,msg_len); // printf("mqtt send tax end\n"); break; case COLL_GATE_HEART_QUERY: //0x66网关与采集器的上行心跳包 set_led_status(p_msg->taxinfo.comdata.coll_no,1); collect_rcv_analyze0x66((uint8_t *)p_msg,msg_len); break; case COLL_GATE_FIRMMSG_QUERY://0x68采集器上发固件信息 printf("recevie cm 0x68\r\n"); set_led_status(p_msg->taxinfo.firmMsg.coll_no,1); collect_rcv_analyze0x68((uint8_t *)p_msg,msg_len); break; case COLL_GATE_ENCODER_QUERY: // 0x6C 编码器数据 set_led_status(p_msg->taxinfo.firmMsg.coll_no,1); collect_rcv_analyze0x6C((uint8_t *)p_msg,msg_len); break; case 0x22: // 升级重新传指令, 采集器上发的指令 printf("\r\n 收到0x22指令\r\n"); g_runData.repeatUpdateTime = TickCounter; g_runData.readUpdateStatusTime = 0; if(g_runData.bUpdateHost == 0) break; lora_gw_ota_proc(&sys_net, p_msg); break; case 0x23: // 升级成功,主设备接收从设备的上报指令 printf("rcv 0x23 cmd ,delay = %d\r\n",a); if(g_runData.bResetUpdate == 2) { // 从设备时, srand(TickCounter); a = rand() % 233+200; timeout_setValue(&g_updateProg.upStatusOut,a); timeout_start(&g_updateProg.upStatusOut); } else if(g_runData.bResetUpdate == 0) // 主设备 gateway_update_status_rcv(p_msg,msg_len); break; case 0x16: // 通知采集器升级 break; case net_msg_type_update_start: // 网关升级网关指令开始0x13 printf("\r\n 收到0x13指令\r\n"); gateway_lora_ota_proc(p_msg); break; case net_msg_type_update_continues: // 0x14指令 printf("\r\n 收到0x14指令\r\n"); gateway_lora_ota_proc(p_msg); break; case net_msg_type_update_retransmit_rsp: // 0x15指令 printf("\r\n 收到0x15指令\r\n"); gateway_lora_ota_proc(p_msg); break; case COLL_GATE_TRANSMIT: // 0x01 透传指令 collect_rcv_analyze0x01_0x2052((uint8_t*)p_msg,msg_len); break; default: break; } lora_queue_mem_freeRx(p_msg); } } void lora_queue_proc_testTx(void) { OS_ERR err; gateway_collect_com_t *p_msg; OS_MSG_SIZE msg_len; // uint8_t coll = 0; // printf("net_queue_proc 1111\r\n"); OSSemPend(&sys_loraTX.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err); p_msg = (gateway_collect_com_t *)OSQPend(&sys_loraTX.lora_q, 0, OS_OPT_PEND_NON_BLOCKING, &msg_len, NULL, &err); /* blocking. */ OSSemPost(&sys_loraTX.sem, OS_OPT_POST_ALL, &err); if(p_msg&&msg_len) { if(p_msg->type == 0x57) { /* printf("++++++++++ msg type = 0x%x collSN = %d,port=%d, gun=%d +++++\r\n",\ p_msg->type,\ p_msg->taxinfo.data.device_sn,\ p_msg->taxinfo.data.tax_no,p_msg->taxinfo.data.gun_msgid);*/ } g_loraCollMsg.info[p_msg->taxinfo.info[4]].sendNum++; lora_send_test((uint8_t *)p_msg, msg_len); lora_queue_mem_free(p_msg); g_loraCollMsg.lora_sendCount++; if(device_fixed_info.Work_State == DEV_WORK_STATE_OTA_RETRANSMIT) { ota_retransmit_delay.timeout = OTA_CAD_FREE_DELAYTIME; ota_retransmit_delay.counter = TickCounter; ota_continuous_end_flag = OTA_CONTINUOUS_DELAY; } // printf("发送loraSend = %d,采集器(%d):发送:%d\r\n",g_loraCollMsg.lora_sendCount,p_msg->taxinfo.info[4],g_loraCollMsg.info[p_msg->taxinfo.info[4]].sendNum); } else { lora_state = lora_state_idle; // printf("\r\n lora state idel 11111111 \r\n"); } } void lora_task(void) { //inner_msg_format_t *p_msg = NULL; // OS_MSG_SIZE msg_len = 0; // OS_ERR err; // uint32_t i = 0; /* 发送消息 */ // if(downlink_config.collect_num == 0) return; lora_queue_proc_test(); switch(lora_state) { case lora_state_idle: //idle Radio.Standby(); Radio.Rx( LORA_RX_TIMEOUT_VALUE ); lora_state = lora_state_send;// lora_state_rcv; // printf("lora rx state\n"); case lora_state_rcv: // lora_queue_proc_test(); // lora_state = lora_state_send; break; case lora_state_send: if(sys_loraTX.lora_q.MsgQ.NbrEntries >0){ //除列不为空 Radio.Standby(); Radio.StartCad(); lora_state = lora_state_max; break; } // lora_state = lora_state_rcv; break; case lora_state_sendRept: if(g_loraCadCount>0) { if(TickCounter- g_cadTick>=g_cadTickTime){ Radio.Standby(); Radio.StartCad(); g_cadTick = TickCounter; printf("\r\n&&&&&&& timer out \r\n"); } if(g_loraCadCount>1){ lora_queue_proc_testTx(); g_loraCadCount = 0; printf("\r\n ^^^^^^2 count \r\n"); } } break; case lora_state_max: break; default: break; } Radio.IrqProcess( ); if(timeout_isOut(&g_loraRcvTime)) { // 一个小时没有收到数据,则重新启lora模块 //SX126xReset( ); printf("lora one hour no recv,reset loar\r\n"); lora_init("golden_beans"); } } void lora_init(char *device_id) { OS_ERR err; uint8_t loraindex = 0;//g_runData.curloraIndex; OSSemCreate(&sys_loraTX.sem, "lora_sem", 1, &err);//创建信号量 OSQCreate(&sys_loraTX.lora_q, "lora_queue", 8, &err);//创建网络消息处理队列 OSMemCreate(&sys_loraTX.lora_m, "lora_memory", sys_loraTX.memory, 8, 256, &err);//创建内存管理池 OSSemCreate(&sys_loraRx.sem, "lora_semRx", 1, &err);//创建信号量 OSQCreate(&sys_loraRx.lora_q, "lora_queueRx", 8, &err);//创建网络消息处理队列 OSMemCreate(&sys_loraRx.lora_m, "lora_memoryRx", sys_loraRx.memory, 8, 256, &err);//创建内存管理池 loraindex = g_runData.curloraIndex; init_lora_param(); RadioEventsObj.TxDone = SX126xOnTxDone; RadioEventsObj.RxDone = SX126xOnRxDone; RadioEventsObj.TxTimeout = SX126xOnTxTimeout; RadioEventsObj.RxTimeout = SX126xOnRxTimeout; RadioEventsObj.RxError = SX126xOnRxError; RadioEventsObj.CadDone = SX126xOnCadDone; Radio.Init( &RadioEventsObj ); Radio.SetChannel(g_loraPa[loraindex].freq); Radio.SetTxConfig( MODEM_LORA, g_loraPa[loraindex].power, 0, g_loraPa[loraindex].bandwidth, g_loraPa[loraindex].spreadingFactor, g_loraPa[loraindex].codingrate, g_loraPa[loraindex].preambleLen, LORA_FIX_LENGTH_PAYLOAD_ON, true, 0, 0, LORA_IQ_INVERSION_ON, 5000 );//参数:lora模式,发射功率,fsk用的lora设置为0就可以,带宽,纠错编码率,前导码长度,固定长度数据包(一般是不固定的所以选false),crc校验,0表示关闭跳频,跳频之间的符号数(关闭跳频这个参数没有意义),这个应该是表示是否要翻转中断电平的,超时时间 Radio.SetRxConfig( MODEM_LORA, g_loraPa[loraindex].bandwidth, g_loraPa[loraindex].spreadingFactor, g_loraPa[loraindex].codingrate, 0, g_loraPa[loraindex].preambleLen, LORA_SX126X_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0, true, 0, 0, LORA_IQ_INVERSION_ON, false ); SX126xConfigureCad( CAD_SYMBOL_NUM, CAD_DET_PEAK,CAD_DET_MIN, CAD_TIMEOUT_MS); Radio.StartCad(); lora_state = lora_state_rcv; timeout_setValue(&g_loraRcvTime,60*60*1000); timeout_start(&g_loraRcvTime); return; }