Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,507 @@
/**
* 传感器数据服务 - 使用 executeAs<T> 方式进行类型转换
* 减少UI层的类型转换问题
*/
import supa from '@/components/supadb/aksupainstance.uts'
import type { AkReqResponse } from '@/uni_modules/ak-req/index.uts'
import type {
SensorMeasurement,
SensorAnalysisResult,
DeviceInfo
} from './types.uts'
// Helper function to create error response factories
function createErrorResponseFactory<T>(defaults: T) {
return (message: string): AkReqResponse<T> => ({
status: 500,
data: defaults,
headers: {},
error: new UniError('SenseDataService', -1, message),
total: null,
page: null,
limit: null,
hasmore: null,
origin: null
});
}
// 保留原 createErrorResponse 以兼容其它调用(如有)
function createErrorResponse<T>(data: T, message: string): AkReqResponse<T> {
return createErrorResponseFactory<T>(data)(message);
}
// 查询参数类型
export type SensorDataParams = {
device_id ?: string | null
user_id ?: string | null
measurement_type ?: string | null
start_date ?: string | null
end_date ?: string | null
limit ?: number | null
offset ?: number | null
}
export type DeviceParams = {
user_id ?: string | null
device_type ?: string | null
status ?: string | null
}
/**
* 传感器数据服务类
*/
export class SenseDataService {
/**
* 获取传感器测量数据列表
*/
static async getMeasurements(params : SensorDataParams) : Promise<AkReqResponse<Array<SensorMeasurement>>> {
try {
let query = supa
.from('ss_sensor_measurements')
.select('*', {})
.order('measured_at', { ascending: false })
// 添加筛选条件
const deviceId = params.device_id
if (deviceId != null) {
query = query.eq('device_id', deviceId)
}
const userId = params.user_id
if (userId != null && userId !== '') {
query = query.eq('user_id', userId)
}
const measurementType = params.measurement_type
if (measurementType != null) {
query = query.eq('measurement_type', measurementType)
}
const startDate = params.start_date
if (startDate != null) {
query = query.gte('measured_at', startDate)
}
const endDate = params.end_date
if (endDate != null) {
query = query.lte('measured_at', endDate)
} // 分页
const limit = params.limit ?? 20
const offset = params.offset ?? 0
console.log(limit, offset)
// 先设置 limit这会自动计算并设置对应的 range
query = query.limit(limit)
// 如果有 offset需要重新调整 range
if (offset > 0) {
query = query.range(offset, offset + limit - 1)
}
// 如果 limit 为 1使用 single() 方法优化查询
if (limit == 1) {
query = query.single()
}
const response = await query.executeAs<SensorMeasurement>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '获取传感器数据失败';
const empty: SensorMeasurement = {
id: '', device_id: '', user_id: '', measurement_type: '', measured_at: '', unit: '', raw_data: new UTSJSONObject(), created_at: ''
};
const errorSensorMeasurement = createErrorResponseFactory(empty);
const errorSensorMeasurementArr = createErrorResponseFactory([] as SensorMeasurement[]);
if ((params.limit ?? 20) === 1) {
return errorSensorMeasurement(errorMsg);
} else {
return errorSensorMeasurementArr(errorMsg);
}
}
}
/**
* 获取单条传感器测量数据
*/
static async getMeasurementById(id : string) : Promise<AkReqResponse<SensorMeasurement>> {
try {
const response = await supa
.from('ss_sensor_measurements')
.select('*', {})
.eq('id', id)
.single()
.executeAs<SensorMeasurement>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '获取传感器数据详情失败';
const empty: SensorMeasurement = {
id: '', device_id: '', user_id: '', measurement_type: '', measured_at: '', unit: '', raw_data: new UTSJSONObject(), created_at: ''
};
return createErrorResponseFactory(empty)(errorMsg);
}
}
/**
* 获取最新的传感器测量数据(单条记录)
*/
static async getLatestMeasurement(params : SensorDataParams) : Promise<AkReqResponse<SensorMeasurement>> {
try {
let query = supa
.from('ss_sensor_measurements')
.select('*', {})
.order('measured_at', { ascending: false })
// 添加筛选条件
const deviceId = params.device_id
if (deviceId != null) {
query = query.eq('device_id', deviceId)
}
const userId = params.user_id
if (userId != null) {
query = query.eq('user_id', userId)
}
const measurementType = params.measurement_type
if (measurementType != null) {
query = query.eq('measurement_type', measurementType)
}
// 使用 single() 方法获取单条最新记录
const response = await query.single().executeAs<SensorMeasurement>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '获取最新传感器数据失败';
const empty: SensorMeasurement = {
id: '', device_id: '', user_id: '', measurement_type: '', measured_at: '', unit: '', raw_data: new UTSJSONObject(), created_at: ''
};
return createErrorResponseFactory(empty)(errorMsg);
}
}
/**
* 获取设备列表
*/
static async getDevices(params : DeviceParams) : Promise<AkReqResponse<Array<DeviceInfo>>> {
try {
let query = supa
.from('ak_devices')
.select('*', {})
.order('bind_time', { ascending: false })
// 添加筛选条件
const userId = params.user_id
if (userId != null) {
query = query.eq('user_id', userId)
}
const deviceType = params.device_type
if (deviceType != null) {
query = query.eq('device_type', deviceType)
}
const status = params.status
if (status != null) {
query = query.eq('status', status)
}
const response = await query.executeAs<DeviceInfo>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '获取设备列表失败';
return createErrorResponseFactory([] as DeviceInfo[])(errorMsg);
}
}
/**
* 获取设备详情
*/
static async getDeviceById(id : string) : Promise<AkReqResponse<Array<DeviceInfo>>> {
try {
const response = await supa
.from('ak_devices')
.select('*', {})
.eq('id', id)
.single()
.executeAs<DeviceInfo>()
console.log(response)
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '获取设备详情失败';
const empty: DeviceInfo = {
id: '', user_id: '', device_type: '', device_name: '', device_mac: '', bind_time: '', status: '', extra: new UTSJSONObject()
};
return createErrorResponseFactory(empty)(errorMsg);
}
}
/**
* 获取分析结果列表
*/
static async getAnalysisResults(user_id : string, analysis_type ?: string | null) : Promise<AkReqResponse<Array<SensorAnalysisResult>>> {
try {
let query = supa
.from('ak_sensor_analysis')
.select('*', {})
.eq('user_id', user_id)
.order('created_at', { ascending: false })
const analysisType = analysis_type
if (analysisType != null) {
query = query.eq('analysis_type', analysisType)
}
const response = await query.executeAs<SensorAnalysisResult>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '获取分析结果失败';
return createErrorResponseFactory([] as SensorAnalysisResult[])(errorMsg);
}
}/**
* 创建传感器测量数据 - 支持单个或批量
*/
static async createMeasurement(data : UTSJSONObject | Array<UTSJSONObject>) : Promise<AkReqResponse<SensorMeasurement | Array<SensorMeasurement>>> {
return await this.insertMeasurementData(data)
}/**
* 批量创建传感器测量数据(用于模拟器)
* @deprecated 使用 createMeasurement 方法,它现在支持批量插入
*/
static async createMeasurements(dataList : Array<UTSJSONObject>) : Promise<AkReqResponse<Array<SensorMeasurement>>> {
const result = await this.createMeasurement(dataList)
return result as AkReqResponse<Array<SensorMeasurement>>
}
/**
* 绑定设备
*/
static async bindDevice(deviceData : UTSJSONObject) : Promise<AkReqResponse<DeviceInfo>> {
try {
const data = new UTSJSONObject()
// 复制传入的数据
const keys = UTSJSONObject.keys(data)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
data.set(key, deviceData.get(key))
}
data.set('bind_time', new Date().toISOString())
data.set('status', 'online')
const response = await supa
.from('ak_devices')
.insert(data)
.select('*', {})
.single()
.executeAs<DeviceInfo>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '绑定设备失败';
const empty: DeviceInfo = {
id: '', user_id: '', device_type: '', device_name: '', device_mac: '', bind_time: '', status: '', extra: new UTSJSONObject()
};
return createErrorResponseFactory(empty)(errorMsg);
}
}
/**
* 更新设备状态
*/
static async updateDeviceStatus(device_id : string, status : string) : Promise<AkReqResponse<DeviceInfo>> {
try {
const response = await supa
.from('ak_devices')
.update({ status: status })
.eq('id', device_id)
.select('*', {})
.single()
.executeAs<DeviceInfo>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '更新设备状态失败';
const empty: DeviceInfo = {
id: '', user_id: '', device_type: '', device_name: '', device_mac: '', bind_time: '', status: '', extra: new UTSJSONObject()
};
return createErrorResponseFactory(empty)(errorMsg);
}
}
/**
* 解绑设备
*/
static async unbindDevice(device_id : string) : Promise<AkReqResponse<boolean>> {
try {
const response = await supa
.from('ak_devices')
.delete()
.eq('id', device_id)
.execute()
if (response.error === null) {
return {
status: 200,
data: true,
headers: {},
error: null,
total: null,
page: null,
limit: null,
hasmore: null,
origin: null
}
} else {
return createErrorResponseFactory(false)(response.error?.message ?? '设备解绑失败');
}
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '设备解绑失败';
return createErrorResponseFactory(false)(errorMsg);
}
}
/**
* 更新设备信息
*/
static async updateDevice(device_id : string, deviceData : UTSJSONObject) : Promise<AkReqResponse<DeviceInfo>> {
try {
const response = await supa
.from('ak_devices')
.update(deviceData)
.eq('id', device_id)
.select('*', {})
.single()
.executeAs<DeviceInfo>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '更新设备信息失败';
const empty: DeviceInfo = {
id: '', user_id: '', device_type: '', device_name: '', device_mac: '', bind_time: '', status: '', extra: new UTSJSONObject()
};
return createErrorResponseFactory(empty)(errorMsg);
}
}
/**
* 统一的插入方法 - 支持单个或批量插入
* @param data 单个对象或对象数组
* @returns 插入结果
*/
static async insertMeasurements(data : UTSJSONObject | Array<UTSJSONObject>) : Promise<AkReqResponse<SensorMeasurement | Array<SensorMeasurement>>> {
try {
let processedData : UTSJSONObject | Array<UTSJSONObject>
let isBatch = false
if (Array.isArray(data)) {
// 批量插入
isBatch = true
const measurementDataList : Array<UTSJSONObject> = []
for (let i = 0; i < data.length; i++) {
const item = data[i]
const measurementData = new UTSJSONObject()
// 复制传入的数据
const keys = UTSJSONObject.keys(item)
for (let j = 0; j < keys.length; j++) {
const key = keys[j]
measurementData.set(key, item.get(key))
}
measurementData.set('created_at', new Date().toISOString())
measurementDataList.push(measurementData)
}
processedData = measurementDataList
} else {
// 单个插入
const measurementData = new UTSJSONObject()
// 复制传入的数据
const keys = UTSJSONObject.keys(data)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
measurementData.set(key, data.get(key))
}
measurementData.set('created_at', new Date().toISOString())
processedData = measurementData
}
let query = supa
.from('ss_sensor_measurements')
.insert(processedData)
.select('*', {})
// 根据是否批量决定是否使用 single()
if (!isBatch) {
query = query.single()
}
if (isBatch) {
const response = await query.executeAs<SensorMeasurement>()
return response
} else {
const response = await query.executeAs<SensorMeasurement>()
return response
}
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? (Array.isArray(data) ? '批量创建传感器数据失败' : '创建传感器数据失败');
const empty: SensorMeasurement = {
id: '', device_id: '', user_id: '', measurement_type: '', measured_at: '', unit: '', raw_data: new UTSJSONObject(), created_at: ''
};
const errorSensorMeasurement = createErrorResponseFactory(empty);
const errorSensorMeasurementArr = createErrorResponseFactory([] as SensorMeasurement[]);
if (Array.isArray(data)) {
return errorSensorMeasurementArr(errorMsg) as AkReqResponse<SensorMeasurement | Array<SensorMeasurement>>;
} else {
return errorSensorMeasurement(errorMsg) as AkReqResponse<SensorMeasurement | Array<SensorMeasurement>>;
}
}
}
/**
* 传感器测量数据插入方法 - 支持单个或批量插入
* @param data 单个对象或对象数组
* @returns 插入结果
*/
static async insertMeasurementData(data : UTSJSONObject | Array<UTSJSONObject>) : Promise<AkReqResponse<Array<SensorMeasurement>>> {
try {
let processedData : UTSJSONObject | Array<UTSJSONObject>
let isBatch = Array.isArray(data)
if (isBatch) {
// 批量插入
const dataList : Array<UTSJSONObject> = []
const dataArray = data as Array<UTSJSONObject>
for (let i = 0; i < dataArray.length; i++) {
const item = dataArray[i]
const processedItem = new UTSJSONObject()
// 复制传入的数据
const keys = UTSJSONObject.keys(item)
for (let j = 0; j < keys.length; j++) {
const key = keys[j]
processedItem.set(key, item.get(key))
}
processedItem.set('created_at', new Date().toISOString())
dataList.push(processedItem)
}
processedData = dataList
} else {
// 单个插入
const singleData = data as UTSJSONObject
const processedItem = new UTSJSONObject()
// 复制传入的数据
const keys = UTSJSONObject.keys(singleData)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
processedItem.set(key, singleData.get(key))
}
processedItem.set('created_at', new Date().toISOString())
processedData = processedItem
}
let query = supa
.from('ss_sensor_measurements')
.insert(processedData)
const response = await query.executeAs<SensorMeasurement>()
return response
} catch (error) {
const errorMsg = typeof error === 'string' ? error : error?.message ?? '插入传感器数据失败';
return createErrorResponseFactory([] as SensorMeasurement[])(errorMsg) as AkReqResponse<SensorMeasurement | Array<SensorMeasurement>>;
}
}
}