2026-08-10 21:18:36 +08:00
# 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 ;
2026-08-18 19:26:06 +08:00
/*==== 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 ) ;
}
2026-08-10 21:18:36 +08:00
/*==== <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 ) {
2026-08-15 06:40:38 +08:00
g_net_ui_phase = NET_UI_4G_RESET ;
2026-08-10 21:18:36 +08:00
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_PP ; g . Pull = GPIO_NOPULL ; g . Speed = GPIO_SPEED_FREQ_LOW ;
HAL_GPIO_Init ( CAT_RST_PORT , & g ) ;
CAT_RST_HIGH ( ) ; HAL_Delay ( 1000 ) ; CAT_RST_LOW ( ) ;
for ( int i = 0 ; i < 40 ; i + + ) { IWDG_Feed ( ) ; HAL_Delay ( 100 ) ; } /* <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 ( ) ;
2026-08-15 07:27:30 +08:00
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> */
2026-08-10 21:18:36 +08:00
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 ;
2026-08-15 06:40:38 +08:00
g_net_ui_phase = NET_UI_4G_ATTACH ;
2026-08-10 21:18:36 +08:00
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
2026-08-15 17:50:38 +08:00
static char s_iccid [ 24 ] = { 0 } ; /* SIM <20> <> <EFBFBD> ţ<EFBFBD> MQTT OK <20> <> <EFBFBD> ϱ <EFBFBD> ƽ ̨ */
2026-08-10 21:18:36 +08:00
static int cat_connect_network ( void ) {
log_info ( " > 4G: <20> <> <EFBFBD> <EFBFBD> ... " ) ;
2026-08-15 06:40:38 +08:00
g_net_ui_phase = NET_UI_4G_AT ;
2026-08-10 21:18:36 +08:00
/* <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 ;
2026-08-15 06:40:38 +08:00
g_net_ui_phase = NET_UI_4G_SIM ; /* AT ͨ<> <CDA8> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ʼ <EFBFBD> <CABC> <EFBFBD> <EFBFBD> SIM/<2F> ź<EFBFBD> */
2026-08-10 21:18:36 +08:00
/* <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> <> " ) ;
2026-08-15 06:40:38 +08:00
g_net_ui_phase = NET_UI_4G_NOSIM ;
2026-08-10 21:18:36 +08:00
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 ;
}
2026-08-15 17:50:38 +08:00
/* <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 ;
2026-08-16 18:47:41 +08:00
while ( p [ n ] > = ' 0 ' & & p [ n ] < = ' 9 ' & & n < 19 ) n + + ; /* ֻȡ 19 λ<> <CEBB> <EFBFBD> ű<EFBFBD> <C5B1> 壬ĩλУ <CEBB> <D0A3> <EFBFBD> ַ<EFBFBD> (<28> <> <EFBFBD> <EFBFBD> ӡ<EFBFBD> <D3A1> <EFBFBD> <EFBFBD> ĸ)<29> <> <EFBFBD> ϴ<EFBFBD> */
2026-08-15 17:50:38 +08:00
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> " ) ;
}
2026-08-10 21:18:36 +08:00
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 ;
2026-08-18 19:26:06 +08:00
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> " ) ;
}
2026-08-10 21:18:36 +08:00
}
log_info ( " > 4G: <20> <> <EFBFBD> <EFBFBD> OK " ) ; return 0 ;
}
/*==== MQTT Connect ====*/
static int cat_connect_mqtt ( void ) {
2026-08-15 06:40:38 +08:00
g_net_ui_phase = NET_UI_4G_MQTT ;
2026-08-10 21:18:36 +08:00
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> ====*/
2026-08-16 19:14:20 +08:00
int air780e_mqtt_report ( const char * header , const char * ota_id , int val ) {
if ( ! header | | ! ota_id | | ! ota_id [ 0 ] ) return - 1 ;
2026-08-10 21:18:36 +08:00
static char cmd [ 300 ] ;
if ( strstr ( header , " progress " ) ) {
/* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϱ <EFBFBD> <CFB1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ˾<EFBFBD> <CBBE> <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 ) ;
CAT1_printf ( " %s " , cmd ) ;
2026-08-16 19:14:20 +08:00
return 0 ;
2026-08-10 21:18:36 +08:00
} 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) " ) ;
2026-08-16 19:14:20 +08:00
return - 1 ;
2026-08-10 21:18:36 +08:00
}
2026-08-16 19:14:20 +08:00
log_info ( " > OTA <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ϱ <EFBFBD> : success=%d " , val ) ;
return 0 ;
2026-08-10 21:18:36 +08:00
}
}
/*==== 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> " ) ;
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 ;
2026-08-18 15:47:58 +08:00
/* 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 ( ) ;
2026-08-10 21:18:36 +08:00
}
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 ;
2026-08-18 16:13:38 +08:00
/* ģ<> <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 ; }
2026-08-10 21:18:36 +08:00
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> 500 ms <EFBFBD> <EFBFBD> Ĭ β <EFBFBD> <EFBFBD> ÿ <EFBFBD> <EFBFBD> <EFBFBD> ֿ <EFBFBD> Լ ʡ 0.5 s */
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 ;
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_report ( " iot.ota.result.post " , ota_id , 1 ) ;
bg_delay ( 3000 ) ; /* <20> ȴ<EFBFBD> MQTT <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ϣ<EFBFBD> <CFA2> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ɺ<EFBFBD> <C9BA> ٸ<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> */
2026-08-16 19:14:20 +08:00
/* <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 )
2026-08-10 21:18:36 +08:00
{
W25Q64_OtaInfo info ;
2026-08-16 19:14:20 +08:00
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 ) ;
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> <> ) " ) ;
}
2026-08-10 21:18:36 +08:00
2026-08-16 19:14:20 +08:00
/* <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> */
2026-08-10 21:18:36 +08:00
char id_buf [ 24 ] = { 0 } ;
snprintf ( id_buf , sizeof ( id_buf ) , " %u " , info . new_version ) ; /* <20> ð汾<C3B0> <E6B1BE> <EFBFBD> <EFBFBD> Ϊ id <20> ϱ <EFBFBD> */
2026-08-16 19:14:20 +08:00
return NET_mqtt_report ( " iot.ota.confirm.post " , id_buf , 1 ) ;
2026-08-10 21:18:36 +08:00
}
/*==== Init ====*/
void air780e_init ( void ) {
log_info ( " > 4G: <20> <> ʼ <EFBFBD> <CABC> ... " ) ;
memset ( & mqtt_cfg , 0 , sizeof ( mqtt_cfg ) ) ;
strncpy ( mqtt_cfg . ClientID , MQTT_CLIENT_ID , sizeof ( mqtt_cfg . ClientID ) - 1 ) ;
strncpy ( mqtt_cfg . Username , MQTT_USERNAME , sizeof ( mqtt_cfg . Username ) - 1 ) ;
strncpy ( mqtt_cfg . Passward , MQTT_PASSWORD , sizeof ( mqtt_cfg . Passward ) - 1 ) ;
strncpy ( mqtt_cfg . ServerIP , MQTT_SERVER_IP , sizeof ( mqtt_cfg . ServerIP ) - 1 ) ;
mqtt_cfg . ServerPort = MQTT_SERVER_PORT ;
strncpy ( mqtt_cfg . Topic , MQTT_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 ) ;
2026-08-16 19:14:20 +08:00
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> */
2026-08-15 17:50:38 +08:00
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 ) ;
2026-08-16 19:14:20 +08:00
HAL_Delay ( 300 ) ;
2026-08-15 17:50:38 +08:00
}
2026-08-10 21:18:36 +08:00
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 ~ 600 m <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 )
{
2026-08-18 19:26:06 +08:00
if ( ! g_gps_on ) { s_gps_tick = 0 ; s_gps_first = 1 ; return ; } /* GPS0 <20> رն<D8B1> λ */
2026-08-10 21:18:36 +08:00
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 ( ) ;
}