Initial import
This commit is contained in:
236
sql.go
Normal file
236
sql.go
Normal file
@@ -0,0 +1,236 @@
|
||||
package hamview
|
||||
|
||||
const (
|
||||
sqlCreateRadio = `
|
||||
CREATE TABLE IF NOT EXISTS radio (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(64) NOT NULL UNIQUE,
|
||||
is_online BOOLEAN NOT NULL DEFAULT false,
|
||||
device VARCHAR(100),
|
||||
manufacturer VARCHAR(100),
|
||||
firmware_date TIMESTAMPTZ,
|
||||
firmware_version VARCHAR(32),
|
||||
antenna VARCHAR(100),
|
||||
modulation VARCHAR(16) NOT NULL,
|
||||
protocol VARCHAR(16) NOT NULL,
|
||||
latitude NUMERIC(10, 8), -- GPS latitude in decimal degrees
|
||||
longitude NUMERIC(11, 8), -- GPS longitude in decimal degrees
|
||||
altitude REAL, -- Altitude in meters
|
||||
frequency DOUBLE PRECISION,
|
||||
bandwidth DOUBLE PRECISION,
|
||||
rx_frequency DOUBLE PRECISION,
|
||||
tx_frequency DOUBLE PRECISION,
|
||||
power REAL,
|
||||
gain REAL,
|
||||
lora_sf SMALLINT,
|
||||
lora_cr SMALLINT,
|
||||
extra JSONB
|
||||
);
|
||||
`
|
||||
sqlIndexRadioName = `CREATE INDEX IF NOT EXISTS idx_radio_name ON radio(name);`
|
||||
sqlIndexRadioProtocol = `CREATE INDEX IF NOT EXISTS idx_radio_protocol ON radio(protocol);`
|
||||
sqlGeometryRadioPosition = `SELECT AddGeometryColumn('public', 'radio', 'position', 4326, 'POINT', 2);`
|
||||
)
|
||||
|
||||
const (
|
||||
sqlCreateAPRSStation = `
|
||||
CREATE TABLE IF NOT EXISTS aprs_station (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
address VARCHAR(10) NOT NULL UNIQUE,
|
||||
last_heard TIMESTAMPTZ NOT NULL,
|
||||
last_path TEXT[],
|
||||
last_comment TEXT
|
||||
);
|
||||
`
|
||||
sqlCreateAPRSPacket = `
|
||||
CREATE TABLE IF NOT EXISTS aprs_packet (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
src_address VARCHAR(10) NOT NULL,
|
||||
dst_address VARCHAR(10) NOT NULL,
|
||||
comment TEXT,
|
||||
payload BYTEA,
|
||||
raw BYTEA,
|
||||
received_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
`
|
||||
)
|
||||
|
||||
const (
|
||||
sqlCreateMeshCorePacket = `
|
||||
CREATE TABLE IF NOT EXISTS meshcore_packet (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
snr REAL NOT NULL DEFAULT 0,
|
||||
rssi SMALLINT NOT NULL DEFAULT 0,
|
||||
hash BYTEA NOT NULL, -- Used for deduplication
|
||||
route_type SMALLINT NOT NULL,
|
||||
payload_type SMALLINT NOT NULL,
|
||||
path BYTEA,
|
||||
payload BYTEA,
|
||||
raw BYTEA,
|
||||
parsed JSONB,
|
||||
received_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
`
|
||||
sqlIndexMeshCorePacketHash = `CREATE INDEX IF NOT EXISTS idx_meshcore_packet_hash ON meshcore_packet(hash);`
|
||||
sqlIndexMeshCorePacketPayloadType = `CREATE INDEX IF NOT EXISTS idx_meshcore_packet_payload_type ON meshcore_packet(payload_type);`
|
||||
)
|
||||
|
||||
const (
|
||||
sqlCreateMeshCoreNode = `
|
||||
CREATE TABLE IF NOT EXISTS meshcore_node (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
last_advert_id BIGINT NOT NULL REFERENCES meshcore_packet(id) ON DELETE CASCADE,
|
||||
node_type SMALLINT NOT NULL DEFAULT 0,
|
||||
public_key BYTEA NOT NULL UNIQUE,
|
||||
name TEXT,
|
||||
local_time TIMESTAMPTZ NOT NULL,
|
||||
first_heard TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
last_heard TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
last_latitude NUMERIC(10, 8), -- GPS latitude in decimal degrees
|
||||
last_longitude NUMERIC(11, 8), -- GPS longitude in decimal degrees
|
||||
last_position GEOMETRY(POINT, 4326)
|
||||
);
|
||||
`
|
||||
sqlIndexMeshCoreNodePublicKey = `CREATE INDEX IF NOT EXISTS idx_meshcore_node_public_key ON meshcore_node(public_key);`
|
||||
sqlIndexMeshCoreNodeName = `CREATE INDEX IF NOT EXISTS idx_meshcore_node_name ON meshcore_node(name);`
|
||||
sqlAlterMeshCoreNodePrefix = `ALTER TABLE meshcore_node ADD COLUMN IF NOT EXISTS prefix BYTEA GENERATED ALWAYS AS (substring(public_key, 0, 2)) STORED;`
|
||||
sqlGeometryMeshCoreNodePosition = `SELECT AddGeometryColumn('public', 'meshcore_node', 'position', 4326, 'POINT', 2);`
|
||||
sqlAlterMeshCoreNodeLastPosition = `
|
||||
ALTER TABLE meshcore_node
|
||||
ADD COLUMN last_position GEOMETRY(Point, 4326)
|
||||
GENERATED ALWAYS AS (
|
||||
CASE
|
||||
WHEN last_latitude IS NOT NULL AND last_longitude IS NOT NULL THEN ST_SetSRID(ST_MakePoint(last_latitude, last_longitude), 4326)
|
||||
ELSE NULL
|
||||
END
|
||||
) STORED;`
|
||||
)
|
||||
|
||||
const (
|
||||
sqlCreateMeshCoreNodePosition = `
|
||||
CREATE TABLE IF NOT EXISTS meshcore_node_position (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
node_id BIGINT NOT NULL REFERENCES meshcore_node(id) ON DELETE CASCADE,
|
||||
heard_at TIMESTAMPTZ NOT NULL,
|
||||
latitude NUMERIC(10, 8), -- GPS latitude in decimal degrees
|
||||
longitude NUMERIC(11, 8) -- GPS longitude in decimal degrees
|
||||
);
|
||||
`
|
||||
sqlGeometryMeshCoreNodePositionPosition = `SELECT AddGeometryColumn('public', 'meshcore_node_position', 'position', 4326, 'POINT', 2);`
|
||||
sqlIndexMeshCoreNodePositionPosition = `CREATE INDEX IF NOT EXISTS idx_meshcore_node_position_position ON meshcore_node_position USING GIST (position);`
|
||||
)
|
||||
|
||||
const (
|
||||
sqlSelectMeshCoreNodesLastPosition = `
|
||||
WITH ranked_positions AS (
|
||||
SELECT
|
||||
node_id, latitude, longitude, position,
|
||||
ROW_NUMBER() OVER (PARTITION BY node_id ORDER BY heard_at DESC) as rn
|
||||
FROM meshcore_node_position
|
||||
)
|
||||
SELECT
|
||||
r.snr,
|
||||
r.rssi,
|
||||
n.name,
|
||||
n.public_key,
|
||||
n.prefix,
|
||||
n.node_type,
|
||||
n.first_heard,
|
||||
n.last_heard,
|
||||
p.latitude,
|
||||
p.longitude
|
||||
FROM
|
||||
meshcore_node n
|
||||
LEFT JOIN ranked_positions p ON n.id = p.node_id AND p.rn = 1
|
||||
LEFT JOIN meshcore_packet r ON r.id = n.last_advert_id
|
||||
WHERE
|
||||
n.node_type = $1
|
||||
ORDER BY last_heard DESC LIMIT $2;
|
||||
`
|
||||
sqlSelectMeshCorePackets = `
|
||||
SELECT
|
||||
snr,
|
||||
rssi,
|
||||
hash,
|
||||
route_type,
|
||||
payload_type,
|
||||
path,
|
||||
received_at,
|
||||
raw,
|
||||
parsed
|
||||
FROM
|
||||
meshcore_packet
|
||||
ORDER BY
|
||||
received_at DESC
|
||||
LIMIT $1;
|
||||
`
|
||||
sqlSelectMeshCorePacketsByHash = `
|
||||
SELECT
|
||||
snr,
|
||||
rssi,
|
||||
hash,
|
||||
route_type,
|
||||
payload_type,
|
||||
path,
|
||||
received_at,
|
||||
raw,
|
||||
parsed
|
||||
FROM
|
||||
meshcore_packet
|
||||
WHERE
|
||||
hash = $1
|
||||
ORDER BY
|
||||
received_at DESC;
|
||||
`
|
||||
sqlSelectMeshCorePacketsByRepeaterWindowed = `
|
||||
SELECT
|
||||
to_timestamp(round(EXTRACT(EPOCH FROM received_at) / $1) * $1) as window,
|
||||
cast(to_hex(get_byte(path, length(path)-2)) as text) AS repeater,
|
||||
count(id) AS packets
|
||||
FROM
|
||||
meshcore_packet
|
||||
WHERE
|
||||
length(path) >= 2 AND
|
||||
received_at >= $2
|
||||
GROUP BY
|
||||
round(EXTRACT(EPOCH FROM received_at) / $1),
|
||||
cast(to_hex(get_byte(path, length(path)-2)) as text);
|
||||
`
|
||||
sqlSelectMeshCorePacketPathNodes = `
|
||||
WITH RECURSIVE
|
||||
params AS (
|
||||
$1::BYTEA as path,
|
||||
$2::NUMERIC(10, 8) as start_latitude,
|
||||
$3::NUMERIC(11, 8) as start_longitude,
|
||||
$4::DOUBLE PRECISION as max_range_m
|
||||
),
|
||||
|
||||
path_prefix AS (
|
||||
SELECT
|
||||
)
|
||||
`
|
||||
)
|
||||
|
||||
const (
|
||||
sqlCreateMeshCoreIdentity = `
|
||||
CREATE TABLE IF NOT EXISTS meshcore_identity (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(32) NOT NULL UNIQUE,
|
||||
public_key BYTEA(32) NOT NULL UNIQUE,
|
||||
private_key BYTEA(64) NOT NULL
|
||||
);
|
||||
`
|
||||
)
|
||||
|
||||
const (
|
||||
sqlCreateMeshCoreGroup = `
|
||||
CREATE TABLE IF NOT EXISTS meshcore_group (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(32) NOT NULL UNIQUE,
|
||||
hash SMALLINT NOT NULL,
|
||||
shared_key VARCHAR(64) NOT NULL,
|
||||
is_public BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
`
|
||||
)
|
||||
Reference in New Issue
Block a user