|
|
|
@ -5,7 +5,8 @@ import (
|
|
|
|
"encoding/base64"
|
|
|
|
"encoding/base64"
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"github.com/towgo/towgo/errors/terror"
|
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
|
|
|
|
|
|
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"os"
|
|
|
|
@ -60,13 +61,13 @@ func FirmwareRead(deviceId string, address uint32, length uint16) (*FirmwareRead
|
|
|
|
// 4. 发送命令并获取响应
|
|
|
|
// 4. 发送命令并获取响应
|
|
|
|
respData, err := pushCommand(deviceId, frame, "读取固件数据")
|
|
|
|
respData, err := pushCommand(deviceId, frame, "读取固件数据")
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "设备[%s]读取固件数据失败(地址:0x%X, 长度:%d)", deviceId, address, length)
|
|
|
|
return nil, gerror.Wrapf(err, "设备[%s]读取固件数据失败(地址:0x%X, 长度:%d)", deviceId, address, length)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 解析响应帧
|
|
|
|
// 5. 解析响应帧
|
|
|
|
frameResp, err := ParseBlockFrame(respData)
|
|
|
|
frameResp, err := ParseBlockFrame(respData)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "设备[%s]解析固件响应失败", deviceId)
|
|
|
|
return nil, gerror.Wrapf(err, "设备[%s]解析固件响应失败", deviceId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
block := &FirmwareReadBlock{}
|
|
|
|
block := &FirmwareReadBlock{}
|
|
|
|
block.Address = binary.LittleEndian.Uint32(frameResp.Data[0:4])
|
|
|
|
block.Address = binary.LittleEndian.Uint32(frameResp.Data[0:4])
|
|
|
|
@ -182,14 +183,14 @@ func FirmwareUpgrade(deviceId string, firmware []byte, startAddr uint32) (unique
|
|
|
|
frimwareVer := hex.EncodeToString(blockHash[:])
|
|
|
|
frimwareVer := hex.EncodeToString(blockHash[:])
|
|
|
|
read, err := FirmwareRead(deviceId, startAddr, uint16(blockSize))
|
|
|
|
read, err := FirmwareRead(deviceId, startAddr, uint16(blockSize))
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return uniqueId, addr, terror.Wrapf(err, "验证设备上最新固件包失败")
|
|
|
|
return uniqueId, addr, gerror.Wrapf(err, "验证设备上最新固件包失败")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
deviceHash := sha256.Sum256(read.Data)
|
|
|
|
deviceHash := sha256.Sum256(read.Data)
|
|
|
|
deviceVer := hex.EncodeToString(deviceHash[:])
|
|
|
|
deviceVer := hex.EncodeToString(deviceHash[:])
|
|
|
|
if deviceVer != frimwareVer {
|
|
|
|
if deviceVer != frimwareVer {
|
|
|
|
os.WriteFile("./blockData.txt", []byte(fmt.Sprintf("% X", blockData)), 0666)
|
|
|
|
os.WriteFile("./blockData.txt", []byte(fmt.Sprintf("% X", blockData)), 0666)
|
|
|
|
os.WriteFile("./readData.txt", []byte(fmt.Sprintf("% X", read.Data)), 0666)
|
|
|
|
os.WriteFile("./readData.txt", []byte(fmt.Sprintf("% X", read.Data)), 0666)
|
|
|
|
return uniqueId, addr, terror.Newf("设备最新不完整,建议擦除分区重试 %s != %s %d %d", frimwareVer, deviceVer, len(blockData), len(read.Data))
|
|
|
|
return uniqueId, addr, gerror.Newf("设备最新不完整,建议擦除分区重试 %s != %s %d %d", frimwareVer, deviceVer, len(blockData), len(read.Data))
|
|
|
|
}*/
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -264,7 +265,7 @@ func EraseSector(deviceId string) (*WriteResponse, error) {
|
|
|
|
// 发送写入命令
|
|
|
|
// 发送写入命令
|
|
|
|
resp, err := WriteCmd(deviceId, eraseSector, data, "擦除扇区", UpdateMarker)
|
|
|
|
resp, err := WriteCmd(deviceId, eraseSector, data, "擦除扇区", UpdateMarker)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "设备[%s]擦除扇区失败", deviceId)
|
|
|
|
return nil, gerror.Wrapf(err, "设备[%s]擦除扇区失败", deviceId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证响应状态
|
|
|
|
// 验证响应状态
|
|
|
|
@ -317,7 +318,7 @@ func FirmwareDataWrite(deviceId string, extDataLen byte, addr uint32, writeLen u
|
|
|
|
// 4. 发送写入命令
|
|
|
|
// 4. 发送写入命令
|
|
|
|
resp, err := WriteCmd(deviceId, firmwareData, cmdData, "下发固件数据", UpdateMarker)
|
|
|
|
resp, err := WriteCmd(deviceId, firmwareData, cmdData, "下发固件数据", UpdateMarker)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "\n设备[%s]下发固件数据失败", deviceId)
|
|
|
|
return nil, gerror.Wrapf(err, "\n设备[%s]下发固件数据失败", deviceId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if !resp.Success {
|
|
|
|
if !resp.Success {
|
|
|
|
@ -333,7 +334,7 @@ func LockFirmware(deviceId string) (*WriteResponse, error) {
|
|
|
|
// 无数据 payload(参考示例指令:数据长度0x00)
|
|
|
|
// 无数据 payload(参考示例指令:数据长度0x00)
|
|
|
|
resp, err := WriteCmd(deviceId, lockFirmware, []byte{00}, "固件加锁")
|
|
|
|
resp, err := WriteCmd(deviceId, lockFirmware, []byte{00}, "固件加锁")
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "设备[%s]固件加锁失败", deviceId)
|
|
|
|
return nil, gerror.Wrapf(err, "设备[%s]固件加锁失败", deviceId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if !resp.Success {
|
|
|
|
if !resp.Success {
|
|
|
|
@ -348,26 +349,26 @@ func LockFirmware(deviceId string) (*WriteResponse, error) {
|
|
|
|
func GetFirmwareFromLocal(localPath string) ([]byte, error) {
|
|
|
|
func GetFirmwareFromLocal(localPath string) ([]byte, error) {
|
|
|
|
// 校验路径合法性
|
|
|
|
// 校验路径合法性
|
|
|
|
if localPath == "" {
|
|
|
|
if localPath == "" {
|
|
|
|
return nil, terror.New("本地固件路径不能为空")
|
|
|
|
return nil, gerror.New("本地固件路径不能为空")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
absPath, err := filepath.Abs(localPath)
|
|
|
|
absPath, err := filepath.Abs(localPath)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "读取固件绝对路径失败(%s)", localPath)
|
|
|
|
return nil, gerror.Wrapf(err, "读取固件绝对路径失败(%s)", localPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查文件是否存在
|
|
|
|
// 检查文件是否存在
|
|
|
|
fileInfo, err := os.Stat(absPath)
|
|
|
|
fileInfo, err := os.Stat(absPath)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "固件文件不存在或无法访问(%s)", absPath)
|
|
|
|
return nil, gerror.Wrapf(err, "固件文件不存在或无法访问(%s)", absPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if fileInfo.IsDir() {
|
|
|
|
if fileInfo.IsDir() {
|
|
|
|
return nil, terror.Newf("路径指向目录,不是固件文件(%s)", absPath)
|
|
|
|
return nil, gerror.Newf("路径指向目录,不是固件文件(%s)", absPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 读取文件内容
|
|
|
|
// 读取文件内容
|
|
|
|
firmwareData, err := os.ReadFile(absPath)
|
|
|
|
firmwareData, err := os.ReadFile(absPath)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "读取固件文件失败(%s)", absPath)
|
|
|
|
return nil, gerror.Wrapf(err, "读取固件文件失败(%s)", absPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
g.Log().Infof("成功从本地读取固件,路径:%s,大小:%d字节", absPath, len(firmwareData))
|
|
|
|
g.Log().Infof("成功从本地读取固件,路径:%s,大小:%d字节", absPath, len(firmwareData))
|
|
|
|
@ -379,7 +380,7 @@ func GetFirmwareFromLocal(localPath string) ([]byte, error) {
|
|
|
|
func GetFirmwareFromURL(url string) ([]byte, error) {
|
|
|
|
func GetFirmwareFromURL(url string) ([]byte, error) {
|
|
|
|
// 校验URL合法性
|
|
|
|
// 校验URL合法性
|
|
|
|
if url == "" {
|
|
|
|
if url == "" {
|
|
|
|
return nil, terror.New("固件下载URL不能为空")
|
|
|
|
return nil, gerror.New("固件下载URL不能为空")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if filepath.Ext(url) != ".bin" {
|
|
|
|
if filepath.Ext(url) != ".bin" {
|
|
|
|
g.Log().Warnf("固件URL后缀非.bin,可能不是有效固件文件(%s)", url)
|
|
|
|
g.Log().Warnf("固件URL后缀非.bin,可能不是有效固件文件(%s)", url)
|
|
|
|
@ -391,19 +392,19 @@ func GetFirmwareFromURL(url string) ([]byte, error) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
resp, err := client.Get(url)
|
|
|
|
resp, err := client.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "固件下载请求失败(%s)", url)
|
|
|
|
return nil, gerror.Wrapf(err, "固件下载请求失败(%s)", url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
defer resp.Body.Close() // 确保响应体关闭
|
|
|
|
defer resp.Body.Close() // 确保响应体关闭
|
|
|
|
|
|
|
|
|
|
|
|
// 校验响应状态
|
|
|
|
// 校验响应状态
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
return nil, terror.Newf("固件下载失败,HTTP状态码:%d(%s)", resp.StatusCode, url)
|
|
|
|
return nil, gerror.Newf("固件下载失败,HTTP状态码:%d(%s)", resp.StatusCode, url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 读取响应内容
|
|
|
|
// 读取响应内容
|
|
|
|
firmwareData, err := io.ReadAll(resp.Body)
|
|
|
|
firmwareData, err := io.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, terror.Wrapf(err, "读取固件响应内容失败(%s)", url)
|
|
|
|
return nil, gerror.Wrapf(err, "读取固件响应内容失败(%s)", url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
g.Log().Infof("成功从网络下载固件,URL:%s,大小:%d字节", url, len(firmwareData))
|
|
|
|
g.Log().Infof("成功从网络下载固件,URL:%s,大小:%d字节", url, len(firmwareData))
|
|
|
|
|