261 lines
7.2 KiB
Plaintext
261 lines
7.2 KiB
Plaintext
// DFU (Device Firmware Update) 工具类
|
|
// 用于处理设备固件升级过程
|
|
import supa, { supaReady } from '@/components/supadb/aksupainstance.uts'
|
|
|
|
export type FirmwareInfo {
|
|
version: string
|
|
url: string
|
|
size: number
|
|
checksum: string
|
|
description?: string
|
|
}
|
|
|
|
//https://ak3.oulog.com/storage/v1/object/public/akmon/OmFw2510221553.zip
|
|
export type FirmwareConfig {
|
|
default_value: string
|
|
default_key?: string
|
|
}
|
|
|
|
export type DFUProgress {
|
|
stage: 'downloading' | 'verifying' | 'uploading' | 'upgrading' | 'completed'
|
|
progress: number // 0-100
|
|
message: string
|
|
}
|
|
|
|
export class DFUTool {
|
|
private progressCallback?: (progress: DFUProgress) => void
|
|
|
|
constructor(progressCallback?: (progress: DFUProgress) => void) {
|
|
this.progressCallback = progressCallback
|
|
}
|
|
|
|
/**
|
|
* 检查是否有可用的固件升级
|
|
* @param currentHardwareVersion 当前硬件版本
|
|
* @param currentSoftwareVersion 当前软件版本
|
|
* @returns 固件信息或null
|
|
*/
|
|
async checkFirmwareUpdate(currentHardwareVersion: string, currentSoftwareVersion: string): Promise<FirmwareInfo | null> {
|
|
try {
|
|
// 从Supabase查询最新固件版本
|
|
const result = await supa
|
|
.from('ak_global_config')
|
|
.select('default_value,default_key', {})
|
|
.eq('config_key', 'cfwatch_hardware_version')
|
|
.single()
|
|
.executeAs<FirmwareConfig>()
|
|
console.log(result.data)
|
|
const data = result.data as FirmwareConfig
|
|
if (result.error !=null ) {
|
|
console.log('查询固件版本失败:', result.error)
|
|
return null
|
|
}
|
|
|
|
const firmwareConfig = data
|
|
|
|
// 比较版本号,检查是否需要升级
|
|
if (this.compareVersions(currentSoftwareVersion, firmwareConfig.default_value) < 0) {
|
|
return {
|
|
version: firmwareConfig.default_value,
|
|
url: firmwareConfig.default_key,
|
|
size: 0,
|
|
checksum: '',
|
|
description: ''
|
|
}
|
|
}
|
|
|
|
return null
|
|
} catch (error) {
|
|
console.error('检查固件升级失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 执行固件升级
|
|
* @param firmwareInfo 固件信息
|
|
* @param deviceId 设备ID
|
|
* @returns 升级结果
|
|
*/
|
|
async performFirmwareUpdate(firmwareInfo: FirmwareInfo, deviceId: string): Promise<boolean> {
|
|
try {
|
|
this.updateProgress('downloading', 0, '开始下载固件...')
|
|
|
|
// 下载固件文件
|
|
const firmwareData = await this.downloadFirmware(firmwareInfo.url)
|
|
|
|
this.updateProgress('verifying', 50, '验证固件完整性...')
|
|
|
|
// 验证文件完整性
|
|
if (!this.verifyFirmware(firmwareData, firmwareInfo.checksum)) {
|
|
throw new Error('固件校验失败')
|
|
}
|
|
|
|
this.updateProgress('uploading', 70, '上传固件到设备...')
|
|
|
|
// 执行DFU升级
|
|
const success = await this.executeDFU(firmwareData, deviceId)
|
|
|
|
if (success) {
|
|
this.updateProgress('completed', 100, '固件升级完成')
|
|
return true
|
|
} else {
|
|
throw new Error('DFU升级失败')
|
|
}
|
|
} catch (error) {
|
|
console.error('固件升级失败:', error)
|
|
this.updateProgress('completed', 0, `升级失败: ${error}`)
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 下载固件文件
|
|
*/
|
|
private async downloadFirmware(url: string): Promise<ArrayBuffer> {
|
|
return new Promise((resolve, reject) => {
|
|
uni.downloadFile({
|
|
url: url,
|
|
success: (res) => {
|
|
if (res.statusCode === 200) {
|
|
// 读取下载的文件
|
|
uni.getFileSystemManager().readFile({
|
|
filePath: res.tempFilePath,
|
|
success: (readRes) => {
|
|
resolve(readRes.data as ArrayBuffer)
|
|
},
|
|
fail: reject
|
|
})
|
|
} else {
|
|
reject(new Error(`下载失败: ${res.statusCode}`))
|
|
}
|
|
},
|
|
fail: reject
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 验证固件完整性
|
|
*/
|
|
private verifyFirmware(data: ArrayBuffer, expectedChecksum: string): boolean {
|
|
// 简单的校验和验证(可以根据需要实现更复杂的校验)
|
|
const hash = this.calculateSimpleHash(data)
|
|
return hash === expectedChecksum
|
|
}
|
|
|
|
/**
|
|
* 执行DFU升级
|
|
*/
|
|
private async executeDFU(firmwareData: ArrayBuffer, deviceId: string): Promise<boolean> {
|
|
// 这里实现具体的DFU协议
|
|
// 需要根据设备的DFU协议来实现
|
|
// 这是一个简化的实现,实际需要根据具体设备协议调整
|
|
|
|
try {
|
|
// 1. 进入DFU模式
|
|
await this.enterDFUMode(deviceId)
|
|
|
|
// 2. 发送固件数据包
|
|
await this.sendFirmwarePackets(firmwareData, deviceId)
|
|
|
|
// 3. 验证升级结果
|
|
await this.verifyUpdate(deviceId)
|
|
|
|
return true
|
|
} catch (error) {
|
|
console.error('DFU执行失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 进入DFU模式
|
|
*/
|
|
private async enterDFUMode(deviceId: string): Promise<void> {
|
|
// 实现进入DFU模式的逻辑
|
|
// 通常需要发送特定的命令到设备
|
|
}
|
|
|
|
/**
|
|
* 发送固件数据包
|
|
*/
|
|
private async sendFirmwarePackets(firmwareData: ArrayBuffer, deviceId: string): Promise<void> {
|
|
// 实现分包发送固件的逻辑
|
|
const packetSize = 20 // 根据设备协议调整
|
|
const totalPackets = Math.ceil(firmwareData.byteLength / packetSize)
|
|
|
|
for (let i = 0; i < totalPackets; i++) {
|
|
const start = i * packetSize
|
|
const end = Math.min(start + packetSize, firmwareData.byteLength)
|
|
const packet = firmwareData.slice(start, end)
|
|
|
|
// 发送数据包
|
|
await this.sendPacket(packet, deviceId)
|
|
|
|
// 更新进度
|
|
const progress = Math.round((i + 1) / totalPackets * 100)
|
|
this.updateProgress('uploading', 70 + (progress * 0.2), `上传进度: ${i + 1}/${totalPackets}`)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送单个数据包
|
|
*/
|
|
private async sendPacket(packet: ArrayBuffer, deviceId: string): Promise<void> {
|
|
// 实现BLE发送数据包的逻辑
|
|
}
|
|
|
|
/**
|
|
* 验证升级结果
|
|
*/
|
|
private async verifyUpdate(deviceId: string): Promise<void> {
|
|
// 实现验证升级结果的逻辑
|
|
}
|
|
|
|
/**
|
|
* 计算简单校验和
|
|
*/
|
|
private calculateSimpleHash(data: ArrayBuffer): string {
|
|
const view = new Uint8Array(data)
|
|
let hash = 0
|
|
for (let i = 0; i < view.length; i++) {
|
|
hash = ((hash << 5) - hash + view[i]) & 0xffffffff
|
|
}
|
|
return hash.toString(16)
|
|
}
|
|
|
|
/**
|
|
* 比较版本号
|
|
*/
|
|
private compareVersions(version1: string, version2: string): number {
|
|
const v1Parts = version1.split('.').map((item) => parseInt(item))
|
|
const v2Parts = version2.split('.').map((item) => parseInt(item))
|
|
|
|
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
const v1 = v1Parts[i] != null ? v1Parts[i] : 0
|
|
const v2 = v2Parts[i] != null ? v2Parts[i] : 0
|
|
|
|
if (v1 > v2) return 1
|
|
if (v1 < v2) return -1
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
/**
|
|
* 更新进度
|
|
*/
|
|
private updateProgress(stage: 'downloading' | 'verifying' | 'uploading' | 'upgrading' | 'completed', progress: number, message: string): void {
|
|
if (this.progressCallback != null) {
|
|
this.progressCallback({
|
|
stage,
|
|
progress: Math.min(100, Math.max(0, progress)),
|
|
message
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// 导出单例实例
|
|
export const dfuTool = new DFUTool(null) |