93 lines
3.0 KiB
JavaScript
93 lines
3.0 KiB
JavaScript
import { randomUUID } from "node:crypto";
|
|
import { getPool } from "../db/pool";
|
|
function nowIso() {
|
|
return new Date().toISOString();
|
|
}
|
|
function normalizeStatus(status) {
|
|
if (status === "accepted" || status === "delivered" || status === "failed" || status === "timeout") {
|
|
return status;
|
|
}
|
|
return "accepted";
|
|
}
|
|
function mapCommand(row) {
|
|
return {
|
|
id: row.id,
|
|
device_id: row.device_id,
|
|
command: row.command,
|
|
payload: row.payload_json || {},
|
|
status: row.status,
|
|
requested_at: row.requested_at,
|
|
acknowledged_at: row.acknowledged_at || null,
|
|
result_payload: row.result_payload_json || null,
|
|
reason: row.reason || null
|
|
};
|
|
}
|
|
export async function createDeviceCommand(payload) {
|
|
const entity = {
|
|
id: `cmd_${randomUUID()}`,
|
|
device_id: payload.device_id,
|
|
command: payload.command,
|
|
payload: payload.payload || {},
|
|
status: normalizeStatus(payload.status || "accepted"),
|
|
requested_at: nowIso(),
|
|
acknowledged_at: null,
|
|
result_payload: null,
|
|
reason: null
|
|
};
|
|
const { rows } = await getPool().query(`INSERT INTO device_commands (
|
|
id,
|
|
device_id,
|
|
command,
|
|
payload_json,
|
|
status,
|
|
requested_at,
|
|
acknowledged_at,
|
|
result_payload_json,
|
|
reason
|
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
|
RETURNING *`, [
|
|
entity.id,
|
|
entity.device_id,
|
|
entity.command,
|
|
entity.payload,
|
|
entity.status,
|
|
entity.requested_at,
|
|
entity.acknowledged_at,
|
|
entity.result_payload,
|
|
entity.reason
|
|
]);
|
|
return mapCommand(rows[0]);
|
|
}
|
|
export async function listDeviceCommands(deviceId) {
|
|
const { rows } = await getPool().query("SELECT * FROM device_commands WHERE device_id = $1 ORDER BY requested_at DESC", [deviceId]);
|
|
return rows.map(mapCommand);
|
|
}
|
|
export async function getDeviceCommandById(deviceId, commandId) {
|
|
const { rows } = await getPool().query("SELECT * FROM device_commands WHERE device_id = $1 AND id = $2", [deviceId, commandId]);
|
|
return rows[0] ? mapCommand(rows[0]) : null;
|
|
}
|
|
export function toDeviceCommandPayload(command) {
|
|
return mapCommand(command);
|
|
}
|
|
export function toDeviceCommandPayloadBrief(command) {
|
|
return {
|
|
command_id: command.id,
|
|
device_id: command.device_id,
|
|
command: command.command,
|
|
status: command.status,
|
|
requested_at: command.requested_at,
|
|
acknowledged_at: command.acknowledged_at
|
|
};
|
|
}
|
|
export async function acknowledgeDeviceCommand(payload) {
|
|
const now = nowIso();
|
|
const { rows } = await getPool().query(`UPDATE device_commands
|
|
SET status = $3,
|
|
acknowledged_at = $4,
|
|
result_payload_json = $5,
|
|
reason = $6
|
|
WHERE device_id = $1 AND id = $2
|
|
RETURNING *`, [payload.device_id, payload.command_id, payload.status, now, payload.result_payload || null, payload.reason || null]);
|
|
return rows[0] ? mapCommand(rows[0]) : null;
|
|
}
|