Initial commit of akmon project
This commit is contained in:
261
uts/utils/dfu.uts
Normal file
261
uts/utils/dfu.uts
Normal file
@@ -0,0 +1,261 @@
|
||||
// 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)
|
||||
Reference in New Issue
Block a user