1011 lines
38 KiB
C
1011 lines
38 KiB
C
|
|
#include "air780e.h"
|
|||
|
|
#include "ota_app.h"
|
|||
|
|
#include "relay.h"
|
|||
|
|
#include "led.h"
|
|||
|
|
#include "network.h"
|
|||
|
|
#include "uart.h"
|
|||
|
|
#include "main.h"
|
|||
|
|
#include "system.h"
|
|||
|
|
#include "24c02.h"
|
|||
|
|
#include "proto.h"
|
|||
|
|
#include "feed_scale.h"
|
|||
|
|
#include "app_loop.h"
|
|||
|
|
#include "reset_log.h"
|
|||
|
|
#include "../W25Q64/w25q64.h"
|
|||
|
|
#include "FreeRTOS.h"
|
|||
|
|
#include "task.h"
|
|||
|
|
#include "stdio.h"
|
|||
|
|
#include "string.h"
|
|||
|
|
#include <stdarg.h>
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <math.h>
|
|||
|
|
|
|||
|
|
/* ATָ<54><EFBFBD><EEB7A2>: <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>USART3<54><33><EFBFBD><EFBFBD>, ĩβ<C4A9>Զ<EFBFBD><D4B6><EFBFBD>\r\n */
|
|||
|
|
void CAT1_printf(const char *fmt, ...)
|
|||
|
|
{
|
|||
|
|
static uint32_t last_tx_tick = 0;
|
|||
|
|
char buf[384];
|
|||
|
|
int n;
|
|||
|
|
va_list ap;
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> AT ָ<><D6B8>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD>ټ<EFBFBD><D9BC><EFBFBD> 30ms<6D><73><EFBFBD><EFBFBD>֤ 4G ģ<>鲻<EFBFBD><E9B2BB><EFBFBD><EFBFBD> */
|
|||
|
|
while (HAL_GetTick() - last_tx_tick < 30) {
|
|||
|
|
HAL_Delay(1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
va_start(ap, fmt);
|
|||
|
|
n = vsnprintf(buf, sizeof(buf), fmt, ap);
|
|||
|
|
va_end(ap);
|
|||
|
|
|
|||
|
|
HAL_UART_Transmit(&huart3, (uint8_t *)buf, strlen(buf), 500);
|
|||
|
|
HAL_UART_Transmit(&huart3, (uint8_t *)"\r\n", 2, 500);
|
|||
|
|
last_tx_tick = HAL_GetTick();
|
|||
|
|
|
|||
|
|
if (n >= (int)sizeof(buf)) {
|
|||
|
|
log_warn("> CAT1: <20><><EFBFBD>ͽض<CDBD>!<21><> %d <20>ֽ<EFBFBD>", n);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD> MPUB <20><><EFBFBD>ͳɹ<CDB3><C9B9><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>״η<D7B4><CEB7><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD>Ϊ OTA ҵ<><EFBFBD><F1BDA1BF><EFBFBD>־֮һ */
|
|||
|
|
if (g_air780e_mqtt_ready && !g_air780e_first_publish_ok && strstr(buf, "AT+MPUB")) {
|
|||
|
|
g_air780e_first_publish_ok = 1;
|
|||
|
|
log_info("> 4G: <20>״η<D7B4><CEB7><EFBFBD><EFBFBD>ɹ<EFBFBD>");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uint8_t U2_CopyBuff[U2_COPY_SIZE];
|
|||
|
|
volatile uint16_t U2_CopyIndex = 0;
|
|||
|
|
volatile uint8_t U2_CopyFlag = 0;
|
|||
|
|
volatile uint8_t g_air780e_mqtt_ready = 0;
|
|||
|
|
volatile uint8_t g_air780e_first_publish_ok = 0;
|
|||
|
|
|
|||
|
|
static MqttConfig mqtt_cfg;
|
|||
|
|
|
|||
|
|
/* GNSS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><D6BE>cat_connect_network <20><> AT+CGNSPWR <20>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD> 1<><31>Air780EG <20><><EFBFBD>У<EFBFBD> */
|
|||
|
|
static uint8_t s_gnss_present = 0;
|
|||
|
|
|
|||
|
|
/*==== GPS <20><>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>أ<EFBFBD>EEPROM 173<37><33><EFBFBD>հ<EFBFBD><D5B0>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϣ<EFBFBD>====*/
|
|||
|
|
uint8_t g_gps_on = 0;
|
|||
|
|
|
|||
|
|
void gps_load_mode(void)
|
|||
|
|
{
|
|||
|
|
uint8_t v = 0xFF;
|
|||
|
|
eepromReadData(GPS_MODE_ADDR, &v, 1);
|
|||
|
|
if (v > 1) v = PRODUCT_WITH_GPS;
|
|||
|
|
g_gps_on = v;
|
|||
|
|
log_info("> GPS <20><>λ: %s", v ? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : "<EFBFBD>ر<EFBFBD>(GPS0)");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void gps_set_mode(uint8_t on)
|
|||
|
|
{
|
|||
|
|
on = on ? 1 : 0;
|
|||
|
|
g_gps_on = on;
|
|||
|
|
eepromWriteData(GPS_MODE_ADDR, &on, 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== <20>ⲿ Flash У<>飺<EFBFBD><E9A3BA>ȡ<EFBFBD>̼<EFBFBD>ͷ 8 <20>ֽ<EFBFBD><D6BD>жϺϷ<CFBA><CFB7><EFBFBD> ====
|
|||
|
|
* <EFBFBD><EFBFBD> static<EFBFBD><EFBFBD>WiFi OTA(net_wifi_ota.c) <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
int Verify_Firmware_External(uint32_t ext_addr, uint32_t size)
|
|||
|
|
{
|
|||
|
|
uint8_t hdr[8];
|
|||
|
|
W25Q64_Read(ext_addr, hdr, 8);
|
|||
|
|
uint32_t sp = (uint32_t)hdr[0] | ((uint32_t)hdr[1] << 8) | ((uint32_t)hdr[2] << 16) | ((uint32_t)hdr[3] << 24);
|
|||
|
|
uint32_t rv = (uint32_t)hdr[4] | ((uint32_t)hdr[5] << 8) | ((uint32_t)hdr[6] << 16) | ((uint32_t)hdr[7] << 24);
|
|||
|
|
if ((sp & 0x2FFE0000ul) != 0x20000000ul) { log_info("> VF ext: SP=0x%X", (unsigned)sp); return 0; }
|
|||
|
|
if (rv < Application_1_Addr || rv > (Application_1_Addr + size)) { log_info("> VF ext: RV=0x%X", (unsigned)rv); return 0; }
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== 4G Reset Control ====*/
|
|||
|
|
/*==== 4G Reset Control ====*/
|
|||
|
|
static void cat_reset(void) {
|
|||
|
|
g_net_ui_phase = NET_UI_4G_RESET;
|
|||
|
|
log_info("> 4G: <20><>λ...");
|
|||
|
|
|
|||
|
|
/* <20>ر<EFBFBD> NVIC <20>ж<EFBFBD>, <20><>ֹģ<D6B9>鸴λ<E9B8B4>ڼ<EFBFBD><DABC><EFBFBD><EFBFBD>봥<EFBFBD><EBB4A5><EFBFBD>жϷ籩 */
|
|||
|
|
HAL_NVIC_DisableIRQ(USART3_IRQn);
|
|||
|
|
HAL_NVIC_DisableIRQ(DMA1_Channel3_IRQn);
|
|||
|
|
HAL_UART_DMAStop(&huart3);
|
|||
|
|
/* ȷ<><C8B7> DMA ͨ<><CDA8><EFBFBD>ر<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־ */
|
|||
|
|
DMA1_Channel3->CCR &= ~DMA_CCR_EN;
|
|||
|
|
while (DMA1_Channel3->CCR & DMA_CCR_EN);
|
|||
|
|
DMA1->IFCR = DMA_IFCR_CGIF3;
|
|||
|
|
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
|
|||
|
|
__HAL_UART_CLEAR_OREFLAG(&huart3);
|
|||
|
|
__HAL_UART_CLEAR_PEFLAG(&huart3);
|
|||
|
|
__HAL_UART_CLEAR_FEFLAG(&huart3);
|
|||
|
|
__HAL_UART_CLEAR_NEFLAG(&huart3);
|
|||
|
|
U2_CopyIndex = 0;
|
|||
|
|
U2_CopyBuff[0] = 0;
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
|
|||
|
|
GPIO_InitTypeDef g = {0};
|
|||
|
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
|||
|
|
g.Pin = CAT_RST_PIN; g.Mode = GPIO_MODE_OUTPUT_OD; g.Pull = GPIO_NOPULL; g.Speed = GPIO_SPEED_FREQ_LOW;
|
|||
|
|
HAL_GPIO_Init(CAT_RST_PORT, &g);
|
|||
|
|
CAT_RST_HIGH(); HAL_Delay(1000); /* <20><>©<EFBFBD>ͷ<EFBFBD>=<3D><><EFBFBD><EFBFBD> */
|
|||
|
|
CAT_RST_LOW(); /* <20><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>λ */
|
|||
|
|
for (int i = 0; i < 40; i++) { IWDG_Feed(); HAL_Delay(100); } /* 4s */
|
|||
|
|
CAT_RST_HIGH(); /* V1.7.0: <20><>λ<EFBFBD><CEBB>ֱ<EFBFBD><D6B1>ģ<EFBFBD><C4A3>, <20><>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD>, <20><><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>һֱ<D2BB><D6B1><EFBFBD><EFBFBD>ס */ /* <20><>4s<34><73><EFBFBD>ڼ<EFBFBD>ι<EFBFBD><CEB9> */
|
|||
|
|
|
|||
|
|
/* ģ<>鸴λ<E9B8B4><CEBB><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DMA+IDLE <20><><EFBFBD><EFBFBD> */
|
|||
|
|
U2_CopyIndex = 0;
|
|||
|
|
U2_CopyBuff[0] = 0;
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD><DCB4>ڵ<EFBFBD> UART <20><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־ */
|
|||
|
|
__HAL_UART_CLEAR_PEFLAG(&huart3);
|
|||
|
|
__HAL_UART_CLEAR_FEFLAG(&huart3);
|
|||
|
|
__HAL_UART_CLEAR_NEFLAG(&huart3);
|
|||
|
|
__HAL_UART_CLEAR_OREFLAG(&huart3);
|
|||
|
|
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
|
|||
|
|
HAL_UART_Receive_DMA(&huart3, Rx_Buf, Rx_Max);
|
|||
|
|
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
|
|||
|
|
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
|
|||
|
|
HAL_NVIC_EnableIRQ(USART3_IRQn);
|
|||
|
|
|
|||
|
|
log_info("> 4G: <20><>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* OTA ǰֱ<C7B0><D6B1>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD>λ 4G ģ<><C4A3>, <20><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ʱһ<CAB1><D2BB> */
|
|||
|
|
static void ota_module_reset(void) {
|
|||
|
|
cat_reset();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== AT Command: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ====*/
|
|||
|
|
/* <20><>Ƭ<EFBFBD><C6AC>ʱ<EFBFBD><CAB1>RTOS <20>棩<EFBFBD><E6A3A9>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> vTaskDelay <EFBFBD>ó<EFBFBD> CPU<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/LED/ι<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD> <EFBFBD>˻<EFBFBD>Ϊ HAL_Delay + ι<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD> static<EFBFBD><EFBFBD>WiFi <EFBFBD><EFBFBD><EFBFBD><EFBFBD>(esp8266.c)<EFBFBD><EFBFBD> AT <EFBFBD>ȴ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>øû<EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
void bg_delay(uint32_t ms)
|
|||
|
|
{
|
|||
|
|
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
|
|||
|
|
while (ms >= 20) {
|
|||
|
|
vTaskDelay(20);
|
|||
|
|
ms -= 20;
|
|||
|
|
}
|
|||
|
|
if (ms) vTaskDelay(ms);
|
|||
|
|
} else {
|
|||
|
|
while (ms >= 20) {
|
|||
|
|
HAL_Delay(20);
|
|||
|
|
IWDG_Feed();
|
|||
|
|
app_oled_presched_tick(); /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD>ˢ<EFBFBD><CBA2><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
ms -= 20;
|
|||
|
|
}
|
|||
|
|
if (ms) HAL_Delay(ms);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* cmd: ATָ<54><D6B8>, expect: <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD>, retry: <20><><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>, timeout: <20><>ʱ(<28><>100ms) */
|
|||
|
|
/* <20><><EFBFBD><EFBFBD> 0=<3D>ɹ<EFBFBD>, <20><>0=ʧ<><CAA7> */
|
|||
|
|
uint8_t catSendCmd(const char *cmd, const char *expect, uint8_t retry, uint8_t timeout) {
|
|||
|
|
uint8_t result = 1;
|
|||
|
|
while (retry > 0 && result != 0) {
|
|||
|
|
/* ֻ<><D6BB>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>ѵIJ<D1B5><C4B2><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>20KB<4B><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
U2_CopyIndex = 0;
|
|||
|
|
U2_CopyBuff[0] = 0;
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
|
|||
|
|
CAT1_printf("%s", cmd);
|
|||
|
|
|
|||
|
|
uint8_t t = timeout;
|
|||
|
|
while (--t) {
|
|||
|
|
bg_delay(100);
|
|||
|
|
if (U2_CopyFlag) {
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
if (strstr((char *)U2_CopyBuff, expect)) {
|
|||
|
|
result = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (t == 0) {
|
|||
|
|
log_warn("> AT <20><>ʱ [r%u]: %s", retry, cmd);
|
|||
|
|
}
|
|||
|
|
retry--;
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD>ݾɽӿ<C9BD>: <20><><EFBFBD>η<EFBFBD><CEB7><EFBFBD>, timeout <20><><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><D7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) */
|
|||
|
|
int air780e_send_at(const char *cmd, const char *expect, int timeout_ms) {
|
|||
|
|
return catSendCmd(cmd, expect, 1, (uint8_t)((timeout_ms + 99) / 100));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20>ȴ<EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>總<EFBFBD><E7B8BD>: <20><>ѯ AT+CGATT?, ֱ<><D6B1> +CGATT: 1 <20><> PDN <20><><EFBFBD><EFBFBD> */
|
|||
|
|
static int cat_wait_cgatt_attached(int max_wait_s) {
|
|||
|
|
int waited = 0;
|
|||
|
|
while (waited < max_wait_s * 10) {
|
|||
|
|
U2_CopyIndex = 0;
|
|||
|
|
U2_CopyBuff[0] = 0;
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
g_net_ui_phase = NET_UI_4G_ATTACH;
|
|||
|
|
CAT1_printf("AT+CGATT?");
|
|||
|
|
|
|||
|
|
uint8_t t = 30; /* <20><><EFBFBD>β<EFBFBD>ѯ<EFBFBD><D1AF> 3 <20><> */
|
|||
|
|
while (--t) {
|
|||
|
|
bg_delay(100);
|
|||
|
|
if (U2_CopyFlag) {
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "+CGATT: 1")) {
|
|||
|
|
log_info("> 4G: CGATT <20>Ѹ<EFBFBD><D1B8><EFBFBD>");
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "+CGEV: ME PDN ACT 1")) {
|
|||
|
|
log_info("> 4G: PDN <20>Ѽ<EFBFBD><D1BC><EFBFBD>");
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
waited += 30; /* ÿ<><C3BF><EFBFBD><EFBFBD>ѯԼ 3 <20><> */
|
|||
|
|
log_info("> 4G: CGATT δ<><CEB4><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD> %d/%d", waited / 10, max_wait_s);
|
|||
|
|
}
|
|||
|
|
log_warn("> 4G: CGATT <20><><EFBFBD>ų<EFBFBD>ʱ");
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== Network ====*/
|
|||
|
|
/* 4G ģ<><C4A3>Ŀ<EFBFBD>겨<EFBFBD><EAB2A8><EFBFBD>ʣ<EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC> 115200<30><30>AT+IPR <20><><EFBFBD>ú<EFBFBD><C3BA><EFBFBD><EFBFBD>籣<EFBFBD><E7B1A3> */
|
|||
|
|
#define CAT_BAUD_TARGET 921600u
|
|||
|
|
#define CAT_BAUD_DEFAULT 115200u
|
|||
|
|
|
|||
|
|
static char s_iccid[24] = {0}; /* SIM <20><><EFBFBD>ţ<EFBFBD>MQTT OK <20><><EFBFBD>ϱ<EFBFBD>ƽ̨ */
|
|||
|
|
|
|||
|
|
static int cat_connect_network(void) {
|
|||
|
|
log_info("> 4G: <20><><EFBFBD><EFBFBD>...");
|
|||
|
|
g_net_ui_phase = NET_UI_4G_AT;
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>Ȱ<EFBFBD> 115200 ̽<>⣨<EFBFBD><E2A3A8><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>Ӧģʽ<C4A3><CABD>ģ<EFBFBD>鲻<EFBFBD>ܱ<EFBFBD>
|
|||
|
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⴰ<EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>˾̶<EFBFBD>Ϊ 921600 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>棻
|
|||
|
|
<EFBFBD><EFBFBD>ͨ˵<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹ̶<EFBFBD> 921600<EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD> */
|
|||
|
|
USART3_SetBaudRate(CAT_BAUD_DEFAULT);
|
|||
|
|
if (catSendCmd("AT", "OK", 1, 5) == 0) {
|
|||
|
|
if (catSendCmd("AT+IPR=921600", "OK", 1, 30) != 0) return -1;
|
|||
|
|
USART3_SetBaudRate(CAT_BAUD_TARGET);
|
|||
|
|
bg_delay(100);
|
|||
|
|
catSendCmd("AT&W", "OK", 1, 20); /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>ģ<EFBFBD>鸴λ<E9B8B4><EFBFBD> 921600 */
|
|||
|
|
if (catSendCmd("AT", "OK", 3, 20) != 0) return -1;
|
|||
|
|
log_info("> 4G: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -> 921600");
|
|||
|
|
} else {
|
|||
|
|
USART3_SetBaudRate(CAT_BAUD_TARGET);
|
|||
|
|
if (catSendCmd("AT", "OK", 3, 20) != 0) return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (catSendCmd("AT", "OK", 3, 20) != 0) return -1;
|
|||
|
|
if (catSendCmd("ATE0", "OK", 1, 10) != 0) return -1;
|
|||
|
|
g_net_ui_phase = NET_UI_4G_SIM; /* AT ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD> SIM/<2F>ź<EFBFBD> */
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD> SIM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD>ѯ AT+CPIN?<3F><>ʶ<EFBFBD><CAB6><EFBFBD><EFBFBD> SIM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
int sim_retry = 3;
|
|||
|
|
while (sim_retry-- > 0) {
|
|||
|
|
U2_CopyIndex = 0; U2_CopyBuff[0] = 0; U2_CopyFlag = 0;
|
|||
|
|
CAT1_printf("AT+CPIN?");
|
|||
|
|
uint8_t t = 30;
|
|||
|
|
while (--t) {
|
|||
|
|
bg_delay(100);
|
|||
|
|
if (U2_CopyFlag) {
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "READY")) {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "NO SIM") ||
|
|||
|
|
strstr((char *)U2_CopyBuff, "NOSIM") ||
|
|||
|
|
strstr((char *)U2_CopyBuff, "SIM NOT INSERTED") ||
|
|||
|
|
strstr((char *)U2_CopyBuff, "+CME ERROR: 10")) {
|
|||
|
|
log_warn("> 4G: δ<><CEB4><EFBFBD> SIM <20><>");
|
|||
|
|
g_net_ui_phase = NET_UI_4G_NOSIM;
|
|||
|
|
g_no_sim_detected = 1;
|
|||
|
|
return -2;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "READY")) break;
|
|||
|
|
HAL_Delay(1000);
|
|||
|
|
}
|
|||
|
|
if (!strstr((char *)U2_CopyBuff, "READY")) {
|
|||
|
|
log_warn("> 4G: SIM δ<><CEB4><EFBFBD><EFBFBD>");
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><>ȡ SIM <20><><EFBFBD><EFBFBD> ICCID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<D7B2><CDB9><EFBFBD><EFBFBD><EFBFBD>ƽ̨<C6BD>ɲ鿨<C9B2>Žɷѣ<C9B7> */
|
|||
|
|
{
|
|||
|
|
s_iccid[0] = 0;
|
|||
|
|
if (catSendCmd("AT+ICCID", "+ICCID:", 1, 10) == 0) {
|
|||
|
|
char *p = strstr((char *)U2_CopyBuff, "+ICCID:");
|
|||
|
|
if (p) {
|
|||
|
|
p += 7;
|
|||
|
|
while (*p == ' ') p++;
|
|||
|
|
int n = 0;
|
|||
|
|
while (n < 20 && ((p[n] >= '0' && p[n] <= '9') ||
|
|||
|
|
(p[n] >= 'A' && p[n] <= 'Z') || (p[n] >= 'a' && p[n] <= 'z'))) n++; /* <20><><EFBFBD><EFBFBD>+<2B><>Сд<D0A1><D0B4>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 20 λ */
|
|||
|
|
memcpy(s_iccid, p, n);
|
|||
|
|
s_iccid[n] = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (s_iccid[0]) log_info("> 4G: ICCID %s", s_iccid);
|
|||
|
|
else log_warn("> 4G: ICCID <20><>ȡʧ<C8A1><CAA7>");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (cat_wait_cgatt_attached(30) != 0) return -1;
|
|||
|
|
|
|||
|
|
/* <20>ź<EFBFBD><C5BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣺AT+CSQ <20><> +CSQ: rssi,ber<65><72>rssi 0~31<33><31>99=δ֪/<2F><><EFBFBD>źţ<C5BA><C5A3><EFBFBD>
|
|||
|
|
* ת<EFBFBD>ɰٷֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD>ʱ<EFBFBD>ñ<EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> -3<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD> WiFi<EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD>ź<EFBFBD>ƫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><20%<EFBFBD><EFBFBD>ֻ<EFBFBD>澯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
g_no_signal_detected = 0;
|
|||
|
|
if (catSendCmd("AT+CSQ", "+CSQ:", 1, 15) == 0) {
|
|||
|
|
char *p = strstr((char *)U2_CopyBuff, "+CSQ: ");
|
|||
|
|
int rssi = p ? atoi(p + 6) : 99;
|
|||
|
|
int pct = (rssi >= 0 && rssi <= 31) ? (rssi * 100 / 31) : 0;
|
|||
|
|
log_info("> 4G: <20>ź<EFBFBD> %d%% (rssi=%d)", pct, rssi);
|
|||
|
|
if (rssi == 99 || rssi < 2) {
|
|||
|
|
log_error("> 4G: <20><><EFBFBD>ź<EFBFBD> (%d%%)", pct);
|
|||
|
|
g_no_signal_detected = 1;
|
|||
|
|
return -3;
|
|||
|
|
}
|
|||
|
|
if (pct < 20) {
|
|||
|
|
log_warn("> 4G: <20>ź<EFBFBD><C5BA><EFBFBD> (%d%%)", pct);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
log_warn("> 4G: CSQ <20><>ѯʧ<D1AF><CAA7>,<2C><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (catSendCmd("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", "OK", 1, 20) != 0) return -1;
|
|||
|
|
if (catSendCmd("AT+SAPBR=3,1,\"APN\",\"\"", "OK", 1, 20) != 0) return -1;
|
|||
|
|
if (catSendCmd("AT+SAPBR=1,1", "OK", 3, 150) != 0) return -1;
|
|||
|
|
|
|||
|
|
/* GNSS <20>ϵ<EFBFBD> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>Air780EG <20><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>/GPS<50><53><EFBFBD><EFBFBD> PDP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܿ<EFBFBD><DCBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD> GNSS <EFBFBD>汾ģ<EFBFBD>飨<EFBFBD><EFBFBD> Air780E<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ERROR<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>澯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* ͬʱ<EFBFBD><EFBFBD> s_gnss_present=0 <EFBFBD>رպ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>ѯ */
|
|||
|
|
s_gnss_present = 0;
|
|||
|
|
if (g_gps_on) {
|
|||
|
|
if (catSendCmd("AT+CGNSPWR=1", "OK", 1, 30) != 0) {
|
|||
|
|
log_warn("> 4G: GNSS <20>ϵ<EFBFBD>ʧ<EFBFBD><CAA7>(ģ<><C4A3><EFBFBD><EFBFBD> GNSS?)");
|
|||
|
|
} else if (catSendCmd("AT+CGNSAID=31,1,1,1", "OK", 1, 30) != 0) {
|
|||
|
|
log_warn("> 4G: GNSS <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>");
|
|||
|
|
} else {
|
|||
|
|
s_gnss_present = 1;
|
|||
|
|
log_info("> 4G: GNSS <20>ѿ<EFBFBD><D1BF><EFBFBD>");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log_info("> 4G: <20><><EFBFBD><EFBFBD> OK"); return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== MQTT Connect ====*/
|
|||
|
|
static int cat_connect_mqtt(void) {
|
|||
|
|
g_net_ui_phase = NET_UI_4G_MQTT;
|
|||
|
|
char b[120]; log_info("> 4G: MQTT...");
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD> catSendCmd <20>ȴ<EFBFBD> MCONNECT <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
sprintf(b, "AT+MCONFIG=\"%s\",\"%s\",\"%s\",0,0,0,0", mqtt_cfg.ClientID, mqtt_cfg.Username, mqtt_cfg.Passward);
|
|||
|
|
if (catSendCmd(b, "OK", 1, 15) != 0) return -1;
|
|||
|
|
|
|||
|
|
/* <20>ȴ<EFBFBD> TCP <20><><EFBFBD><EFBFBD>: "CONNECT OK" <20><> "OK" */
|
|||
|
|
sprintf(b, "AT+MIPSTART=\"%s\",%d", mqtt_cfg.ServerIP, mqtt_cfg.ServerPort);
|
|||
|
|
if (catSendCmd(b, "OK", 1, 60) != 0) return -1;
|
|||
|
|
/* <20>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>ȴ<EFBFBD> OK, <20><><EFBFBD>Լ<EFBFBD><D4BC>ݴ<EFBFBD><DDB4><EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٵ<EFBFBD>һ<EFBFBD><D2BB> CONNECT OK */
|
|||
|
|
if (!strstr((char *)U2_CopyBuff, "CONNECT OK")) {
|
|||
|
|
int tcp_t = 30; /* 3s */
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
while (--tcp_t >= 0) {
|
|||
|
|
bg_delay(100);
|
|||
|
|
if (U2_CopyFlag) {
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "CONNECT OK") ||
|
|||
|
|
strstr((char *)U2_CopyBuff, "+MIPCALLBACK")) break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (tcp_t < 0) {
|
|||
|
|
log_warn("> 4G: TCP <20><><EFBFBD>ӳ<EFBFBD>ʱ,last[%d]: %.80s", U2_CopyIndex, U2_CopyBuff);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD> MQTT <20><><EFBFBD><EFBFBD> */
|
|||
|
|
if (catSendCmd("AT+MCONNECT=1,60", "OK", 1, 60) != 0) return -1;
|
|||
|
|
/* <20>ȴ<EFBFBD> MQTT <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>Air780E <20><><EFBFBD><EFBFBD> CONNACK OK <20><>ʾ<EFBFBD>ɹ<EFBFBD> */
|
|||
|
|
if (!strstr((char *)U2_CopyBuff, "CONNACK OK") && !strstr((char *)U2_CopyBuff, "CONNECT OK")) {
|
|||
|
|
int mqtt_t = 30; /* 3s */
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
while (--mqtt_t >= 0) {
|
|||
|
|
bg_delay(100);
|
|||
|
|
if (U2_CopyFlag) {
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "CONNACK OK") ||
|
|||
|
|
strstr((char *)U2_CopyBuff, "CONNECT OK") ||
|
|||
|
|
strstr((char *)U2_CopyBuff, "+MCONNECTED")) break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (mqtt_t < 0) {
|
|||
|
|
log_warn("> 4G: MQTT <20><><EFBFBD>ӳ<EFBFBD>ʱ,last[%d]: %.80s", U2_CopyIndex, U2_CopyBuff);
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sprintf(b, "AT+MSUB=\"%s%s\",0", mqtt_cfg.Topic, mqtt_cfg.ClientID);
|
|||
|
|
if (catSendCmd(b, "SUBACK", 1, 50) != 0) {
|
|||
|
|
/* <20><><EFBFBD><EFBFBD>û<EFBFBD>ȵ<EFBFBD> SUBACK <20><><EFBFBD>ȵ<EFBFBD><C8B5><EFBFBD> OK, Ҳ<>㶩<EFBFBD><E3B6A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѽ<EFBFBD><D1BD><EFBFBD> */
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "OK")) {
|
|||
|
|
log_info("> 4G: MSUB <20>ѽ<EFBFBD><D1BD><EFBFBD>(OK)");
|
|||
|
|
} else {
|
|||
|
|
log_warn("> 4G: MSUB ʧ<><CAA7>,buff[%d]: %.80s", U2_CopyIndex, U2_CopyBuff);
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
log_info("> 4G: MQTT OK"); return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== OTA: <20>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD> ====*/
|
|||
|
|
/* <20>汾<EFBFBD>Ŵ<EFBFBD><C5B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> EEPROM (MqttInfoStr.Ver), <20>ϵ籣<CFB5><E7B1A3> */
|
|||
|
|
uint16_t ota_get_version(void) {
|
|||
|
|
return MqttInfoStr.Ver;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int ota_ver_save(uint16_t ver) {
|
|||
|
|
MqttInfo_Str tmp;
|
|||
|
|
int retry = 3;
|
|||
|
|
|
|||
|
|
while (retry--) {
|
|||
|
|
MqttInfoStr.Ver = ver;
|
|||
|
|
uint8_t err = eepromWriteData(0, &MqttInfoStr, MQTT_STRUCT_LEN);
|
|||
|
|
if (err == 0) {
|
|||
|
|
/* д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̻ض<CCBB><D8B6><EFBFBD>֤ */
|
|||
|
|
memset(&tmp, 0, MQTT_STRUCT_LEN);
|
|||
|
|
eepromReadData(0, &tmp, MQTT_STRUCT_LEN);
|
|||
|
|
if (tmp.Ver == ver) {
|
|||
|
|
log_info("> OTA <20>汾<EFBFBD>ѱ<EFBFBD><D1B1>沢У<E6B2A2><D0A3>: %u", ver);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
log_warn("> OTA <20>汾У<E6B1BE>鲻ƥ<E9B2BB><C6A5>: д<><D0B4>=%u, <20><>ȡ=%u", ver, tmp.Ver);
|
|||
|
|
}
|
|||
|
|
HAL_Delay(20);
|
|||
|
|
}
|
|||
|
|
log_warn("> OTA <20>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>: %u", ver);
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== MQTT Publish: OTA<54><41><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> ====*/
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD>"<22><><EFBFBD>˾<EFBFBD><CBBE><EFBFBD>"<22>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD> OK <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD> result.post(success)<29><>
|
|||
|
|
* ƽ̨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> confirm.post<EFBFBD><EFBFBD><EFBFBD><EFBFBD> OK+30s <EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>ΪȨ<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD>ź<EFBFBD> */
|
|||
|
|
void air780e_mqtt_result_nowait(const char *header, const char *ota_id, int val) {
|
|||
|
|
if (!header || !ota_id || !ota_id[0]) return;
|
|||
|
|
static char cmd[300];
|
|||
|
|
sprintf(cmd, "AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22%s\\22,\\22body\\22:{\\22id\\22:\\22%.16s\\22,\\22success\\22:%s}}\"",
|
|||
|
|
MqttInfoStr.ClientID, header, ota_id, val ? "true" : "false");
|
|||
|
|
CAT1_printf("%s", cmd);
|
|||
|
|
log_info("> OTA <20><><EFBFBD><EFBFBD><EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD>(<28><><EFBFBD><EFBFBD>OK): success=%d", val);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int air780e_mqtt_report(const char *header, const char *ota_id, int val) {
|
|||
|
|
if (!header || !ota_id || !ota_id[0]) return -1;
|
|||
|
|
static char cmd[300];
|
|||
|
|
if (strstr(header, "progress")) {
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD> OK ȷ<><C8B7><EFBFBD>ʹʧ<EFA3A8><CAA7><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD> 1 <20>Σ<EFBFBD><CEA3><EFBFBD><EFBFBD><EFBFBD>ƽ̨"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"<22>ɿ<EFBFBD><C9BF><EFBFBD>λ<EFBFBD><CEBB>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ 10% <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ~3s<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȿɼ<EFBFBD> */
|
|||
|
|
sprintf(cmd, "AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22%s\\22,\\22body\\22:{\\22id\\22:\\22%.16s\\22,\\22progress\\22:%d}}\"",
|
|||
|
|
MqttInfoStr.ClientID, header, ota_id, val);
|
|||
|
|
if (catSendCmd(cmd, "OK", 2, 15) != 0) {
|
|||
|
|
log_warn("> OTA <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD>Ӧ<EFBFBD><D3A6>: %d%%", val);
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
} else {
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD>ƽ̨<C6BD>ݴ<EFBFBD><DDB4>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɿ<EFBFBD><C9BF>ʹ<CDB4><EFA1AA><EFBFBD><EFBFBD> OK <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
sprintf(cmd, "AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22%s\\22,\\22body\\22:{\\22id\\22:\\22%.16s\\22,\\22success\\22:%s}}\"",
|
|||
|
|
MqttInfoStr.ClientID, header, ota_id, val ? "true" : "false");
|
|||
|
|
if (catSendCmd(cmd, "OK", 3, 30) != 0) {
|
|||
|
|
log_warn("> OTA <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD>ʧ<EFBFBD><CAA7>(<28><><EFBFBD><EFBFBD> 3 <20><><EFBFBD><EFBFBD> OK)");
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
log_info("> OTA <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD>: success=%d", val);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== MQTT Dispatch (with dedup) ====*/
|
|||
|
|
/* <20><><EFBFBD><EFBFBD> U2_CopyBuff <20>еĵ<D0B5>һ<EFBFBD><D2BB> MQTT <20><>Ϣ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ */
|
|||
|
|
static void dispatch_one_mqtt_msg(void) {
|
|||
|
|
char *d = (char *)U2_CopyBuff;
|
|||
|
|
char *sub = strstr(d, "+MSUB:");
|
|||
|
|
char *next = NULL;
|
|||
|
|
int has_next = 0;
|
|||
|
|
|
|||
|
|
if (!sub && !strstr(d, "CLOSED") && !strstr(d, "+NO Service") && !strstr(d, "boot.rom")) {
|
|||
|
|
U2_CopyIndex = 0;
|
|||
|
|
U2_CopyBuff[0] = 0;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> +MSUB */
|
|||
|
|
if (sub) {
|
|||
|
|
char *p = sub + 6;
|
|||
|
|
next = strstr(p, "+MSUB:");
|
|||
|
|
if (next) has_next = 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><>ʱ<EFBFBD>ض<EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> */
|
|||
|
|
char saved = 0;
|
|||
|
|
if (next) {
|
|||
|
|
saved = *next;
|
|||
|
|
*next = '\0';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log_info("> MQTT: %.200s", d);
|
|||
|
|
if (strstr(d, "+NO Service")) {
|
|||
|
|
if (next) *next = saved;
|
|||
|
|
log_error("> 4G <20>쳣: <20><EFBFBD><DEB7><EFBFBD>,<2C><>λ");
|
|||
|
|
reset_log_mark(RSN_NO_SERVICE);
|
|||
|
|
HAL_Delay(1000);
|
|||
|
|
NVIC_SystemReset();
|
|||
|
|
}
|
|||
|
|
if (strstr(d, "CLOSED")) {
|
|||
|
|
if (next) *next = saved;
|
|||
|
|
log_error("> 4G <20>쳣: MQTT/TCP <20>ѶϿ<D1B6>,<2C><>λ");
|
|||
|
|
reset_log_mark(RSN_KICKED);
|
|||
|
|
HAL_Delay(1000);
|
|||
|
|
NVIC_SystemReset();
|
|||
|
|
}
|
|||
|
|
if (strstr(d, "boot.rom")) {
|
|||
|
|
if (next) *next = saved;
|
|||
|
|
log_error("> 4G <20>쳣: ģ<><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(boot.rom),<2C><>λ");
|
|||
|
|
reset_log_mark(RSN_4G_MODULE);
|
|||
|
|
HAL_Delay(1000);
|
|||
|
|
NVIC_SystemReset();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ҵ<><D2B5><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>idȥ<64><C8A5>/<2F>̵<EFBFBD><CCB5><EFBFBD>/OTA<54><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᵽ<EFBFBD><E1B5BD><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD> */
|
|||
|
|
net_dispatch_message(d);
|
|||
|
|
|
|||
|
|
/* <20>ָ<EFBFBD><D6B8>ض<EFBFBD> */
|
|||
|
|
if (next) *next = saved;
|
|||
|
|
|
|||
|
|
/* <20>ƶ<EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ */
|
|||
|
|
if (has_next && next) {
|
|||
|
|
int remain = U2_CopyIndex - (int)(next - d);
|
|||
|
|
if (remain > 0) {
|
|||
|
|
memmove(U2_CopyBuff, next, remain);
|
|||
|
|
U2_CopyIndex = remain;
|
|||
|
|
U2_CopyBuff[U2_CopyIndex] = '\0';
|
|||
|
|
U2_CopyFlag = 1; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
} else {
|
|||
|
|
U2_CopyIndex = 0;
|
|||
|
|
U2_CopyBuff[0] = 0;
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
U2_CopyIndex = 0;
|
|||
|
|
U2_CopyBuff[0] = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== MODBUS CRC16 ====
|
|||
|
|
* <EFBFBD><EFBFBD> static<EFBFBD><EFBFBD>WiFi OTA(net_wifi_ota.c) <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
uint16_t crc16_modbus_update(uint16_t crc, uint8_t data) {
|
|||
|
|
crc ^= data;
|
|||
|
|
for (int i = 0; i < 8; i++) {
|
|||
|
|
if (crc & 1) crc = (crc >> 1) ^ 0xA001;
|
|||
|
|
else crc >>= 1;
|
|||
|
|
}
|
|||
|
|
return crc;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== OTA Download via HTTP Range ====*/
|
|||
|
|
static void air780e_trigger_ota_body(const char *host, int port, const char *path, const char *ota_id, uint16_t new_ver, uint16_t crc16);
|
|||
|
|
|
|||
|
|
/* OTA <20><><EFBFBD><EFBFBD>: ֹͣͶι + <20><><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>緢<EFBFBD><E7B7A2>, Ȼ<><C8BB>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD>ء<EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD>سɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> body <EFBFBD><EFBFBD>ֱ<EFBFBD>Ӹ<EFBFBD>λ; ʧ<EFBFBD>ܷ<EFBFBD><EFBFBD>غ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
void air780e_trigger_ota(const char *host, int port, const char *path, const char *ota_id, uint16_t new_ver, uint16_t crc16) {
|
|||
|
|
log_info("> OTA: <20><><EFBFBD><EFBFBD>");
|
|||
|
|
g_net_ui_phase = NET_UI_OTA; /* OLED <20><>ʾ OTA <20><><EFBFBD><EFBFBD>ҳ */
|
|||
|
|
g_ota_pct = 0;
|
|||
|
|
g_ota_active = 1; /* <20><>ͣ<EFBFBD><CDA3><EFBFBD><EFBFBD>ѯ/<2F>̵<EFBFBD><CCB5><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>·<EFBFBD><C2B7><EFBFBD>Ḵλ<E1B8B4><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
feedScaleStop(); /* <20><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>ֹͣͶι״̬<D7B4><CCAC> */
|
|||
|
|
relaySet(1, 0); /* <20><EFBFBD>ģʽ<C4A3><CABD>ֱ<EFBFBD>ӶϿ<D3B6>Ͷι<CDB6>̵<EFBFBD><CCB5><EFBFBD> */
|
|||
|
|
g_net_tx_busy = 1; /* <20><><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD> NET_publish_*, <20><>ֹ<EFBFBD><D6B9> AT Ӧ<><D3A6><EFBFBD><EFBFBD>֯ */
|
|||
|
|
air780e_trigger_ota_body(host, port, path, ota_id, new_ver, crc16);
|
|||
|
|
g_net_tx_busy = 0;
|
|||
|
|
/* body <20>κ<EFBFBD>ʧ<EFBFBD><CAA7>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD>غ<EFBFBD><D8BA><EFBFBD><EFBFBD>븴λ<EBB8B4><CEBB>OTA <20><><EFBFBD><EFBFBD><EFBFBD>Ѹ<EFBFBD>λ<EFBFBD><CEBB> 4G ģ<>飬
|
|||
|
|
* MQTT ʵ<EFBFBD><EFBFBD><EFBFBD>ѶϿ<EFBFBD><EFBFBD><EFBFBD> ready <EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<EFBFBD><EFBFBD>"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>ٴ<EFBFBD> OTA */
|
|||
|
|
log_warn("> OTA: ʧ<><CAA7><EFBFBD><EFBFBD>ֹ,<2C><>λ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>");
|
|||
|
|
reset_log_mark(RSN_OTA_FAIL);
|
|||
|
|
HAL_Delay(100);
|
|||
|
|
NVIC_SystemReset();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void air780e_trigger_ota_body(const char *host, int port, const char *path, const char *ota_id, uint16_t new_ver, uint16_t crc16) {
|
|||
|
|
ota_module_reset(); int r; log_info("> OTA: <20><><EFBFBD><EFBFBD>...");
|
|||
|
|
for (r=5;r>0;r--){if(air780e_send_at("AT","OK",3000)==0)break;log_info("> AT %d",r);bg_delay(1000);}
|
|||
|
|
if(r==0)return;
|
|||
|
|
bg_delay(500); /* ģ<><C4A3><EFBFBD>ջ<EFBFBD>OK, <20>Ե<EFBFBD><D4B5>ٷ<EFBFBD><D9B7><EFBFBD>һ<EFBFBD><D2BB> */
|
|||
|
|
log_info("> OTA: <20>ڶ<EFBFBD><DAB6><EFBFBD> AT <20><><EFBFBD><EFBFBD>");
|
|||
|
|
if(air780e_send_at("AT","OK",5000)!=0){log_warn("> <20>ڶ<EFBFBD><DAB6><EFBFBD> AT ʧ<><CAA7>");return;}
|
|||
|
|
log_info("> OTA: <20>ڶ<EFBFBD><DAB6><EFBFBD> AT <20>ɹ<EFBFBD>");
|
|||
|
|
if(air780e_send_at("ATE0","OK",5000)!=0)return;
|
|||
|
|
for(r=3;r>0;r--){if(air780e_send_at("AT+CPIN?","READY",5000)==0)break;log_info("> SIM %d",r);}
|
|||
|
|
if(r==0)return;
|
|||
|
|
if(air780e_send_at("AT+CSQ","OK",3000)!=0)return;
|
|||
|
|
|
|||
|
|
/* ģ<><C4A3> OTA <20><><EFBFBD>ڸո<DAB8>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><C8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¸<EFBFBD><C2B8><EFBFBD>(CATT=1)<29>ټ<EFBFBD><D9BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)ʱ SAPBR=1,1 <EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>(S3) */
|
|||
|
|
log_info("> OTA: <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>總<EFBFBD><E7B8BD>...");
|
|||
|
|
if (cat_wait_cgatt_attached(30) != 0) { log_warn("> OTA: <20><><EFBFBD>ų<EFBFBD>ʱ"); return; }
|
|||
|
|
|
|||
|
|
log_info("> SAPBR...");
|
|||
|
|
if(air780e_send_at("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"","OK",3000)!=0){log_info("> S1");return;}
|
|||
|
|
if(air780e_send_at("AT+SAPBR=3,1,\"APN\",\"\"","OK",3000)!=0){log_info("> S2");return;}
|
|||
|
|
if(air780e_send_at("AT+SAPBR=1,1","OK",10000)!=0){log_info("> S3");return;}
|
|||
|
|
if(air780e_send_at("AT+SAPBR=2,1","OK",3000)!=0){log_info("> S4");return;}
|
|||
|
|
|
|||
|
|
/* MQTT connect for OTA progress reporting<6E><67><EFBFBD><EFBFBD><F0B2BDBC>飬<EFBFBD><E9A3AC><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>Ҫ<EFBFBD>ܿ<EFBFBD><DCBF><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
{ static char b[120]; sprintf(b,"AT+MCONFIG=\"%s\",\"%s\",\"%s\",0,0,0,0",mqtt_cfg.ClientID,mqtt_cfg.Username,mqtt_cfg.Passward);
|
|||
|
|
if(air780e_send_at(b,"OK",2000)!=0)log_warn("> OTA: MCONFIG ʧ<><CAA7>");
|
|||
|
|
sprintf(b,"AT+MIPSTART=\"%s\",%d",mqtt_cfg.ServerIP,mqtt_cfg.ServerPort);
|
|||
|
|
if(air780e_send_at(b,"OK",10000)!=0)log_warn("> OTA: MIPSTART ʧ<><CAA7>");
|
|||
|
|
if(air780e_send_at("AT+MCONNECT=1,60","OK",10000)!=0)log_warn("> OTA: MCONNECT ʧ<><CAA7>");
|
|||
|
|
log_info("> OTA: MQTT <20><><EFBFBD><EFBFBD>"); }
|
|||
|
|
|
|||
|
|
static char buf[250], fu[150]; sprintf(fu,"http://%s:%d%s",host,port,path);
|
|||
|
|
log_info("> HTTP: %s",fu);
|
|||
|
|
if(air780e_send_at("AT+HTTPINIT","OK",5000)!=0){log_info("> INIT");return;}
|
|||
|
|
sprintf(buf,"AT+HTTPPARA=\"URL\",\"%s\"",fu);
|
|||
|
|
if(air780e_send_at(buf,"OK",5000)!=0){log_info("> URL");air780e_send_at("AT+HTTPTERM","OK",2000);return;}
|
|||
|
|
|
|||
|
|
log_info("> HEAD...");
|
|||
|
|
if(air780e_send_at("AT+HTTPACTION=2","+HTTPACTION:",10000)!=0){log_info("> HEAD");air780e_send_at("AT+HTTPTERM","OK",2000);return;}
|
|||
|
|
int file_size=0;
|
|||
|
|
{
|
|||
|
|
memset(U2_CopyBuff,0,U2_COPY_SIZE);U2_CopyIndex=0;U2_CopyFlag=0;
|
|||
|
|
HAL_UART_Transmit(&huart3,(uint8_t*)"AT+HTTPHEAD\r\n",14,500);
|
|||
|
|
int t=2000;while(t>0){bg_delay(50);t-=50;if(strstr((char*)U2_CopyBuff,"OK"))break;}
|
|||
|
|
char *cl=strstr((char*)U2_CopyBuff,"Content-Length:");if(!cl)cl=strstr((char*)U2_CopyBuff,"content-length:");
|
|||
|
|
if(cl){cl=strchr(cl,':');if(cl){cl++;while(*cl==' '||*cl=='\t')cl++;while(*cl>='0'&&*cl<='9'){file_size=file_size*10+(*cl-'0');cl++;}}}
|
|||
|
|
}
|
|||
|
|
log_info("> <20><>С=%dB",file_size);
|
|||
|
|
|
|||
|
|
log_info("**************************************");
|
|||
|
|
log_info("* OTA <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ *");
|
|||
|
|
log_info("* <20><>С: %d <20>ֽ<EFBFBD> *",file_size);
|
|||
|
|
log_info("**************************************");
|
|||
|
|
log_info("> <20><><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD> W25Q64 <20>²<EFBFBD>λ...");
|
|||
|
|
W25Q64_EraseRegion(W25Q64_SLOT_NEW_ADDR, W25Q64_SLOT_SIZE);
|
|||
|
|
log_info("> W25Q64 <20>²<EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
|||
|
|
|
|||
|
|
/* Air780EG <20>ֲHTTPREAD <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3072 <20>ֽ<EFBFBD> */
|
|||
|
|
#define OTA_DL_CHUNK 3072
|
|||
|
|
|
|||
|
|
int total=0, offset=0, last_pct = -1;
|
|||
|
|
uint16_t crc_acc = 0xFFFF;
|
|||
|
|
air780e_mqtt_report("iot.ota.progress.post", ota_id, 0);
|
|||
|
|
log_info("[<5B><><EFBFBD><EFBFBD>] <20><>ʼ >>>");
|
|||
|
|
while(1){
|
|||
|
|
log_info("> DL ƫ<><C6AB>=%d", offset);
|
|||
|
|
sprintf(buf,"AT+HTTPPARA=\"BREAK\",%d",offset);
|
|||
|
|
if(air780e_send_at(buf,"OK",3000)!=0){log_info("> BRK ʧ<><CAA7>");break;}
|
|||
|
|
sprintf(buf,"AT+HTTPPARA=\"BREAKEND\",%d",offset+OTA_DL_CHUNK-1);
|
|||
|
|
if(air780e_send_at(buf,"OK",3000)!=0){log_info("> BRKEND ʧ<><CAA7>");break;}
|
|||
|
|
if(air780e_send_at("AT+HTTPACTION=0","+HTTPACTION:",5000)!=0){log_info("> ACT @%d",offset);break;}
|
|||
|
|
|
|||
|
|
int start = U2_CopyIndex;
|
|||
|
|
HAL_UART_Transmit(&huart3, (uint8_t *)"AT+HTTPREAD\r\n", 14, 500);
|
|||
|
|
|
|||
|
|
/* <20><> "+HTTPREAD: <len>" ͷ<><CDB7><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3>Ƚ<EFBFBD><C8BD>գ<EFBFBD><D5A3>չ<EFBFBD> len <20>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
<EFBFBD><EFBFBD><EFBFBD>ٵ<EFBFBD> 500ms <EFBFBD><EFBFBD>Ĭβ<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD>Լʡ 0.5s */
|
|||
|
|
int dlen=0, body=-1;
|
|||
|
|
{ uint32_t t0=HAL_GetTick();
|
|||
|
|
while(HAL_GetTick()-t0 < 10000){
|
|||
|
|
if(body<0){
|
|||
|
|
for(int k=start;k<(int)U2_CopyIndex-11;k++){
|
|||
|
|
if(U2_CopyBuff[k]=='+'&&U2_CopyBuff[k+1]=='H'&&U2_CopyBuff[k+2]=='T'&&U2_CopyBuff[k+3]=='T'&&U2_CopyBuff[k+4]=='P'&&
|
|||
|
|
U2_CopyBuff[k+5]=='R'&&U2_CopyBuff[k+6]=='E'&&U2_CopyBuff[k+7]=='A'&&U2_CopyBuff[k+8]=='D'&&U2_CopyBuff[k+9]==':'){
|
|||
|
|
int j=k+10, d=0;
|
|||
|
|
while(j<(int)U2_CopyIndex&&(U2_CopyBuff[j]==' '||U2_CopyBuff[j]=='\t'))j++;
|
|||
|
|
while(j<(int)U2_CopyIndex&&U2_CopyBuff[j]>='0'&&U2_CopyBuff[j]<='9'){d=d*10+(U2_CopyBuff[j]-'0');j++;}
|
|||
|
|
while(j<(int)U2_CopyIndex&&U2_CopyBuff[j]!='\n')j++;
|
|||
|
|
if(j<(int)U2_CopyIndex){dlen=d;body=j+1;} /* ͷ<><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}else if((int)U2_CopyIndex-body>=dlen){
|
|||
|
|
break; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
}
|
|||
|
|
bg_delay(20);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if(dlen<=0||body<0){log_info("> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> @%d",offset);break;}
|
|||
|
|
|
|||
|
|
/* У<><D0A3>ʵ<EFBFBD>ʽ<EFBFBD><CABD>ճ<EFBFBD><D5B3><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>㹻<EFBFBD><E3B9BB><EFBFBD><EFBFBD>ֹ DMA <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ʧ */
|
|||
|
|
if ((int)U2_CopyIndex - body < dlen) {
|
|||
|
|
log_warn("> DL <20><><EFBFBD>ݿ<EFBFBD> @%d <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD> %d/%d <20>ֽ<EFBFBD>,<2C><><EFBFBD><EFBFBD>...", offset, U2_CopyIndex - body, dlen);
|
|||
|
|
air780e_send_at("AT+HTTPTERM","OK",3000);
|
|||
|
|
air780e_mqtt_report("iot.ota.result.post", ota_id, 0);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
W25Q64_WriteBuffer(W25Q64_SLOT_NEW_ADDR + offset, &U2_CopyBuff[body], dlen);
|
|||
|
|
if (!W25Q64_Verify(W25Q64_SLOT_NEW_ADDR + offset, &U2_CopyBuff[body], dlen)) {
|
|||
|
|
log_error("> W25Q64 У<><D0A3>ʧ<EFBFBD><CAA7> offset=%d,<2C><>ֹ OTA", offset);
|
|||
|
|
air780e_send_at("AT+HTTPTERM","OK",3000);
|
|||
|
|
air780e_mqtt_report("iot.ota.result.post", ota_id, 0);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
for (int i = 0; i < dlen; i++) crc_acc = crc16_modbus_update(crc_acc, U2_CopyBuff[body + i]);
|
|||
|
|
|
|||
|
|
offset+=dlen;total+=dlen;
|
|||
|
|
if(file_size>0){int pct=total*100/file_size;if(pct>100)pct=100;
|
|||
|
|
g_ota_pct = pct; /* OLED <20><><EFBFBD><EFBFBD> */
|
|||
|
|
log_info("> [%3d%%] %d/%dB",pct,total,file_size);
|
|||
|
|
if(pct/10 > last_pct/10){last_pct = pct; air780e_mqtt_report("iot.ota.progress.post", ota_id, pct); LED2_TOGGLE;}
|
|||
|
|
}
|
|||
|
|
else log_info("> +%dB=%dB",dlen,total);
|
|||
|
|
if(dlen<OTA_DL_CHUNK||(file_size>0&&total>=file_size)||offset>=Application_Size)break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
air780e_send_at("AT+HTTPTERM","OK",3000);
|
|||
|
|
if(total==0){log_info("> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");air780e_mqtt_report("iot.ota.result.post", ota_id, 0);return;}
|
|||
|
|
if(file_size<=0)file_size=total;
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD> MODBUS CRC16 У<><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD>̼<EFBFBD> */
|
|||
|
|
log_info("> W25Q64 CRC16=0x%04X (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>=0x%04X)", crc_acc, crc16);
|
|||
|
|
if (crc16 != 0 && crc_acc != crc16) {
|
|||
|
|
log_error("> W25Q64 CRC16 <20><>ƥ<EFBFBD><C6A5>!<21><>ֹ OTA");
|
|||
|
|
air780e_mqtt_report("iot.ota.result.post", ota_id, 0);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log_info(">>> У<><D0A3> %dB...", file_size);
|
|||
|
|
if(!Verify_Firmware_External(W25Q64_SLOT_NEW_ADDR, file_size)){
|
|||
|
|
log_info("[ʧ<><CAA7>]");air780e_mqtt_report("iot.ota.result.post", ota_id, 0);return;
|
|||
|
|
}
|
|||
|
|
log_info("[ OK ] <20>̼<EFBFBD>У<EFBFBD><D0A3>ͨ<EFBFBD><CDA8>!");
|
|||
|
|
log_info("**************************************");
|
|||
|
|
log_info("* OTA <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! *");
|
|||
|
|
log_info("* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BootLoader... *");
|
|||
|
|
log_info("**************************************");
|
|||
|
|
air780e_mqtt_result_nowait("iot.ota.result.post", ota_id, 1);
|
|||
|
|
bg_delay(1000); /* <20><>ģ<EFBFBD><C4A3>һ<EFBFBD>㷢<EFBFBD><E3B7A2>ʱ<EFBFBD>伴<EFBFBD><E4BCB4>λ<EFBFBD><CEBB>Ȩ<EFBFBD><C8A8>֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> confirm.post <20>е<EFBFBD><D0B5><EFBFBD> */
|
|||
|
|
/* ֻ<>ѹ̼<D1B9><CCBC><EFBFBD>Ϣд<CFA2><D0B4> W25Q64<36><34><EFBFBD>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD> APP ȷ<>ϳɹ<CFB3><C9B9><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4> EEPROM */
|
|||
|
|
W25Q64_OTA_SetNewInfo(new_ver, file_size, crc16);
|
|||
|
|
reset_log_mark(RSN_OTA_UPDATE);
|
|||
|
|
bg_delay(100); NVIC_SystemReset();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20>̼<EFBFBD><CCBC><EFBFBD><EFBFBD>º<EFBFBD><C2BA><EFBFBD> APP <20><><EFBFBD>ã<EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȶ<EFBFBD><C8B6><EFBFBD>д<EFBFBD><D0B4> EEPROM <20>汾<EFBFBD><E6B1BE> */
|
|||
|
|
/* <20><><EFBFBD><EFBFBD> 0=ȷ<><C8B7>֪ͨ<CDA8><D6AA><EFBFBD>ʹ<EFBFBD>ƽ̨<C6BD><CCA8>1=<3D><EFBFBD><DEB9><EFBFBD> OTA<54><41>-1=<3D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>ϵ<EFBFBD>֪ͨδ<D6AA>ʹ<CDB4>ϲ<EFBFBD>Ӧ<EFBFBD>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD>ԣ<EFBFBD> */
|
|||
|
|
int air780e_ota_confirm(void)
|
|||
|
|
{
|
|||
|
|
W25Q64_OtaInfo info;
|
|||
|
|
if (W25Q64_OTA_ReadInfo(&info) != 0) return 1;
|
|||
|
|
if (info.update_state != W25Q64_STATE_INSTALLED) return 1;
|
|||
|
|
|
|||
|
|
if (!info.app_confirmed) {
|
|||
|
|
/* <20><><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3>汾<EFBFBD><E6B1BE> + ȷ<>ϱ<EFBFBD>־<EFBFBD><D6BE><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD>ֹ֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD>ʧ<EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD> BL <20><><EFBFBD>лع<D0BB> */
|
|||
|
|
if (info.new_version > 0) {
|
|||
|
|
ota_ver_save(info.new_version);
|
|||
|
|
/* <20>汾<EFBFBD>Ÿո<C5B8><D5B8>£<EFBFBD><C2A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>״̬ + fwver<65><72>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ̨Ҫ<EFBFBD><EFBFBD><EFBFBD>´δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>°汾<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
relayStatueUpdata();
|
|||
|
|
char vb[24];
|
|||
|
|
snprintf(vb, sizeof(vb), "%s:%u", FIRMWARE_VERSION_STR, (unsigned)MqttInfoStr.Ver);
|
|||
|
|
NET_publish_version(vb);
|
|||
|
|
}
|
|||
|
|
int ok = 0;
|
|||
|
|
for (int i = 0; i < 3 && !ok; i++) {
|
|||
|
|
W25Q64_OTA_SetConfirmed();
|
|||
|
|
W25Q64_OtaInfo chk;
|
|||
|
|
if (W25Q64_OTA_ReadInfo(&chk) == 0 && chk.app_confirmed) ok = 1;
|
|||
|
|
else bg_delay(50);
|
|||
|
|
}
|
|||
|
|
if (ok) log_info("> OTA ȷ<>ϱ<EFBFBD>־<EFBFBD><D6BE>д<EFBFBD><D0B4>");
|
|||
|
|
else log_error("> OTA ȷ<><C8B7>д<EFBFBD><D0B4>ʧ<EFBFBD><CAA7>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3 <20><>)");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʿɿ<CABF><C9BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3>Ȳ<EFBFBD><C8B2><EFBFBD> result.post<73><74><EFBFBD><EFBFBD>ƽ̨<C6BD><CCA8><EFBFBD><EFBFBD> id<69><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"<22><><EFBFBD><EFBFBD>"<22><>־<EFBFBD><D6BE><EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> id <EFBFBD><EFBFBD><EFBFBD><EFBFBD> EEPROM(175~194)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؿ<EFBFBD>ʼʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD>룩<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0xFF */
|
|||
|
|
int rc = 0;
|
|||
|
|
{
|
|||
|
|
char oid[20];
|
|||
|
|
eepromReadData(175, oid, sizeof(oid));
|
|||
|
|
if ((uint8_t)oid[0] != 0xFF && oid[0] != 0) {
|
|||
|
|
oid[19] = 0;
|
|||
|
|
rc |= NET_mqtt_report("iot.ota.result.post", oid, 1);
|
|||
|
|
if (rc == 0) {
|
|||
|
|
memset(oid, 0xFF, sizeof(oid));
|
|||
|
|
eepromWriteData(175, oid, sizeof(oid)); /* <20><><EFBFBD>ʹ<CDB4><EFA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD>ظ<EFBFBD> */
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD>"ȷ<>ϳɹ<CFB3>"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD>ɣ<EFBFBD>4G/WiFi ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD> */
|
|||
|
|
char id_buf[24] = {0};
|
|||
|
|
snprintf(id_buf, sizeof(id_buf), "%u", info.new_version); /* <20>ð汾<C3B0><E6B1BE><EFBFBD><EFBFBD>Ϊ id <20>ϱ<EFBFBD> */
|
|||
|
|
rc |= NET_mqtt_report("iot.ota.confirm.post", id_buf, 1);
|
|||
|
|
return rc;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*==== Init ====*/
|
|||
|
|
void air780e_init(void) {
|
|||
|
|
log_info("> 4G: <20><>ʼ<EFBFBD><CABC>...");
|
|||
|
|
memset(&mqtt_cfg,0,sizeof(mqtt_cfg));
|
|||
|
|
strncpy(mqtt_cfg.ClientID,MqttInfoStr.ClientID,sizeof(mqtt_cfg.ClientID)-1);
|
|||
|
|
strncpy(mqtt_cfg.Username,MqttInfoStr.Username,sizeof(mqtt_cfg.Username)-1);
|
|||
|
|
strncpy(mqtt_cfg.Passward,MqttInfoStr.Passward,sizeof(mqtt_cfg.Passward)-1);
|
|||
|
|
strncpy(mqtt_cfg.ServerIP,MqttInfoStr.ServerIP,sizeof(mqtt_cfg.ServerIP)-1);
|
|||
|
|
mqtt_cfg.ServerPort=MqttInfoStr.ServerPort;
|
|||
|
|
strncpy(mqtt_cfg.Topic,MqttInfoStr.Topic,sizeof(mqtt_cfg.Topic)-1);
|
|||
|
|
|
|||
|
|
int retry = 3;
|
|||
|
|
while (retry-- > 0) {
|
|||
|
|
cat_reset();
|
|||
|
|
int net_ret = cat_connect_network();
|
|||
|
|
if (net_ret == -2) {
|
|||
|
|
/* <20><> SIM <20><><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2>л<EFBFBD><D0BB><EFBFBD> WiFi */
|
|||
|
|
log_warn("> 4G: <20><> SIM,<2C><>ֹ 4G <20><>ʼ<EFBFBD><CABC>");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (net_ret == -3) {
|
|||
|
|
/* <20><><EFBFBD>źţ<C5BA><C5A3>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD>/<2F>л<EFBFBD> WiFi */
|
|||
|
|
log_warn("> 4G: <20><><EFBFBD>ź<EFBFBD>,<2C><>ֹ 4G <20><>ʼ<EFBFBD><CABC>");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (net_ret != 0) {
|
|||
|
|
log_warn("> 4G: <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>,<2C><><EFBFBD><EFBFBD> %d", retry);
|
|||
|
|
HAL_Delay(5000);
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
if (cat_connect_mqtt() == 0) {
|
|||
|
|
g_air780e_mqtt_ready = 1;
|
|||
|
|
log_info("> 4G: Ready");
|
|||
|
|
HAL_Delay(50);
|
|||
|
|
char pub[256];
|
|||
|
|
sprintf(pub, "AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.prop.post\\22,\\22body\\22:{\\22pow\\22:1}}\"", MqttInfoStr.ClientID);
|
|||
|
|
CAT1_printf("%s", pub);
|
|||
|
|
HAL_Delay(300); /* <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3> MQTT <20><><EFBFBD><EFBFBD><EFBFBD>Ŷ<EFBFBD>ײ<EFBFBD><D7B2> */
|
|||
|
|
if (s_iccid[0]) {
|
|||
|
|
sprintf(pub, "AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.prop.post\\22,\\22body\\22:{\\22iccid\\22:\\22%s\\22}}\"", MqttInfoStr.ClientID, s_iccid);
|
|||
|
|
CAT1_printf("%s", pub);
|
|||
|
|
HAL_Delay(300);
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
log_warn("> 4G: MQTT ʧ<><CAA7>,<2C><><EFBFBD><EFBFBD> %d", retry);
|
|||
|
|
air780e_send_at("AT+MDISCONNECT", "OK", 2000);
|
|||
|
|
air780e_send_at("AT+MIPSTOP", "OK", 2000);
|
|||
|
|
HAL_Delay(3000);
|
|||
|
|
}
|
|||
|
|
log_error("> 4G: <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>,<2C><> SIM=%d, <20><><EFBFBD>ź<EFBFBD>=%d", g_no_sim_detected, g_no_signal_detected);
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD> SIM <20><><EFBFBD><EFBFBD><EFBFBD>źţ<C5BA><C5A3><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD>/<2F><> WiFi<46><69><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD>и<EFBFBD>λ<EFBFBD><CEBB>Ϊ */
|
|||
|
|
if (!g_no_sim_detected && !g_no_signal_detected) {
|
|||
|
|
reset_log_mark(RSN_4G_FAIL);
|
|||
|
|
HAL_Delay(100);
|
|||
|
|
NVIC_SystemReset();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== GNSS (<28><><EFBFBD><EFBFBD>/GPS) <20><>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD> 4G ͨ<><CDA8>(Air780EG <20><><EFBFBD><EFBFBD>GNSS) ====
|
|||
|
|
* <EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD>air780EG-V1.1<EFBFBD><EFBFBD><EFBFBD>뱱<EFBFBD><EFBFBD>GPS<EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>
|
|||
|
|
* AT+CGNSINF <EFBFBD><EFBFBD> +CGNSINF: run,fix,UTC,lat,lon,...<EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><EFBFBD>Ϊʮ<EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵ļ<EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>OTA <EFBFBD>ڼ䲻<EFBFBD><EFBFBD><EFBFBD><EFBFBD> AT<EFBFBD><EFBFBD>
|
|||
|
|
* <EFBFBD><EFBFBD>ƽ̨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sscanf <EFBFBD><EFBFBD> scanset<EFBFBD><EFBFBD> */
|
|||
|
|
#define GPS_FIRST_DELAY_MS 60000u /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״β<D7B4>ѯ<EFBFBD>ӳ٣<D3B3><D9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1> */
|
|||
|
|
#define GPS_REPORT_INTERVAL_MS 300000u /* <20><>λ<EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD> 5min */
|
|||
|
|
|
|||
|
|
/*==== WGS-84 <20><> GCJ-02<30><32><EFBFBD>ߵ<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>ת<EFBFBD><D7AA> ====
|
|||
|
|
* GPS ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> WGS-84 ԭʼ<EFBFBD><EFBFBD><EFBFBD>ֱ꣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸߵµ<EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 100~600m <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD>ƣ<EFBFBD>
|
|||
|
|
* <EFBFBD>ϱ<EFBFBD>ǰ<EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD> GCJ-02<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD>ԭֵ<EFBFBD><EFBFBD> */
|
|||
|
|
#define GCJ_PI 3.1415926535897932384626
|
|||
|
|
#define GCJ_A 6378245.0 /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˹<EFBFBD><CBB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F2B3A4B0><EFBFBD> */
|
|||
|
|
#define GCJ_EE 0.00669342162296594323 /* ƫ<><C6AB><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD> */
|
|||
|
|
|
|||
|
|
static double gcj_transform_lat(double x, double y)
|
|||
|
|
{
|
|||
|
|
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x));
|
|||
|
|
ret += (20.0 * sin(6.0 * x * GCJ_PI) + 20.0 * sin(2.0 * x * GCJ_PI)) * 2.0 / 3.0;
|
|||
|
|
ret += (20.0 * sin(y * GCJ_PI) + 40.0 * sin(y / 3.0 * GCJ_PI)) * 2.0 / 3.0;
|
|||
|
|
ret += (160.0 * sin(y / 12.0 * GCJ_PI) + 320.0 * sin(y * GCJ_PI / 30.0)) * 2.0 / 3.0;
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static double gcj_transform_lon(double x, double y)
|
|||
|
|
{
|
|||
|
|
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x));
|
|||
|
|
ret += (20.0 * sin(6.0 * x * GCJ_PI) + 20.0 * sin(2.0 * x * GCJ_PI)) * 2.0 / 3.0;
|
|||
|
|
ret += (20.0 * sin(x * GCJ_PI) + 40.0 * sin(x / 3.0 * GCJ_PI)) * 2.0 / 3.0;
|
|||
|
|
ret += (150.0 * sin(x / 12.0 * GCJ_PI) + 300.0 * sin(x / 30.0 * GCJ_PI)) * 2.0 / 3.0;
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void wgs84_to_gcj02(double wgs_lon, double wgs_lat, double *gcj_lon, double *gcj_lat)
|
|||
|
|
{
|
|||
|
|
/* <20>й<EFBFBD><D0B9><EFBFBD><EFBFBD>ⲻ<EFBFBD><E2B2BB>ƫ<EFBFBD><C6AB> */
|
|||
|
|
if (wgs_lon < 72.004 || wgs_lon > 137.8347 || wgs_lat < 0.8293 || wgs_lat > 55.8271) {
|
|||
|
|
*gcj_lon = wgs_lon;
|
|||
|
|
*gcj_lat = wgs_lat;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
double dlat = gcj_transform_lat(wgs_lon - 105.0, wgs_lat - 35.0);
|
|||
|
|
double dlon = gcj_transform_lon(wgs_lon - 105.0, wgs_lat - 35.0);
|
|||
|
|
double radlat = wgs_lat / 180.0 * GCJ_PI;
|
|||
|
|
double magic = sin(radlat);
|
|||
|
|
magic = 1 - GCJ_EE * magic * magic;
|
|||
|
|
double sqrtmagic = sqrt(magic);
|
|||
|
|
dlat = (dlat * 180.0) / ((GCJ_A * (1 - GCJ_EE)) / (magic * sqrtmagic) * GCJ_PI);
|
|||
|
|
dlon = (dlon * 180.0) / (GCJ_A / sqrtmagic * cos(radlat) * GCJ_PI);
|
|||
|
|
*gcj_lat = wgs_lat + dlat;
|
|||
|
|
*gcj_lon = wgs_lon + dlon;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static uint32_t s_gps_tick = 0;
|
|||
|
|
static uint8_t s_gps_first = 1;
|
|||
|
|
|
|||
|
|
static void air780e_gps_poll(void)
|
|||
|
|
{
|
|||
|
|
if (!g_gps_on) { s_gps_tick = 0; s_gps_first = 1; return; } /* GPS0 <20>رն<D8B1>λ */
|
|||
|
|
if (!g_air780e_mqtt_ready) { s_gps_tick = 0; s_gps_first = 1; return; }
|
|||
|
|
if (!s_gnss_present) return;
|
|||
|
|
if (g_net_tx_busy) return; /* OTA <20><><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><DABC><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD> AT */
|
|||
|
|
|
|||
|
|
uint32_t now = HAL_GetTick();
|
|||
|
|
if (s_gps_tick == 0) { s_gps_tick = now; return; }
|
|||
|
|
if (now - s_gps_tick < (s_gps_first ? GPS_FIRST_DELAY_MS : GPS_REPORT_INTERVAL_MS)) return;
|
|||
|
|
s_gps_tick = now;
|
|||
|
|
s_gps_first = 0;
|
|||
|
|
|
|||
|
|
/* <20>建<EFBFBD>壬<EFBFBD><E5A3AC> AT+CGNSINF <20><>ѯ<EFBFBD><D1AF>λ */
|
|||
|
|
U2_CopyIndex = 0; U2_CopyBuff[0] = 0; U2_CopyFlag = 0;
|
|||
|
|
CAT1_printf("AT+CGNSINF");
|
|||
|
|
|
|||
|
|
int t = 20; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2s */
|
|||
|
|
while (--t) {
|
|||
|
|
bg_delay(100);
|
|||
|
|
if (U2_CopyFlag) {
|
|||
|
|
/* <20><>ƽ̨<C6BD><CCA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD> dispatch <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "+MSUB:")) return;
|
|||
|
|
if (strstr((char *)U2_CopyBuff, "+CGNSINF:")) break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (t == 0) { log_warn("> GPS: CGNSINF <20><>ʱ"); return; }
|
|||
|
|
|
|||
|
|
/* <20>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶΣ<D6B6>+CGNSINF: run,fix,UTC,lat,lon,... */
|
|||
|
|
char *q = strstr((char *)U2_CopyBuff, "+CGNSINF:") + 10;
|
|||
|
|
int run = atoi(q);
|
|||
|
|
char *c1 = strchr(q, ','); /* run <20><><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD> */
|
|||
|
|
char *c2 = c1 ? strchr(c1 + 1, ',') : NULL; /* fix <20><><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD> */
|
|||
|
|
char *c3 = c2 ? strchr(c2 + 1, ',') : NULL; /* UTC <20><><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD> <20><> lat <20><><EFBFBD><EFBFBD> */
|
|||
|
|
char *c4 = c3 ? strchr(c3 + 1, ',') : NULL; /* lat <20><><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD> <20><> lon <20><><EFBFBD><EFBFBD> */
|
|||
|
|
char *c5 = c4 ? strchr(c4 + 1, ',') : NULL; /* lon <20><><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD> */
|
|||
|
|
int fix = c1 ? atoi(c1 + 1) : 0;
|
|||
|
|
|
|||
|
|
char lat[12] = {0}, lon[13] = {0};
|
|||
|
|
if (c3 && c4 && c5) {
|
|||
|
|
int ll = (int)(c4 - (c3 + 1));
|
|||
|
|
int ol = (int)(c5 - (c4 + 1));
|
|||
|
|
if (ll > 0 && ll <= 11) { memcpy(lat, c3 + 1, ll); }
|
|||
|
|
if (ol > 0 && ol <= 12) { memcpy(lon, c4 + 1, ol); }
|
|||
|
|
}
|
|||
|
|
U2_CopyIndex = 0; U2_CopyBuff[0] = 0; U2_CopyFlag = 0;
|
|||
|
|
|
|||
|
|
/* <20><>λ<EFBFBD><CEBB>Ч(fix!=1)<29><><EFBFBD>ֶ<EFBFBD>ȱʧ<C8B1><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѳ<EFBFBD><D1B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
if (fix != 1 || lat[0] == 0 || lon[0] == 0) {
|
|||
|
|
log_info("> GPS: δ<><CEB4>λ(run=%d fix=%d),<2C><><EFBFBD><EFBFBD>", run, fix);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* WGS-84 <20><> GCJ-02<30><32><EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>ڸߵµ<DFB5>ͼ */
|
|||
|
|
{
|
|||
|
|
double glon, glat;
|
|||
|
|
wgs84_to_gcj02(atof(lon), atof(lat), &glon, &glat);
|
|||
|
|
snprintf(lat, sizeof(lat), "%.6f", glat);
|
|||
|
|
snprintf(lon, sizeof(lon), "%.6f", glon);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log_info("> GPS: %s,%s", lon, lat); /* <20>ߵ<EFBFBD>/GeoJSON ϰ<>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ */
|
|||
|
|
CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.prop.post\\22,\\22body\\22:{\\22GPS\\22:\\22%s,%s\\22}}\"",
|
|||
|
|
MqttInfoStr.ClientID, lon, lat);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*==== Process ====*/
|
|||
|
|
void air780e_process(void){
|
|||
|
|
/* ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> MQTT <20><>Ϣ */
|
|||
|
|
while(U2_CopyFlag){
|
|||
|
|
U2_CopyFlag = 0;
|
|||
|
|
dispatch_one_mqtt_msg();
|
|||
|
|
}
|
|||
|
|
air780e_gps_poll();
|
|||
|
|
}
|
|||
|
|
|