372 lines
14 KiB
PL/PgSQL
372 lines
14 KiB
PL/PgSQL
-- 可穿戴设备管理扩展表和数据
|
|
-- 扩展现有的 ak_devices 表,添加可穿戴设备特有的信息
|
|
|
|
-- 设备类型表 - 定义各种设备类型的详细信息
|
|
CREATE TABLE IF NOT EXISTS public.ak_device_types (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
type_code VARCHAR(32) UNIQUE NOT NULL, -- 设备类型代码
|
|
type_name VARCHAR(64) NOT NULL, -- 设备类型名称
|
|
category VARCHAR(32) NOT NULL, -- 设备分类 (wearable, sensor, scale等)
|
|
icon VARCHAR(32), -- 图标标识
|
|
description TEXT, -- 设备描述
|
|
supported_features TEXT[], -- 支持的功能列表
|
|
battery_life_hours INT DEFAULT 168, -- 预期电池续航时间(小时)
|
|
connection_types TEXT[] DEFAULT ARRAY['bluetooth'], -- 连接方式
|
|
is_active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
|
);
|
|
COMMENT ON TABLE public.ak_device_types IS '设备类型定义表';
|
|
|
|
-- 插入可穿戴设备类型数据
|
|
INSERT INTO public.ak_device_types (type_code, type_name, category, icon, description, supported_features, battery_life_hours, connection_types) VALUES
|
|
('smart_band', '智能手环', 'wearable', '⌚', '轻便的腕戴式健康监测设备', ARRAY['heart_rate', 'steps', 'sleep', 'notifications'], 168, ARRAY['bluetooth']),
|
|
('smart_watch', '智能手表', 'wearable', '⌚', '功能丰富的智能穿戴设备', ARRAY['heart_rate', 'steps', 'sleep', 'gps', 'calls', 'apps'], 48, ARRAY['bluetooth', 'wifi']),
|
|
('smart_ring', '智能指环', 'wearable', '💍', '极简设计的指戴式健康监测设备', ARRAY['heart_rate', 'sleep', 'temperature'], 240, ARRAY['bluetooth']),
|
|
('heart_rate_monitor', '心率监测器', 'sensor', '❤️', '专业的心率监测设备', ARRAY['heart_rate', 'hrv'], 720, ARRAY['bluetooth', 'ant+']),
|
|
('fitness_tracker', '健身追踪器', 'wearable', '🏃', '专注运动数据追踪的设备', ARRAY['steps', 'calories', 'distance', 'workout'], 120, ARRAY['bluetooth']),
|
|
('smart_scale', '智能体重秤', 'scale', '⚖️', '智能体重和身体成分测量设备', ARRAY['weight', 'body_fat', 'muscle_mass', 'bone_mass'], 8760, ARRAY['bluetooth', 'wifi']),
|
|
('blood_pressure_monitor', '血压监测器', 'sensor', '🩺', '血压和脉搏监测设备', ARRAY['blood_pressure', 'pulse'], 720, ARRAY['bluetooth']),
|
|
('smart_earbuds', '智能耳机', 'wearable', '🎧', '具备健康监测功能的智能耳机', ARRAY['heart_rate', 'steps', 'music'], 24, ARRAY['bluetooth']),
|
|
('posture_monitor', '姿态监测器', 'sensor', '🧘', '姿态和动作分析设备', ARRAY['posture', 'movement', 'vibration_alert'], 240, ARRAY['bluetooth']),
|
|
('sleep_monitor', '睡眠监测器', 'sensor', '😴', '专业的睡眠质量监测设备', ARRAY['sleep', 'breathing', 'temperature'], 720, ARRAY['bluetooth']);
|
|
|
|
-- 设备状态历史表 - 记录设备状态变化
|
|
CREATE TABLE IF NOT EXISTS public.ak_device_status_history (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
device_id uuid REFERENCES public.ak_devices(id) ON DELETE CASCADE,
|
|
status VARCHAR(16) NOT NULL, -- active, offline, charging, low_battery, error
|
|
battery_level INT, -- 电池电量百分比
|
|
firmware_version VARCHAR(32), -- 固件版本
|
|
last_sync_time TIMESTAMP WITH TIME ZONE, -- 最后同步时间
|
|
signal_strength INT, -- 信号强度 (-100 to 0 dBm)
|
|
extra_data JSONB, -- 其他状态数据
|
|
recorded_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
|
);
|
|
COMMENT ON TABLE public.ak_device_status_history IS '设备状态历史记录表';
|
|
|
|
CREATE INDEX idx_device_status_history_device_id ON public.ak_device_status_history(device_id);
|
|
CREATE INDEX idx_device_status_history_recorded_at ON public.ak_device_status_history(recorded_at);
|
|
|
|
-- 设备设置表 - 存储设备的个性化设置
|
|
CREATE TABLE IF NOT EXISTS public.ak_device_settings (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
device_id uuid REFERENCES public.ak_devices(id) ON DELETE CASCADE,
|
|
setting_key VARCHAR(64) NOT NULL, -- 设置项名称
|
|
setting_value TEXT, -- 设置值
|
|
data_type VARCHAR(16) DEFAULT 'string', -- string, number, boolean, json
|
|
description TEXT, -- 设置描述
|
|
is_user_configurable BOOLEAN DEFAULT true, -- 用户是否可配置
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
|
);
|
|
COMMENT ON TABLE public.ak_device_settings IS '设备个性化设置表';
|
|
|
|
CREATE INDEX idx_device_settings_device_id ON public.ak_device_settings(device_id);
|
|
CREATE UNIQUE INDEX idx_device_settings_unique ON public.ak_device_settings(device_id, setting_key);
|
|
|
|
-- 设备数据同步记录表
|
|
CREATE TABLE IF NOT EXISTS public.ak_device_sync_logs (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
device_id uuid REFERENCES public.ak_devices(id) ON DELETE CASCADE,
|
|
sync_type VARCHAR(32) NOT NULL, -- full, incremental, health_data, settings
|
|
sync_status VARCHAR(16) NOT NULL, -- started, success, failed, partial
|
|
records_synced INT DEFAULT 0, -- 同步的记录数
|
|
data_size_bytes BIGINT DEFAULT 0, -- 同步的数据大小
|
|
start_time TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
|
end_time TIMESTAMP WITH TIME ZONE,
|
|
error_message TEXT, -- 错误信息
|
|
sync_details JSONB -- 同步详情
|
|
);
|
|
COMMENT ON TABLE public.ak_device_sync_logs IS '设备数据同步日志表';
|
|
|
|
CREATE INDEX idx_device_sync_logs_device_id ON public.ak_device_sync_logs(device_id);
|
|
CREATE INDEX idx_device_sync_logs_start_time ON public.ak_device_sync_logs(start_time);
|
|
|
|
-- 插入一些示例设备设置
|
|
INSERT INTO public.ak_device_settings (device_id, setting_key, setting_value, data_type, description, is_user_configurable)
|
|
SELECT
|
|
d.id,
|
|
setting_key,
|
|
setting_value,
|
|
data_type,
|
|
description,
|
|
is_user_configurable
|
|
FROM public.ak_devices d
|
|
CROSS JOIN (
|
|
VALUES
|
|
('heart_rate_alert_enabled', 'true', 'boolean', '心率异常提醒开关', true),
|
|
('heart_rate_alert_threshold', '100', 'number', '心率提醒阈值(bpm)', true),
|
|
('step_goal', '10000', 'number', '每日步数目标', true),
|
|
('notification_enabled', 'true', 'boolean', '通知推送开关', true),
|
|
('auto_sleep_detection', 'true', 'boolean', '自动睡眠检测', true),
|
|
('vibration_intensity', 'medium', 'string', '震动强度设置', true),
|
|
('display_brightness', '80', 'number', '屏幕亮度百分比', true),
|
|
('auto_sync_interval', '30', 'number', '自动同步间隔(分钟)', true),
|
|
('sedentary_reminder', 'true', 'boolean', '久坐提醒', true),
|
|
('water_reminder_interval', '120', 'number', '喝水提醒间隔(分钟)', true)
|
|
) AS settings(setting_key, setting_value, data_type, description, is_user_configurable)
|
|
WHERE d.device_type IN ('smart_band', 'smart_watch', 'fitness_tracker')
|
|
ON CONFLICT (device_id, setting_key) DO NOTHING;
|
|
|
|
-- 创建获取设备详细信息的函数
|
|
CREATE OR REPLACE FUNCTION get_device_details(p_device_id uuid)
|
|
RETURNS TABLE (
|
|
device_id uuid,
|
|
device_name VARCHAR(64),
|
|
device_type VARCHAR(32),
|
|
device_mac VARCHAR(64),
|
|
status VARCHAR(16),
|
|
battery_level INT,
|
|
last_sync TIMESTAMP WITH TIME ZONE,
|
|
firmware_version VARCHAR(32),
|
|
bind_time TIMESTAMP WITH TIME ZONE,
|
|
type_info JSONB,
|
|
recent_settings JSONB,
|
|
sync_stats JSONB
|
|
)
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
d.id,
|
|
d.device_name,
|
|
d.device_type,
|
|
d.device_mac,
|
|
d.status,
|
|
(d.extra->>'battery')::INT as battery_level,
|
|
(d.extra->>'last_sync')::TIMESTAMP WITH TIME ZONE as last_sync,
|
|
d.extra->>'firmware_version' as firmware_version,
|
|
d.bind_time,
|
|
|
|
-- 设备类型信息
|
|
CASE
|
|
WHEN dt.id IS NOT NULL THEN
|
|
jsonb_build_object(
|
|
'type_name', dt.type_name,
|
|
'category', dt.category,
|
|
'icon', dt.icon,
|
|
'description', dt.description,
|
|
'supported_features', dt.supported_features,
|
|
'battery_life_hours', dt.battery_life_hours,
|
|
'connection_types', dt.connection_types
|
|
)
|
|
ELSE NULL
|
|
END as type_info,
|
|
|
|
-- 最近的设备设置
|
|
COALESCE(
|
|
(
|
|
SELECT jsonb_object_agg(ds.setting_key, ds.setting_value)
|
|
FROM public.ak_device_settings ds
|
|
WHERE ds.device_id = d.id
|
|
AND ds.is_user_configurable = true
|
|
LIMIT 10
|
|
),
|
|
'{}'::jsonb
|
|
) as recent_settings,
|
|
|
|
-- 同步统计
|
|
COALESCE(
|
|
(
|
|
SELECT jsonb_build_object(
|
|
'total_syncs', COUNT(*),
|
|
'successful_syncs', COUNT(*) FILTER (WHERE sync_status = 'success'),
|
|
'last_sync_time', MAX(start_time),
|
|
'last_sync_status', (
|
|
SELECT sync_status
|
|
FROM public.ak_device_sync_logs dsl2
|
|
WHERE dsl2.device_id = d.id
|
|
ORDER BY start_time DESC
|
|
LIMIT 1
|
|
)
|
|
)
|
|
FROM public.ak_device_sync_logs dsl
|
|
WHERE dsl.device_id = d.id
|
|
AND dsl.start_time >= CURRENT_DATE - INTERVAL '30 days'
|
|
),
|
|
jsonb_build_object('total_syncs', 0, 'successful_syncs', 0)
|
|
) as sync_stats
|
|
|
|
FROM public.ak_devices d
|
|
LEFT JOIN public.ak_device_types dt ON dt.type_code = d.device_type
|
|
WHERE d.id = p_device_id;
|
|
END;
|
|
$$;
|
|
|
|
-- 创建获取用户设备统计的函数
|
|
CREATE OR REPLACE FUNCTION get_user_device_stats(p_user_id uuid)
|
|
RETURNS TABLE (
|
|
total_devices INT,
|
|
active_devices INT,
|
|
online_devices INT,
|
|
low_battery_devices INT,
|
|
device_type_distribution JSONB,
|
|
recent_activity JSONB
|
|
)
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
COUNT(*)::INT as total_devices,
|
|
COUNT(*) FILTER (WHERE d.status = 'active')::INT as active_devices,
|
|
COUNT(*) FILTER (
|
|
WHERE d.status = 'active'
|
|
AND (d.extra->>'last_sync')::TIMESTAMP WITH TIME ZONE > NOW() - INTERVAL '30 minutes'
|
|
)::INT as online_devices,
|
|
COUNT(*) FILTER (
|
|
WHERE (d.extra->>'battery')::INT < 20
|
|
)::INT as low_battery_devices,
|
|
|
|
-- 设备类型分布
|
|
COALESCE(
|
|
jsonb_object_agg(
|
|
d.device_type,
|
|
COUNT(*)
|
|
) FILTER (WHERE d.device_type IS NOT NULL),
|
|
'{}'::jsonb
|
|
) as device_type_distribution,
|
|
|
|
-- 最近活动
|
|
COALESCE(
|
|
(
|
|
SELECT jsonb_build_object(
|
|
'recent_syncs', COUNT(*),
|
|
'successful_syncs', COUNT(*) FILTER (WHERE sync_status = 'success'),
|
|
'last_24h_syncs', COUNT(*) FILTER (WHERE start_time >= NOW() - INTERVAL '24 hours')
|
|
)
|
|
FROM public.ak_device_sync_logs dsl
|
|
JOIN public.ak_devices dd ON dd.id = dsl.device_id
|
|
WHERE dd.user_id = p_user_id
|
|
AND dsl.start_time >= NOW() - INTERVAL '7 days'
|
|
),
|
|
jsonb_build_object('recent_syncs', 0, 'successful_syncs', 0, 'last_24h_syncs', 0)
|
|
) as recent_activity
|
|
|
|
FROM public.ak_devices d
|
|
WHERE d.user_id = p_user_id;
|
|
END;
|
|
$$;
|
|
|
|
-- 创建更新设备状态的函数
|
|
CREATE OR REPLACE FUNCTION update_device_status(
|
|
p_device_id uuid,
|
|
p_status VARCHAR(16),
|
|
p_battery_level INT DEFAULT NULL,
|
|
p_firmware_version VARCHAR(32) DEFAULT NULL,
|
|
p_signal_strength INT DEFAULT NULL,
|
|
p_extra_data JSONB DEFAULT NULL
|
|
)
|
|
RETURNS BOOLEAN
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
device_exists BOOLEAN;
|
|
BEGIN
|
|
-- 检查设备是否存在
|
|
SELECT EXISTS(
|
|
SELECT 1 FROM public.ak_devices
|
|
WHERE id = p_device_id
|
|
) INTO device_exists;
|
|
|
|
IF NOT device_exists THEN
|
|
RETURN FALSE;
|
|
END IF;
|
|
|
|
-- 更新设备表中的状态
|
|
UPDATE public.ak_devices
|
|
SET
|
|
status = p_status,
|
|
extra = extra || jsonb_build_object(
|
|
'battery', COALESCE(p_battery_level, (extra->>'battery')::INT),
|
|
'firmware_version', COALESCE(p_firmware_version, extra->>'firmware_version'),
|
|
'last_sync', CURRENT_TIMESTAMP
|
|
)
|
|
WHERE id = p_device_id;
|
|
|
|
-- 记录状态变化历史
|
|
INSERT INTO public.ak_device_status_history (
|
|
device_id,
|
|
status,
|
|
battery_level,
|
|
firmware_version,
|
|
last_sync_time,
|
|
signal_strength,
|
|
extra_data
|
|
) VALUES (
|
|
p_device_id,
|
|
p_status,
|
|
p_battery_level,
|
|
p_firmware_version,
|
|
CURRENT_TIMESTAMP,
|
|
p_signal_strength,
|
|
p_extra_data
|
|
);
|
|
|
|
RETURN TRUE;
|
|
END;
|
|
$$;
|
|
|
|
-- 创建设备数据同步记录函数
|
|
CREATE OR REPLACE FUNCTION log_device_sync(
|
|
p_device_id uuid,
|
|
p_sync_type VARCHAR(32),
|
|
p_sync_status VARCHAR(16),
|
|
p_records_synced INT DEFAULT 0,
|
|
p_data_size_bytes BIGINT DEFAULT 0,
|
|
p_error_message TEXT DEFAULT NULL,
|
|
p_sync_details JSONB DEFAULT NULL
|
|
)
|
|
RETURNS uuid
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
sync_log_id uuid;
|
|
BEGIN
|
|
INSERT INTO public.ak_device_sync_logs (
|
|
device_id,
|
|
sync_type,
|
|
sync_status,
|
|
records_synced,
|
|
data_size_bytes,
|
|
end_time,
|
|
error_message,
|
|
sync_details
|
|
) VALUES (
|
|
p_device_id,
|
|
p_sync_type,
|
|
p_sync_status,
|
|
p_records_synced,
|
|
p_data_size_bytes,
|
|
CASE WHEN p_sync_status IN ('success', 'failed', 'partial') THEN CURRENT_TIMESTAMP ELSE NULL END,
|
|
p_error_message,
|
|
p_sync_details
|
|
) RETURNING id INTO sync_log_id;
|
|
|
|
RETURN sync_log_id;
|
|
END;
|
|
$$;
|
|
|
|
-- 创建清理旧数据的函数
|
|
CREATE OR REPLACE FUNCTION cleanup_device_old_data(p_days_to_keep INT DEFAULT 90)
|
|
RETURNS INT
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
deleted_count INT;
|
|
BEGIN
|
|
-- 清理旧的状态历史记录
|
|
DELETE FROM public.ak_device_status_history
|
|
WHERE recorded_at < CURRENT_DATE - INTERVAL '1 day' * p_days_to_keep;
|
|
|
|
GET DIAGNOSTICS deleted_count = ROW_COUNT;
|
|
|
|
-- 清理旧的同步日志
|
|
DELETE FROM public.ak_device_sync_logs
|
|
WHERE start_time < CURRENT_DATE - INTERVAL '1 day' * p_days_to_keep;
|
|
|
|
RETURN deleted_count;
|
|
END;
|
|
$$;
|