#ifndef __CLOUDTASK_H
#define __CLOUDTASK_H
#include "task.h"
#include "queue.h"
#include "timers.h"
#define FRAME_DATA_LEN 512 // 帧数据最大长度
// 帧协议格式定义
typedef struct CloudComFrameStru
{
uint16_t frameHead; // 帧头
uint16_t frameLen; // 帧长度
uint16_t frameNo; // 帧序号
uint8_t frameMark; // 帧标志
uint8_t frameCmd; // 帧命令
uint8_t frameData[FRAME_DATA_LEN]; // 帧数据
uint16_t frameDataLen; // 帧数据长度
uint8_t frameCheck; // 帧校验
} CloudComFrame;
// 主控同wifi/bt通信任务
static TaskHandle_t taskHandleCloudCom = NULL;
// 帧流水号
// static uint16_t frameNo = 1; // 用于多帧连续发送
// 重发标志
static volatile uint8_t retryFlag = 0; // 0: 不需要重发 1: 需要重发
// 当前发送帧
static CloudComFrame curr_frame = {0};
// 主控给wifi/bt发送消息队列
static QueueHandle_t cloudComSendQueueHandle = NULL;
// Wifi/Bt给主控接收消息队列
// static QueueHandle_t cloudComRecvQueueHandle = NULL;
// 重发消息队列
static QueueHandle_t retryQueueHandle = NULL;
// 定时器
static TimerHandle_t heartPackTimerHandle; // 心跳定时器
static TimerHandle_t retryTimerHandle; // 重发定时器
static TimerHandle_t itvTimerHandle; // ITV定时器
static TimerHandle_t freqItvTimerHandle; // 频繁itv上报定时器
static TimerHandle_t reportSwitchTimerHandle;// 上报开关定时器
static volatile uint8_t retryCount = 0; // 重发计数器
static volatile uint8_t heartPackCount = 0; // 心跳计数器
// 联网状态和信号强度
typedef struct NetInfoStru
{
// 0: 未连接路由器 1: 一键配置中 2: AP模式 3: 连接路由器,但是没有连接云
// 4:连接路由器,并且连接云 5:连接上路由器,没有得到IP
uint8_t netStatus; // 联网状态
// D8: -40dBm
int16_t signalPower; // 信号强度
} NetInfo;
// 发送产品ID
typedef struct ProductIdStru
{
// 0: 成功 1: 失败
uint8_t result; // 录入产品ID结果
char proId[32]; // 产品ID
} ProductId;
// mac / version
typedef struct MacVerStru
{
uint8_t mac[6]; // mac
uint8_t ver[4]; // version
} MacVer;
// ITV类型中的I(Index)
typedef enum ENUM_ITV_ID
{
ITV_ID_DEVIC_TYPE = 1, ///主控类型 0x01
ITV_ID_DTC, /// Device Type Code 0x02
ITV_ID_INV_VERH, ///逆变器固件版本高位 0x03
ITV_ID_INV_VERM, ///逆变器固件版本中位 0x04
ITV_ID_INV_VERL, ///逆变器固件版本低位 0x05
ITV_ID_MAIN_VERH, ///主控固件版本高位 0x06
ITV_ID_MAIN_VERM, ///主控固件版本中位 0x07
ITV_ID_MAIN_VERL, ///主控固件版本低位 0x08
ITV_ID_HARD_VERH, ///主控硬件版本高位 0x09
ITV_ID_HARD_VERM, ///主控硬件版本中位 0x0A
ITV_ID_HARD_VERL, ///主控硬件版本低位 0x0B
ITV_ID_SN, ///主控序列号 0X0C
ITV_ID_INV_TYPE, ///逆变器类型 0X0D
ITV_ID_P_RATE, ///额定功率 0X0E
ITV_ID_INV_CAP_RATE, ///逆变器标称容量 0X0F
ITV_ID_INV_SLEEP_TIME, ///逆变器休眠时间设置//1-999分钟,默认720分钟 //最大26bit u16 0X10
ITV_ID_DISP_SLEEP_TIMER, ///屏幕休眠时间设置//0-60分钟,默认5分钟 u8//TODO 这个时间和背光延时区别? 0X11
ITV_ID_OUT_TYPE, ///输出电压类型 0X12
ITV_ID_FREQ_TYPE, ///输出频率类型 0X13
ITV_ID_CHARGE_IMAX, ///"Max Charge Current最大充电电流" //市电一致,没有混合充电 0X14
ITV_ID_CHARGE_VMAX, ///"Bulk Charge Volt充电恒压点" //没有 0X15
ITV_ID_CHARGE_VFLOAT, ///"Float Charge Volt充电浮充点" //没有 0X16
ITV_ID_ACCHARGE_IMAX, ///"Max Ac charge current最大市电充电电流" 0X17
ITV_ID_CHARGE_PMAX, ///"Max charge watt充电功率最大值" //没有 0X18
ITV_ID_BAT_OFF, ///"Bat cut off voltage or SOC关机电压或关机的电池容量" //0.1 0X19
ITV_ID_BLIGHT_DELAY, ///背光延时 //和背光熄灭的区别?//TODO 0X1A
ITV_ID_DNS, ///域名系统 //主控只读 0X1B
ITV_ID_IP, /// IP地址 //主控只读 0X1C
ITV_ID_PORT, ///端口号 //主控只读 0X1D
ITV_ID_MAC, /// Mac地址 //主控只读 0X1E
ITV_ID_REMOTE_IP, ///远端IP地址 //主控只读 0X1F
ITV_ID_REMOTE_PORT, ///远端端口号 //主控只读 0X20
ITV_ID_REMOTE_URL, ///远端域名 //主控只读 0X21
ITV_ID_SUB_MASK, ///子网掩码 //主控只读 0X22
ITV_ID_DEF_GATEWAY, ///默认网关 //主控只读 0X23
ITV_ID_BT_MAC, ///蓝牙的 MAC 地址 //主控只读 0X24
ITV_ID_BLE_TOKEN, ///蓝牙密钥 //主控只读 0X25
ITV_ID_WIFI_SSID, /// WIFI 模块要链接热点名称 //主控只读 0X26
ITV_ID_WIFI_PASSWORD, /// WIFI 模块要链接的热点密钥 //主控只读 0X27
ITV_ID_WIFI_CONFIG, /// WIFI 模块相关配置信息 //主控只读 0X28
ITV_ID_WIFI_MODE, /// Wifi 模式切换 //主控只读 0X29
ITV_ID_DHCP_EN, /// DHCP 使能 //主控只读 0X2A
ITV_ID_WIFI_STATE, /// Wifi 连接状态 //主控只读 0X2B
ITV_ID_OTA_URL, /// OTA升级路径 //主控只读 0X2C
ITV_ID_OTA_STEP, /// OTA升级进度 //TODO 0X2D
ITV_ID_OTA_STATE, /// OTA升级状态 0X2E
ITV_ID_RESET_EN, ///重启开关使能 //没有 0X2F
ITV_ID_FUNC_EN, ///功能开关 //错误自恢复是没有的 //屏蔽过载是禁止的 //关背光灯?//TODO只能开关蜂鸣器功能 0X30
ITV_ID_SYS_TIME, ///系统时间 //主控只读 0X31
ITV_ID_TIME_OFFSET, ///时区偏移 //主控只读 0X32
ITV_ID_FUNC_CMD, ///工作命令 //1是恢复出厂设置 0不管
ITV_ID_OUT_EN, ///输出开关 //TODO bit0 usb bit1 car 这个是模块是否使能 0X34
ITV_ID_NET_EN, ///网络开关 //?? 0X35
ITV_ID_SYS_STATE, ///系统状态机 //BUG 0X36
ITV_ID_P_IN_SUM, ///输入总功率 // 0X37
ITV_ID_V_ACIN, ///输入AC电源电压 // 0X38
ITV_ID_FREQ_ACIN, ///输入AC电源频率 // 0X39
ITV_ID_P_ACIN, ///"AC input watt (low)市电输入功率" // 0X3A
ITV_ID_V_PV, ///"PV1 voltagePV(光伏)电压" // 0X3B
ITV_ID_P_PV_CHARGE, ///"PV charge powerPV(光伏)充电功率" // 0X3C
ITV_ID_I_PV_CHARGE, ///"Buck1 currentPV充电电流" // 0X3D
ITV_ID_V_BAT, ///电池电压 // 0X3E
ITV_ID_SOC_BAT, ///电池容量百分比 //循环老化? 0X3F
ITV_ID_P_CHARGE_SUM, ///充电总功率 // 0X40
ITV_ID_I_CHARGE_SUM, ///充电总电流 // 0X41
ITV_ID_P_AC_CHARGE, ///市电充电功率 // 0X42
ITV_ID_I_AC_CHARGE, ///市电充电电流 // 0X43
ITV_ID_RELEASE_CHARGE_TIME, ///剩余充电时间 // 0X44
ITV_ID_ELEASE_DISCHARGE_TIME, ///剩余放电时间 // 0X45
ITV_ID_P_AC_DISCHARGE, ///市电放电功率 // 0X46
ITV_ID_P_BAT_DISCHARGE, ///电池放电功率 // 0X47
ITV_ID_I_BAT_DISCHARGE, ///电池放电电流 // 0X48
ITV_ID_P_BAT, ///电池功率 // 0X49
ITV_ID_P_OUT_SUM, ///输出总功率 // 0X4A
ITV_ID_I_OUT, ///输出电流 // 0X4B
ITV_ID_P_INV_OUT, ///逆变输出功率 // 0X4C
ITV_ID_I_INV_OUT, ///逆变输出电流 // 0X4D
ITV_ID_V_AC_OUT, ///输出AC电源电压 // 0X4E
ITV_ID_FREQ_AC_OUT, ///输出AC电源频率 // 0X4F
ITV_ID_SOC_LOAD, ///负载百分比 // 0X50
ITV_ID_V_CIGAR_LIGHTER, ///"Car voltage车充点烟器电压"//没有哦 0X51
ITV_ID_P_CIGAR_LIGHTER, ///"Car Watt车充点烟器功率"//没有哦 0X52
ITV_ID_I_V_CIGAR_LIGHTER, ///"Car Current车充点烟器电流" 0X53
ITV_ID_V_USB1, /// Usb1电压 0X54
ITV_ID_V_USB2, /// Usb2电压 0X55
ITV_ID_V_USB3, /// Usb3电压 0X56
ITV_ID_V_USB4, /// Usb4电压 0X57
ITV_ID_V_USB5, /// Usb5电压 0X58
ITV_ID_V_USB6, /// Usb6电压 0X59
ITV_ID_I_USB1, /// Usb1电流 0X5A
ITV_ID_I_USB2, /// Usb2电流 0X5B
ITV_ID_I_USB3, /// Usb3电流 0X5C
ITV_ID_I_USB4, /// Usb4电流 0X5D
ITV_ID_I_USB5, /// Usb5电流 0X5E
ITV_ID_I_USB6, /// Usb6电流 0X5F
ITV_ID_P_USB1, /// Usb1功率 0X60
ITV_ID_P_USB2, /// Usb2功率 0X61
ITV_ID_P_USB3, /// Usb3功率 0X62
ITV_ID_P_USB4, /// Usb4功率 0X63
ITV_ID_P_USB5, /// Usb5功率 0X64
ITV_ID_P_USB6, /// Usb6功率 0X65
ITV_ID_P_OP_DC, ///无线充电功率 0X66
ITV_ID_OUT_STATE, ///输出开关状态 //实际状态 0X67
ITV_ID_TEMP_INV, ///逆变散热片温度 0X68
ITV_ID_TEMP_BAT, ///电池内部温度 0X69
ITV_ID_TEMP_PD1, /// PD板1温度 0X6A
ITV_ID_TEMP_PD2, /// PD板2温度 0X6B
ITV_ID_TEMP_PV, /// PV(光伏)温度 0X6C
ITV_ID_TEMP_TR, ///变压器温度 0X6D
ITV_ID_TEMP_DC, ///"DC-DC Temperature电池散热片温度" 0X6E
ITV_ID_ERROR, ///错误码 0X6F
ITV_ID_WARNING, ///警告码 0X70
ITV_ID_ERROR_BMS, /// Bms出错 0X71
ITV_ID_BLIGHT_DUTY, // 背光占空比 0x72
ITV_ID_POWER_CMD, // 电源输出命令 0x73
ITV_ID_LED_STATE, // Led灯状态 0x74
ITV_ID_POWER_BOOST_EN, // 降额带载使能开关 0x75
ITV_ID_MAX, ///最大ID号
} ITV_ID;
// ITV帧数据构造定义
typedef struct ITV_INDEX_ARRAY_STRU
{
uint16_t indexArr[ITV_ID_MAX]; // 存放index数组
uint16_t indexArrLen; // index数组长度
} ITV_INDEX_ARRAY;
// ITV中的T(type)
typedef enum ENUM_ITV_TYPE
{
ITV_TYPE_STRING = 0, ///string
ITV_TYPE_U8, ///u8
ITV_TYPE_S16, ///s16
ITV_TYPE_S32, ///s32
ITV_TYPE_U16, ///u16
ITV_TYPE_U32, ///u32
ITV_TYPE_FLOAT, ///float
ITV_TYPE_S8, ///s8
ITV_TYPE_S8A, ///s8[]
ITV_TYPE_BOOL, ///bool
} ITV_TYPE;
#pragma pack(push) //数据压站
#pragma pack(1) //按BYTE对齐
typedef char tStringDef; ///字符串类型
typedef struct ITV_Stru ///itv数据结构
{
/* data */
uint16_t u16Index; ///itv的ID号
uint8_t u8Type; ///itv的数据类型
union
{
/* data */
tStringDef *ptStringData; ///字符串
uint8_t *pu8Data; ///无符号
int16_t *ps16Data;
int32_t *ps32Data;
uint16_t *pu16Data;
uint32_t *pu32Data;
float *pfData; ///浮点型
int8_t *ps8Data;
int8_t *pas8Data; 字节数组型
uint8_t *pbData; 布尔型
}upData; ///新数据
union
{
/* data */
tStringDef *ptStringData; ///字符串
uint8_t *pu8Data; ///无符号
int16_t *ps16Data;
int32_t *ps32Data;
uint16_t *pu16Data;
uint32_t *pu32Data;
float *pfData; ///浮点型
int8_t *ps8Data;
int8_t *pas8Data; 字节数组型
uint8_t *pbData; 布尔型
}lastData; ///旧数据
union
{
/* data */
tStringDef *ptStringData; ///字符串
uint8_t *pu8Data; ///无符号
int16_t *ps16Data;
int32_t *ps32Data;
uint16_t *pu16Data;
uint32_t *pu32Data;
float *pfData; ///浮点型
int8_t *ps8Data;
int8_t *pas8Data; 字节数组型
uint8_t *pbData; 布尔型
}setData; ///设置数据
} tITVDef;
typedef struct
{
/* data */
uint8_t u8DevicType; ///主控类型
uint16_t u16DTC; /// Device Type Code
uint16_t u16InvVerH; ///逆变器固件版本高位
uint16_t u16InvVerM; ///逆变器固件版本中位
uint16_t u16InvVerL; ///逆变器固件版本低位
uint16_t u16MainVerH; ///主控固件版本高位
uint16_t u16MainVerM; ///主控固件版本中位
uint16_t u16MainVerL; ///主控固件版本低位
uint16_t u16HardVerH; ///主控硬件版本高位
uint16_t u16HardVerM; ///主控硬件版本中位
uint16_t u16HardVerL; ///主控硬件版本低位
tStringDef tSN[32]; ///主控序列号
uint8_t u8InvType; ///逆变器类型
uint32_t u32PRate; ///额定功率
uint8_t u8InvNomCap; ///逆变器标称容量
uint16_t u16InvSleepTime; ///逆变器休眠时间设置
uint8_t u8DispSleepTime; ///屏幕休眠时间设置
uint8_t u8OutPowerType; ///输出电压类型
uint8_t u8OutFreqType; ///输出频率类型
uint16_t u16ChargeCurrMax; ///"Max Charge Current最大充电电流"
uint16_t u16ChargeVolt; ///"Bulk Charge Volt充电恒压点"
uint16_t u16FloatChargeVolt; ///"Float Charge Volt充电浮充点"
uint16_t u16IAcChargeCurrMax; ///"Max Ac charge current最大市电充电电流"
uint8_t u8PChargePowerMax; ///"Max charge watt充电功率最大值"
uint16_t u16SocBatOff; ///"Bat cut off voltage or SOC关机电压或关机的电池容量"
float fBLightDelay; ///背光延时
tStringDef tDNS[32]; ///域名系统
tStringDef tIP[32]; /// IP地址
tStringDef tPort[32]; ///端口号
tStringDef tMac[32]; /// Mac地址
tStringDef tRemoteIP[32]; ///远端IP地址
tStringDef tRemotePort[32]; ///远端端口号
tStringDef tRemoteURL[32]; ///远端域名
tStringDef tSubnetMask[32]; ///子网掩码
tStringDef tDefaultGateway[32]; ///默认网关
tStringDef tBTMAC[32]; ///蓝牙的 MAC 地址
tStringDef tBLETOKEN[32]; ///蓝牙密钥
tStringDef tWiFiSSID[32]; /// WIFI 模块要链接热点名称
tStringDef tWiFiPassword[32]; /// WIFI 模块要链接的热点密钥
tStringDef s8WiFiConfig[7]; /// WIFI 模块相关配置信息
uint8_t u8WifiMode; /// Wifi 模式切换
uint8_t u8DHCPEn; /// DHCP 使能
uint8_t u8WIFIConnectState; /// Wifi 连接状态
tStringDef tOTAURL[1]; /// OTA升级路径
uint8_t u8OTAStep; /// OTA升级进度
uint8_t u8OTAState; /// OTA升级状态
uint8_t u8RestartEn; ///重启开关使能
uint8_t u8FuncEN; ///功能开关
uint32_t u32SysTime; ///系统时间
int32_t s32TimeOffset; ///时区偏移
uint8_t u8CmdFunc; ///工作命令
uint8_t u8OutputEn; ///输出开关
uint16_t u16WifiBLESw; ///网络开关
uint8_t u8SysStatus; ///系统状态机
uint16_t u16PInSum; ///输入总功率
uint16_t u16VACIn; ///输入AC电源电压
uint16_t u16FreqACIn; ///输入AC电源频率
uint32_t u32PACIn; ///"AC input watt (low)市电输入功率"
uint16_t u16VPv1; ///"PV1 voltagePV(光伏)电压"
uint32_t u32PPvCharge; ///"PV charge powerPV(光伏)充电功率"
uint16_t u16IPvCharge; ///"Buck1 currentPV充电电流"
uint16_t u16VBat; ///电池电压
uint8_t u8BatSoc; ///电池容量百分比
uint16_t u16PChargeSum; ///充电总功率
uint16_t u16IChargeSum; ///充电总电流
uint32_t u32PACCharge; ///市电充电功率
uint16_t u16IACCharge; ///市电充电电流
uint16_t u16ReleaseChargeTime; ///剩余充电时间
uint16_t u16ReleaseDisChargeTime; ///剩余放电时间
uint32_t u32PACDisCharge; ///市电放电功率
uint32_t u32PBatDisCharge; ///电池放电功率
uint16_t u16IBatDisCharge; ///电池放电电流
uint32_t u32Pbat; ///电池功率
uint16_t u16POutSum; ///输出总功率
uint16_t u16Iout; ///输出电流
uint32_t u32PInvOut; ///逆变输出功率
uint16_t u16IInvOut; ///逆变输出电流
uint16_t u16VACOut; ///输出AC电源电压
uint16_t u16FreqACOut; ///输出AC电源频率
uint16_t u16LoadSoc; ///负载百分比
uint16_t u16VCarPower; ///"Car voltage车充点烟器电压"
uint16_t u16PCarPower; ///"Car Watt车充点烟器功率"
uint16_t u16ICarPower; ///"Car Current车充点烟器电流"
uint16_t u16VUsbOut1; /// Usb1电压
uint16_t u16VUsbOut2; /// Usb2电压
uint16_t u16VUsbOut3; /// Usb3电压
uint16_t u16VUsbOut4; /// Usb4电压
uint16_t u16VUsbOut5; /// Usb5电压
uint16_t u16VUsbOut6; /// Usb6电压
uint16_t u16IUsbOut1; /// Usb1电流
uint16_t u16IUsbOut2; /// Usb2电流
uint16_t u16IUsbOut3; /// Usb3电流
uint16_t u16IUsbOut4; /// Usb4电流
uint16_t u16IUsbOut5; /// Usb5电流
uint16_t u16IUsbOut6; /// Usb6电流
uint16_t u16PUsbOut1; /// Usb1功率
uint16_t u16PUsbOut2; /// Usb2功率
uint16_t u16PUsbOut3; /// Usb3功率
uint16_t u16PUsbOut4; /// Usb4功率
uint16_t u16PUsbOut5; /// Usb5功率
uint16_t u16PUsbOut6; /// Usb6功率
uint16_t u16POpDc; ///无线充电功率
uint8_t u8OutputStatus; ///输出开关状态
int16_t s16TempInv; ///逆变散热片温度
int16_t s16TempBat; ///电池内部温度
int16_t s16TempPD1; ///PD板1温度
int16_t s16TempPD2; ///PD板2温度
int16_t s16TempPV; ///PV(光伏)温度
int16_t s16TempTr; ///变压器温度
int16_t s16TempDc; ///"DC-DC Temperature电池散热片温度"
uint32_t u32ErrorBit; ///错误码
uint16_t u16ErrorBmsBit; /// Bms出错
uint32_t u32WarningBit; ///警告码
uint16_t u16BLightDuty; 背光占空比
uint8_t u8PowerCmd; 电源输出命令
uint8_t u8LedState; // Led灯状态
uint8_t u8PowerBoostEn; // 降额带载使能开关
} tVitaDataDef;
#pragma pack(pop) //恢复设置
// 配置SN
typedef struct SN_Stru
{
uint8_t result; // 配置SN
char snNo[32]; // 产品SN
} SN;
// 设置主控时间
typedef struct MainCtrlTimeStru
{
uint32_t utc;
int32_t timeOffset;
} MainCtrlTime;
// 配网模式
typedef struct ConfigNetModeStru
{
uint8_t mode; // 配网模式
} ConfigNetMode;
// 测试结果
typedef struct TestResultStru
{
// 0: wifi和ble测试失败 1: wifi测试失败 2:ble测试失败 3:wifi和ble测试成功
uint8_t testResult; // 测试结果
} TestResult;
// 主控版本
typedef struct MainCtrlVerStru
{
uint8_t softVer[4]; // 软件版本
uint8_t hardVer[4]; // 硬件版本
uint16_t devType; // 设备类型
} MainCtrlVer;
/*-----------------------------主控请求网络模块----------------------------------*/
// 主控发送配网指令
void startSetNet(uint8_t type);
// 查询联网状态和信号强度
void queryNetInfo(void);
// 获取联网状态和信号强度
NetInfo getNetInfo(CloudComFrame* frame);
// 构建产品id
void createProductId(uint8_t (*pd)[32]);
// 发送产品ID
void sendProductId(uint8_t* data, uint16_t dataLen);
// 获取发送产品ID结果
ProductId getProductResult(CloudComFrame* frame);
// 启动测试流程
void startTest(void);
// 重启网络模块
void restartNetModule(uint8_t u8Type);
// 恢复出厂设置
void factoryReset(uint8_t type);
// 查询mac地址和软件版本号
void queryMacAndSoftVer(void);
// 获取mac和version
MacVer getMacAndSoftVer(CloudComFrame* frame);
// 汇报ITV
void sendITV(uint8_t* data, uint16_t dataLen, uint16_t frameNo);
// 用于上报全部ITV数据,分割为FRAME_DATA_LEN的数据上报
ITV_INDEX_ARRAY getITV_Index_ArrayLimitDataLen(void);
/*-----------------------------------------------------------------------------
函数目的: 构造ITV数据
参数: data 返回ITV数据,所以该数据由调用者自己在外部定义,然后传参
indexArr 传入ITV_ID类型的数组
len 传入ITV_ID数组的实际大小
警告: 1、 调用该函数前,需要给ITV静态全局变量tVitaData赋值
2、 构造ITV数据的大小不能超过FRAME_DATA_LEN,调用者确保最终回传data不会超过FRAME_DATA_LEN
返回值: 成功: 1 失败: 0
-----------------------------------------------------------------------------*/
uint16_t Create_ITV_Data(uint8_t (*data)[FRAME_DATA_LEN], uint16_t indexArr[ITV_ID_MAX], uint16_t len);
// 获取网络时间
MainCtrlTime getNetTimeData(CloudComFrame* frame);
// 获取网络时间
void getNetTime(void);
// 创建SN
void createSN(uint8_t (*data)[32]);
// 配置SN
void setSN(uint8_t* data, uint16_t dataLen);
// 获取配置SN结果
SN getSN_Result(CloudComFrame* frame);
// 发送心跳包
void sendHeartPack(void);
// 查询产品ID
void queryProductId(void);
// 查询产品SN
void queryProductSN(void);
// 创建主控版本数据
void createMainCtrlVer(uint8_t (*data)[10]);
// 主控版本上报
void reportMainCtrlVer(uint8_t* data, uint16_t dataLen);
// 获取支持配网模式
ConfigNetMode getSupportNetMode(CloudComFrame* frame);
// 查询支持配网模式
void querySupportSetNetMode(void);
// 创建主控上行cmd+data
uint16_t createCmdData(uint8_t* srcData, uint8_t* dstData);
// 主控上行cmd+data
void sendMainCtrlCmdData(uint8_t* data, uint16_t dataLen);
// ITV数据状态变化更新上报,分割为FRAME_DATA_LEN的数据上报
ITV_INDEX_ARRAY getFreq_ITV_Index_ArrayLimitData(void);
// 状态变化更新指令
void sendStatusChange(uint8_t* data, uint16_t dataLen, uint16_t frameNo);
/*------------------------------------------网络模块请求主控---------------------------------------*/
// 回复网络模块查询主控状态
void responseForQueryMainCtrlStatus(void);
// 回复网络模块标准属性控制
void responseForPropertyCtrl(uint8_t* data, uint16_t dataLen);
// 解析网络模块ITV数据
ITV_INDEX_ARRAY parseNetModuleITV(uint8_t* data, uint16_t totalDataLen);
// 回复联网状态指令
void responseForNetStatus(void);
// 回复恢复出厂设置
void responseForFactoryReset(void);
// 回复设置主控时间
void responseForSetMainCtrlTime(void);
// 校验cmd+data数据合理性
uint8_t checkCmdDataValid(uint8_t* data, uint16_t dataLen);
// 回复网络模块cmd+data下行
void responseForCmdData(uint8_t result);
// 获取测试结果
TestResult getTestResult(CloudComFrame* frame);
// 回复网络模块发送测试结果
void responseForTest(void);
// 上传云端通信错误
void reportCloudCommErr(void);
// 查询主控版本
void responseMainCtrlVer(uint8_t* data, uint16_t dataLen);
/*---------------------------------------升级流程----------------------------------------------*/
// 通知主控有升级
void responseMainCtrlUpdate(uint8_t* data, uint16_t dataLen);
// 请求开始升级
void requestStartUpdate(uint8_t* data, uint16_t dataLen);
// 升级信息校验
uint8_t checkUpdateInfo(uint8_t *data);
// 请求发送升级数据包
void requestSendUpdatePack(uint8_t* data, uint16_t dataLen, uint16_t frameNo);
// 发送升级结果
void sendUpdateResult(uint8_t result);
// 回复升级结果
void responseUpdateResult(void);
/*-----------------------------------------通信初始化------------------------------------------*/
// 创建通信消息队列
void createCloudComMsgQueue(void);
// 串口0同wifi/bt通信任务
void vCloudComTaskHandleServer(void *pvParameters);
// 云通信任务初始化
void vCloudComTaskInit(void);
// 给wifi/bt发送数据
void sendDataToWifi(void);
// 接收wifi/bt的数据
void receiveWifiData(void);
// 解析帧数据
CloudComFrame parseFrameData(void);
// 帧校验
uint8_t frameCheck(uint8_t *data, uint16_t dataLen);
// 协议解析
void protocolParse(CloudComFrame* frame);
// 心跳包定时回调
void vHeartPackTimer(TimerHandle_t xTimer);
// 消息重发回调
void retryTimer(TimerHandle_t xTimer);
// itv定时回调
void itvTimer(TimerHandle_t xTimer);
// freq itv定时回调
void freqItvTimer(TimerHandle_t xTimer);
// 打开上报定时器开关
void openReportSwitchTimer(TimerHandle_t xTimer);
// 定时器初始化
void cloudComTimerInit(void);
// 打印帧数据
void printfFrame(CloudComFrame* frame, uint8_t isRecv);
// 小端数据转化为大端数据
void smallEndianToBigEndian(uint8_t* data, uint8_t dataLen);
// 帧数据大小端转换
void frameDataToBigEndian(CloudComFrame* frame);
// 上电初始化数据发送
void sendDataForStartUp(void);
// 获取升级类型 0:不在升级中 1: 主控升级中 2: wifi升级中
uint8_t getUpdateType(void);
#endif
/*********************************************************************
* 内容摘要: 主控同wifi通信处理
* 其它说明: 无
* 当前版本: V1.0
* 作 者:
* 完成日期: 2022/11/11
**********************************************************************/
#include "cloudTask.h"
#include "cloud_uart.h"
#include "log.h"
#include "cloudIap.h"
#include "main.h"
// 在cloudOpe.c中定义
extern void vSetItvData(uint8_t* itvData, uint16_t itvDataLen, uint8_t isResponse);
// ITV全局变量
tVitaDataDef tVitaData = {0};
// 上一次的ITV静态全局变量
static tVitaDataDef lastVitaData = {0};
// 记录设置的ITV静态全局变量
static tVitaDataDef stSetVitaData = {0};
// 联网信息
NetInfo netInfo = {0};
// 发送产品ID结果
ProductId productId = {0};
// mac和version
MacVer macVer = {0};
// 网络时间
MainCtrlTime netTime = {0};
// SN
SN sn = {0};
// 配网模式
ConfigNetMode netMode = {0};
// 测试结果
TestResult testResult = {0};
// 主控版本
MainCtrlVer mainCtrlVer = {0};
const tITVDef tITVDataDevice[] =
{
/*0x01*/ {ITV_ID_DEVIC_TYPE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8DevicType)}, {.pu8Data = &(lastVitaData.u8DevicType)}, {.pu8Data = &(stSetVitaData.u8DevicType)}}, ///主控类型
/*0x02*/ {ITV_ID_DTC, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16DTC)}, {.pu16Data = &(lastVitaData.u16DTC)}, {.pu16Data = &(stSetVitaData.u16DTC)}}, ///Device Type Code
/*0x03*/ {ITV_ID_INV_VERH, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16InvVerH)}, {.pu16Data = &(lastVitaData.u16InvVerH)}, {.pu16Data = &(stSetVitaData.u16InvVerH)}}, ///逆变器固件版本高位
/*0x04*/ {ITV_ID_INV_VERM, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16InvVerM)}, {.pu16Data = &(lastVitaData.u16InvVerM)}, {.pu16Data = &(stSetVitaData.u16InvVerM)}}, ///逆变器固件版本中位
/*0x05*/ {ITV_ID_INV_VERL, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16InvVerL)}, {.pu16Data = &(lastVitaData.u16InvVerL)}, {.pu16Data = &(stSetVitaData.u16InvVerL)}}, ///逆变器固件版本低位
/*0x06*/ {ITV_ID_MAIN_VERH, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16MainVerH)}, {.pu16Data = &(lastVitaData.u16MainVerH)}, {.pu16Data = &(stSetVitaData.u16MainVerH)}}, ///主控固件版本高位
/*0x07*/ {ITV_ID_MAIN_VERM, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16MainVerM)}, {.pu16Data = &(lastVitaData.u16MainVerM)}, {.pu16Data = &(stSetVitaData.u16MainVerM)}}, ///主控固件版本中位
/*0x08*/ {ITV_ID_MAIN_VERL, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16MainVerL)}, {.pu16Data = &(lastVitaData.u16MainVerL)}, {.pu16Data = &(stSetVitaData.u16MainVerL)}}, ///主控固件版本低位
/*0x09*/ {ITV_ID_HARD_VERH, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16HardVerH)}, {.pu16Data = &(lastVitaData.u16HardVerH)}, {.pu16Data = &(stSetVitaData.u16HardVerH)}}, ///主控硬件版本高位
/*0x0A*/ {ITV_ID_HARD_VERM, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16HardVerM)}, {.pu16Data = &(lastVitaData.u16HardVerM)}, {.pu16Data = &(stSetVitaData.u16HardVerM)}}, ///主控硬件版本中位
/*0x0B*/ {ITV_ID_HARD_VERL, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16HardVerL)}, {.pu16Data = &(lastVitaData.u16HardVerL)}, {.pu16Data = &(stSetVitaData.u16HardVerL)}}, ///主控硬件版本低位
/*0X0C*/ {ITV_ID_SN, ITV_TYPE_STRING, {.ptStringData = tVitaData.tSN}, {.ptStringData = lastVitaData.tSN}, {.ptStringData = stSetVitaData.tSN}}, ///主控序列号
/*0X0D*/ {ITV_ID_INV_TYPE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8InvType)}, {.pu8Data = &(lastVitaData.u8InvType)}, {.pu8Data = &(stSetVitaData.u8InvType)}}, ///逆变器类型
/*0X0E*/ {ITV_ID_P_RATE, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32PRate)}, {.pu32Data = &(lastVitaData.u32PRate)}, {.pu32Data = &(stSetVitaData.u32PRate)}}, ///额定功率
/*0X0F*/ {ITV_ID_INV_CAP_RATE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8InvNomCap)}, {.pu8Data = &(lastVitaData.u8InvNomCap)}, {.pu8Data = &(stSetVitaData.u8InvNomCap)}}, ///逆变器标称容量
/*0X10*/ {ITV_ID_INV_SLEEP_TIME, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16InvSleepTime)}, {.pu16Data = &(lastVitaData.u16InvSleepTime)}, {.pu16Data = &(stSetVitaData.u16InvSleepTime)}}, ///逆变器休眠时间设置
/*0X11*/ {ITV_ID_DISP_SLEEP_TIMER, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8DispSleepTime)}, {.pu8Data = &(lastVitaData.u8DispSleepTime)}, {.pu8Data = &(stSetVitaData.u8DispSleepTime)}}, ///屏幕休眠时间设置
/*0X12*/ {ITV_ID_OUT_TYPE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8OutPowerType)}, {.pu8Data = &(lastVitaData.u8OutPowerType)}, {.pu8Data = &(stSetVitaData.u8OutPowerType)}}, ///输出电压类型
/*0X13*/ {ITV_ID_FREQ_TYPE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8OutFreqType)}, {.pu8Data = &(lastVitaData.u8OutFreqType)}, {.pu8Data = &(stSetVitaData.u8OutFreqType)}}, ///输出频率类型
/*0X14*/ {ITV_ID_CHARGE_IMAX, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16ChargeCurrMax)}, {.pu16Data = &(lastVitaData.u16ChargeCurrMax)}, {.pu16Data = &(stSetVitaData.u16ChargeCurrMax)}}, ///"Max Charge Current最大充电电流"
/*0X15*/ {ITV_ID_CHARGE_VMAX, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16ChargeVolt)}, {.pu16Data = &(lastVitaData.u16ChargeVolt)}, {.pu16Data = &(stSetVitaData.u16ChargeVolt)}}, ///"Bulk Charge Volt充电恒压点"
/*0X16*/ {ITV_ID_CHARGE_VFLOAT, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16FloatChargeVolt)}, {.pu16Data = &(lastVitaData.u16FloatChargeVolt)}, {.pu16Data = &(stSetVitaData.u16FloatChargeVolt)}}, ///"Float Charge Volt充电浮充点"
/*0X17*/ {ITV_ID_ACCHARGE_IMAX, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IAcChargeCurrMax)}, {.pu16Data = &(lastVitaData.u16IAcChargeCurrMax)}, {.pu16Data = &(stSetVitaData.u16IAcChargeCurrMax)}}, ///"Max Ac charge current最大市电充电电流"
/*0X18*/ {ITV_ID_CHARGE_PMAX, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8PChargePowerMax)}, {.pu8Data = &(lastVitaData.u8PChargePowerMax)}, {.pu8Data = &(stSetVitaData.u8PChargePowerMax)}}, ///"Max charge watt充电功率最大值"
/*0X19*/ {ITV_ID_BAT_OFF, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16SocBatOff)}, {.pu16Data = &(lastVitaData.u16SocBatOff)}, {.pu16Data = &(stSetVitaData.u16SocBatOff)}}, ///"Bat cut off voltage or SOC关机电压或关机的电池容量"
/*0X1A*/ {ITV_ID_BLIGHT_DELAY, ITV_TYPE_FLOAT, {.pfData = &(tVitaData.fBLightDelay)}, {.pfData = &(lastVitaData.fBLightDelay)}, {.pfData = &(stSetVitaData.fBLightDelay)}}, ///背光延时
/*0X1B*/ {ITV_ID_DNS, ITV_TYPE_STRING, {.ptStringData = tVitaData.tDNS}, {.ptStringData = lastVitaData.tDNS}, {.ptStringData = stSetVitaData.tDNS}}, ///域名系统
/*0X1C*/ {ITV_ID_IP, ITV_TYPE_STRING, {.ptStringData = tVitaData.tIP}, {.ptStringData = lastVitaData.tIP}, {.ptStringData = stSetVitaData.tIP}}, ///IP地址
/*0X1D*/ {ITV_ID_PORT, ITV_TYPE_STRING, {.ptStringData = tVitaData.tPort}, {.ptStringData = lastVitaData.tPort}, {.ptStringData = stSetVitaData.tPort}}, ///端口号
/*0X1E*/ {ITV_ID_MAC, ITV_TYPE_STRING, {.ptStringData = tVitaData.tMac}, {.ptStringData = lastVitaData.tMac}, {.ptStringData = stSetVitaData.tMac}}, ///Mac地址
/*0X1F*/ {ITV_ID_REMOTE_IP, ITV_TYPE_STRING, {.ptStringData = tVitaData.tRemoteIP}, {.ptStringData = lastVitaData.tRemoteIP}, {.ptStringData = stSetVitaData.tRemoteIP}}, ///远端IP地址
/*0X20*/ {ITV_ID_REMOTE_PORT, ITV_TYPE_STRING, {.ptStringData = tVitaData.tRemotePort}, {.ptStringData = lastVitaData.tRemotePort}, {.ptStringData = stSetVitaData.tRemotePort}}, ///远端端口号
/*0X21*/ {ITV_ID_REMOTE_URL, ITV_TYPE_STRING, {.ptStringData = tVitaData.tRemoteURL}, {.ptStringData = lastVitaData.tRemoteURL}, {.ptStringData = stSetVitaData.tRemoteURL}}, ///远端域名
/*0X22*/ {ITV_ID_SUB_MASK, ITV_TYPE_STRING, {.ptStringData = tVitaData.tSubnetMask}, {.ptStringData = lastVitaData.tSubnetMask}, {.ptStringData = stSetVitaData.tSubnetMask}}, ///子网掩码
/*0X23*/ {ITV_ID_DEF_GATEWAY, ITV_TYPE_STRING, {.ptStringData = tVitaData.tDefaultGateway}, {.ptStringData = lastVitaData.tDefaultGateway}, {.ptStringData = stSetVitaData.tDefaultGateway}}, ///默认网关
/*0X24*/ {ITV_ID_BT_MAC, ITV_TYPE_STRING, {.ptStringData = tVitaData.tBTMAC}, {.ptStringData = lastVitaData.tBTMAC}, {.ptStringData = stSetVitaData.tBTMAC}}, ///蓝牙的 MAC 地址
/*0X25*/ {ITV_ID_BLE_TOKEN, ITV_TYPE_STRING, {.ptStringData = tVitaData.tBLETOKEN}, {.ptStringData = lastVitaData.tBLETOKEN}, {.ptStringData = stSetVitaData.tBLETOKEN}}, ///蓝牙密钥
/*0X26*/ {ITV_ID_WIFI_SSID, ITV_TYPE_STRING, {.ptStringData = tVitaData.tWiFiSSID}, {.ptStringData = lastVitaData.tWiFiSSID}, {.ptStringData = stSetVitaData.tWiFiSSID}}, ///WIFI 模块要链接热点名称
/*0X27*/ {ITV_ID_WIFI_PASSWORD, ITV_TYPE_STRING, {.ptStringData = tVitaData.tWiFiPassword}, {.ptStringData = lastVitaData.tWiFiPassword}, {.ptStringData = stSetVitaData.tWiFiPassword}}, ///WIFI 模块要链接的热点密钥
/*0X28*/ {ITV_ID_WIFI_CONFIG, ITV_TYPE_S8A, {.ptStringData = tVitaData.s8WiFiConfig}, {.ptStringData = lastVitaData.s8WiFiConfig}, {.ptStringData = stSetVitaData.s8WiFiConfig}}, ///WIFI 模块相关配置信息
/*0X29*/ {ITV_ID_WIFI_MODE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8WifiMode)}, {.pu8Data = &(lastVitaData.u8WifiMode)}, {.pu8Data = &(stSetVitaData.u8WifiMode)}}, ///Wifi 模式切换
/*0X2A*/ {ITV_ID_DHCP_EN, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8DHCPEn )}, {.pu8Data = &(lastVitaData.u8DHCPEn )}, {.pu8Data = &(stSetVitaData.u8DHCPEn )}}, ///DHCP 使能
/*0X2B*/ {ITV_ID_WIFI_STATE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8WIFIConnectState)}, {.pu8Data = &(lastVitaData.u8WIFIConnectState)}, {.pu8Data = &(stSetVitaData.u8WIFIConnectState)}}, ///Wifi 连接状态
/*0X2C*/ {ITV_ID_OTA_URL, ITV_TYPE_STRING, {.ptStringData = &(tVitaData.tOTAURL[0])}, {.ptStringData = &(lastVitaData.tOTAURL[0])}, {.ptStringData = &(stSetVitaData.tOTAURL[0])}}, ///OTA升级路径
/*0X2D*/ {ITV_ID_OTA_STEP, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8OTAStep)}, {.pu8Data = &(lastVitaData.u8OTAStep)}, {.pu8Data = &(stSetVitaData.u8OTAStep)}}, ///OTA升级进度
/*0X2E*/ {ITV_ID_OTA_STATE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8OTAState)}, {.pu8Data = &(lastVitaData.u8OTAState)}, {.pu8Data = &(stSetVitaData.u8OTAState)}}, ///OTA升级状态
/*0X2F*/ {ITV_ID_RESET_EN, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8RestartEn)}, {.pu8Data = &(lastVitaData.u8RestartEn)}, {.pu8Data = &(stSetVitaData.u8RestartEn)}}, ///重启开关使能
/*0X30*/ {ITV_ID_FUNC_EN, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8FuncEN)}, {.pu8Data = &(lastVitaData.u8FuncEN)}, {.pu8Data = &(stSetVitaData.u8FuncEN)}}, ///功能开关
/*0X31*/ {ITV_ID_SYS_TIME, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32SysTime)}, {.pu32Data = &(lastVitaData.u32SysTime)}, {.pu32Data = &(stSetVitaData.u32SysTime)}}, ///系统时间
/*0X32*/ {ITV_ID_TIME_OFFSET, ITV_TYPE_S32, {.ps32Data = &(tVitaData.s32TimeOffset)}, {.ps32Data = &(lastVitaData.s32TimeOffset)}, {.ps32Data = &(stSetVitaData.s32TimeOffset)}}, ///时区偏移
/*0X33*/ {ITV_ID_FUNC_CMD, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8CmdFunc)}, {.pu8Data = &(lastVitaData.u8CmdFunc)}, {.pu8Data = &(stSetVitaData.u8CmdFunc)}}, ///工作命令
/*0X34*/ {ITV_ID_OUT_EN, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8OutputEn)}, {.pu8Data = &(lastVitaData.u8OutputEn)}, {.pu8Data = &(stSetVitaData.u8OutputEn)}}, ///输出开关
/*0X35*/ {ITV_ID_NET_EN, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16WifiBLESw)}, {.pu16Data = &(lastVitaData.u16WifiBLESw)}, {.pu16Data = &(stSetVitaData.u16WifiBLESw)}}, ///网络开关
/*0X36*/ {ITV_ID_SYS_STATE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8SysStatus)}, {.pu8Data = &(lastVitaData.u8SysStatus)}, {.pu8Data = &(stSetVitaData.u8SysStatus)}}, ///系统状态机
/*0X37*/ {ITV_ID_P_IN_SUM, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PInSum)}, {.pu16Data = &(lastVitaData.u16PInSum)}, {.pu16Data = &(stSetVitaData.u16PInSum)}}, ///输入总功率
/*0X38*/ {ITV_ID_V_ACIN, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VACIn)}, {.pu16Data = &(lastVitaData.u16VACIn)}, {.pu16Data = &(stSetVitaData.u16VACIn)}}, ///输入AC电源电压
/*0X39*/ {ITV_ID_FREQ_ACIN, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16FreqACIn)}, {.pu16Data = &(lastVitaData.u16FreqACIn)}, {.pu16Data = &(stSetVitaData.u16FreqACIn)}}, ///输入AC电源频率
/*0X3A*/ {ITV_ID_P_ACIN, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32PACIn)}, {.pu32Data = &(lastVitaData.u32PACIn)}, {.pu32Data = &(stSetVitaData.u32PACIn)}}, ///"AC input watt (low)市电输入功率"
/*0X3B*/ {ITV_ID_V_PV, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VPv1)}, {.pu16Data = &(lastVitaData.u16VPv1)}, {.pu16Data = &(stSetVitaData.u16VPv1)}}, ///"PV1 voltagePV(光伏)电压"
/*0X3C*/ {ITV_ID_P_PV_CHARGE, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32PPvCharge)}, {.pu32Data = &(lastVitaData.u32PPvCharge)}, {.pu32Data = &(stSetVitaData.u32PPvCharge)}}, ///"PV charge powerPV(光伏)充电功率"
/*0X3D*/ {ITV_ID_I_PV_CHARGE, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IPvCharge)}, {.pu16Data = &(lastVitaData.u16IPvCharge)}, {.pu16Data = &(stSetVitaData.u16IPvCharge)}}, ///"Buck1 currentPV充电电流"
/*0X3E*/ {ITV_ID_V_BAT, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VBat)}, {.pu16Data = &(lastVitaData.u16VBat)}, {.pu16Data = &(stSetVitaData.u16VBat)}}, ///电池电压
/*0X3F*/ {ITV_ID_SOC_BAT, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8BatSoc)}, {.pu8Data = &(lastVitaData.u8BatSoc)}, {.pu8Data = &(stSetVitaData.u8BatSoc)}}, ///电池容量百分比
/*0X40*/ {ITV_ID_P_CHARGE_SUM, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PChargeSum)}, {.pu16Data = &(lastVitaData.u16PChargeSum)}, {.pu16Data = &(stSetVitaData.u16PChargeSum)}}, ///充电总功率
/*0X41*/ {ITV_ID_I_CHARGE_SUM, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IChargeSum)}, {.pu16Data = &(lastVitaData.u16IChargeSum)}, {.pu16Data = &(stSetVitaData.u16IChargeSum)}}, ///充电总电流
/*0X42*/ {ITV_ID_P_AC_CHARGE, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32PACCharge)}, {.pu32Data = &(lastVitaData.u32PACCharge)}, {.pu32Data = &(stSetVitaData.u32PACCharge)}}, ///市电充电功率
/*0X43*/ {ITV_ID_I_AC_CHARGE, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IACCharge)}, {.pu16Data = &(lastVitaData.u16IACCharge)}, {.pu16Data = &(stSetVitaData.u16IACCharge)}}, ///市电充电电流
/*0X44*/ {ITV_ID_RELEASE_CHARGE_TIME, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16ReleaseChargeTime)}, {.pu16Data = &(lastVitaData.u16ReleaseChargeTime)}, {.pu16Data = &(stSetVitaData.u16ReleaseChargeTime)}}, ///剩余充电时间
/*0X45*/ {ITV_ID_ELEASE_DISCHARGE_TIME, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16ReleaseDisChargeTime)}, {.pu16Data = &(lastVitaData.u16ReleaseDisChargeTime)}, {.pu16Data = &(stSetVitaData.u16ReleaseDisChargeTime)}}, ///剩余放电时间
/*0X46*/ {ITV_ID_P_AC_DISCHARGE, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32PACDisCharge)}, {.pu32Data = &(lastVitaData.u32PACDisCharge)}, {.pu32Data = &(stSetVitaData.u32PACDisCharge)}}, ///市电放电功率
/*0X47*/ {ITV_ID_P_BAT_DISCHARGE, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32PBatDisCharge)}, {.pu32Data = &(lastVitaData.u32PBatDisCharge)}, {.pu32Data = &(stSetVitaData.u32PBatDisCharge)}}, ///电池放电功率
/*0X48*/ {ITV_ID_I_BAT_DISCHARGE, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IBatDisCharge)}, {.pu16Data = &(lastVitaData.u16IBatDisCharge)}, {.pu16Data = &(stSetVitaData.u16IBatDisCharge)}}, ///电池放电电流
/*0X49*/ {ITV_ID_P_BAT, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32Pbat)}, {.pu32Data = &(lastVitaData.u32Pbat)}, {.pu32Data = &(stSetVitaData.u32Pbat)}}, ///电池功率
/*0X4A*/ {ITV_ID_P_OUT_SUM, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16POutSum)}, {.pu16Data = &(lastVitaData.u16POutSum)}, {.pu16Data = &(stSetVitaData.u16POutSum)}}, ///输出总功率
/*0X4B*/ {ITV_ID_I_OUT, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16Iout)}, {.pu16Data = &(lastVitaData.u16Iout)}, {.pu16Data = &(stSetVitaData.u16Iout)}}, ///输出电流
/*0X4C*/ {ITV_ID_P_INV_OUT, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32PInvOut)}, {.pu32Data = &(lastVitaData.u32PInvOut)}, {.pu32Data = &(stSetVitaData.u32PInvOut)}}, ///逆变输出功率
/*0X4D*/ {ITV_ID_I_INV_OUT, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IInvOut)}, {.pu16Data = &(lastVitaData.u16IInvOut)}, {.pu16Data = &(stSetVitaData.u16IInvOut)}}, ///逆变输出电流
/*0X4E*/ {ITV_ID_V_AC_OUT, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VACOut)}, {.pu16Data = &(lastVitaData.u16VACOut)}, {.pu16Data = &(stSetVitaData.u16VACOut)}}, ///输出AC电源电压
/*0X4F*/ {ITV_ID_FREQ_AC_OUT, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16FreqACOut)}, {.pu16Data = &(lastVitaData.u16FreqACOut)}, {.pu16Data = &(stSetVitaData.u16FreqACOut)}}, ///输出AC电源频率
/*0X50*/ {ITV_ID_SOC_LOAD, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16LoadSoc)}, {.pu16Data = &(lastVitaData.u16LoadSoc)}, {.pu16Data = &(stSetVitaData.u16LoadSoc)}}, ///负载百分比
/*0X51*/ {ITV_ID_V_CIGAR_LIGHTER, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VCarPower)}, {.pu16Data = &(lastVitaData.u16VCarPower)}, {.pu16Data = &(stSetVitaData.u16VCarPower)}}, ///"Car voltage车充点烟器电压"
/*0X52*/ {ITV_ID_P_CIGAR_LIGHTER, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PCarPower)}, {.pu16Data = &(lastVitaData.u16PCarPower)}, {.pu16Data = &(stSetVitaData.u16PCarPower)}}, ///"Car Watt车充点烟器功率"
/*0X53*/ {ITV_ID_I_V_CIGAR_LIGHTER, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16ICarPower)}, {.pu16Data = &(lastVitaData.u16ICarPower)}, {.pu16Data = &(stSetVitaData.u16ICarPower)}}, ///"Car Current车充点烟器电流"
/*0X54*/ {ITV_ID_V_USB1, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VUsbOut1)}, {.pu16Data = &(lastVitaData.u16VUsbOut1)}, {.pu16Data = &(stSetVitaData.u16VUsbOut1)}}, ///Usb1电压
/*0X55*/ {ITV_ID_V_USB2, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VUsbOut2)}, {.pu16Data = &(lastVitaData.u16VUsbOut2)}, {.pu16Data = &(stSetVitaData.u16VUsbOut2)}}, ///Usb2电压
/*0X56*/ {ITV_ID_V_USB3, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VUsbOut3)}, {.pu16Data = &(lastVitaData.u16VUsbOut3)}, {.pu16Data = &(stSetVitaData.u16VUsbOut3)}}, ///Usb3电压
/*0X57*/ {ITV_ID_V_USB4, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VUsbOut4)}, {.pu16Data = &(lastVitaData.u16VUsbOut4)}, {.pu16Data = &(stSetVitaData.u16VUsbOut4)}}, ///Usb4电压
/*0X58*/ {ITV_ID_V_USB5, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VUsbOut5)}, {.pu16Data = &(lastVitaData.u16VUsbOut5)}, {.pu16Data = &(stSetVitaData.u16VUsbOut5)}}, ///Usb5电压
/*0X59*/ {ITV_ID_V_USB6, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16VUsbOut6)}, {.pu16Data = &(lastVitaData.u16VUsbOut6)}, {.pu16Data = &(stSetVitaData.u16VUsbOut6)}}, ///Usb6电压
/*0X5A*/ {ITV_ID_I_USB1, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IUsbOut1)}, {.pu16Data = &(lastVitaData.u16IUsbOut1)}, {.pu16Data = &(stSetVitaData.u16IUsbOut1)}}, ///Usb1电流
/*0X5B*/ {ITV_ID_I_USB2, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IUsbOut2)}, {.pu16Data = &(lastVitaData.u16IUsbOut2)}, {.pu16Data = &(stSetVitaData.u16IUsbOut2)}}, ///Usb2电流
/*0X5C*/ {ITV_ID_I_USB3, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IUsbOut3)}, {.pu16Data = &(lastVitaData.u16IUsbOut3)}, {.pu16Data = &(stSetVitaData.u16IUsbOut3)}}, ///Usb3电流
/*0X5D*/ {ITV_ID_I_USB4, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IUsbOut4)}, {.pu16Data = &(lastVitaData.u16IUsbOut4)}, {.pu16Data = &(stSetVitaData.u16IUsbOut4)}}, ///Usb4电流
/*0X5E*/ {ITV_ID_I_USB5, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IUsbOut5)}, {.pu16Data = &(lastVitaData.u16IUsbOut5)}, {.pu16Data = &(stSetVitaData.u16IUsbOut5)}}, ///Usb5电流
/*0X5F*/ {ITV_ID_I_USB6, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16IUsbOut6)}, {.pu16Data = &(lastVitaData.u16IUsbOut6)}, {.pu16Data = &(stSetVitaData.u16IUsbOut6)}}, ///Usb6电流
/*0X60*/ {ITV_ID_P_USB1, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PUsbOut1)}, {.pu16Data = &(lastVitaData.u16PUsbOut1)}, {.pu16Data = &(stSetVitaData.u16PUsbOut1)}}, ///Usb1功率
/*0X61*/ {ITV_ID_P_USB2, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PUsbOut2)}, {.pu16Data = &(lastVitaData.u16PUsbOut2)}, {.pu16Data = &(stSetVitaData.u16PUsbOut2)}}, ///Usb2功率
/*0X62*/ {ITV_ID_P_USB3, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PUsbOut3)}, {.pu16Data = &(lastVitaData.u16PUsbOut3)}, {.pu16Data = &(stSetVitaData.u16PUsbOut3)}}, ///Usb3功率
/*0X63*/ {ITV_ID_P_USB4, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PUsbOut4)}, {.pu16Data = &(lastVitaData.u16PUsbOut4)}, {.pu16Data = &(stSetVitaData.u16PUsbOut4)}}, ///Usb4功率
/*0X64*/ {ITV_ID_P_USB5, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PUsbOut5)}, {.pu16Data = &(lastVitaData.u16PUsbOut5)}, {.pu16Data = &(stSetVitaData.u16PUsbOut5)}}, ///Usb5功率
/*0X65*/ {ITV_ID_P_USB6, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16PUsbOut6)}, {.pu16Data = &(lastVitaData.u16PUsbOut6)}, {.pu16Data = &(stSetVitaData.u16PUsbOut6)}}, ///Usb6功率
/*0X66*/ {ITV_ID_P_OP_DC, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16POpDc)}, {.pu16Data = &(lastVitaData.u16POpDc)}, {.pu16Data = &(stSetVitaData.u16POpDc)}}, ///无线充电功率
/*0X67*/ {ITV_ID_OUT_STATE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8OutputStatus)}, {.pu8Data = &(lastVitaData.u8OutputStatus)}, {.pu8Data = &(stSetVitaData.u8OutputStatus)}}, ///输出开关状态
/*0X68*/ {ITV_ID_TEMP_INV, ITV_TYPE_S16, {.ps16Data = &(tVitaData.s16TempInv)}, {.ps16Data = &(lastVitaData.s16TempInv)}, {.ps16Data = &(stSetVitaData.s16TempInv)}}, ///逆变散热片温度
/*0X69*/ {ITV_ID_TEMP_BAT, ITV_TYPE_S16, {.ps16Data = &(tVitaData.s16TempBat)}, {.ps16Data = &(lastVitaData.s16TempBat)}, {.ps16Data = &(stSetVitaData.s16TempBat)}}, ///电池内部温度
/*0X6A*/ {ITV_ID_TEMP_PD1, ITV_TYPE_S16, {.ps16Data = &(tVitaData.s16TempPD1)}, {.ps16Data = &(lastVitaData.s16TempPD1)}, {.ps16Data = &(stSetVitaData.s16TempPD1)}}, ///PD板1温度
/*0X6B*/ {ITV_ID_TEMP_PD2, ITV_TYPE_S16, {.ps16Data = &(tVitaData.s16TempPD2)}, {.ps16Data = &(lastVitaData.s16TempPD2)}, {.ps16Data = &(stSetVitaData.s16TempPD2)}}, ///PD板2温度
/*0X6C*/ {ITV_ID_TEMP_PV, ITV_TYPE_S16, {.ps16Data = &(tVitaData.s16TempPV)}, {.ps16Data = &(lastVitaData.s16TempPV)}, {.ps16Data = &(stSetVitaData.s16TempPV)}}, ///PV(光伏)温度
/*0X6D*/ {ITV_ID_TEMP_TR, ITV_TYPE_S16, {.ps16Data = &(tVitaData.s16TempTr)}, {.ps16Data = &(lastVitaData.s16TempTr)}, {.ps16Data = &(stSetVitaData.s16TempTr)}}, ///变压器温度
/*0X6E*/ {ITV_ID_TEMP_DC, ITV_TYPE_S16, {.ps16Data = &(tVitaData.s16TempDc)}, {.ps16Data = &(lastVitaData.s16TempDc)}, {.ps16Data = &(stSetVitaData.s16TempDc)}}, ///"DC-DC Temperature电池散热片温度"
/*0X6F*/ {ITV_ID_ERROR, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32ErrorBit)}, {.pu32Data = &(lastVitaData.u32ErrorBit)}, {.pu32Data = &(stSetVitaData.u32ErrorBit)}}, ///错误码
/*0X70*/ {ITV_ID_WARNING, ITV_TYPE_U32, {.pu32Data = &(tVitaData.u32WarningBit)}, {.pu32Data = &(lastVitaData.u32WarningBit)}, {.pu32Data = &(stSetVitaData.u32WarningBit)}}, ///警告码
/*0X71*/ {ITV_ID_ERROR_BMS, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16ErrorBmsBit)}, {.pu16Data = &(lastVitaData.u16ErrorBmsBit)}, {.pu16Data = &(stSetVitaData.u16ErrorBmsBit)}}, ///Bms出错
/*0x72*/ {ITV_ID_BLIGHT_DUTY, ITV_TYPE_U16, {.pu16Data = &(tVitaData.u16BLightDuty)},{.pu16Data = &(lastVitaData.u16BLightDuty)}, {.pu16Data = &(stSetVitaData.u16BLightDuty)}}, 背光占空比
/*0x73*/ {ITV_ID_POWER_CMD, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8PowerCmd)},{.pu8Data = &(lastVitaData.u8PowerCmd)},{.pu8Data = &(stSetVitaData.u8PowerCmd)}}, 电源输出命令
/*0x74*/ {ITV_ID_LED_STATE, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8LedState)},{.pu8Data = &(lastVitaData.u8LedState)},{.pu8Data = &(stSetVitaData.u8LedState)}}, // Led灯状态
/*0x75*/ {ITV_ID_POWER_BOOST_EN, ITV_TYPE_U8, {.pu8Data = &(tVitaData.u8PowerBoostEn)},{.pu8Data = &(lastVitaData.u8PowerBoostEn)},{.pu8Data = &(stSetVitaData.u8PowerBoostEn)}}, // 降额带载使能开关
{0}
};
extern uint8_t UART0_TX_BUF[UART0_TX_LEN];
extern uint8_t DMA_BUF_BUSY;
extern uint8_t UART0_RX_BUF[UART0_RX_LEN];
extern uint8_t UART0_RX_STAT;
extern uint32_t UART0_RX_NUM;
// ITV index
static uint16_t itv_index = ITV_ID_DEVIC_TYPE; // 用于ITV全部数据分段上报
// 升级信息
static UpdateInfo updateInfo = {0}; // 用于保存升级配置信息
// OTA 升级包接收长度
static uint32_t recvDataLen = 0;
// 升级类型 0: 不在升级中 01:主控 02:wifi
static volatile uint8_t updateType = 0; // 区分升级类型
// 是否已经擦除app备份区flash
static volatile uint8_t isBackUpAppErased = 0;
// 是否上报itv数据
static uint8_t isReportItv = 1; // 用于升级停止上报ITV数据
#define COMPARE_PART_DATA // 用于状态更新上报 0x81指令
#ifdef COMPARE_PART_DATA
static const ITV_INDEX_ARRAY constFreqItvIndexArray =
{
.indexArr =
{
ITV_ID_INV_SLEEP_TIME,
ITV_ID_DISP_SLEEP_TIMER,
ITV_ID_BLIGHT_DELAY,
ITV_ID_FREQ_TYPE,
ITV_ID_CHARGE_PMAX,
ITV_ID_BAT_OFF,
ITV_ID_FUNC_EN,
ITV_ID_FUNC_CMD,
ITV_ID_NET_EN,
ITV_ID_OUT_STATE,
ITV_ID_BLIGHT_DUTY,
ITV_ID_POWER_CMD,
ITV_ID_LED_STATE,
ITV_ID_POWER_BOOST_EN,
ITV_ID_ERROR,
ITV_ID_WARNING,
ITV_ID_ERROR_BMS
},
.indexArrLen = 17
};
#endif
// 状态频繁更新上报数组
static ITV_INDEX_ARRAY freqItvIndexArray = {0};
// 状态频繁更新上报数组index
static uint16_t freq_itv_index = 0;
/**********************************************************************
* 功能描述: 给wifi发送帧数据
* 输入参数: frame: 帧数据指针
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
static void sendQueueHandle(CloudComFrame *frame)
{
BaseType_t ret = xQueueSend(cloudComSendQueueHandle, frame, 60/portTICK_PERIOD_MS); // 队列满,等待60ms
if (ret != pdTRUE)
{
yl_printf("cloudComSendQueue Full!");
}
}
/**********************************************************************
* 功能描述: 给wifi发送帧数据,插入队列头部
* 输入参数: frame: 帧数据指针
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
static void sendQueueFrontHandle(CloudComFrame *frame)
{
BaseType_t ret = xQueueSendToFront(cloudComSendQueueHandle, frame, 60/portTICK_PERIOD_MS); // 队列满,等待60ms
if (ret != pdTRUE)
{
yl_printf("cloudComSendQueue Full!");
}
}
/**********************************************************************
* 功能描述: 主控发送配网指令
* 输入参数: type:{0x01: 一键配网 0x02: AP配网 0x06: WPS联网方式 0x07: 蓝牙配网}
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void startSetNet(uint8_t type)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 10;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x01;
frame.frameData[0] = type;
frame.frameDataLen = 1;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 查询联网状态和信号强度
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void queryNetInfo(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x02;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 获取联网状态和信号强度
* 输入参数: frame: 帧数据指针
* 输出参数: 无
* 返 回 值: 网络状态信息
* 其它说明: 无
***********************************************************************/
NetInfo getNetInfo(CloudComFrame* frame)
{
NetInfo data = {0};
if (frame->frameDataLen != 2)
{
yl_printf("getNetInfo Failed By Err: %d \r\n", frame->frameDataLen);
return data;
}
data.netStatus = frame->frameData[0];
data.signalPower = frame->frameData[1];
return data;
}
/**********************************************************************
* 功能描述: 构建产品id
* 输入参数: 无
* 输出参数: pd: 产品id字节数组
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void createProductId(uint8_t (*pd)[32])
{
if (pd == NULL)
{
return;
}
memcpy(&(*pd)[0], productId.proId, sizeof(productId.proId));
}
/**********************************************************************
* 功能描述: 发送产品ID
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void sendProductId(uint8_t* data, uint16_t dataLen)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x03;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 获取发送产品ID结果
* 输入参数: frame:帧数据指针
* 输出参数: 无
* 返 回 值: 产品ID信息
* 其它说明: 无
***********************************************************************/
ProductId getProductResult(CloudComFrame* frame)
{
ProductId data = {0};
if (frame->frameDataLen != 1)
{
yl_printf("getProductResult Failed By Err: %d \r\n", frame->frameDataLen);
return data;
}
data.result = frame->frameData[0];
return data;
}
/**********************************************************************
* 功能描述: 启动测试流程
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void startTest(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x04;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 重启网络模块
* 输入参数: u8Type, 1: 重启网络模块 2:整机关机 3: wifi关机
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void restartNetModule(uint8_t u8Type)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+1;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x05;
frame.frameData[0] = u8Type;
frame.frameDataLen = 1;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueFrontHandle(&frame);
}
/**********************************************************************
* 功能描述: 恢复出厂设置
* 输入参数: type: {bit0: 清除连接路由配置,连接默认路由;bit1: 清除网络模块云端绑定关系;
* bit2:清空网络模块下面子设备}
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void factoryReset(uint8_t type)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+1;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x06;
frame.frameData[0] = type;
frame.frameDataLen = 1;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 查询mac地址和软件版本号
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void queryMacAndSoftVer(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x07;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 获取mac和version
* 输入参数: frame:帧数据指针
* 输出参数: 无
* 返 回 值: Mac地址和版本信息
* 其它说明: 无
***********************************************************************/
MacVer getMacAndSoftVer(CloudComFrame* frame)
{
MacVer data = {0};
if (frame->frameDataLen != 10)
{
yl_printf("getMacAndSoftVer Failed By Err: %d \r\n", frame->frameDataLen);
return data;
}
memcpy(data.mac, frame->frameData, sizeof(data.mac));
memcpy(data.ver, &(frame->frameData[6]), sizeof(data.ver));
return data;
}
/**********************************************************************
* 功能描述: 汇报ITV
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度; frameNo: 帧序号
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void sendITV(uint8_t* data, uint16_t dataLen, uint16_t frameNo)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = frameNo;
frame.frameMark = 0x80;
frame.frameCmd = 0x08;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: ITV数据状态变化更新上报,分割为FRAME_DATA_LEN的数据上报
* 输入参数: 无
* 输出参数: 无
* 返 回 值: itv下标数组和数组实际长度
* 其它说明: 无
***********************************************************************/
ITV_INDEX_ARRAY getFreq_ITV_Index_ArrayLimitData(void)
{
ITV_INDEX_ARRAY info = {0};
uint16_t offset = 0;
for (; freq_itv_index < freqItvIndexArray.indexArrLen; ++freq_itv_index)
{
// index
uint16_t index = freqItvIndexArray.indexArr[freq_itv_index];
if ((offset+sizeof(index)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
offset += 2;
// type
uint8_t type = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].u8Type;
if ((offset+sizeof(type)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
offset += 1;
// value
uint16_t dataLen = 0;
switch (type) {
case ITV_TYPE_STRING:
// 数据长度
dataLen = strlen(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData);
if ((offset+sizeof(dataLen)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
offset += 2;
// 数据
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_U8:
dataLen = sizeof(uint8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_S16:
dataLen = sizeof(int16_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_S32:
dataLen = sizeof(int32_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_U16:
dataLen = sizeof(uint16_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_U32:
dataLen = sizeof(uint32_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_FLOAT:
dataLen = sizeof(float);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_S8:
dataLen = sizeof(int8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_S8A:
dataLen = strlen(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData);
if ((offset+sizeof(dataLen)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
offset += 2;
// 数据
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_BOOL:
dataLen = sizeof(uint8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = index;
info.indexArrLen++;
offset += dataLen;
break;
default:
break;
}
}
return info;
}
/**********************************************************************
* 功能描述: 用于上报全部ITV数据,分割为FRAME_DATA_LEN的数据上报
* 输入参数: 无
* 输出参数: 无
* 返 回 值: itv下标数组和数组实际长度
* 其它说明: 无
***********************************************************************/
ITV_INDEX_ARRAY getITV_Index_ArrayLimitDataLen(void)
{
ITV_INDEX_ARRAY info = {0};
uint16_t offset = 0;
for (; itv_index < ITV_ID_MAX; ++itv_index)
{
// index
if ((offset+sizeof(itv_index)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
offset += 2;
// type
uint8_t type = tITVDataDevice[itv_index-ITV_ID_DEVIC_TYPE].u8Type;
if ((offset+sizeof(type)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
offset += 1;
// value
uint16_t dataLen = 0;
switch (type) {
case ITV_TYPE_STRING:
// 数据长度
dataLen = strlen(tITVDataDevice[itv_index-ITV_ID_DEVIC_TYPE].upData.ptStringData);
if ((offset+sizeof(dataLen)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
offset += 2;
// 数据
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_U8:
dataLen = sizeof(uint8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_S16:
dataLen = sizeof(int16_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_S32:
dataLen = sizeof(int32_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_U16:
dataLen = sizeof(uint16_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_U32:
dataLen = sizeof(uint32_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_FLOAT:
dataLen = sizeof(float);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_S8:
dataLen = sizeof(int8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_S8A:
dataLen = strlen(tITVDataDevice[itv_index-ITV_ID_DEVIC_TYPE].upData.ptStringData);
if ((offset+sizeof(dataLen)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
offset += 2;
// 数据
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
case ITV_TYPE_BOOL:
dataLen = sizeof(uint8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return info;
}
info.indexArr[info.indexArrLen] = itv_index;
info.indexArrLen++;
offset += dataLen;
break;
default:
break;
}
}
return info;
}
/*-----------------------------------------------------------------------------
函数目的: 构造ITV数据
参数: data 返回ITV数据,所以该数据由调用者自己在外部定义,然后传参
indexArr 传入ITV_ID类型的数组
len 传入ITV_ID数组的实际大小
警告: 构造ITV数据的大小不能超过FRAME_DATA_LEN
返回值: 成功: 1 失败: 0
-----------------------------------------------------------------------------*/
uint16_t Create_ITV_Data(uint8_t (*data)[FRAME_DATA_LEN], uint16_t indexArr[ITV_ID_MAX], uint16_t len)
{
if (*data == NULL)
{
yl_printf("Create_ITV_Data Call Failed! \r\n");
return 0;
}
uint16_t i = 0;
uint16_t offset = 0;
memset(*data, 0, FRAME_DATA_LEN);
uint8_t arr[4] = {0};
for (; i < len; ++i)
{
uint16_t index = indexArr[i];
if (index < ITV_ID_DEVIC_TYPE || index >= ITV_ID_MAX)
{
return 0;
}
uint8_t type = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].u8Type;
if ((offset+sizeof(index)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
// index大小端转换
memcpy(arr, &index, sizeof(index));
smallEndianToBigEndian(arr, sizeof(index));
memcpy(&(*data)[offset], arr, sizeof(index));
offset += 2;
if ((offset+sizeof(type)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(&(*data)[offset], &type, sizeof(type));
offset += 1;
uint16_t dataLen = 0;
switch (type) {
case ITV_TYPE_STRING:
dataLen = strlen(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData);
if ((offset+sizeof(dataLen)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(arr, &dataLen, sizeof(dataLen));
smallEndianToBigEndian(arr, sizeof(dataLen));
memcpy(&(*data)[offset], arr, sizeof(dataLen));
offset += 2;
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(&(*data)[offset], tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData, dataLen);
offset += dataLen;
break;
case ITV_TYPE_U8:
dataLen = sizeof(uint8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(&(*data)[offset], tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu8Data, dataLen);
offset += dataLen;
break;
case ITV_TYPE_S16:
dataLen = sizeof(int16_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(arr, tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps16Data, dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(&(*data)[offset], arr, dataLen);
offset += dataLen;
break;
case ITV_TYPE_S32:
dataLen = sizeof(int32_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(arr, tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps32Data, dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(&(*data)[offset], arr, dataLen);
offset += dataLen;
break;
case ITV_TYPE_U16:
dataLen = sizeof(uint16_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(arr, tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu16Data, dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(&(*data)[offset], arr, dataLen);
offset += dataLen;
break;
case ITV_TYPE_U32:
dataLen = sizeof(uint32_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(arr, tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu32Data, dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(&(*data)[offset], arr, dataLen);
offset += dataLen;
break;
case ITV_TYPE_FLOAT:
dataLen = sizeof(float);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(arr, tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pfData, dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(&(*data)[offset], arr, dataLen);
offset += dataLen;
break;
case ITV_TYPE_S8:
dataLen = sizeof(int8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(&(*data)[offset], tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps8Data, dataLen);
offset += dataLen;
break;
case ITV_TYPE_S8A: // 将字节数组转化为字符串,用于确定数据长度
dataLen = strlen(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData);
if ((offset+sizeof(dataLen)) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(arr, &dataLen, sizeof(dataLen));
smallEndianToBigEndian(arr, sizeof(dataLen));
memcpy(&(*data)[offset], arr, sizeof(dataLen));
offset += 2;
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(&(*data)[offset], tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData, dataLen);
offset += dataLen;
break;
case ITV_TYPE_BOOL:
dataLen = sizeof(uint8_t);
if ((offset+dataLen) > FRAME_DATA_LEN) // 构造ITV数据的大小超过FRAME_DATA_LEN
{
return 0;
}
memcpy(&(*data)[offset], tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pbData, dataLen);
offset += dataLen;
break;
default:
break;
}
}
return offset;
}
/**********************************************************************
* 功能描述: 获取网络时间
* 输入参数: frame:帧数据指针
* 输出参数: 无
* 返 回 值: 网络时间信息
* 其它说明: 无
***********************************************************************/
MainCtrlTime getNetTimeData(CloudComFrame* frame)
{
MainCtrlTime data = {0};
if (frame->frameDataLen != 8)
{
yl_printf("getNetTimeData Failed By Err: %d \r\n", frame->frameDataLen);
return data;
}
data.utc = (frame->frameData[0] << 24) + (frame->frameData[1] << 16) +
(frame->frameData[2] << 8) + frame->frameData[3];
data.timeOffset = (frame->frameData[4] << 24) + (frame->frameData[5] << 16) +
(frame->frameData[6] << 8) + frame->frameData[7];
return data;
}
/**********************************************************************
* 功能描述: 获取网络时间
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void getNetTime(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x09;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 创建SN
* 输入参数: 无
* 输出参数: data:SN字节数组
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void createSN(uint8_t (*data)[32])
{
if (data == NULL)
{
return;
}
memcpy(&(*data)[0], sn.snNo, sizeof(sn.snNo));
}
/**********************************************************************
* 功能描述: 配置SN
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void setSN(uint8_t* data, uint16_t dataLen)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x0b;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 获取配置SN结果
* 输入参数: frame:帧数据指针
* 输出参数: 无
* 返 回 值: SN号
* 其它说明: 无
***********************************************************************/
SN getSN_Result(CloudComFrame* frame)
{
SN data = {0};
if (frame->frameDataLen != 1)
{
yl_printf("getSN_Result Failed By Err: %d \r\n", frame->frameDataLen);
return data;
}
data.result = frame->frameData[0];
return data;
}
/**********************************************************************
* 功能描述: 发送心跳包
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void sendHeartPack(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x0C;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 查询产品ID
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void queryProductId(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x10;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 查询产品SN
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void queryProductSN(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x11;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 创建主控版本数据
* 输入参数: 无
* 输出参数: data:主控版本字节数组
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void createMainCtrlVer(uint8_t (*data)[10])
{
if (data == NULL)
{
return;
}
uint8_t len = sizeof(mainCtrlVer.softVer);
memcpy(&(*data)[0], mainCtrlVer.softVer, len);
memcpy(&(*data)[len], mainCtrlVer.hardVer, sizeof(mainCtrlVer.hardVer));
len += sizeof(mainCtrlVer.hardVer);
// 设备类型大小端转化
uint8_t arr[2] = {0};
memcpy(arr, &mainCtrlVer.devType, 2);
smallEndianToBigEndian(arr, 2);
memcpy(&(*data)[len], arr, 2);
}
/**********************************************************************
* 功能描述: 主控版本上报
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void reportMainCtrlVer(uint8_t* data, uint16_t dataLen)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x13;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 获取支持配网模式
* 输入参数: frame:帧数据指针
* 输出参数: 无
* 返 回 值: 产品ID信息
* 其它说明: 无
***********************************************************************/
ConfigNetMode getSupportNetMode(CloudComFrame* frame)
{
ConfigNetMode data = {0};
if (frame->frameDataLen != 1)
{
yl_printf("getSupportNetMode Failed By Err: %d \r\n", frame->frameDataLen);
return data;
}
data.mode = frame->frameData[0];
return data;
}
/**********************************************************************
* 功能描述: 查询支持配网模式
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void querySupportSetNetMode(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x15;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 创建主控上行cmd+data
* 输入参数: srcData: 查询/设置参数itv字节数组
* 输出参数: dstData: itv实际数据字节数组
* 返 回 值: dstData字节数组长度
* 其它说明: 无
***********************************************************************/
uint16_t createCmdData(uint8_t* srcData, uint8_t* dstData)
{
uint8_t cmd = srcData[0];
uint16_t dstDataLen = 0;
ITV_INDEX_ARRAY indexArray = {0};
if (cmd == 0x03 || cmd == 0x04) // 查询itv数据
{
uint8_t paraNum = srcData[1];
// 填充index
uint8_t i = 0;
for (; i < paraNum; ++i)
{
indexArray.indexArr[i] = (srcData[2+i*2] << 8) + srcData[3+i*2];
}
indexArray.indexArrLen = paraNum;
}
else if (cmd == 0x06) // 设置单个itv数据
{
indexArray.indexArr[0] = (srcData[2]<<8)+srcData[3];
indexArray.indexArrLen = 1;
}
// 构造目标数据
uint8_t data[FRAME_DATA_LEN] = {0};
uint16_t dataLen = Create_ITV_Data(&data, indexArray.indexArr, indexArray.indexArrLen);
if ((dataLen > 0) && (dataLen < FRAME_DATA_LEN)) // 构造数据成功
{
dstData[0] = cmd;
memcpy(&dstData[1], data, dataLen);
dstDataLen = dataLen+1;
}
else // 需要查询/设置的index数据过多
{
yl_printf("0x80 srcData index num over!");
}
return dstDataLen;
}
/**********************************************************************
* 功能描述: 主控上行cmd+data
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void sendMainCtrlCmdData(uint8_t* data, uint16_t dataLen)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0x80;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 状态变化更新指令
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度; frameNo: 帧序号
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void sendStatusChange(uint8_t* data, uint16_t dataLen, uint16_t frameNo)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = frameNo;
frame.frameMark = 0x80;
frame.frameCmd = 0x81;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 回复网络模块查询主控状态
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseForQueryMainCtrlStatus(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x82;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 解析网络模块ITV数据
* 输入参数: data: 帧数据字节数组; totalDataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: itv下标数组和数组实际长度
* 其它说明: 无
***********************************************************************/
ITV_INDEX_ARRAY parseNetModuleITV(uint8_t* data, uint16_t totalDataLen)
{
uint16_t offset = 0;
uint16_t dataLen = 0;
ITV_INDEX_ARRAY indexArrInfo = {0};
while (offset < totalDataLen)
{
if ((offset+sizeof(uint16_t)) > totalDataLen)
{
return indexArrInfo;
}
// itv index
uint16_t index = (data[offset] << 8) + data[offset+1];
if (index < ITV_ID_DEVIC_TYPE || index >= ITV_ID_MAX)
{
return indexArrInfo;
}
offset += 2;
if ((offset+sizeof(uint8_t)) > totalDataLen)
{
return indexArrInfo;
}
uint8_t type = data[offset];
offset += 1;
uint8_t arr[4] = {0};
switch (type) {
case ITV_TYPE_STRING:
dataLen = (data[offset] << 8) + data[offset+1];
if ((offset+sizeof(dataLen)) > totalDataLen)
{
return indexArrInfo;
}
offset += 2;
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.ptStringData, &data[offset], dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_U8:
dataLen = sizeof(uint8_t);
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.pu8Data, &data[offset], dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_S16:
dataLen = sizeof(int16_t);
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(arr, &data[offset], dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.ps16Data, arr, dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_S32:
dataLen = sizeof(int32_t);
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(arr, &data[offset], dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.ps32Data, arr, dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_U16:
dataLen = sizeof(uint16_t);
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(arr, &data[offset], dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.pu16Data, arr, dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_U32:
dataLen = sizeof(uint32_t);
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(arr, &data[offset], dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.pu32Data, arr, dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_FLOAT:
dataLen = sizeof(float);
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(arr, &data[offset], dataLen);
smallEndianToBigEndian(arr, dataLen);
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.pfData, arr, dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_S8:
dataLen = sizeof(int8_t);
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.ps8Data, &data[offset], dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_S8A:
dataLen = (data[offset] << 8) + data[offset+1];
if ((offset+sizeof(dataLen)) > totalDataLen)
{
return indexArrInfo;
}
offset += 2;
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.ptStringData, &data[offset], dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
case ITV_TYPE_BOOL:
dataLen = sizeof(uint8_t);
if ((offset+dataLen) > totalDataLen)
{
return indexArrInfo;
}
memcpy(tITVDataDevice[index-ITV_ID_DEVIC_TYPE].setData.pbData, &data[offset], dataLen);
offset += dataLen;
// 存储index
indexArrInfo.indexArr[indexArrInfo.indexArrLen] = index;
indexArrInfo.indexArrLen++;
break;
default:
break;
}
}
return indexArrInfo;
}
/**********************************************************************
* 功能描述: 回复网络模块标准属性控制
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseForPropertyCtrl(uint8_t* data, uint16_t dataLen)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x83;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 回复联网状态指令
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseForNetStatus(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x84;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 回复恢复出厂设置
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseForFactoryReset(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x86;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 回复设置主控时间
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseForSetMainCtrlTime(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x87;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 校验cmd+data数据合理性
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 0: 成功 1:无相关cmd 2:data长度错误
* 其它说明: 无
***********************************************************************/
uint8_t checkCmdDataValid(uint8_t* data, uint16_t dataLen)
{
if (dataLen < 4) // 数据长度不对
{
return 2; // data长度错误
}
uint8_t cmd = data[0];
uint8_t paraNum = data[1];
if ((cmd == 0x03) || (cmd == 0x04)) // 查询ITV参数
{
if (1+1+paraNum*2 != dataLen)
{
return 2;
}
}
else if (cmd == 0x06) // 设置ITV数据
{
if (1+1+paraNum != dataLen) {
return 2;
}
vSetItvData(&data[2], (uint16_t)paraNum, 0);
}
else
{
return 1; // 无相关cmd
}
return 0; // 成功
}
/**********************************************************************
* 功能描述: 回复网络模块cmd+data下行
* 输入参数: result:{0: 成功 1:无相关cmd 2:data长度错误}
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseForCmdData(uint8_t result)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 10;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x8A;
frame.frameData[0] = result;
frame.frameDataLen = 1;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 获取测试结果
* 输入参数: frame:帧数据指针
* 输出参数: 无
* 返 回 值: 测试结果
* 其它说明: 无
***********************************************************************/
TestResult getTestResult(CloudComFrame* frame)
{
TestResult data = {0};
if (frame->frameDataLen != 1)
{
yl_printf("getTestResult Failed By Err: %d \r\n", frame->frameDataLen);
return data;
}
data.testResult = frame->frameData[0];
return data;
}
/**********************************************************************
* 功能描述: 回复网络模块发送测试结果
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseForTest(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x8C;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 上传云端通信错误
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void reportCloudCommErr(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x8F;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 查询主控版本
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseMainCtrlVer(uint8_t* data, uint16_t dataLen)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x91;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 通知主控有升级
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseMainCtrlUpdate(uint8_t* data, uint16_t dataLen)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = 1;
frame.frameMark = 0x40;
frame.frameCmd = 0x8D;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 升级信息校验
* 输入参数: data: 帧数据字节数组
* 输出参数: 无
* 返 回 值: 0:成功 1:失败
* 其它说明: 无
***********************************************************************/
uint8_t checkUpdateInfo(uint8_t *data)
{
updateInfo.headFlag = (data[0] << 24) + (data[1] << 16) +
(data[2] << 8) + data[3];
updateInfo.totalFrameNum = (data[4] << 24) + (data[5] << 16) +
(data[6] << 8) + data[7];
updateInfo.updateFileSize = (data[8] << 24) + (data[9] << 16) +
(data[10] << 8) + data[11];
updateInfo.crc32Check = (data[12] << 24) + (data[13] << 16) +
(data[14] << 8) + data[15];
// 判断头部标识,记录升级配置信息
if (updateInfo.headFlag == UPDATE_HEAD_FLAG)
{
updateInfo.flag = 1;
return 0; // 成功
}
return 1; // 失败
}
/**********************************************************************
* 功能描述: 请求开始升级
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void requestStartUpdate(uint8_t* data, uint16_t dataLen)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0xE0;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 请求发送升级数据包
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度; frameNo: 帧序号
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void requestSendUpdatePack(uint8_t* data, uint16_t dataLen, uint16_t frameNo)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9+dataLen;
frame.frameNo = frameNo;
frame.frameMark = 0x80;
frame.frameCmd = 0xE1;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, data, dataLen);
frame.frameDataLen = dataLen;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 发送升级结果
* 输入参数: result: {0:升级成功 1:升级失败,校验失败 2: 升级失败,数据长度不对}
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void sendUpdateResult(uint8_t result)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 10;
frame.frameNo = 1;
frame.frameMark = 0x80;
frame.frameCmd = 0xE2;
frame.frameData[0] = result;
frame.frameDataLen = 1;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 回复升级结果
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void responseUpdateResult(void)
{
CloudComFrame frame;
frame.frameHead = 0xAA55;
frame.frameLen = 9;
frame.frameNo = 0;
frame.frameMark = 0x40;
frame.frameCmd = 0xE2;
frame.frameDataLen = 0;
frame.frameCheck = frameCheck((uint8_t*)&frame, frame.frameLen);
sendQueueHandle(&frame);
}
/**********************************************************************
* 功能描述: 帧数据大小端转换
* 输入参数: frame:帧数据指针
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void frameDataToBigEndian(CloudComFrame* frame)
{
uint8_t arr[4];
uint16_t offset = 0;
// 帧头
uint16_t len = sizeof(frame->frameHead);
memcpy(arr, &frame->frameHead, len);
smallEndianToBigEndian(arr, len);
memcpy(UART0_TX_BUF+offset, arr, len);
offset += len;
// 帧长度
len = sizeof(frame->frameLen);
memcpy(arr, &frame->frameLen, len);
smallEndianToBigEndian(arr, len);
memcpy(UART0_TX_BUF+offset, arr, len);
offset += len;
// 帧序号
len = sizeof(frame->frameNo);
memcpy(arr, &frame->frameNo, len);
smallEndianToBigEndian(arr, len);
memcpy(UART0_TX_BUF+offset, arr, len);
offset += len;
// 帧标志
len = sizeof(frame->frameMark);
memcpy(UART0_TX_BUF+offset, &frame->frameMark, len);
offset += len;
// 帧命令
len = sizeof(frame->frameCmd);
memcpy(UART0_TX_BUF+offset, &frame->frameCmd, len);
offset += len;
// 帧数据
len = frame->frameDataLen;
memcpy(UART0_TX_BUF+offset, frame->frameData, len);
offset += len;
// 帧校验字
len = sizeof(frame->frameCheck);
memcpy(UART0_TX_BUF+offset, &frame->frameCheck, len);
offset += len;
}
/**********************************************************************
* 功能描述: 给wifi/bt发送数据
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void sendDataToWifi(void)
{
if (DMA_BUF_BUSY == 0) // Uart0 Tx空闲
{
BaseType_t xReturn = pdFALSE;
CloudComFrame frame = {0};
// 如果上一条数据发送成功,则取出队列中的下一条数据, 否则重发数据
if (retryFlag == 0)
{
xReturn = xQueueReceive(cloudComSendQueueHandle, &frame, 0);
if (xReturn == pdTRUE)
{
DMA_BUF_BUSY = 1;
// 帧数据大小端转换
memset(UART0_TX_BUF, 0, sizeof(UART0_TX_BUF));
frameDataToBigEndian(&frame);
/* 设置DMA传输 */
dma_channel_disable(DMA0, DMA_CH3); /* 关闭DMA传输才可以进行设置 */
dma_memory_address_config(DMA0, DMA_CH3, (uint32_t)UART0_TX_BUF);
dma_transfer_number_config(DMA0, DMA_CH3, frame.frameLen);
dma_channel_enable(DMA0, DMA_CH3); /* 开启DMA传输 */
if (frame.frameCmd != 0x0C &&
frame.frameCmd != 0x82 &&
frame.frameCmd != 0x83 &&
frame.frameCmd != 0x84 &&
frame.frameCmd != 0x86 &&
frame.frameCmd != 0x87 &&
frame.frameCmd != 0x8A &&
frame.frameCmd != 0x8C &&
frame.frameCmd != 0x8F &&
frame.frameCmd != 0x91 &&
frame.frameCmd != 0x8D &&
frame.frameCmd != 0xE0 &&
frame.frameCmd != 0xE1 &&
frame.frameCmd != 0xE2) // 非心跳包、非回复包
{
retryFlag = 1;
// 将当前发送帧保存
memcpy(&curr_frame, &frame, sizeof(frame));
// 开启重发定时器
retryCount = 0;
BaseType_t xReturn = xTimerStart(retryTimerHandle, 0);
if (xReturn == pdFALSE)
{
yl_printf("Start Retry Timer Failed!");
}
}
}
}
else // 定时器里不能做耗时发送动作,所以创建重发消息队列
{
xReturn = xQueueReceive(retryQueueHandle, &frame, 0);
if (xReturn == pdTRUE)
{
frameDataToBigEndian(&frame);
/* 设置DMA传输 */
dma_channel_disable(DMA0, DMA_CH3); /* 关闭DMA传输才可以进行设置 */
dma_memory_address_config(DMA0, DMA_CH3, (uint32_t)UART0_TX_BUF);
dma_transfer_number_config(DMA0, DMA_CH3, frame.frameLen);
dma_channel_enable(DMA0, DMA_CH3); /* 开启DMA传输 */
}
}
// 打印发送帧数据
if (frame.frameHead == 0xAA55)
{
printfFrame(&frame, 0);
}
}
}
/**********************************************************************
* 功能描述: 协议解析
* 输入参数: frame: 帧数据指针
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void protocolParse(CloudComFrame* frame)
{
printfFrame(frame, 1);
if (frame->frameCmd == 0x0C) // 心跳包
{
heartPackCount = 0;
return;
}
else if (frame->frameCmd == 0x01) // 配网指令
{
return;
}
else if (frame->frameCmd == 0x02) // 查询联网状态及信号强度
{
NetInfo data = getNetInfo(frame);
netInfo.netStatus = data.netStatus;
netInfo.signalPower = data.signalPower;
}
else if (frame->frameCmd == 0x03) // 发送产品ID
{
ProductId data = getProductResult(frame);
productId.result = data.result;
}
else if (frame->frameCmd == 0x04) // 启动测试流程
{
return;
}
else if (frame->frameCmd == 0x05) // 重启网络模块
{
return;
}
else if (frame->frameCmd == 0x06) // 恢复出厂设置
{
return;
}
else if (frame->frameCmd == 0x07) // 查询mac地址和软件版本号
{
MacVer data = getMacAndSoftVer(frame);
memcpy(macVer.mac, data.mac, sizeof(data.mac));
memcpy(macVer.ver, data.ver, sizeof(data.ver));
}
else if (frame->frameCmd == 0x08) // 汇报ITV
{
// 汇报后续ITV
if (itv_index >= ITV_ID_MAX)
{
return;
}
// 汇报第 N 条ITV数据
uint8_t data[FRAME_DATA_LEN] = {0};
ITV_INDEX_ARRAY info = getITV_Index_ArrayLimitDataLen();
uint16_t dataLen = Create_ITV_Data(&data, info.indexArr, info.indexArrLen);
if (dataLen > 0)
{
uint16_t frameNo = frame->frameNo;
sendITV(data, dataLen, frameNo+1);
}
return;
}
else if (frame->frameCmd == 0x09) // 获取网络时间
{
MainCtrlTime data = getNetTimeData(frame);
netTime.utc = data.utc;
netTime.timeOffset = data.timeOffset;
}
else if (frame->frameCmd == 0x0B) // 配置SN
{
SN data = getSN_Result(frame);
sn.result = data.result;
}
else if (frame->frameCmd == 0x10) // 查询产品ID
{
memcpy(productId.proId, frame->frameData, frame->frameDataLen);
}
else if (frame->frameCmd == 0x11) // 查询产品SN
{
memcpy(sn.snNo, frame->frameData, frame->frameDataLen);
}
else if (frame->frameCmd == 0x13) // 主控版本上报
{
return;
}
else if (frame->frameCmd == 0x15) // 查询支持的配网模式
{
ConfigNetMode data = getSupportNetMode(frame);
netMode.mode = data.mode;
}
else if (frame->frameCmd == 0x80) // 主控上行cmd+data
{
return;
}
else if (frame->frameCmd == 0x81) // 状态变化更新指令
{
// 上报后续状态更新ITV数据
if (freq_itv_index >= freqItvIndexArray.indexArrLen)
{
return;
}
// 上报第 N 条 频繁上报itv数据
uint8_t data[FRAME_DATA_LEN] = {0};
ITV_INDEX_ARRAY info = getFreq_ITV_Index_ArrayLimitData();
uint16_t dataLen = Create_ITV_Data(&data, info.indexArr, info.indexArrLen);
if (dataLen > 0)
{
uint16_t frameNo = frame->frameNo;
sendStatusChange(data, dataLen, frameNo+1);
}
return;
}
else if (frame->frameCmd == 0x82) // 网络模块获取主控状态
{
// 初始化 itv_index
itv_index = ITV_ID_DEVIC_TYPE;
// 回复收到指令
responseForQueryMainCtrlStatus();
// 汇报第一条ITV数据
uint8_t data[FRAME_DATA_LEN] = {0};
ITV_INDEX_ARRAY info = getITV_Index_ArrayLimitDataLen();
uint16_t dataLen = Create_ITV_Data(&data, info.indexArr, info.indexArrLen);
if (dataLen > 0)
{
sendITV(data, dataLen, 1);
}
return;
}
else if (frame->frameCmd == 0x83) // 网络模块标准属性控制指令
{
if (frame->frameDataLen > FRAME_DATA_LEN)
{
yl_printf("0x83 data Len more than %d", FRAME_DATA_LEN);
return;
}
vSetItvData(frame->frameData, frame->frameDataLen, 1);
}
else if (frame->frameCmd == 0x84) // 联网状态指令
{
// 更新联网状态对象
NetInfo data = getNetInfo(frame);
netInfo.netStatus = data.netStatus;
netInfo.signalPower = data.signalPower;
// 回复收到指令
responseForNetStatus();
}
else if (frame->frameCmd == 0x86) // 恢复出厂设置
{
responseForFactoryReset();
}
else if (frame->frameCmd == 0x87) // 设置主控时间
{
// 更新网络时间
MainCtrlTime data = getNetTimeData(frame);
netTime.utc = data.utc;
netTime.timeOffset = data.timeOffset;
// 回复收到指令
responseForSetMainCtrlTime();
}
else if (frame->frameCmd == 0x8A) // 网络模块cmd+data下行
{
// 校验数据,回复收到指令
uint8_t result = checkCmdDataValid(frame->frameData, frame->frameDataLen);
responseForCmdData(result);
// 根据cmd类型回复对应数据
if (result == 0) // cmd数据正确
{
uint8_t dstData[FRAME_DATA_LEN];
uint16_t dstDataLen = createCmdData(frame->frameData, dstData);
if (dstDataLen > 0)
{
sendMainCtrlCmdData(dstData, dstDataLen);
}
}
}
else if (frame->frameCmd == 0x8C) // 网络模块发送测试结果
{
// 更新测试结果对象
TestResult data = getTestResult(frame);
testResult.testResult = data.testResult;
// 回复收到指令
responseForTest();
}
else if (frame->frameCmd == 0x8F) // 上传云端通信错误
{
reportCloudCommErr();
}
else if (frame->frameCmd == 0x91) // 查询主控版本
{
uint8_t data[10] = {0};
createMainCtrlVer(&data);
responseMainCtrlVer(data, sizeof(data));
return;
}
else if (frame->frameCmd == 0x8D) // 通知主控有升级
{
isBackUpAppErased = 0; // 重新擦除App备份区flash
if (frame->frameDataLen < 1)
{
yl_printf("0x8D dataLen: %d less than 1!");
return;
}
updateType = frame->frameData[0];
extern uint8_t isCanUpdate(void);
uint8_t ret = isCanUpdate();
// 主控允许升级或者wifi有升级,电量充足
if ((ret == 0 && updateType == 1) || (updateType == 2 && ret != 1))
{
// 关闭上报定时器
isReportItv = 0;
// 重新打开上报开关超时定时器
xTimerStart(reportSwitchTimerHandle, 0);
}
else
{
updateType = 0; // 不在升级中
}
if (updateType == 2) // wifi升级只有0,1两种状态
{
if (ret != 1) // 非电量低,wifi允许升级
{
ret = 0;
}
}
responseMainCtrlUpdate(&ret, 1);
}
else if (frame->frameCmd == 0xE0) // 请求开始升级
{
if (frame->frameDataLen < 16)
{
yl_printf("0xE0 request update dataLen < 16 !");
return;
}
uint8_t ret = checkUpdateInfo(frame->frameData);
if (ret == 0) // 校验成功
{
// 短时间重复擦除flash会导致mcu重启
if (isBackUpAppErased == 0) // App备份区flash未被擦除过
{
// 擦除flash
fmcErasePages(FMC_WRITE_START_ADDR, FMC_WRITE_END_ADDR);
ret = checkEraseFlash(FMC_WRITE_START_ADDR, FMC_WRITE_END_ADDR);
if (ret == 1) // 擦除flash失败
{
yl_printf("Erase BackUp APP Failed!");
}
isBackUpAppErased = 1;
resetWriteStartAddr(); // 为写升级数据做准备
}
}
else
{ // 校验失败
updateType = 0; // 不在升级中
// 开启上报定时器
isReportItv = 1;
}
requestStartUpdate(&ret, 1);
}
else if (frame->frameCmd == 0xE1) // 请求发送升级数据包
{
if (frame->frameNo == 1) { // 第一帧
recvDataLen = 0;
}
// 防止多帧重复发送,导致计算升级帧字节长度出错
float lastFrameNo = recvDataLen * 1.0 / FRAME_DATA_LEN;
if (frame->frameNo >= (lastFrameNo + 1))
{
recvDataLen += frame->frameDataLen;
}
uint8_t ret;
if (frame->frameNo < updateInfo.totalFrameNum) // 前n帧升级数据包
{
if (frame->frameDataLen != FRAME_DATA_LEN)
{
yl_printf("frameNo: %d, frameDataLen: %d is less than %d", frame->frameNo, frame->frameDataLen, FRAME_DATA_LEN);
ret = 1;
requestSendUpdatePack(&ret, 1, frame->frameNo);
return;
}
ret = 0;
// 写升级包flash
fmcWriteFromRecvUart(frame->frameData, frame->frameDataLen);
requestSendUpdatePack(&ret, 1, frame->frameNo);
}
else if (frame->frameNo == updateInfo.totalFrameNum) // 最后一帧升级数据包
{
ret = 0;
// 写升级包flash
fmcWriteFromRecvUart(frame->frameData, frame->frameDataLen);
requestSendUpdatePack(&ret, 1, frame->frameNo);
yl_printf("____recvLen:%d______totalSize:%d_______", recvDataLen, updateInfo.updateFileSize);
if (recvDataLen != updateInfo.updateFileSize)
{
sendUpdateResult(2); // 升级数据长度不对
updateType = 0; // 不在升级中
return;
}
// 开始校验升级结果
uint32_t result = 0;
crc32Check(FMC_WRITE_START_ADDR, updateInfo.updateFileSize, &result);
if (result == updateInfo.crc32Check) // crc32校验成功
{
// 写升级配置flash
fmcErasePages(UPDATE_CONFIG_START_ADDR, UPDATE_CONFIG_END_ADDR);
ret = checkEraseFlash(UPDATE_CONFIG_START_ADDR, UPDATE_CONFIG_END_ADDR);
if (ret == 1)
{
yl_printf("Erase Update Info Failed!");
}
fmcWrite(UPDATE_CONFIG_START_ADDR, (uint8_t *)&updateInfo, sizeof(UpdateInfo));
UpdateInfo info = (*(volatile UpdateInfo *)UPDATE_CONFIG_START_ADDR);
if (memcmp(&updateInfo, &info, sizeof(UpdateInfo)) == 0) // 升级配置信息写入成功
{
yl_printf("/-----------------Update Success----------------/");
sendUpdateResult(0); // 升级成功
}
else
{
yl_printf("write update info failed!");
sendUpdateResult(1); // 升级失败,校验失败
updateType = 0; // 不在升级中
}
}
else
{
yl_printf("crc check failed!");
sendUpdateResult(1); // 升级失败,校验失败
updateType = 0; // 不在升级中
}
}
else // 帧序号大于总帧数
{
ret = 1;
yl_printf("frameNo: %d more than totalFrameNum: %d !", frame->frameNo, updateInfo.totalFrameNum);
requestSendUpdatePack(&ret, 1, frame->frameNo);
}
}
else if (frame->frameCmd == 0xE2) // 发送升级结果
{
responseUpdateResult();
if (frame->frameDataLen > 0)
{
uint8_t result = frame->frameData[0];
if (updateType == 1 && result == 0) // 主控升级成功
{
// 重启主控
__set_FAULTMASK(1);
//NVIC_SystemReset();
//修改为正常关机,因为硬件问题,复位和正常关机时一样的
vApiMachineModeQueueWrite(eIdxMachineWorkModeDown);
}
else
{
isReportItv = 1;
}
}
updateType = 0; // 不在升级中
}
// 通知底层,数据有变化
// xQueueSend(cloudComRecvQueueHandle, frame, 0);
}
/**********************************************************************
* 功能描述: 帧校验
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 帧校验结果
* 其它说明: 无
***********************************************************************/
uint8_t frameCheck(uint8_t *data, uint16_t dataLen)
{
uint16_t i = 0;
uint8_t checkCode = 0;
for (; i < dataLen-1; ++i)
{
checkCode += data[i];
}
return (checkCode ^ 0x33);
}
/**********************************************************************
* 功能描述: 解析帧数据
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 帧数据
* 其它说明: 无
***********************************************************************/
CloudComFrame parseFrameData(void)
{
CloudComFrame frame;
frame.frameHead = (UART0_RX_BUF[0] << 8) + UART0_RX_BUF[1];
frame.frameLen = (UART0_RX_BUF[2] << 8) + UART0_RX_BUF[3];
frame.frameNo = (UART0_RX_BUF[4] << 8) + UART0_RX_BUF[5];
frame.frameMark = UART0_RX_BUF[6];
frame.frameCmd = UART0_RX_BUF[7];
if ((UART0_RX_NUM - 9) > 0)
{
frame.frameDataLen = UART0_RX_NUM-9;
memset(frame.frameData, 0, sizeof(frame.frameData));
memcpy(frame.frameData, &UART0_RX_BUF[8], frame.frameDataLen);
}
else
{
frame.frameDataLen = 0;
}
frame.frameCheck = UART0_RX_BUF[UART0_RX_NUM-1];
return frame;
}
/**********************************************************************
* 功能描述: 接收wifi/bt的数据
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void receiveWifiData(void)
{
if (UART0_RX_STAT > 0) // 接收到数据
{
UART0_RX_STAT = 0;
// printfHex(UART0_RX_BUF, UART0_RX_NUM);
if (UART0_RX_NUM >= 9 && UART0_RX_NUM <= (FRAME_DATA_LEN+9)) // 指令长度9-1024
{
CloudComFrame frame = parseFrameData();
uint16_t frameHead = frame.frameHead;
uint8_t frameCode = frame.frameCheck;
uint8_t frameCheckCode = frameCheck(UART0_RX_BUF, UART0_RX_NUM);
if (frameHead == 0xAA55 && frameCode == frameCheckCode)
{
retryFlag = 0; // 成功接收到数据,不需要重发
BaseType_t xReturn = pdFALSE;
xReturn = xTimerStop(retryTimerHandle, 0);
if (xReturn == pdFALSE) // 重发定时器停止失败
{
yl_printf("Stop Retry Timer Failed!");
}
// 协议解析
protocolParse(&frame);
}
else
{
if (frameHead != 0xAA55)
{
yl_printf("Cloud Comm Parse Protocol Failed! Frame Head Err: 0X%04X \r\n", frameHead);
}
if (frameCode != frameCheckCode)
{
yl_printf("Cloud Comm Parse Protocol Failed! Frame Check Err: frameCode: 0x%02X, frameCheck: 0x%02X \r\n", frameCode, frameCheckCode);
}
}
}
else
{
yl_printf("Recv Uart0 DataLen Error! Err: %d", UART0_RX_NUM);
}
}
}
/**********************************************************************
* 功能描述: 串口0同wifi/bt通信任务
* 输入参数: pvParameters: 系统参数不使用
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void vCloudComTaskHandleServer(void *pvParameters)
{
while (1)
{
sendDataToWifi();
receiveWifiData();
vTaskDelay(60/portTICK_PERIOD_MS); // 延时60ms
// size_t freeHeapSize = xPortGetFreeHeapSize();
// UBaseType_t taskFreeSize = uxTaskGetStackHighWaterMark(taskHandleCloudCom);
// yl_printf("____freeHeap:%d_________", freeHeapSize);
// yl_printf("____freeTask:%d_________", taskFreeSize);
}
}
/**********************************************************************
* 功能描述: 云通讯任务初始化
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void vCloudComTaskInit(void)
{
BaseType_t xReturned;
xReturned = xTaskCreate((TaskFunction_t)vCloudComTaskHandleServer,
(const char *)"cloud communication server",
(uint16_t)800,
(void *)NULL,
(UBaseType_t)4,
(TaskHandle_t *)&taskHandleCloudCom);
if (xReturned == pdFAIL)
{
yl_printf("Cloud Communication Task Create Failed! \r\n");
}
}
/**********************************************************************
* 功能描述: 创建通信消息队列
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void createCloudComMsgQueue(void)
{
cloudComSendQueueHandle = xQueueCreate(4, sizeof(CloudComFrame));
if (cloudComSendQueueHandle == NULL)
{
yl_printf("Create Cloud Comm Send MsgQueue Failed! \r\n");
}
// cloudComRecvQueueHandle = xQueueCreate(4, sizeof(CloudComFrame));
// if (cloudComRecvQueueHandle == NULL) {
// yl_printf("Create Cloud Comm Recv MsgQueue Failed! \r\n");
// }
retryQueueHandle = xQueueCreate(3, sizeof(CloudComFrame));
if (retryQueueHandle == NULL)
{
yl_printf("Create Cloud Comm Retry MsgQueue Failed! \r\n");
}
}
/**********************************************************************
* 功能描述: 心跳包定时回调 10s发送一次
* 输入参数: xTimer: 系统参数不使用
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void vHeartPackTimer(TimerHandle_t xTimer)
{
if (heartPackCount >= 2) // 串口通信异常
{
BaseType_t xReturn = xTimerStop(heartPackTimerHandle, 0);
if (xReturn == pdFALSE) // 重发定时器停止失败
{
yl_printf("Stop Heart Pack Timer Failed!");
}
}
// 升级过程中,不发心跳包
if (isReportItv == 0)
{
return;
}
sendHeartPack();
heartPackCount++;
}
/**********************************************************************
* 功能描述: 消息重发回调
* 输入参数: xTimer: 系统参数不使用
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void retryTimer(TimerHandle_t xTimer)
{
if (retryCount < 2)
{ // 重发2次
retryCount++;
xQueueSendToFront(retryQueueHandle, &curr_frame, 0);
}
else
{
retryCount = 0;
retryFlag = 0;
BaseType_t xReturn = xTimerStop(retryTimerHandle, 0);
if (xReturn == pdFALSE) // 重发定时器停止失败
{
yl_printf("Stop Retry Timer Failed!");
}
}
}
/**********************************************************************
* 功能描述: itv定时回调
* 输入参数: xTimer: 系统参数不使用
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void itvTimer(TimerHandle_t xTimer)
{
if (isReportItv == 0)
{
return;
}
// 初始化 itv_index
itv_index = ITV_ID_DEVIC_TYPE;
// 汇报第一条ITV数据
uint8_t data[FRAME_DATA_LEN] = {0};
ITV_INDEX_ARRAY info = getITV_Index_ArrayLimitDataLen();
uint16_t dataLen = Create_ITV_Data(&data, info.indexArr, info.indexArrLen);
if (dataLen > 0)
{
sendITV(data, dataLen, 1);
}
}
/**********************************************************************
* 功能描述: itv全局数据改变
* 输入参数: 无
* 输出参数: 无
* 返 回 值: itv设置参数是否改变 ,1:改变 0:未改变
* 其它说明: 无
***********************************************************************/
static uint8_t isChangedForFreqItvData(void)
{
#ifdef COMPARE_PART_DATA
uint16_t i = 0;
for (; i < constFreqItvIndexArray.indexArrLen; ++i)
{
uint16_t index = constFreqItvIndexArray.indexArr[i];
uint8_t type = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].u8Type;
void* newVal = NULL;
void* oldVal = NULL;
// 用于浮点数据类型
float fNewVal = 0;
float fOldVal = 0;
uint32_t u32NewVal = 0;
uint32_t u32OldVal = 0;
switch (type) {
case ITV_TYPE_STRING:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ptStringData;
if (strcmp((char*)newVal, (char*)oldVal) != 0) // 当前值不同
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
strcpy((char*)oldVal, (char*)newVal);
}
break;
case ITV_TYPE_U8:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu8Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pu8Data;
if ((*(uint8_t*)newVal) != (*(uint8_t*)oldVal))
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(uint8_t*)oldVal) = (*(uint8_t*)newVal);
}
break;
case ITV_TYPE_S16:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps16Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ps16Data;
if ((*(int16_t*)newVal) != (*(int16_t*)oldVal))
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(int16_t*)oldVal) = (*(int16_t*)newVal);
}
break;
case ITV_TYPE_S32:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps32Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ps32Data;
if ((*(int32_t*)newVal) != (*(int32_t*)oldVal))
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(int32_t*)oldVal) = (*(int32_t*)newVal);
}
break;
case ITV_TYPE_U16:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu16Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pu16Data;
if ((*(uint16_t*)newVal) != (*(uint16_t*)oldVal))
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(uint16_t*)oldVal) = (*(uint16_t*)newVal);
}
break;
case ITV_TYPE_U32:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu32Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pu32Data;
if ((*(uint32_t*)newVal) != (*(uint32_t*)oldVal))
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(uint32_t*)oldVal) = (*(uint32_t*)newVal);
}
break;
case ITV_TYPE_FLOAT:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pfData;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pfData;
memcpy(&fNewVal, newVal, sizeof(float));
memcpy(&fOldVal, oldVal, sizeof(float));
u32NewVal = fNewVal*100;
u32OldVal = fOldVal*100;
if ((u32NewVal-u32OldVal) != 0)
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
memcpy(oldVal, newVal, sizeof(float));
}
break;
case ITV_TYPE_S8:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps8Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ps8Data;
if ((*(int8_t*)newVal) != (*(int8_t*)oldVal))
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(int8_t*)oldVal) = (*(int8_t*)newVal);
}
break;
case ITV_TYPE_S8A:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ptStringData;
if (strcmp((char*)newVal, (char*)oldVal) != 0) // 当前值不同
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
strcpy((char*)oldVal, (char*)newVal);
}
break;
case ITV_TYPE_BOOL:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pbData;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pbData;
if ((*(uint8_t*)newVal) != (*(uint8_t*)oldVal))
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(uint8_t*)oldVal) = (*(uint8_t*)newVal);
}
break;
default:
break;
}
};
if (freqItvIndexArray.indexArrLen > 0)
{ // itv数据有变化
return 1;
}
return 0;
#else
uint16_t index = ITV_ID_DEVIC_TYPE;
for (; index < ITV_ID_MAX; ++index) {
uint8_t type = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].u8Type;
void* newVal = NULL;
void* oldVal = NULL;
// 用于浮点数据类型
float fNewVal = 0;
float fOldVal = 0;
uint32_t u32NewVal = 0;
uint32_t u32OldVal = 0;
switch (type) {
case ITV_TYPE_STRING:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ptStringData;
if (strcmp((char*)newVal, (char*)oldVal) != 0) { // 当前值不同
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
strcpy((char*)oldVal, (char*)newVal);
}
break;
case ITV_TYPE_U8:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu8Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pu8Data;
if ((*(uint8_t*)newVal) != (*(uint8_t*)oldVal)) {
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(uint8_t*)oldVal) = (*(uint8_t*)newVal);
}
break;
case ITV_TYPE_S16:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps16Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ps16Data;
if ((*(int16_t*)newVal) != (*(int16_t*)oldVal)) {
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(int16_t*)oldVal) = (*(int16_t*)newVal);
}
break;
case ITV_TYPE_S32:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps32Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ps32Data;
if ((*(int32_t*)newVal) != (*(int32_t*)oldVal)) {
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(int32_t*)oldVal) = (*(int32_t*)newVal);
}
break;
case ITV_TYPE_U16:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu16Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pu16Data;
if ((*(uint16_t*)newVal) != (*(uint16_t*)oldVal)) {
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(uint16_t*)oldVal) = (*(uint16_t*)newVal);
}
break;
case ITV_TYPE_U32:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pu32Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pu32Data;
if ((*(uint32_t*)newVal) != (*(uint32_t*)oldVal)) {
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(uint32_t*)oldVal) = (*(uint32_t*)newVal);
}
break;
case ITV_TYPE_FLOAT:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pfData;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pfData;
memcpy(&fNewVal, newVal, sizeof(float));
memcpy(&fOldVal, oldVal, sizeof(float));
u32NewVal = fNewVal*100;
u32OldVal = fOldVal*100;
if ((u32NewVal-u32OldVal) != 0)
{
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
memcpy(oldVal, newVal, sizeof(float));
}
break;
case ITV_TYPE_S8:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ps8Data;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ps8Data;
if ((*(int8_t*)newVal) != (*(int8_t*)oldVal)) {
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(int8_t*)oldVal) = (*(int8_t*)newVal);
}
break;
case ITV_TYPE_S8A:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.ptStringData;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.ptStringData;
if (strcmp((char*)newVal, (char*)oldVal) != 0) { // 当前值不同
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
strcpy((char*)oldVal, (char*)newVal);
}
break;
case ITV_TYPE_BOOL:
newVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].upData.pbData;
oldVal = tITVDataDevice[index-ITV_ID_DEVIC_TYPE].lastData.pbData;
if ((*(uint8_t*)newVal) != (*(uint8_t*)oldVal)) {
freqItvIndexArray.indexArr[freqItvIndexArray.indexArrLen] = index;
freqItvIndexArray.indexArrLen++;
(*(uint8_t*)oldVal) = (*(uint8_t*)newVal);
}
break;
default:
break;
}
}
if (freqItvIndexArray.indexArrLen > 0) { // itv数据有变化
return 1;
};
return 0;
#endif
}
/**********************************************************************
* 功能描述: freq itv定时回调
* 输入参数: xTimer: 系统定时器回调参数,不使用
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void freqItvTimer(TimerHandle_t xTimer)
{
if (isReportItv == 0)
{
return;
}
memset(&freqItvIndexArray, 0, sizeof(ITV_INDEX_ARRAY));
if (isChangedForFreqItvData() == 1) // itv全局数据改变
{
// 初始化 freq_itv_index
freq_itv_index = 0;
// 汇报第一条ITV数据
uint8_t data[FRAME_DATA_LEN] = {0};
ITV_INDEX_ARRAY info = getFreq_ITV_Index_ArrayLimitData();
uint16_t dataLen = Create_ITV_Data(&data, info.indexArr, info.indexArrLen);
if (dataLen > 0)
{
sendStatusChange(data, dataLen, 1);
}
}
}
/**********************************************************************
* 功能描述: 打开上报定时器开关
* 输入参数: xTimer: 系统定时器回调参数,不使用
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void openReportSwitchTimer(TimerHandle_t xTimer)
{
updateType = 0; // 不在升级中
// 开启itv上报定时器
isReportItv = 1;
}
/**********************************************************************
* 功能描述: 定时器初始化
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void cloudComTimerInit(void)
{
// 心跳包
heartPackTimerHandle = xTimerCreate("heart pack",
(TickType_t)(10 * 1000 / portTICK_PERIOD_MS), // 10s 默认
pdTRUE, //周期
(void *)4,
(TimerCallbackFunction_t)vHeartPackTimer);
if (heartPackTimerHandle == NULL)
{
yl_printf("heart pack xTimerCreate Create Failed!");
}
else
{
xTimerStart(heartPackTimerHandle, 0);
}
// 重发包
retryTimerHandle = xTimerCreate("retry",
(TickType_t)(1000 / portTICK_PERIOD_MS), // 1s 默认
pdTRUE, //周期
(void *)5,
(TimerCallbackFunction_t)retryTimer);
if (retryTimerHandle == NULL)
{
yl_printf("retry xTimerCreate Create Failed!");
}
// itv定时包
itvTimerHandle = xTimerCreate("itv",
(TickType_t)(3 * 1000 / portTICK_PERIOD_MS), // 3s 默认
pdTRUE, //周期
(void *)6,
(TimerCallbackFunction_t)itvTimer);
if (itvTimerHandle == NULL)
{
yl_printf("itv xTimerCreate Create Failed!");
}
else
{
xTimerStart(itvTimerHandle, 0);
}
// 频繁上报itv数据包
freqItvTimerHandle = xTimerCreate("freq itv",
(TickType_t)(1 * 1000 / portTICK_PERIOD_MS), // 1s 默认
pdTRUE, //周期
(void *)7,
(TimerCallbackFunction_t)freqItvTimer);
if (freqItvTimerHandle == NULL)
{
yl_printf("freq itv xTimerCreate Create Failed!");
}
else
{
xTimerStart(freqItvTimerHandle, 0);
}
// 用于升级计时5min后,打开上报定时器
reportSwitchTimerHandle = xTimerCreate("report switch",
(TickType_t)(5 * 60 * 1000 / portTICK_PERIOD_MS), // 5min 默认
pdFALSE, //单次
(void *)8,
(TimerCallbackFunction_t)openReportSwitchTimer);
if (reportSwitchTimerHandle == NULL)
{
yl_printf("report switch xTimerCreate Create Failed!");
}
}
/**********************************************************************
* 功能描述: 打印帧数据
* 输入参数: frame:帧数据 isRecv:是否是接收帧还是发送帧
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void printfFrame(CloudComFrame* frame, uint8_t isRecv)
{
#if LOG_YL_ENABLE
if (isRecv == 1)
{
printf("Recv Data: ");
}
else
{
printf("Send Data: ");
}
printf("frameHead: 0x%04X, frameLen: %d, frameNo: %d, frameMark: 0x%02X, frameCmd: 0x%02X, frameDataLen: %d, frameData:",
frame->frameHead, frame->frameLen,
frame->frameNo, frame->frameMark, frame->frameCmd, frame->frameDataLen);
uint16_t i = 0;
for (; i < frame->frameDataLen; ++i)
{
printf(" %02X", frame->frameData[i]);
}
printf(", frameCheck: 0x%02X \r\n", frame->frameCheck);
#endif
}
/**********************************************************************
* 功能描述: 小端数据转化为大端数据
* 输入参数: dataLen:帧数据字节数组长度
* 输出参数: data: 帧数据字节数组
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void smallEndianToBigEndian(uint8_t* data, uint8_t dataLen)
{
uint8_t i = 0;
uint8_t arr[4] = {0};
memcpy(arr, data, dataLen);
for (; i < dataLen; ++i)
{
data[i] = arr[dataLen-1-i];
}
}
/**********************************************************************
* 功能描述: 获取升级类型
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 0:不在升级中 1: 主控升级中 2: wifi升级中
* 其它说明: 无
***********************************************************************/
uint8_t getUpdateType(void)
{
return updateType;
}
/**********************************************************************
* 功能描述: 上电初始化数据发送
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void sendDataForStartUp(void)
{
extern void vApiWifiDataWriteAll(void);
vApiWifiDataWriteAll();
// 初始化 itv_index
itv_index = ITV_ID_DEVIC_TYPE;
// 汇报第一条ITV数据
uint8_t data[FRAME_DATA_LEN] = {0};
ITV_INDEX_ARRAY info = getITV_Index_ArrayLimitDataLen();
uint16_t dataLen = Create_ITV_Data(&data, info.indexArr, info.indexArrLen);
if (dataLen > 0)
{
sendITV(data, dataLen, 1);
}
}
#ifndef __CLOUDIAP_H
#define __CLOUDIAP_H
#include "gd32f30x.h"
#define FMC_PAGE_SIZE ((uint16_t)0x800U) // 单页2k字节
#define APP_START_ADDR ((uint32_t)0x08007800U) // app起始地址
#define APP_END_ADDR ((uint32_t)0x08021FFFU) // app结束地址
#define FMC_WRITE_START_ADDR ((uint32_t)0x08022000U) // app备份区起始地址
#define FMC_WRITE_END_ADDR ((uint32_t)0x0803C7FFU) // app备份区结束地址
#define UPDATE_CONFIG_START_ADDR ((uint32_t)0x0803C800U) // 升级配置信息起始地址
#define UPDATE_CONFIG_END_ADDR ((uint32_t)0x0803D7FFU) // 升级配置信息结束地址
#pragma pack(push) //数据压栈
#pragma pack(1) //按BYTE对齐
typedef struct UpdateInfoStru
{
uint32_t headFlag; // 头部标识
uint32_t totalFrameNum; // 升级包总帧数
uint32_t updateFileSize; // 升级文件大小
uint32_t crc32Check; // crc32校验
uint8_t flag; // 1: 有更新 其他: 无更新
} UpdateInfo;
#pragma pack(pop) //恢复设置
// 擦除flash
void fmcErasePages(uint32_t startAddr, uint32_t endAddr);
// 重置flash写起始地址
void resetWriteStartAddr(void);
// 接收串口数据写flash 注:前面的帧数据必须是4的整数倍,最后一帧可以不是4的整数倍
void fmcWriteFromRecvUart(uint8_t *data, uint32_t dataLen);
// 写flash
void fmcWrite(uint32_t startAddr, uint8_t *data, uint32_t dataLen);
// 擦除flash校验
uint8_t checkEraseFlash(uint32_t startAddr, uint32_t endAddr);
// Md5校验
void md5Check(uint32_t checkStartAddr, uint32_t dataLen, uint8_t* result);
// crc32校验
void crc32Check(uint32_t checkStartAddr, uint32_t dataLen, uint32_t* result);
#endif
/*********************************************************************
* 内容摘要: 主控升级
* 其它说明: 无
* 当前版本: V1.0
* 作 者:
* 完成日期: 2022/11/11
**********************************************************************/
#include "cloudIap.h"
#include "log.h"
#include "cloudMd5.h"
// 备份区起始地址
static uint32_t writeStartAddr = FMC_WRITE_START_ADDR;
#define CRC32_InitalValue 0xFFFFFFFF
#define CRC32_Polynomial 0x04C11DB7
#define CRC32_XOROUT 0xFFFFFFFF
const uint32_t CRC32_table[] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
/**********************************************************************
* 功能描述: 擦除flash
* 输入参数: startAddr: flahs起始地址 endAddr:flash结束地址
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void fmcErasePages(uint32_t startAddr, uint32_t endAddr)
{
fmc_unlock();
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
uint32_t PageNum = (endAddr - startAddr) / FMC_PAGE_SIZE;
uint32_t EraseCounter = 0;
fmc_state_enum flashStatus = FMC_READY;
for (; (EraseCounter < PageNum) && (flashStatus == FMC_READY); EraseCounter++)
{
flashStatus = fmc_page_erase(startAddr + (FMC_PAGE_SIZE * EraseCounter));
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
// 看门狗喂狗
fwdgt_write_enable();
fwdgt_counter_reload();
}
fmc_lock();
}
/**********************************************************************
* 功能描述: 重置flash写起始地址
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void resetWriteStartAddr(void)
{
writeStartAddr = FMC_WRITE_START_ADDR;
}
/**********************************************************************
* 功能描述: 接收串口数据写flash
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 前面的帧数据必须是4的整数倍,最后一帧可以不是4的整数倍
***********************************************************************/
void fmcWriteFromRecvUart(uint8_t *data, uint32_t dataLen)
{
fmc_unlock();
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
uint8_t remain = dataLen % 4;
uint32_t i = 4;
uint32_t *addr = (uint32_t *)data;
fmc_state_enum flashStatus = FMC_READY;
for (; (i <= dataLen) && (flashStatus == FMC_READY); i = i + 4)
{
flashStatus = fmc_word_program(writeStartAddr, *addr);
writeStartAddr += 4;
addr++;
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
// 看门狗喂狗
fwdgt_write_enable();
fwdgt_counter_reload();
}
if (remain != 0) // 写最后一帧数据用 0x010203 -> 0xff030201 小端
{
uint32_t word = 0;
for (i = 0; i < remain; ++i)
{
word += (data[dataLen-remain-i] << (8*i));
}
for (i = remain; i < 4; ++i)
{
word += (0xff << (8*i));
}
if (flashStatus == FMC_READY)
{
fmc_word_program(writeStartAddr, word);
writeStartAddr += 4;
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
// 看门狗喂狗
fwdgt_write_enable();
fwdgt_counter_reload();
}
}
fmc_lock();
}
/**********************************************************************
* 功能描述: 写flash
* 输入参数: startAddr: flash起始地址 data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void fmcWrite(uint32_t startAddr, uint8_t *data, uint32_t dataLen)
{
fmc_unlock();
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
uint8_t remain = dataLen % 4;
uint32_t i = 4;
uint32_t *addr = (uint32_t *)data;
fmc_state_enum flashStatus = FMC_READY;
for (; (i <= dataLen) && (flashStatus == FMC_READY); i = i + 4)
{
flashStatus = fmc_word_program(startAddr, *addr);
startAddr += 4;
addr++;
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
// 看门狗喂狗
fwdgt_write_enable();
fwdgt_counter_reload();
}
if (remain != 0) // 写最后一帧数据用 0x010203 -> 0xff030201 小端
{
uint32_t word = 0;
for (i = 0; i < remain; ++i)
{
word += (data[dataLen-remain-i] << (8*i));
}
for (i = remain; i < 4; ++i)
{
word += (0xff << (8*i));
}
if (flashStatus == FMC_READY)
{
fmc_word_program(startAddr, word);
startAddr += 4;
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
// 看门狗喂狗
fwdgt_write_enable();
fwdgt_counter_reload();
}
}
fmc_lock();
}
/**********************************************************************
* 功能描述: 擦除flash校验
* 输入参数: startAddr: flash起始地址 endAddr:flash结束地址
* 输出参数: 无
* 返 回 值: 0: 成功 1: 失败
* 其它说明: 无
***********************************************************************/
uint8_t checkEraseFlash(uint32_t startAddr, uint32_t endAddr)
{
uint32_t WordNum = ((endAddr - startAddr) >> 2);
uint32_t *ptrd = (uint32_t *)startAddr;
uint32_t i = 0;
for (i = 0; i < WordNum; ++i)
{
if (0xffffffff != *ptrd)
{
yl_printf("Erase Flash Failed!");
return 1;
}
else
{
ptrd++;
}
}
return 0;
}
/**********************************************************************
* 功能描述: Md5校验
* 输入参数: checkStartAddr: flash校验起始地址 dataLen:校验数据的长度
* 输出参数: result:校验结果保存在字节数组里
* 返 回 值: 0: 成功 1: 失败
* 其它说明: 无
***********************************************************************/
void md5Check(uint32_t checkStartAddr, uint32_t dataLen, uint8_t* result)
{
uint8_t* startAddr = (uint8_t*)checkStartAddr;
md5(startAddr, dataLen, result);
}
/**********************************************************************
* 功能描述: crc32校验公式
* 输入参数: init_value: 初始项 buf:校验数据 buf_len:校验数据长度
* 输出参数: 无
* 返 回 值: 校验结果
* 其它说明: 无
***********************************************************************/
static uint32_t crc_compute_crc32_ext(uint32_t init_value, uint8_t *buf, uint32_t buf_len)
{
uint32_t CRC32_data = init_value;
uint32_t i = 0;
for (; i < buf_len; i++)
{
uint32_t t = (CRC32_data ^ buf[i]) & 0xFF;
CRC32_data = ((CRC32_data >> 8) & 0xFFFFFF) ^ CRC32_table[t];
}
return (uint32_t)(CRC32_data ^ CRC32_XOROUT);
}
/**********************************************************************
* 功能描述: crc32校验
* 输入参数: checkStartAddr: 校验flash起始地址 dataLen:校验数据长度
* 输出参数: result: 校验结果
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void crc32Check(uint32_t checkStartAddr, uint32_t dataLen, uint32_t* result)
{
uint8_t *buf = (uint8_t *)checkStartAddr;
*result = crc_compute_crc32_ext(CRC32_InitalValue, buf, dataLen);
}
/*********************************************************************
* 内容摘要: 主控与wifi串口通信配置
* 其它说明: 无
* 当前版本: V1.0
* 作 者:
* 完成日期: 2022/11/11
**********************************************************************/
#include "cloud_uart.h"
#include "log.h"
uint8_t UART0_TX_BUF[UART0_TX_LEN] = {0}; /* 发送缓冲区 */
volatile uint8_t DMA_BUF_BUSY = 0 ; /* 缓冲区是否已被占用 */
uint8_t UART0_RX_BUF[UART0_RX_LEN] = {0}; /* 双接收缓冲区 */
volatile uint8_t UART0_RX_STAT = 0; /* 接受状态 0x01:已接收到数据*/
uint32_t UART0_RX_NUM = 0; /* 接收到的数据个数 */
/**********************************************************************
* 功能描述: USART0 中断服务函数
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void USART0_IRQHandler(void)
{
if(SET == usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)) // 空闲中断触发
{
usart_interrupt_flag_clear(USART0,USART_INT_FLAG_IDLE); /* 清除空闲中断标志位 */
usart_data_receive(USART0); /* 清除接收完成标志位 */
dma_channel_disable(DMA0, DMA_CH4); /* 关闭DMA传输 */
uint32_t size = dma_transfer_number_get(DMA0,DMA_CH4);
UART0_RX_NUM = sizeof(UART0_RX_BUF) - size; // 获取接收数据大小
// UART0_RX_BUF[UART0_RX_NUM] = '\0';
// yl_printf("Recv Data: %s, size: %d, len: %d", UART0_RX_BUF, UART0_RX_NUM, size);
UART0_RX_STAT = 0x01; /* 接受状态 0x01:已接收到数据 */
/* 重新设置DMA传输 */
dma_memory_address_config(DMA0,DMA_CH4,(uint32_t)UART0_RX_BUF);
dma_transfer_number_config(DMA0,DMA_CH4,sizeof(UART0_RX_BUF));
dma_channel_enable(DMA0, DMA_CH4); /* 开启DMA传输 */
}
}
/**********************************************************************
* 功能描述: DMA0 通道3 中断服务函数 内存到串口0发送过程
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void DMA0_Channel3_IRQHandler(void)
{
/* 清除DMA0 通道3 中断标志位 */
dma_interrupt_flag_clear(DMA0, DMA_CH3, DMA_INT_FLAG_G);
/* 进入中断,表示已经传输完成缓冲区,释放缓冲区 */
if(DMA_BUF_BUSY == 1) DMA_BUF_BUSY = 0;
}
/**********************************************************************
* 功能描述: DMA0 通道4 中断服务函数 串口0到内存接收过程
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void DMA0_Channel4_IRQHandler(void)
{
/* 清除DMA0 通道4 中断标志位 */
dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_G);
}
/**********************************************************************
* 功能描述: USART0串口初始化函数
* 输入参数: bound 波特率
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void uart0_init(uint32_t bound)
{
/* 使能 GPIOA 时钟 */
rcu_periph_clock_enable(RCU_GPIOA);
/* 使能 USART0 时钟 */
rcu_periph_clock_enable(RCU_USART0);
/* PA9 复用为 USART0_Tx */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
/* PA10 复用为 USART0_Rx */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,GPIO_PIN_10);
/* USART0 初始化配置 */
usart_deinit(USART0);
usart_baudrate_set(USART0, bound); /* 设置波特率 */
usart_receive_config(USART0, USART_RECEIVE_ENABLE); /* 使能接收 */
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); /* 使能发送 */
usart_enable(USART0); /* 使能串口0 */
/* 定义一个DMA配置结构体 */
dma_parameter_struct dma_init_struct;
/* 使能 DMA 时钟 */
rcu_periph_clock_enable(RCU_DMA0);
/* 初始化 DMA0 通道3 用于串口发送*/
dma_deinit(DMA0, DMA_CH3);
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; /* 存储器到外设方向 */
dma_init_struct.memory_addr = (uint32_t)UART0_TX_BUF; /* 存储器基地址 */
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; /* 存储器地址自增 */
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; /* 存储器位宽为8位 */
dma_init_struct.number = UART0_TX_LEN; /* 传输数据个数 */
dma_init_struct.periph_addr = ((uint32_t)0x40013804); /* 外设基地址,即USART数据寄存器地址 */
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; /* 外设地址固定不变 */
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; /* 外设数据位宽为8位 */
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; /* 软件优先级为极高*/
dma_init(DMA0, DMA_CH3, &dma_init_struct);
/* DMA循环模式配置,不使用循环模式 */
dma_circulation_disable(DMA0, DMA_CH3);
/* DMA存储器到存储器模式模式配置,不使用存储器到存储器模式*/
dma_memory_to_memory_disable(DMA0, DMA_CH3);
/* USART DMA 发送使能 */
usart_dma_transmit_config(USART0, USART_DENT_ENABLE);
/* DMA0 通道3 中断优先级设置并使能 */
nvic_irq_enable(DMA0_Channel3_IRQn, 0, 0);
/* 使能 DMA0 通道3 传输完成、传输错误中断 */
dma_interrupt_enable(DMA0, DMA_CH3, DMA_INT_FTF|DMA_INT_ERR);
/* 使能 DMA0 通道3 */
dma_channel_enable(DMA0, DMA_CH3);
/* 初始化 DMA0 通道4 用于串口接收*/
dma_deinit(DMA0, DMA_CH4);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; /* 外设到存储器方向 */
dma_init_struct.memory_addr = (uint32_t)UART0_RX_BUF; /* 存储器基地址 */
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; /* 存储器地址自增 */
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; /* 存储器位宽为8位 */
dma_init_struct.number = UART0_RX_LEN; /* 传输数据个数 */
dma_init_struct.periph_addr = ((uint32_t)0x40013804); /* 外设基地址,即USART数据寄存器地址 */
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; /* 外设地址固定不变 */
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; /* 外设数据位宽为8位 */
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; /* 软件优先级为极高*/
dma_init(DMA0, DMA_CH4, &dma_init_struct);
/* DMA循环模式配置,不使用循环模式 */
dma_circulation_disable(DMA0, DMA_CH4);
/* DMA存储器到存储器模式模式配置,不使用存储器到存储器模式*/
dma_memory_to_memory_disable(DMA0, DMA_CH4);
/* USART DMA 发送和接收使能 */
usart_dma_transmit_config(USART0, USART_DENT_ENABLE|USART_DENR_ENABLE);
/* DMA0 通道4 中断优先级设置并使能 */
nvic_irq_enable(DMA0_Channel4_IRQn, 0, 0);
/* 使能 DMA0 通道4 半传输、传输完成、传输错误中断 */
dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF|DMA_INT_HTF|DMA_INT_ERR);
/* 使能 DMA0 通道4 */
dma_channel_enable(DMA0, DMA_CH4);
/* USART中断设置,抢占优先级0,子优先级0 */
nvic_irq_enable(USART0_IRQn, 0, 0);
/* 使能USART0空闲中断 */
usart_interrupt_enable(USART0, USART_INT_IDLE);
}
/**********************************************************************
* 功能描述: 打印十六进制数
* 输入参数: data: 帧数据字节数组; dataLen:帧数据字节数组长度
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
void printfHex(uint8_t *data, uint16_t dateLen)
{
#if LOG_YL_ENABLE
printf("Recv Data: Hex:");
uint16_t i = 0;
for(; i < dateLen; ++i)
{
printf(" %02X", data[i]);
}
printf("\r\n");
#endif
}
/*********************************************************************
* 内容摘要: BootLoader
* 其它说明: 无
* 当前版本: V1.0
* 作 者:
* 完成日期: 2022/11/11
**********************************************************************/
#include "gd32f30x.h"
#include "log.h"
#include "cloudIap.h"
#include "systick.h"
#define USART4_BUAD 115200U // 波特率
typedef void (*func_app)(void);
volatile func_app func;//func需定义为全局变量
/**********************************************************************
* 功能描述: 跳转app
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
static void run_app(void)
{
yl_printf("/-----------------Start Jump To App----------------/");
unsigned long app_addr = APP_START_ADDR;
//跳转前关闭bootloader打开的中断,防止中断使能而应用程序没有相应的中断处理函数
rcu_deinit();
NVIC_DisableIRQ(UART4_IRQn);
/* 关闭滴答定时器,复位到默认值 */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/* 关闭全局中断 */
__set_PRIMASK(0);
/* 关闭所有中断,清除所有中断挂起标志 */
for (uint32_t i = 0; i < 8; i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
/* 使能全局中断 */
__set_PRIMASK(1);
unsigned long stack_pointer = *(unsigned long*)app_addr;
//栈顶地址是否合法(假定sram大小为48k,栈顶指针不会超过0xBFFF)
//举例,应用程序栈顶指针 = 0x20006958
if((stack_pointer & 0x2fff0000) == 0x20000000)
{
func = (func_app)(*(volatile unsigned long*)(app_addr + 4));
__set_MSP(stack_pointer);//将应用程序的栈顶指针保存到寄存器,需放在跳转前最后一步!
__set_CONTROL(0);
func();
}
}
/**********************************************************************
* 功能描述: 串口4初始化
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
static void uart4Init(void)
{
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
gpio_init(GPIOD, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
nvic_irq_enable(UART4_IRQn, 8, 0);
/* enable USART clock */
rcu_periph_clock_enable(RCU_UART4);
/* USART configure */
usart_deinit(UART4);
usart_baudrate_set(UART4, USART4_BUAD);
usart_parity_config(UART4, USART_PM_NONE);
usart_word_length_set(UART4, USART_WL_8BIT);
usart_stop_bit_set(UART4, USART_STB_1BIT);
usart_receive_config(UART4, USART_RECEIVE_ENABLE);
usart_transmit_config(UART4, USART_TRANSMIT_ENABLE);
usart_enable(UART4);
}
/**********************************************************************
* 功能描述: 电源自锁
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
***********************************************************************/
static void lockPower(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
gpio_bit_set(GPIOA, GPIO_PIN_12);
}
int main(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
systick_config();
lockPower();
uart4Init();
yl_printf("/------------------Boot StartUp--------------/");
// 检测App是否更新
UpdateInfo updateInfo = (*(volatile UpdateInfo *)UPDATE_CONFIG_START_ADDR);
if (updateInfo.flag == 1) // 有更新
{
uint8_t eraseResult = 0;
uint32_t firewareSize = 0;
uint32_t result = 0;
while (1)
{
yl_printf("/----------------Enetr Update Process--------------------/");
fmcErasePages(APP_START_ADDR, APP_END_ADDR); // 先擦除App
eraseResult = checkEraseFlash(APP_START_ADDR, APP_END_ADDR); // 校验flash是否擦除完成
if (eraseResult == 1) // 擦除失败
{
yl_printf("/----------------Erase App Failed--------------------/\r\n\r\n\r\n");
delay_1ms(1000); // 延时1s
continue;
}
yl_printf("/----------------Erase App Success--------------------/");
// 将备份区flash数据拷贝到app
firewareSize = updateInfo.updateFileSize;
yl_printf("/---------------Start Copy BackUp_App To App--------------------/");
fmcWrite(APP_START_ADDR, (uint8_t *)FMC_WRITE_START_ADDR, firewareSize);
yl_printf("/----------------Start Crc32 Check--------------------/");
crc32Check(APP_START_ADDR, firewareSize, &result);
if (result != updateInfo.crc32Check) // md5校验失败
{
yl_printf("/----------------Check Crc32 Failed--------------------/\r\n\r\n\r\n");
delay_1ms(1000); // 延时1s
continue;
}
yl_printf("/----------------Check Crc32 Success--------------------/");
// 更新固件信息跳转到APP
updateInfo.flag = 0;
// 擦除升级配置信息
fmcErasePages(UPDATE_CONFIG_START_ADDR, UPDATE_CONFIG_END_ADDR);
fmcWrite(UPDATE_CONFIG_START_ADDR, (uint8_t *)&updateInfo, sizeof(UpdateInfo));
// 检验配置信息写入是否成功
UpdateInfo info = (*(volatile UpdateInfo *)UPDATE_CONFIG_START_ADDR);
if (memcmp(&updateInfo, &info, sizeof(UpdateInfo)) == 0)
{
break;
}
else
{
yl_printf("/----------------Version Config Update Failed--------------------/\r\n\r\n\r\n");
delay_1ms(1000);
}
}
}
// 跳转APP
run_app();
while (1)
{
yl_printf("Jump To App Failed!");
delay_1ms(1000); // 延时1s
}
}