add/delete cycle updates, shifting more to socketIO plus support for two device types

This commit is contained in:
2025-12-24 18:39:48 -06:00
parent 0658c47230
commit c67e30d5c6
2 changed files with 124 additions and 16 deletions

120
index.js
View File

@@ -80,13 +80,48 @@ io.on('connection', async (socket) => {
}
else {
const successResponse = {
type: 'success',
code: 200,
message: 'Device found'
};
console.log("success");
socket.emit("success", successResponse);
console.log("success - sending device state");
// For peripheral devices, send current device state
if (payload.type === "peripheral") {
try {
// Get peripheral states for this device
const {rows: periphRows} = await pool.query(
"select last_pos, peripheral_number, await_calib, calibrated from peripherals where device_id=$1",
[id]
);
const successResponse = {
type: 'success',
code: 200,
message: 'Device authenticated',
deviceState: periphRows.map(row => ({
port: row.peripheral_number,
lastPos: row.last_pos,
awaitCalib: row.await_calib,
calibrated: row.calibrated
}))
};
socket.emit("device_init", successResponse);
} catch (err) {
console.error("Error fetching device state:", err);
socket.emit("device_init", {
type: 'success',
code: 200,
message: 'Device authenticated',
deviceState: []
});
}
} else {
// User connection
const successResponse = {
type: 'success',
code: 200,
message: 'User connected'
};
socket.emit("success", successResponse);
}
}
} catch (error) {
@@ -270,10 +305,11 @@ app.get('/device_list', authenticateToken, async (req, res) => {
try {
console.log("device List request");
console.log(req.user);
const {rows} = await pool.query('select id, device_name from devices where user_id = $1', [req.user]);
const {rows} = await pool.query('select id, device_name, max_ports from devices where user_id = $1', [req.user]);
const deviceNames = rows.map(row => row.device_name);
const deviceIds = rows.map(row => row.id);
res.status(200).json({ device_ids: deviceIds, devices: deviceNames });
const maxPorts = rows.map(row => row.max_ports);
res.status(200).json({ device_ids: deviceIds, devices: deviceNames, max_ports: maxPorts });
} catch {
res.status(500).json({error: 'Internal Server Error'});
}
@@ -283,11 +319,12 @@ app.get('/device_name', authenticateToken, async (req, res) => {
console.log("deviceName");
try {
const {deviceId} = req.query;
const {rows} = await pool.query('select device_name from devices where id=$1 and user_id=$2',
const {rows} = await pool.query('select device_name, max_ports from devices where id=$1 and user_id=$2',
[deviceId, req.user]);
if (rows.length != 1) return res.sendStatus(404);
const deviceName = rows[0].device_name;
res.status(200).json({device_name: deviceName});
const maxPorts = rows[0].max_ports;
res.status(200).json({device_name: deviceName, max_ports: maxPorts});
} catch {
res.sendStatus(500);
}
@@ -313,10 +350,11 @@ app.post('/add_device', authenticateToken, async (req, res) => {
console.log("add device request");
console.log(req.user);
console.log(req.peripheral);
const {deviceName} = req.body;
const {deviceName, maxPorts} = req.body;
console.log(deviceName);
const {rows} = await pool.query("insert into devices (user_id, device_name) values ($1, $2) returning id",
[req.user, deviceName]
const ports = maxPorts || 4; // Default to 4 for multi-port devices
const {rows} = await pool.query("insert into devices (user_id, device_name, max_ports) values ($1, $2, $3) returning id",
[req.user, deviceName, ports]
); // finish token return based on device ID.
const deviceInitToken = await createTempPeriphToken(rows[0].id);
res.status(201).json({token: deviceInitToken});
@@ -346,11 +384,39 @@ app.get('/verify_device', authenticateToken, async (req, res) => {
console.log("device verify");
try{
console.log(req.peripheral);
// Check if this is a single-port device
const {rows: deviceRows} = await pool.query("select max_ports, user_id from devices where id=$1", [req.peripheral]);
if (deviceRows.length === 0) {
return res.status(404).json({error: "Device not found"});
}
const maxPorts = deviceRows[0].max_ports;
const userId = deviceRows[0].user_id;
// For single-port devices, automatically create the peripheral if it doesn't exist
if (maxPorts === 1) {
const {rows: periphRows} = await pool.query(
"select id from peripherals where device_id=$1",
[req.peripheral]
);
if (periphRows.length === 0) {
// Create default peripheral for C6 device
await pool.query(
"insert into peripherals (device_id, peripheral_number, peripheral_name, user_id) values ($1, 1, $2, $3)",
[req.peripheral, "Main Blind", userId]
);
console.log("Created default peripheral for single-port device");
}
}
await pool.query("delete from device_tokens where device_id=$1", [req.peripheral]);
const newToken = await createPeripheralToken(req.peripheral);
console.log("New Token", newToken);
res.json({token: newToken, id: req.peripheral});
} catch {
} catch (error) {
console.error("Error in verify_device:", error);
res.status(500).json({error: "server error"});
}
});
@@ -508,10 +574,32 @@ app.post('/delete_device', authenticateToken, async (req, res) => {
return res.status(404).json({ error: 'Device not found' });
}
// Get socket ID before deleting tokens
const {rows: tokenRows} = await pool.query(
"select socket from device_tokens where device_id=$1 and connected=TRUE",
[rows[0].id]
);
// Delete device tokens
await pool.query("delete from device_tokens where device_id=$1", [rows[0].id]);
// Forcefully disconnect the Socket.IO connection if device is connected
if (tokenRows.length > 0) {
tokenRows.forEach(row => {
if (row.socket) {
const socket = io.sockets.sockets.get(row.socket);
if (socket) {
console.log(`Forcefully disconnecting device socket ${row.socket}`);
socket.emit('device_deleted', { message: 'Device has been deleted from the account' });
socket.disconnect(true);
}
}
});
}
res.sendStatus(204);
} catch {
} catch (error) {
console.error("Error deleting device:", error);
res.status(500).json({error: "server error"});
}
});

View File

@@ -0,0 +1,20 @@
-- Migration: Add max_ports column to devices table to support different device types
-- BlindMaster-C6: max_ports = 1 (single servo)
-- BlindMaster Device: max_ports = 4 (multi-port)
-- Add max_ports column with default value of 4 for existing devices
ALTER TABLE devices
ADD COLUMN max_ports INTEGER NOT NULL DEFAULT 4;
-- Add a check constraint to ensure max_ports is between 1 and 4
ALTER TABLE devices
ADD CONSTRAINT devices_max_ports_check CHECK (max_ports >= 1 AND max_ports <= 4);
-- For existing devices, you may want to set max_ports based on the number of peripherals
-- Uncomment the following line if you want to auto-detect based on existing peripherals:
-- UPDATE devices d SET max_ports = GREATEST(1, (SELECT COUNT(*) FROM peripherals p WHERE p.device_id = d.id));
-- Create an index for faster queries
CREATE INDEX idx_devices_max_ports ON devices(max_ports);
COMMENT ON COLUMN devices.max_ports IS 'Maximum number of ports/peripherals this device supports (1 for C6, 4 for multi-port)';