feat: 添加驾驶数据存储功能并优化相关逻辑

This commit is contained in:
wangzhongjie 2025-03-31 15:24:08 +08:00
parent db2b9abcca
commit 8ba301348d
8 changed files with 123 additions and 422 deletions

View File

@ -8,6 +8,7 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import { BaseInfoType, CarInfoType, ExaminerInfoType } from '../model';
import { tcpUtil } from '../utils/TcpRequest';
import DB from '../utils/DbSql';
import { DrivingDataStorage } from '../utils/business/DrivingDataStorage';
export default class EntryAbility extends UIAbility {
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
@ -28,6 +29,7 @@ export default class EntryAbility extends UIAbility {
const arrClose = [0x55, 0xaa, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00]
// TODO UDP缺失
// globalThis?.lightLineUdp?.send(arrCloseBuffer);
DrivingDataStorage.close()
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}

View File

@ -2,7 +2,6 @@ import common from '@ohos.app.ability.common';
import router from '@ohos.router';
import { getEsCarModel, getSyncData, } from '../common/service/initable';
import { getUDP, getUDP2 } from '../common/utils/GlobalUdp';
import { initJudgeUdp } from '../common/utils/UdpJudge';
import { judgeConfig } from './judgeSDK/utils/judgeConfig';
import { getTCP } from '../common/utils/GlobalTcp';
@ -22,10 +21,10 @@ import { GetSyncData, InitializeTheCentralTable } from '../utils/table/Operation
import { BusinessError } from '@ohos.base';
import { delPic } from '../utils/Video';
import { FileHelper } from '../utils/FileHelp';
import GetDistance from '../utils/business/GetDistance';
import { GetCurrentTime, NumberToByteArray } from '../utils/Common';
import { GetCurrentTime } from '../utils/Common';
import { ObtainSignalData } from '../utils/business/ObtainSignalData';
import { CentralHeartbeat } from '../utils/business/CentralHeartbeat';
import { DrivingDataStorage } from '../utils/business/DrivingDataStorage';
@Entry
@ -494,7 +493,7 @@ struct Index {
async createAlbum() {
this.fileHelper = new FileHelper();
const time = await GetCurrentTime()
const time = GetCurrentTime()
const date = time.split(' ')[0]
this.fileHelper.createAlbum('jt')
// this.fileHelper.createAlbum('2025-01-02')
@ -522,14 +521,15 @@ struct Index {
// await setCurrentTime();
await SetCurrentTime()
this.timeInfo = AppStorage.get<TimeSynchronizationRspBody>('timeInfo')
const distanceClass = AppStorage.get<boolean>('distanceClass')
if (!distanceClass) {
const distanceClass = new GetDistance(this.context)
await distanceClass.initFolder()
AppStorage.setOrCreate('distanceClass', distanceClass)
console.info('surenjun', 'distanceClass=>初始化完成')
}
// const distanceClass = AppStorage.get<boolean>('distanceClass')
// if (!distanceClass) {
// const distanceClass = new GetDistance(this.context)
// await distanceClass.initFolder()
// AppStorage.setOrCreate('distanceClass', distanceClass)
// console.info('surenjun', 'distanceClass=>初始化完成')
// }
DrivingDataStorage.init(this.context)
DrivingDataStorage.initializeTheDrivingDataFolder()
setTimeout(() => {
this.initParamFlag = true
}, 3000)

View File

@ -14,7 +14,9 @@ import { LANE } from '../judgeSDK/api/judgeSDK.d';
import { GetSyncData, SqlInsertTable } from '../../utils/table/Operation';
import {
getCarStatus, getCenterProjectStatus, plcStrToJson,
getCarStatus,
getCenterProjectStatus,
plcStrToJson,
plcStrToWXJson,
promptWxCode
} from './utils/judgeCommon';
@ -45,7 +47,6 @@ import {
BaseInfoType,
CarInfoType,
CDSBInfo,
DistanceClass,
DrvexamType,
ExaminerInfoType,
ItemInfo,
@ -58,11 +59,13 @@ import {
JudgeKsjs,
JudgeKsxm,
JudgePerformInfo,
JudgeSound, JudgeUI,
JudgeSound,
JudgeUI,
JudgeXmjs,
Km3JudgeInitConfig,
KmItem,
KmItems, MarkRule,
KmItems,
MarkRule,
Plc,
ProjectInfo,
RecordHandleType,
@ -72,6 +75,7 @@ import {
User,
WR
} from '../../model';
import { DrivingDataStorage } from '../../utils/business/DrivingDataStorage';
const judgeTag = 'SURENJUN_JUDGE'
@ -297,8 +301,9 @@ export default class Judge {
wd2: tWD,
h: (this.tempData.gps.hxj) || 1,
})
const distanceClass = AppStorage.get<DistanceClass>('distanceClass')
distanceClass?.setTimeData(Number(((distance / 100).toFixed(2))))
// const distanceClass = AppStorage.get<DistanceClass>('distanceClass')
// distanceClass?.setTimeData(Number(((distance / 100).toFixed(2))))
DrivingDataStorage.setDrivingProcessData(Number(((distance / 100).toFixed(2))))
}
this.prevJd = tJD;
this.prevWd = tWD;

View File

@ -1,17 +0,0 @@
import common from "@ohos.app.ability.common";
// export default class FileUtil {
// private context: common.UIAbilityContext
//
// constructor() {
// }
//
// // 创建文件夹
//
// // 创建并覆盖文件
//
// // 创建或者编辑文件
// // 关闭文件
// // 读取文件
// // 删除文件夹或者文件1:文件夹 2文件 3自定义目录下文件
// }

View File

@ -1,291 +0,0 @@
import media from '@ohos.multimedia.media';
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
export enum PlayStatus {
/**
* 闲置状态, Player刚被创建或者调用了reset方法之后, 进入该状态, 触发idle回调事件
*/
Idle,
/**
* 资源初始化, 调用setSource进入该状态, 触发initialized回调事件
*/
Init,
/**
* 已准备状态, 在Init状态调用prepare方法后进入该状态, 触发prepared回调事件
*/
Prepared,
/**
* 正在播放状态, Prepared/Paused/Completed状态调用play方法进入该状态, 触发playing回调事件
*/
Playing,
/**
* 暂停状态, 在Playing状态调用pause方法进入该状态, 触发paused回调事件
*/
Paused,
/**
* 播放至结尾状态, loop为false时播放到结尾进入该状态, 此时调用play会进入Playing状态和重播, 调用stop进入Stopped状态, 触发completed回调
*/
Completed,
/**
* 停止状态, Prepared/Playing/Paused/Completed状态调用stop方法进入该状态, 触发stopped回调
*/
Stopped,
/**
* 销毁状态, 调用release方法后进入该状态, 触发released回调
*/
Released,
/**
* 错误状态, 当播放引擎发生不可逆的错误进入该状态, 可以调用reset重置, 也可以调用release销毁重建, 触发error回调
*/
Error
}
interface PlayerOption {
mode: "audio" | "video"
loop: boolean
}
export type PlayerSourceType = "network" | "raw" | "local"
type PlayerEvent = media.AVPlayerState | "status"
interface PlayerSourceOption {
/**
* 资源类型 默认为network:网络类型, raw:app预置到resource/rawfile的文件, local:应用沙箱内文件
*/
type?: PlayerSourceType
/**
* type为network时, 传入网络url type为raw时, 传入相对路径 type为local时, 传入沙箱相对路径
*/
url: string
}
export class MediaPlayer {
private context: common.UIAbilityContext
private player?: media.AVPlayer
private option: PlayerOption = {
mode: "video",
loop: false
}
private callback: Map<PlayerEvent, Function[]> = new Map()
constructor(context: common.UIAbilityContext, option?: Partial<PlayerOption>) {
this.context = context
this.option.mode = option?.mode || "video"
this.option.loop = option?.loop || false
}
private _status: PlayStatus = PlayStatus.Idle
/**
* 获取当前播放器状态
* @returns
*/
get status() {
return this._status
}
/**
* 获取媒体资源长度
* @returns
*/
get duration() {
return this.player?.duration ?? 0
}
/**
* 获取媒体资源当前播放进度
* @returns
*/
get current() {
return this.player?.currentTime ?? 0
}
/**
* 设置avplayer输出控件id 仅播放视频需要
* @param id
*/
set surfaceId(id: string) {
this.player!.surfaceId = id
}
/**
* 设置播放音量
* @param volume
*/
set volume(volume: number) {
this.player?.setVolume(volume)
}
/**
* 设置是否循环播放
* @param loop
*/
set loop(loop: boolean) {
if ([PlayStatus.Prepared, PlayStatus.Playing, PlayStatus.Paused, PlayStatus.Completed].includes(this._status)) {
this.player!.loop = loop
}
this.option.loop = loop
}
async create() {
this.player = await media.createAVPlayer()
this.registerPlayerCallback()
}
/**
* 设置播放资源
* @param option
*/
async setSource(option: PlayerSourceOption) {
let fdPath = 'fd://';
if (option.type === "raw") {
let fileDescriptor = await this.context.resourceManager.getRawFd(option.url)
this.player!.fdSrc = fileDescriptor
} else if (option.type === "local") {
let path = this.context.filesDir + option.url;
let file = fs.openSync(path)
this.player!.url = fdPath + file.fd
} else {
this.player!.url = option.url
}
}
async prepare() {
await this.player?.prepare()
}
async play() {
await this.player?.play()
}
async pause() {
await this.player?.pause()
}
async stop() {
await this.player?.stop()
}
async reset() {
await this.player?.reset()
}
async release() {
await this.player?.release()
this.callback.clear()
}
seek(time: number, mode?: media.SeekMode) {
this.player?.seek(time, mode || media.SeekMode.SEEK_PREV_SYNC)
}
speed(speed: media.PlaybackSpeed) {
this.player?.setSpeed(speed)
}
on(type: PlayerEvent, cb: Function) {
if (!this.callback.has(type)) {
this.callback.set(type, [])
}
this.callback.get(type)?.push(cb)
}
once(type: PlayerEvent, cb: Function) {
let onceFn = () => {
cb()
this.off(type, onceFn)
}
this.on(type, onceFn)
}
off(type: PlayerEvent, cb: Function) {
if (!this.callback.has(type)) {
return
}
let cbs = this.callback.get(type)
cbs = cbs?.filter(el => el != cb)
}
private registerPlayerCallback() {
this.player?.on("stateChange", (state, reason) => {
switch (state) {
case "idle": {
this._status = PlayStatus.Idle
this.callback.get("idle")?.forEach(cb => {
cb()
})
break
}
case "initialized": {
this._status = PlayStatus.Init
this.callback.get("initialized")?.forEach(cb => {
cb()
})
this.prepare()
break
}
case "prepared": {
this._status = PlayStatus.Prepared
this.loop = this.option.loop
this.callback.get("prepared")?.forEach(cb => {
cb()
})
break
}
case "playing": {
this._status = PlayStatus.Playing
this.loop = this.option.loop
this.callback.get("playing")?.forEach(cb => {
cb()
})
break
}
case "paused": {
this._status = PlayStatus.Paused
this.loop = this.option.loop
this.callback.get("paused")?.forEach(cb => {
cb()
})
break
}
case "completed": {
this._status = PlayStatus.Completed
this.loop = this.option.loop
this.callback.get("completed")?.forEach(cb => {
cb()
})
break
}
case "stopped": {
this._status = PlayStatus.Stopped
this.callback.get("stopped")?.forEach(cb => {
cb()
})
break
}
case "released": {
this._status = PlayStatus.Released
this.callback.get("released")?.forEach(cb => {
cb()
})
break
}
case "error": {
this._status = PlayStatus.Error
this.callback.get("error")?.forEach(cb => {
cb()
})
break
}
default:
break
}
this.callback.get("status")?.forEach(cb => {
cb(this._status, reason)
})
})
}
}

View File

@ -1,51 +0,0 @@
import dataPreferences from '@ohos.data.preferences';
let preference: dataPreferences.Preferences;
const SYSTEM_DB: string = 'system.db'
let context = getContext(this);
class PreferenceUtils {
async writeData(value: dataPreferences.ValueType, key: string) {
// if (value === null) {
// return;
// }
if (!preference) {
await this.getPreferencesFromStorage(SYSTEM_DB);
}
try {
await preference.put(key, value);
} catch (err) {
console.info(`Failed to put value, Cause: ${err}`);
}
await preference.flush();
}
// 获取其他缓存数据
async getData<T extends dataPreferences.ValueType>(key: string) {
let value: dataPreferences.ValueType = 1;
if (!preference) {
await this.getPreferencesFromStorage(SYSTEM_DB);
}
try {
value = (await preference.get(key, ''));
} catch (err) {
console.info(`Failed to get value, Cause: ${err}`);
}
if (value === '') {
return;
}
return value as T;
}
// 创建登录数据preference
async getPreferencesFromStorage(name: string) {
try {
preference = await dataPreferences.getPreferences(context, name);
} catch (err) {
console.info(`Failed to get preferences, Cause: ${err}`);
}
}
}
export default new PreferenceUtils();

View File

@ -0,0 +1,54 @@
import common from '@ohos.app.ability.common';
import dayTs from '../Date';
import FileUtils from '../FileUtils';
class drivingDataStorage {
public folderPath: string
public time: string
public totalDistance: number
public totalTime: number
public date: string
public fd: number
private fileUtil: FileUtils
constructor() {
}
// 初始化文件夹
async initializeTheDrivingDataFolder() {
const folderPath = await this.fileUtil.initFolder(`/车辆行驶距离统计`);
this.time = dayTs().format("HH:mm:ss")
this.date = dayTs().format("YYYY_MM_DD")
this.folderPath = folderPath;
this.totalDistance = 0;
this.totalTime = 0;
this.fd = await this.fileUtil.editFile(
`${folderPath}/${this.date}.txt`,
`程序启动时间:${this.time} 累计行驶距离:${this.totalDistance}m 累计运行时常:${this.totalTime}min`)
return folderPath
}
// 设置行驶过程数据
async setDrivingProcessData(str: number) {
const content = await this.fileUtil.readFile(`${this.folderPath}/${this.date}.txt`) || '';
const contentArr = content.split('\n').filter(item => item)
this.totalDistance += (str * 1 > 200 ? 200 : str * 1)
this.totalTime += 1;
contentArr[contentArr.length - 1] =
`程序启动时间:${this.time} 累计行驶距离:${(this.totalDistance).toFixed(2)}m 累计运行时常:${Math.ceil(this.totalTime /
60)}min` + '\n'
}
// 初始化
public init(context: common.UIAbilityContext) {
this.fileUtil = new FileUtils(context)
}
// 关闭文件读写
public close() {
this.fileUtil.closeFile(`${this.folderPath}/${this.date}.txt`)
}
}
export const DrivingDataStorage = new drivingDataStorage()

View File

@ -14,7 +14,7 @@ export default class GetDistance {
private fileUtil: FileUtils
// 设置文件夹
public initFolder = async () => {
const time = await GetCurrentTime()
const time = GetCurrentTime()
const folderPath = await this.fileUtil.initFolder(`/车辆行驶距离统计`);
console.info('surenjun folderPath=>', folderPath);
const date = time.split(' ')[0].split('-').join('_')
@ -26,8 +26,7 @@ export default class GetDistance {
this.date = date;
this.fd = await this.fileUtil.editFile(
`${folderPath}/${date}.txt`,
`程序启动时间:${timeStr} 累计行驶距离:${this.totalDistance}m 累计运行时常:${this.totalTime}min`, this.fd
);
`程序启动时间:${timeStr} 累计行驶距离:${this.totalDistance}m 累计运行时常:${this.totalTime}min`);
return folderPath
}
@ -36,9 +35,9 @@ export default class GetDistance {
this.fileUtil = fileUtil;
}
// 过程文件数据
public setTimeData = async (str: number) => {
// const { fileUtil, folderPath, timeStr, date, totalDistance } = this;
console.log('folderPath', this.folderPath)
const content = await this.fileUtil.readFile(`${this.folderPath}/${this.date}.txt`) || '';
const contentArr = content.split('\n').filter(item => item)