Files
akmon/uts/utils/dfu.uts
2026-01-20 08:04:15 +08:00

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)