Refact json response and fixed piezo tone

This commit is contained in:
Nomi Nonsense (Nonszy) 2024-03-10 13:56:38 +07:00
parent 76e9ae14e5
commit e064e198a3
6 changed files with 198 additions and 31 deletions

105
README.md
View File

@ -2,6 +2,10 @@
A **SIMPLE** REST API based serial communication. Assisted Firmata protocol and johnny-five API, enabling software communication with the Arduino board using the Server API. that's it. Idk about electronics and networking actually. But that piece of knowledge motivated me to make some IoT stuff. Enjoy (⁠づ⁠ ̄⁠ ⁠³⁠ ̄⁠)⁠づ
![ENA BBQ](https://media1.tenor.com/m/Nl2_tsGV-qkAAAAC/enadbbq-dreambbq.gif)
<small>*the animation is from ENA BBQ series by JoelG</small>
## Setup
Tools that are required
- Arduino Board
@ -9,7 +13,7 @@ Tools that are required
- [Node.js](https://nodejs.org/en) v16.0.0^ or other javascript runtime
### Board
Arduino assembly guide also available in [johnny-five](https://github.com/rwaldron/johnny-five?tab=readme-ov-file#setup-and-assemble-arduino) documentation\
Arduino assembly guide also available in [johnny-five](https://github.com/rwaldron/johnny-five?tab=readme-ov-file#setup-and-assemble-arduino) documentation
1. Plug in your Board via USB
2. Open Arduino IDE then select your Board
3. Go to `File > Examples > Firmata` Select `StandarFirmataPlus`
@ -61,8 +65,11 @@ Arduino assembly guide also available in [johnny-five](https://github.com/rwaldr
- [Read pin mode](#read-pin-mode)
- [Set pin mode](#set-pin-mode)
- [LED](#led)
- [Read led state](#read-led-state)
- [Set led state](#set-led-state)
- [Read LED state](#read-led-state)
- [Set LED state](#set-led-state)
- [RGB LED](#rgb-led)
- [Read RGB state](#read-rgb-state)
- [Set RGB state](#set-rgb-state)
## Common HTTP Responses
Some HTTP responses are sent with JSON, otherwise an HTML body will be sent which is the default express.js response
@ -82,7 +89,7 @@ Some HTTP responses are sent with JSON, otherwise an HTML body will be sent whic
"pin_state": {
"13": "HIGH"
},
"message": "Pin 13 Set to HIGH"
"message": "Changed pin state 13 to HIGH"
}
```
| Property | Description |
@ -98,7 +105,7 @@ This is an example of javascript code sending a request to turn on the LED light
async function turnOnLed() {
const res = await fetch("http://localhost:3000/led/13/on"); // Set LED to HIGH
const data = await res.json();
console.log(data);
console.log(data); // { status: 200, pin_state: { 13: high }, message: "Pin 13 Set to HIGH" }
}
```
@ -168,7 +175,7 @@ async function turnOnLed() {
## LED
### Read led state
### Read LED state
- **URL Endpoint**
/led/:p/
@ -195,17 +202,17 @@ async function turnOnLed() {
}
```
### Set led state
### Set LED state
- **URL Endpoint**
/pin/:p/:a
/led/:p/:a
- **URL Params**
| Params | Mark | Type | Required | Description |
|--------|------|------|----------|-------------|
| p | pin | `string` | true | Seleced pin |
| a | act | `'on'`, `'off'` | true | Action |
| a | act | `'on'`, `'off'`, `'high'`, `'low'` | true | Action |
- **Method(s)**
@ -219,7 +226,85 @@ async function turnOnLed() {
"pin_state": {
"13": "HIGH"
},
"message": "Led pin 13 setted HIGH"
"message": "Changed pin state 13 to HIGH"
}
```
## RGB LED
### Read RGB state
- **URL Endpoint**
/rgb-led
- **Body**
```javascript
{
r: number,
g: number,
b: number
}
```
- **Method**
`POST`
- **Sample Response**
```json
{
"status": 200,
"pin_state": {
"7": true,
"6": true,
"5": false
}
}
```
### Set RGB state
- **URL Endpoint**
/rgb-led
- **Body**
```javascript
{
r: {
pin: number,
value: boolean
},
g: {
pin: number,
value: boolean
},
b: {
pin: number,
value: boolean
}
}
```
- **Method(s)**
`PATCH`
- **Sample Response**
```json
{
"status": 200,
"pin_state": {
"7": true,
"6": true,
"5": false
},
"message": "Success changed pins 7, 6, 5 to state HIGH, HIGH, LOW"
}
```

View File

@ -9,13 +9,14 @@ export function readLed (req: Request, res: Response): Response<string | any> {
const { p } = req.params;
const pin: number = Number.parseInt(p);
const pinState: digitalValue = board.pins[pin].value == 1 ? 'ON' : 'OFF';
const pinState: voltage = board.pins[pin].value == 1 ? 'HIGH' : 'LOW';
return res.status(200).json({
status: 200,
pin_state: {
[pin]: pinState
}
},
message: `Led pin ${pin} is ${pinState}`
});
}
catch (err) {
@ -32,20 +33,18 @@ export function writeLed (req: Request, res: Response): Response<string | any> {
const act: string = a.toLocaleLowerCase();
const pin: number = Number.parseInt(p);
let state: digitalValue;
let state: voltage;
let volt: voltage;
try {
switch (act) {
case 'on':
state = 'ON';
case 'on' || 'high':
state = 'HIGH';
volt = 1;
console.log(`${req.hostname} | ${pin} | LED: ${state}`);
break;
case 'off':
state = 'OFF';
case 'off' || 'low':
state = 'LOW';
volt = 0;
console.log(`${req.hostname} | ${pin} | LED: ${state}`);
break;
default:
console.log(`${req.hostname} | ${pin} | LED: INVALID ACT`);
@ -54,12 +53,17 @@ export function writeLed (req: Request, res: Response): Response<string | any> {
message: `Invalid act ${act}`
});
}
board.digitalWrite(pin, volt);
console.log(`${req.hostname} | ${pin} | LED: ${state}`);
res.status(200).json({
status: 200,
message: `Success changed pin ${pin} to state ${state}`
pin_state: {
[pin]: state
},
message: `Changed pin state ${pin} to ${state}`
});
}
catch (err) {
@ -147,19 +151,26 @@ export function writeRgbLed (req: Request, res: Response): Response<string | any
isAnode: true
})
const isHigh: boolean | string = true || 'HIGH' || 'high';
led.red = new Led(r.pin);
led.green = new Led(g.pin);
led.blue = new Led(b.pin);
if (r.value == true) led.red.on(); else led.red.off();
if (g.value == true) led.green.on(); else led.green.off();
if (b.value == true) led.blue.on(); else led.blue.off();
if (r.value == isHigh) led.red.on(); else led.red.off();
if (g.value == isHigh) led.green.on(); else led.green.off();
if (b.value == isHigh) led.blue.on(); else led.blue.off();
const pins: string = rgbLeds.map(c => c.pin.toString()).join(", ");
const values: string = rgbLeds.map(c => `${c.value}`).join(", ");
return res.status(200).json({
status: 200,
pin_state: {
[r.pin]: led.red.isOn,
[g.pin]: led.green.isOn,
[b.pin]: led.blue.isOn
},
message: `Success changed pins ${pins} to state ${values}`
});
}

View File

@ -3,7 +3,32 @@ import { Piezo } from "johnny-five";
import { Pitch } from "../melodies";
export function piezoTone (req: Request, res: Response): Response {
const pin: number = Number.parseInt(req.params.p);
const frequency: number = Number.parseInt(req.params.f);
const piezo: Piezo = new Piezo(pin);
piezo.tone(frequency * 7.3, 100);
return res.status(200).json({
status: 200,
pin_tone: {
[pin]: frequency
},
message: `Piezo ${pin} tone ${frequency}`
});
}
export function piezoNote (req: Request, res: Response): Response {
const { pin, note }: { pin: number, note: string } = req.body;
const notePitch = Pitch[note.toUpperCase()];
if (notePitch == null) {
return res.status(400).json({
status: 400,
message: `Invalid note ${note}`
});
}
const piezo: Piezo = new Piezo(pin);
@ -15,7 +40,13 @@ export function piezoTone (req: Request, res: Response): Response {
return res.status(200).json({
status: 200,
message: `Piezo ${pin} tone ${note}`
pin_tone: {
[pin]: notePitch
},
pin_note: {
[pin]: note.toUpperCase()
},
message: `Piezo ${pin} tone note ${note}`
});
}
@ -45,12 +76,17 @@ export function piezoPlayNotes (req: Request, res: Response): Response {
})
.filter((note) => note[0].trim() != "-");
const notesS: string = notes.join(", ");
const notesS: string = notes.length > 4 ?
notes.slice(0, 4).join(", ")+"..." :
notes.join(", ");
piezo.play({ song, tempo });
return res.status(200).json({
status: 200,
pin_notes: {
[pin]: notes
},
message: `Piezo ${pin} play notes ${notesS}`
});
}

View File

@ -18,17 +18,22 @@ const io: Server = new Server(server, {
}
}); // I have no experience at WebSocket, so.. forgive me :)
// Server configuration
const host: string = 'localhost';
const port: number = 3000;
// Express middleware
app.use(express.json());
app.use(express.static('client'));
// Socket.io event handlers
io.on('connection', socketHandler);
// HTTP Routes
app.use('/', view);
app.use('/api-arduino', isBoardConnected, api);
app.use('/api-arduino', isBoardConnected, api); // Board API Controllers
// Run server
console.log("\nRunning Server...");
server.listen(port, () => {
console.log(`Server is connected and running in ${host} at port ${port} 🗣️🗣️🗣️`);

View File

@ -3,7 +3,7 @@ import { Router } from "express";
import { readLed, readRgbLed, writeLed, writeRgbLed } from "../controller/led";
import { readPin, setPin } from "../controller/pin";
import { piezoNoTone, piezoPlayNotes, piezoTone } from "../controller/piezo";
import { piezoNoTone, piezoNote, piezoPlayNotes, piezoTone } from "../controller/piezo";
import { rotateServo } from "../controller/servo";
import { readResistor } from "../controller/photoresistor";
@ -11,22 +11,28 @@ import { isPinNumeric } from "../middleware/pin";
const router: Router = Router();
// Client page
router.get('/hello', (req, res: Response): Response<string> => {
return res.status(200).send("Hello");
})
// PinMode
router.get('/pin/:p', readPin);
router.patch('/pin/:p/:m', setPin);
// LED
router.get('/led/:p', isPinNumeric, readLed);
router.patch('/led/:p/:a', isPinNumeric, writeLed);
router.get('/rgb-led', readRgbLed);
// RGB LED
router.post('/rgb-led', readRgbLed);
router.patch('/rgb-led/', writeRgbLed);
router.patch('/piezo/', piezoTone);
router.patch('/piezo/stop/', piezoNoTone);
// Piezo
router.patch('/piezo/:p/:f', isPinNumeric, piezoTone);
router.patch('/piezo/note', piezoNote);
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

24
test/serial/piezo.ts Normal file
View File

@ -0,0 +1,24 @@
import { Board, Piezo } from "johnny-five";
const board = new Board({
port: '/dev/ttyUSB0',
repl: false
});
board.on('ready', () => {
const piezo = new Piezo(11);
let ins = 0;
board.loop(500, async () => {
piezo.play({
song: "C4",
beats: 1/2,
tempo: 100
})
await new Promise(resolve => setTimeout(resolve, 100));
piezo.note("C4", 100);
await new Promise(resolve => setTimeout(resolve, 100));
piezo.tone(262 * 7.3, 100);
})
})