Initial commit of akmon project
This commit is contained in:
507
pages/sense/senseDataService.uts
Normal file
507
pages/sense/senseDataService.uts
Normal 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>>;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user