From 3d1b9bf3ac9018860cab5c438832c4366970c6cb Mon Sep 17 00:00:00 2001 From: norman-andrians Date: Sat, 16 Mar 2024 23:38:55 +0700 Subject: [PATCH] Add rooms as 'parallel' in socket handler and add digital analog api --- src/controller/basic/analog.ts | 47 ++++++++++++++++ src/controller/basic/digital.ts | 54 +++++++++++++++++++ src/controller/{ => basic}/pin.ts | 4 +- src/controller/{ => components}/led.ts | 4 +- .../{ => components}/photoresistor.ts | 4 +- src/controller/{ => components}/piezo.ts | 2 +- src/controller/{ => components}/servo.ts | 2 +- src/handlers/socketHandler.ts | 50 +++++++++++++---- src/routes/api.ts | 25 ++++++--- 9 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 src/controller/basic/analog.ts create mode 100644 src/controller/basic/digital.ts rename src/controller/{ => basic}/pin.ts (92%) rename src/controller/{ => components}/led.ts (98%) rename src/controller/{ => components}/photoresistor.ts (84%) rename src/controller/{ => components}/piezo.ts (98%) rename src/controller/{ => components}/servo.ts (94%) diff --git a/src/controller/basic/analog.ts b/src/controller/basic/analog.ts new file mode 100644 index 0000000..f09fcf8 --- /dev/null +++ b/src/controller/basic/analog.ts @@ -0,0 +1,47 @@ +import { Request, Response } from "express"; +import { board } from "../../setup"; +import * as Promises from "../../promises"; + +interface AnalogState { + pin: number | string, + value: number +} + +export function analogWrite (req: Request, res: Response): Response { + const { pin, value }: AnalogState = req.body; + + try { + board.analogWrite(pin, value); + + return res.status(200).json({ + status: 200, + analog_state: { + [pin]: value + } + }); + } + catch (err) { + console.error(err); + res.sendStatus(500); + } +} + +export async function analogRead (req: Request, res: Response) { + let { pin } = req.params; + pin = pin[0] == "A" ? pin.slice(1, pin.length) : pin; + + try { + const value = await Promises.analogRead(board, pin); + + return res.status(200).json({ + status: 200, + analog_state: { + [pin]: value + } + }) + } + catch (err) { + console.error(err); + res.sendStatus(500); + } +} \ No newline at end of file diff --git a/src/controller/basic/digital.ts b/src/controller/basic/digital.ts new file mode 100644 index 0000000..c716ab9 --- /dev/null +++ b/src/controller/basic/digital.ts @@ -0,0 +1,54 @@ +import { Request, Response } from "express"; +import { board } from "../../setup"; + +interface DigitalState { + pin: number | string, + state: string +} + +export function digitalWrite (req: Request, res: Response): Response { + const { pin, state }: DigitalState = req.body; + let value: number; + + try { + switch (state) { + case 'LOW' || 0: value = 0; break; + case 'HIGH' || 1: value = 1; break; + default: + return res.status(400).json({ + status: 400, + message: `Invalid state ${state}, read the documentation` + }) + } + + const val = value == 1 ? "HIGH" : "LOW"; + board.digitalWrite(pin, value); + + return res.status(200).json({ + status: 200, + pin_state: { + [pin]: val + } + }); + } + catch (err) { + console.error(err); + res.sendStatus(500); + } +} + +export function digitalRead (req: Request, res: Response): Response { + try { + const { pin } = req.params; + const value = board.pins[pin].value == 1 ? 'HIGH' : 'LOW'; + return res.status(200).json({ + pin_state: { + [pin]: value + } + }); + } + catch (err) { + console.error(err); + res.sendStatus(500); + } +} \ No newline at end of file diff --git a/src/controller/pin.ts b/src/controller/basic/pin.ts similarity index 92% rename from src/controller/pin.ts rename to src/controller/basic/pin.ts index 62d0bf4..677c597 100644 --- a/src/controller/pin.ts +++ b/src/controller/basic/pin.ts @@ -1,6 +1,6 @@ import { Request, Response } from "express"; -import { board, suBoard } from "../setup"; -import { sPinModes } from "."; +import { board, suBoard } from "../../setup"; +import { sPinModes } from ".."; import { Pin } from "johnny-five"; export function readPin (req: Request, res: Response) { diff --git a/src/controller/led.ts b/src/controller/components/led.ts similarity index 98% rename from src/controller/led.ts rename to src/controller/components/led.ts index 21044d8..9ab24bd 100644 --- a/src/controller/led.ts +++ b/src/controller/components/led.ts @@ -1,6 +1,6 @@ import { Request, Response } from "express"; -import { board } from "../setup"; -import { ChannelPins, digitalValue, voltage } from "."; +import { board } from "../../setup"; +import { ChannelPins, digitalValue, voltage } from ".."; import { Led } from "johnny-five"; diff --git a/src/controller/photoresistor.ts b/src/controller/components/photoresistor.ts similarity index 84% rename from src/controller/photoresistor.ts rename to src/controller/components/photoresistor.ts index 4f67a95..3bfe66f 100644 --- a/src/controller/photoresistor.ts +++ b/src/controller/components/photoresistor.ts @@ -1,6 +1,6 @@ import { Request, Response } from "express"; -import { board } from "../setup"; -import { analogRead } from "../promises"; +import { board } from "../../setup"; +import { analogRead } from "../../promises"; export async function readResistor (req: Request, res: Response): Promise> { const { p } = req.params; diff --git a/src/controller/piezo.ts b/src/controller/components/piezo.ts similarity index 98% rename from src/controller/piezo.ts rename to src/controller/components/piezo.ts index e077aa6..2a1e586 100644 --- a/src/controller/piezo.ts +++ b/src/controller/components/piezo.ts @@ -1,6 +1,6 @@ import { Request, Response } from "express"; import { Piezo } from "johnny-five"; -import { Pitch } from "../melodies"; +import { Pitch } from "../../melodies"; export function piezoTone (req: Request, res: Response): Response { const pin: number = Number.parseInt(req.params.p); diff --git a/src/controller/servo.ts b/src/controller/components/servo.ts similarity index 94% rename from src/controller/servo.ts rename to src/controller/components/servo.ts index 7eb19c7..54e66cf 100644 --- a/src/controller/servo.ts +++ b/src/controller/components/servo.ts @@ -1,5 +1,5 @@ import { Request, Response } from "express"; -import { board } from "../setup"; +import { board } from "../../setup"; export function rotateServo (req: Request, res: Response): Response { const { p } = req.params; diff --git a/src/handlers/socketHandler.ts b/src/handlers/socketHandler.ts index cd08ce5..5b9cc3e 100644 --- a/src/handlers/socketHandler.ts +++ b/src/handlers/socketHandler.ts @@ -1,23 +1,55 @@ import { Socket } from "socket.io"; -import { Pin } from "johnny-five"; +import { Pin, Sensor } from "johnny-five"; import { board } from "../setup"; export default (socket: Socket) => { console.log(`${socket.id} | ${socket.client.request.headers.host} | Joined`); - socket.on("servo", (p: string, ang: string) => { - const pin = Number.parseInt(p); - const angle = Number.parseInt(ang); + socket.on("servo", (p: string, ang: string, cb?: (msg?: string) => void) => { + const pin: number = Number.parseInt(p); + const angle: number = Number.parseInt(ang); board.pinMode(pin, Pin.SERVO); board.servoWrite(pin, angle); + + if (cb) cb(`Set servo pin ${p} to ${angle} degrees`); console.log(socket.id, pin, angle); }) - socket.on("set-photoresistor", (pin: string) => { - board.analogRead(pin, (value) => { - socket.emit("photoresistor", value); - console.log(socket.id, "A"+pin, value); - }); + socket.on("set-photoresistor", (pin: string, cb?: (msg?: string) => void) => { + const room = `resistor-${pin}`; + + if (!socket.rooms.has(room)) { + socket.join(room); + + const sensor = new Sensor({ + pin: pin, + board: board, + type: "analog", + freq: 250 + }); + + sensor.on("change", () => { + socket.to(room).emit("photoresistor", sensor.value); + }); + + console.log(`New room: ${room}`); + console.log(`${socket.id} joined room ${room}`); + + if (cb) cb(`Set pin resistor to pin ${pin}`); + } + else { + if (cb) cb(`Resistor pin ${pin} is already used, try to lisen to "photoresistor" room: ${room}`); + } + }) + + socket.on("join-photoresistor", (pin) => { + const room = `resistor-${pin}`; + + if (!socket.rooms.has(room)) { + socket.join(room); + console.log(socket.rooms); + console.log(`${socket.id} Joined room ${room}`); + } }) } \ No newline at end of file diff --git a/src/routes/api.ts b/src/routes/api.ts index f4fe7c5..2215cf2 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -1,17 +1,19 @@ import { Response } from "express"; import { Router } from "express"; -import { readLed, readRgbLed, writeLed, writeRgbLed } from "../controller/led"; -import { readPin, setPin } from "../controller/pin"; -import { piezoNoTone, piezoNote, piezoPlayNotes, piezoTone } from "../controller/piezo"; -import { rotateServo } from "../controller/servo"; -import { readResistor } from "../controller/photoresistor"; +import { readPin, setPin } from "../controller/basic/pin"; +import { digitalRead, digitalWrite } from "../controller/basic/digital"; +import { analogRead, analogWrite } from "../controller/basic/analog"; + +import { readLed, readRgbLed, writeLed, writeRgbLed } from "../controller/components/led"; +import { piezoNoTone, piezoNote, piezoPlayNotes, piezoTone } from "../controller/components/piezo"; +import { rotateServo } from "../controller/components/servo"; +import { readResistor } from "../controller/components/photoresistor"; import { isPinNumeric } from "../middleware/pin"; const router: Router = Router(); -// Client page router.get('/hello', (req, res: Response): Response => { return res.status(200).send("Hello"); }) @@ -20,6 +22,15 @@ router.get('/hello', (req, res: Response): Response => { router.get('/pin/:p', readPin); router.patch('/pin/:p/:m', setPin); +// Digital read/write +router.get('/digital/:pin', digitalRead); +router.patch('/digital', digitalWrite); + +// Analog read/write +router.get('/analog/:pin', analogRead); +router.patch('/analog', analogWrite); + + // LED router.get('/led/:p', isPinNumeric, readLed); router.patch('/led/:p/:a', isPinNumeric, writeLed); @@ -35,7 +46,7 @@ router.patch('/piezo/music/', piezoPlayNotes); router.patch('/piezo/stop/', piezoNoTone); // for real-time communication is deprecated and not recommended -// use other protocol like websocket instead +// use other protocol like websocket instead, we're using socket.io router.patch('/servo/:p/:m', rotateServo); router.get('/photoresistor/:p', readResistor);