Files
akmon/pages/sense/senseDataService.uts
2026-01-20 08:04:15 +08:00

507 lines
15 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 传感器数据服务 - 使用 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>>;
}
}
}