Initial commit of akmon project
This commit is contained in:
423
mock_location.sql
Normal file
423
mock_location.sql
Normal file
@@ -0,0 +1,423 @@
|
||||
-- mock_location.sql
|
||||
-- Populates deterministic wearable location data for demos and local development.
|
||||
-- Requires schema from doc_chat/locations.sql and zhipao.sql (users/devices tables).
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Stable identifiers reused across the script to keep reruns idempotent.
|
||||
CREATE TEMP TABLE __mock_actor AS
|
||||
SELECT
|
||||
'eed3824b-bba1-4309-8048-19d17367c084'::UUID AS user_id,
|
||||
'b2d0aabd-4f7d-42c8-a7a8-9d5b4c67d222'::UUID AS device_id;
|
||||
|
||||
CREATE TEMP TABLE __mock_gateways AS
|
||||
SELECT *
|
||||
FROM (
|
||||
VALUES
|
||||
(
|
||||
'11111111-aaaa-bbbb-cccc-000000000001'::UUID,
|
||||
'北侧主楼网关',
|
||||
'MOCK-GW-NORTH',
|
||||
'active',
|
||||
'main',
|
||||
'north-zone',
|
||||
'教学楼A',
|
||||
'3F',
|
||||
'301',
|
||||
31.230900,
|
||||
121.473200,
|
||||
'WGS84',
|
||||
35.0,
|
||||
30,
|
||||
3.5,
|
||||
0.0,
|
||||
'Mock gateway providing northern coverage',
|
||||
-51.0,
|
||||
12.0
|
||||
),
|
||||
(
|
||||
'11111111-aaaa-bbbb-cccc-000000000002'::UUID,
|
||||
'南侧体育馆网关',
|
||||
'MOCK-GW-SOUTH',
|
||||
'active',
|
||||
'main',
|
||||
'south-zone',
|
||||
'体育馆',
|
||||
'1F',
|
||||
'大厅',
|
||||
31.229700,
|
||||
121.473400,
|
||||
'WGS84',
|
||||
40.0,
|
||||
30,
|
||||
4.0,
|
||||
180.0,
|
||||
'Mock gateway covering southern sports hall',
|
||||
-56.0,
|
||||
11.5
|
||||
),
|
||||
(
|
||||
'11111111-aaaa-bbbb-cccc-000000000003'::UUID,
|
||||
'东侧宿舍楼网关',
|
||||
'MOCK-GW-EAST',
|
||||
'active',
|
||||
'main',
|
||||
'east-zone',
|
||||
'宿舍楼C',
|
||||
'2F',
|
||||
'走廊',
|
||||
31.230100,
|
||||
121.474500,
|
||||
'WGS84',
|
||||
30.0,
|
||||
30,
|
||||
3.0,
|
||||
90.0,
|
||||
'Mock gateway for east dormitory coverage',
|
||||
-53.5,
|
||||
12.5
|
||||
)
|
||||
) AS g(
|
||||
gateway_id,
|
||||
name,
|
||||
system_code,
|
||||
status,
|
||||
campus_code,
|
||||
area_name,
|
||||
building_name,
|
||||
floor_label,
|
||||
room_label,
|
||||
latitude,
|
||||
longitude,
|
||||
coordinate_system,
|
||||
coverage_radius_m,
|
||||
heartbeat_interval_s,
|
||||
install_height_m,
|
||||
orientation_deg,
|
||||
description,
|
||||
base_rssi_dbm,
|
||||
base_snr_db
|
||||
);
|
||||
|
||||
-- Ensure the mock user exists.
|
||||
INSERT INTO public.ak_users (id, username, email, password_hash, role, created_at, updated_at)
|
||||
SELECT
|
||||
actor.user_id,
|
||||
'mock_location_user',
|
||||
'mock_location_user@example.com',
|
||||
crypt('Mock@123', gen_salt('bf')),
|
||||
'student',
|
||||
NOW(),
|
||||
NOW()
|
||||
FROM __mock_actor actor
|
||||
ON CONFLICT (id) DO UPDATE
|
||||
SET
|
||||
username = EXCLUDED.username,
|
||||
email = EXCLUDED.email,
|
||||
password_hash = EXCLUDED.password_hash,
|
||||
updated_at = NOW();
|
||||
|
||||
-- Ensure the mock device exists.
|
||||
INSERT INTO public.ak_devices (
|
||||
id,
|
||||
user_id,
|
||||
device_type,
|
||||
device_name,
|
||||
device_mac,
|
||||
bind_time,
|
||||
status,
|
||||
extra
|
||||
)
|
||||
SELECT
|
||||
actor.device_id,
|
||||
actor.user_id,
|
||||
'wristband',
|
||||
'模拟定位手环',
|
||||
'AA-BB-CC-11-22-33',
|
||||
NOW(),
|
||||
'active',
|
||||
jsonb_build_object(
|
||||
'firmware_version', 'mock-1.0',
|
||||
'hardware_revision', 'rev-A',
|
||||
'notes', 'Mocked location feed device for UI demos'
|
||||
)
|
||||
FROM __mock_actor actor
|
||||
ON CONFLICT (id) DO UPDATE
|
||||
SET
|
||||
user_id = EXCLUDED.user_id,
|
||||
device_type = EXCLUDED.device_type,
|
||||
device_name = EXCLUDED.device_name,
|
||||
device_mac = EXCLUDED.device_mac,
|
||||
status = EXCLUDED.status,
|
||||
extra = EXCLUDED.extra,
|
||||
bind_time = EXCLUDED.bind_time;
|
||||
|
||||
-- Ensure reference gateways are present (upsert by primary key).
|
||||
INSERT INTO location_gateways (
|
||||
id,
|
||||
name,
|
||||
system_code,
|
||||
status,
|
||||
campus_code,
|
||||
area_name,
|
||||
building_name,
|
||||
floor_label,
|
||||
room_label,
|
||||
latitude,
|
||||
longitude,
|
||||
coordinate_system,
|
||||
coverage_radius_m,
|
||||
heartbeat_interval_s,
|
||||
install_height_m,
|
||||
orientation_deg,
|
||||
description
|
||||
)
|
||||
SELECT
|
||||
gateway_id,
|
||||
name,
|
||||
system_code,
|
||||
status,
|
||||
campus_code,
|
||||
area_name,
|
||||
building_name,
|
||||
floor_label,
|
||||
room_label,
|
||||
latitude,
|
||||
longitude,
|
||||
coordinate_system,
|
||||
coverage_radius_m,
|
||||
heartbeat_interval_s,
|
||||
install_height_m,
|
||||
orientation_deg,
|
||||
description
|
||||
FROM __mock_gateways g
|
||||
ON CONFLICT (id) DO UPDATE
|
||||
SET
|
||||
name = EXCLUDED.name,
|
||||
system_code = EXCLUDED.system_code,
|
||||
status = EXCLUDED.status,
|
||||
campus_code = EXCLUDED.campus_code,
|
||||
area_name = EXCLUDED.area_name,
|
||||
building_name = EXCLUDED.building_name,
|
||||
floor_label = EXCLUDED.floor_label,
|
||||
room_label = EXCLUDED.room_label,
|
||||
latitude = EXCLUDED.latitude,
|
||||
longitude = EXCLUDED.longitude,
|
||||
coordinate_system = EXCLUDED.coordinate_system,
|
||||
coverage_radius_m = EXCLUDED.coverage_radius_m,
|
||||
heartbeat_interval_s = EXCLUDED.heartbeat_interval_s,
|
||||
install_height_m = EXCLUDED.install_height_m,
|
||||
orientation_deg = EXCLUDED.orientation_deg,
|
||||
description = EXCLUDED.description,
|
||||
updated_at = NOW();
|
||||
|
||||
-- Clear any previous mock data for the device to keep reruns idempotent.
|
||||
WITH actor AS (SELECT device_id FROM __mock_actor)
|
||||
DELETE FROM wearable_location_snapshots s
|
||||
WHERE s.device_id = (SELECT device_id FROM actor);
|
||||
|
||||
-- Configuration and synthetic data generation (5-second cadence for 10 minutes).
|
||||
WITH params AS (
|
||||
SELECT
|
||||
NOW() - INTERVAL '10 minutes' AS window_start,
|
||||
INTERVAL '5 seconds' AS cadence_interval,
|
||||
120 AS sample_count,
|
||||
22.0 AS base_radius_m,
|
||||
0.92 AS base_confidence
|
||||
),
|
||||
timeline AS (
|
||||
SELECT
|
||||
actor.device_id,
|
||||
actor.user_id,
|
||||
params.window_start + params.cadence_interval * seq AS estimated_at,
|
||||
seq
|
||||
FROM __mock_actor actor,
|
||||
params,
|
||||
generate_series(0, (SELECT sample_count FROM params) - 1) AS seq
|
||||
),
|
||||
path AS (
|
||||
SELECT
|
||||
t.device_id,
|
||||
t.user_id,
|
||||
t.estimated_at,
|
||||
t.seq,
|
||||
31.230300 + 0.00025 * SIN(2 * PI() * t.seq / 40.0) AS latitude,
|
||||
121.473800 + 0.00035 * COS(2 * PI() * t.seq / 40.0) AS longitude,
|
||||
6.5 + 0.2 * SIN(2 * PI() * t.seq / 20.0) AS altitude_m,
|
||||
(SELECT base_radius_m FROM params) + 1.5 * RANDOM() AS uncertainty_radius_m,
|
||||
LEAST(0.99, (SELECT base_confidence FROM params) + 0.05 * RANDOM()) AS confidence
|
||||
FROM timeline t
|
||||
),
|
||||
observation_samples AS (
|
||||
SELECT
|
||||
p.device_id,
|
||||
p.user_id,
|
||||
p.estimated_at,
|
||||
g.gateway_id,
|
||||
g.name AS gateway_name,
|
||||
g.system_code,
|
||||
g.latitude,
|
||||
g.longitude,
|
||||
g.orientation_deg,
|
||||
g.description,
|
||||
(g.base_rssi_dbm + (-3 + RANDOM() * 6))::NUMERIC(5, 2) AS rssi_dbm,
|
||||
(g.base_snr_db + (-0.5 + RANDOM()))::NUMERIC(5, 2) AS snr_db,
|
||||
(18 + RANDOM() * 6)::NUMERIC(7, 2) AS distance_m,
|
||||
(11 + (RANDOM() * 2))::INT AS channel,
|
||||
ROUND((2402 + RANDOM() * 4)::NUMERIC, 2) AS frequency_mhz,
|
||||
(1000 + FLOOR(RANDOM() * 2000))::INT AS packet_sequence,
|
||||
(5 + FLOOR(RANDOM() * 8))::INT AS latency_ms,
|
||||
'gw-firmware-mock-1.0' AS firmware_version,
|
||||
(3.75 + RANDOM() * 0.05)::NUMERIC(6, 3) AS battery_voltage,
|
||||
(25.5 + RANDOM() * 1.5)::NUMERIC(4, 1) AS temperature_c
|
||||
FROM path p
|
||||
CROSS JOIN __mock_gateways g
|
||||
),
|
||||
snapshot_payload AS (
|
||||
SELECT
|
||||
p.device_id,
|
||||
p.user_id,
|
||||
p.estimated_at,
|
||||
p.latitude,
|
||||
p.longitude,
|
||||
p.altitude_m,
|
||||
p.uncertainty_radius_m,
|
||||
p.confidence,
|
||||
p.seq,
|
||||
COUNT(os.gateway_id)::INT AS observation_count,
|
||||
jsonb_agg(
|
||||
jsonb_build_object(
|
||||
'gateway_id', os.gateway_id,
|
||||
'name', os.gateway_name,
|
||||
'system_code', os.system_code,
|
||||
'rssi_dbm', os.rssi_dbm,
|
||||
'snr_db', os.snr_db,
|
||||
'distance_m', os.distance_m,
|
||||
'battery_voltage', os.battery_voltage,
|
||||
'temperature_c', os.temperature_c
|
||||
) ORDER BY os.gateway_id
|
||||
) AS observations_json,
|
||||
jsonb_build_object(
|
||||
'path_index', p.seq,
|
||||
'source', 'mock_location.sql',
|
||||
'mean_distance_m', ROUND(AVG(os.distance_m)::NUMERIC, 2),
|
||||
'mean_snr_db', ROUND(AVG(os.snr_db)::NUMERIC, 2)
|
||||
) AS diagnostics_json
|
||||
FROM path p
|
||||
JOIN observation_samples os
|
||||
ON os.device_id = p.device_id
|
||||
AND os.user_id = p.user_id
|
||||
AND os.estimated_at = p.estimated_at
|
||||
GROUP BY
|
||||
p.device_id,
|
||||
p.user_id,
|
||||
p.estimated_at,
|
||||
p.latitude,
|
||||
p.longitude,
|
||||
p.altitude_m,
|
||||
p.uncertainty_radius_m,
|
||||
p.confidence,
|
||||
p.seq
|
||||
),
|
||||
inserted_snapshots AS (
|
||||
INSERT INTO wearable_location_snapshots (
|
||||
device_id,
|
||||
user_id,
|
||||
estimated_at,
|
||||
window_started_at,
|
||||
window_ended_at,
|
||||
latitude,
|
||||
longitude,
|
||||
altitude_m,
|
||||
coordinate_system,
|
||||
uncertainty_radius_m,
|
||||
confidence,
|
||||
method,
|
||||
algorithm_version,
|
||||
observation_count,
|
||||
campus_code,
|
||||
area_name,
|
||||
building_name,
|
||||
floor_label,
|
||||
room_label,
|
||||
observations,
|
||||
diagnostics,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
sp.device_id,
|
||||
sp.user_id,
|
||||
sp.estimated_at,
|
||||
sp.estimated_at - INTERVAL '2 seconds',
|
||||
sp.estimated_at + INTERVAL '2 seconds',
|
||||
sp.latitude,
|
||||
sp.longitude,
|
||||
sp.altitude_m,
|
||||
'WGS84',
|
||||
sp.uncertainty_radius_m,
|
||||
sp.confidence,
|
||||
'trilateration',
|
||||
'mock-v1',
|
||||
sp.observation_count,
|
||||
'main',
|
||||
'demo-zone',
|
||||
'演示大楼',
|
||||
'3F',
|
||||
'走廊',
|
||||
sp.observations_json,
|
||||
sp.diagnostics_json,
|
||||
NOW(),
|
||||
NOW()
|
||||
FROM snapshot_payload sp
|
||||
RETURNING id, device_id, user_id, estimated_at
|
||||
)
|
||||
INSERT INTO wearable_location_observations (
|
||||
snapshot_id,
|
||||
gateway_id,
|
||||
received_at,
|
||||
gateway_time,
|
||||
rssi_dbm,
|
||||
snr_db,
|
||||
distance_m,
|
||||
channel,
|
||||
frequency_mhz,
|
||||
packet_sequence,
|
||||
latency_ms,
|
||||
firmware_version,
|
||||
payload,
|
||||
created_at
|
||||
)
|
||||
SELECT
|
||||
s.id,
|
||||
os.gateway_id,
|
||||
os.estimated_at,
|
||||
os.estimated_at,
|
||||
os.rssi_dbm,
|
||||
os.snr_db,
|
||||
os.distance_m,
|
||||
os.channel,
|
||||
os.frequency_mhz,
|
||||
os.packet_sequence,
|
||||
os.latency_ms,
|
||||
os.firmware_version,
|
||||
jsonb_build_object(
|
||||
'device_id', os.device_id,
|
||||
'user_id', os.user_id,
|
||||
'gateway_name', os.gateway_name,
|
||||
'system_code', os.system_code,
|
||||
'battery_voltage', os.battery_voltage,
|
||||
'temperature_c', os.temperature_c,
|
||||
'latitude', os.latitude,
|
||||
'longitude', os.longitude,
|
||||
'orientation_deg', os.orientation_deg,
|
||||
'description', os.description
|
||||
),
|
||||
NOW()
|
||||
FROM inserted_snapshots s
|
||||
JOIN observation_samples os
|
||||
ON os.device_id = s.device_id
|
||||
AND os.user_id = s.user_id
|
||||
AND os.estimated_at = s.estimated_at;
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user