Compare commits
No commits in common. "main" and "firmata-legacy" have entirely different histories.
main
...
firmata-le
3
.gitignore
vendored
@ -1,6 +1,3 @@
|
|||||||
example-client/
|
|
||||||
build
|
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
21
LICENSE
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2024 Norman Andriansyah
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
771
README.md
@ -1,772 +1,7 @@
|
|||||||
# Lunar Vein: Arduino
|
# Lunar Vein: Arduino
|
||||||
|
|
||||||
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 (づ ̄ ³ ̄)づ
|
An API server and client to communicate with Arduino boards, that's it. Idk about electronics and networking actually. But that piece of knowledge motivated me to interact it with other software. Enjoy (づ ̄ ³ ̄)づ
|
||||||
|
|
||||||

|
### Setup
|
||||||
|
|
||||||
<small>*the animation is from ENA BBQ series by JoelG</small>
|
- Install all packages with `npm i` or `yarn`
|
||||||
|
|
||||||
## Setup
|
|
||||||
Tools that are required
|
|
||||||
- Arduino Board
|
|
||||||
- [Arduino IDE](https://www.arduino.cc/en/software)
|
|
||||||
- [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
|
|
||||||
1. Plug in your Board via USB
|
|
||||||
2. Open Arduino IDE then select your Board
|
|
||||||
3. Go to `File > Examples > Firmata` Select `StandarFirmataPlus`
|
|
||||||
4. Upload the sketch
|
|
||||||
|
|
||||||
### Server
|
|
||||||
1. Clone project and Install
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/norman-andrians/lunar-vein-arduino.git && cd lunar-vein-arduino
|
|
||||||
npm i
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Add `.env` file in the project root directory with the `SERIAL_PORT` variable
|
|
||||||
|
|
||||||
```dotenv
|
|
||||||
SERIAL_PORT=/dev/ttyUSB0
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Run the project
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
4. If the board is connected try to open the client page in [https://localhost:3000/](https://localhost:3000/)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
#### Other scripts
|
|
||||||
- You can see what ports are connected to the device by running `npm run ports` script.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run ports
|
|
||||||
```
|
|
||||||
```
|
|
||||||
> lunar-vein-arduino@1.0.0 ports
|
|
||||||
> ts-node src/ports/print.ts
|
|
||||||
|
|
||||||
3 Ports available
|
|
||||||
1. /dev/ttyUSB0
|
|
||||||
2. /dev/ttyUSB1
|
|
||||||
3. /dev/ttyACM0
|
|
||||||
```
|
|
||||||
|
|
||||||
# REST API Documentation
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
- [Common HTTP Responses](#common-http-responses)
|
|
||||||
- [JSON Response](#json-response)
|
|
||||||
- [Example Request](#example-request)
|
|
||||||
- [Digital](#digital)
|
|
||||||
- [Digital Read](#digital-read)
|
|
||||||
- [Digital Write](#digital-write)
|
|
||||||
- [Analog](#analog)
|
|
||||||
- [Analog Read](#analog-read)
|
|
||||||
- [Analog Write](#analog-write)
|
|
||||||
- [PIN](#pin)
|
|
||||||
- [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)
|
|
||||||
- [RGB LED](#rgb-led)
|
|
||||||
- [Read RGB state](#read-rgb-state)
|
|
||||||
- [Set RGB state](#set-rgb-state)
|
|
||||||
- [Piezo](#piezo)
|
|
||||||
- [Piezo Tone](#piezo-tone)
|
|
||||||
- [Piezo Note](#piezo-note)
|
|
||||||
- [Piezo Play Music](#piezo-play-music)
|
|
||||||
|
|
||||||
## Common HTTP Responses
|
|
||||||
Some HTTP responses are sent with JSON, otherwise an HTML body will be sent which is the default express.js response
|
|
||||||
|
|
||||||
| HTTP Status | Marks |
|
|
||||||
|-------------|-------|
|
|
||||||
| 200 | The request `act` was successful |
|
|
||||||
| 400 | You may be making an invalid request, try to check the payload or recheck the documentation. |
|
|
||||||
| 404 | The resource wass not found |
|
|
||||||
| 405 | Method not allowed, servers usually only accept `GET` and `PATCH` methods |
|
|
||||||
| 500 | An error in the app server, if it continues please raise an issue or ask to contribute. |
|
|
||||||
|
|
||||||
## JSON Response
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_state": {
|
|
||||||
"13": "HIGH"
|
|
||||||
},
|
|
||||||
"message": "Changed pin state 13 to HIGH"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
| Property | Description |
|
|
||||||
|----------|-------------|
|
|
||||||
| status | HTTP Status code |
|
|
||||||
| pin_state | The state value of the pin that has been changed |
|
|
||||||
| message | Descriptive message of the changed state |
|
|
||||||
|
|
||||||
## Example Request
|
|
||||||
This is an example of sending a request to turn on the LED light, [See LED API](#set-led-state)
|
|
||||||
|
|
||||||
**Using curl**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -X PATCH http://localhost:3000/api-arduino/led/13/on
|
|
||||||
```
|
|
||||||
|
|
||||||
**Using fetch async/await javascript**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
async function turnOnLed() {
|
|
||||||
const res = await fetch("http://localhost:3000/api-arduino/led/13/on", { method: 'PATCH' }); // Set LED to HIGH
|
|
||||||
const data = await res.json();
|
|
||||||
console.log(data); // { status: 200, pin_state: { 13: high }, message: "Pin 13 Set to HIGH" }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Digital
|
|
||||||
|
|
||||||
### Digital Read
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/digital/:pin`
|
|
||||||
|
|
||||||
- **URL Params**
|
|
||||||
|
|
||||||
| Params | Mark | Type | Required | Description |
|
|
||||||
|--------|------|------|----------|-------------|
|
|
||||||
| pin | pin | `string` | true | Seleced pin |
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`GET`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
```javascript
|
|
||||||
fetch("http://localhost:3000/api-arduino/digital/13")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_state": {
|
|
||||||
"13": "HIGH"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Digital Write
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/digital`
|
|
||||||
|
|
||||||
- **Body**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
pin: number,
|
|
||||||
state: 'HIGH' | 'LOW' | 1 | 0 | string
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`PATCH`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var data = {
|
|
||||||
pin: 13,
|
|
||||||
state: 'LOW'
|
|
||||||
}
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
method: 'PATCH',
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
redirect: 'follow'
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch("http://localhost:3000/api-arduino/digital", options)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_state": {
|
|
||||||
"13": "HIGH"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Analog
|
|
||||||
|
|
||||||
### Analog Read
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/analog/:p`
|
|
||||||
|
|
||||||
- **URL Params**
|
|
||||||
|
|
||||||
| Params | Mark | Type | Required | Description |
|
|
||||||
|--------|------|------|----------|-------------|
|
|
||||||
| pin | pin | `string` | true | Seleced pin |
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`GET`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
```javascript
|
|
||||||
fetch("http://localhost:3000/api-arduino/analog/A0")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"analog_state": {
|
|
||||||
"A0": 1023
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Analog Write
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/analog`
|
|
||||||
|
|
||||||
- **Body**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
pin: string | number,
|
|
||||||
value: number
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`PATCH`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var data = {
|
|
||||||
pin: 'A0',
|
|
||||||
value: 1023
|
|
||||||
}
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
method: 'PATCH',
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
redirect: 'follow'
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch("http://localhost:3000/api-arduino/analog", options)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_state": {
|
|
||||||
"13": 1023
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## PIN
|
|
||||||
|
|
||||||
### Read PIN Mode
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/pin/:p/`
|
|
||||||
|
|
||||||
- **URL Params**
|
|
||||||
|
|
||||||
| Params | Mark | Type | Required | Description |
|
|
||||||
|--------|------|------|----------|-------------|
|
|
||||||
| p | pin | `string` | true | Seleced pin |
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`GET`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
fetch("http://localhost:3000/api-arduino/pin/13")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pins": [
|
|
||||||
{
|
|
||||||
"pin": 13,
|
|
||||||
"mode": "OUTPUT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"message": "Pin 13 is OUTPUT"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set PIN Mode
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/pin/:p/:m`
|
|
||||||
|
|
||||||
- **URL Params**
|
|
||||||
|
|
||||||
| Params | Mark | Type | Required | Description |
|
|
||||||
|--------|------|------|----------|-------------|
|
|
||||||
| p | pin | `string` | true | Seleced pin |
|
|
||||||
| m | mode | `'input'`, `'output'`, `'servo'` | true | Pin Mode |
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`PATCH`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
fetch("http://localhost:3000/api-arduino/pin/13/output", { method: 'PATCH' })
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pins": [
|
|
||||||
{
|
|
||||||
"pin": 13,
|
|
||||||
"mode": "OUTPUT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"message": "Pin 13 setted as OUTPUT"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## LED
|
|
||||||
|
|
||||||
### Read LED state
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/led/:p/`
|
|
||||||
|
|
||||||
- **URL Params**
|
|
||||||
|
|
||||||
| Params | Mark | Type | Required | Description |
|
|
||||||
|--------|------|------|----------|-------------|
|
|
||||||
| p | pin | `string` | true | Seleced pin |
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`GET`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
fetch("http://localhost:3000/api-arduino/led/13")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_state": {
|
|
||||||
"13": "HIGH"
|
|
||||||
},
|
|
||||||
"message": "Led pin 13 is HIGH"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set LED state
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/led/:p/:a`
|
|
||||||
|
|
||||||
- **URL Params**
|
|
||||||
|
|
||||||
| Params | Mark | Type | Required | Description |
|
|
||||||
|--------|------|------|----------|-------------|
|
|
||||||
| p | pin | `string` | true | Seleced pin |
|
|
||||||
| a | act | `'on'`, `'off'`, `'high'`, `'low'` | true | Action |
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`PATCH`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
fetch("http://localhost:3000/api-arduino/led/13/output", { method: 'PATCH' })
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_state": {
|
|
||||||
"13": "HIGH"
|
|
||||||
},
|
|
||||||
"message": "Changed pin state 13 to HIGH"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## RGB LED
|
|
||||||
|
|
||||||
### Read RGB state
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/rgb-led`
|
|
||||||
|
|
||||||
- **Body**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
r: number,
|
|
||||||
g: number,
|
|
||||||
b: number
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`POST`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var data = {
|
|
||||||
r: 7,
|
|
||||||
g: 6,
|
|
||||||
b: 5
|
|
||||||
}
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
redirect: 'follow'
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch("http://localhost:3000/api-arduino/rgb-led", options)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_state": {
|
|
||||||
"7": true,
|
|
||||||
"6": true,
|
|
||||||
"5": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set RGB state
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/rgb-led`
|
|
||||||
|
|
||||||
- **Body**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
r: {
|
|
||||||
pin: number,
|
|
||||||
value: boolean
|
|
||||||
},
|
|
||||||
g: {
|
|
||||||
pin: number,
|
|
||||||
value: boolean
|
|
||||||
},
|
|
||||||
b: {
|
|
||||||
pin: number,
|
|
||||||
value: boolean
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`PATCH`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var data = {
|
|
||||||
r: {
|
|
||||||
pin: 7,
|
|
||||||
value: true
|
|
||||||
},
|
|
||||||
g: {
|
|
||||||
pin: 6,
|
|
||||||
value: true
|
|
||||||
},
|
|
||||||
b: {
|
|
||||||
pin: 5,
|
|
||||||
value: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
method: 'PATCH',
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
redirect: 'follow'
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch("http://localhost:3000/api-arduino/rgb-led", options)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_state": {
|
|
||||||
"7": true,
|
|
||||||
"6": true,
|
|
||||||
"5": false
|
|
||||||
},
|
|
||||||
"message": "Success changed pins 7, 6, 5 to state HIGH, HIGH, LOW"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Piezo
|
|
||||||
|
|
||||||
### Piezo Tone
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/piezo/:p/:f`
|
|
||||||
|
|
||||||
- **URL Params**
|
|
||||||
|
|
||||||
| Params | Mark | Type | Required | Description |
|
|
||||||
|--------|------|------|----------|-------------|
|
|
||||||
| p | pin | `string` | true | Seleced pin |
|
|
||||||
| f | frequency | `number` | true | Frequency |
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`PATCH`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
fetch("http://localhost:3000/api-arduino/piezo/6/300", { method: 'PATCH' })
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_tone": {
|
|
||||||
"6": 300
|
|
||||||
},
|
|
||||||
"message": "Piezo 6 tone 300"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Piezo Note
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/piezo/note`
|
|
||||||
|
|
||||||
- **Body**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
pin: number,
|
|
||||||
note: string
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`PATCH`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var data = {
|
|
||||||
pin: 6,
|
|
||||||
note: "B3"
|
|
||||||
}
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
method: 'PATCH',
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
redirect: 'follow'
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch("http://localhost:3000/api-arduino/piezo/note", options)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_tone": {
|
|
||||||
"6": 247
|
|
||||||
},
|
|
||||||
"pin_note": {
|
|
||||||
"6": "B3"
|
|
||||||
},
|
|
||||||
"message": "Piezo 6 tone note B3"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Piezo Play Music
|
|
||||||
- **URL Endpoint**
|
|
||||||
|
|
||||||
`/api-arduino/piezo/music`
|
|
||||||
|
|
||||||
- **Body**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
pin: number,
|
|
||||||
notes: string[],
|
|
||||||
beats: number,
|
|
||||||
tempo: number
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Example
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
pin: 6,
|
|
||||||
notes: ["F4", "G4", "F4", "G4"],
|
|
||||||
beats: 1/4,
|
|
||||||
tempo: 100
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Method**
|
|
||||||
|
|
||||||
`PATCH`
|
|
||||||
|
|
||||||
- **Example Request**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var data = {
|
|
||||||
pin: 6,
|
|
||||||
notes: ["E4", "E4", "F4", "G4", "G4", "F4", "E4", "D4", "C4", "C4", "D4", "E4", "D4", "-", "C4", "C4"], // ode to joy notes
|
|
||||||
beats: 1/2,
|
|
||||||
tempo: 100
|
|
||||||
}
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
method: 'PATCH',
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
redirect: 'follow'
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch("http://localhost:3000/api-arduino/piezo/music", options)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => console.log(res))
|
|
||||||
.catch(err => console.error('error', err));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Example Response**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"pin_notes": {
|
|
||||||
"6": [ "E4", "E4", "F4", "G4", "G4", "F4", "E4", "D4", "C4", "C4", "D4", "E4", "D4", "-", "C4", "C4" ]
|
|
||||||
},
|
|
||||||
"message": "Piezo 6 play notes E4, E4, F4, G4..."
|
|
||||||
}
|
|
||||||
```
|
|
BIN
docs/client.png
Before Width: | Height: | Size: 114 KiB |
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"watch": ["src"],
|
"watch": ["src"],
|
||||||
"ext": ".ts,.js"
|
"ext": ".ts,.js",
|
||||||
|
"exec": "ts-node ./src/index.ts"
|
||||||
}
|
}
|
1289
package-lock.json
generated
15
package.json
@ -1,39 +1,28 @@
|
|||||||
{
|
{
|
||||||
"name": "lunar-vein-arduino",
|
"name": "lunar-vein-arduino",
|
||||||
"version": "0.0.6",
|
"version": "1.0.0",
|
||||||
"description": "A test to arduino",
|
"description": "A test to arduino",
|
||||||
"main": "index.ts",
|
"main": "index.ts",
|
||||||
"author": "Norman Andrians",
|
"author": "Norman Andrians",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "nodemon --exec ts-node ./src",
|
"start": "nodemon",
|
||||||
"dev": "nodemon --exec ts-node ./src/dev.ts",
|
|
||||||
"ports": "ts-node src/ports/print.ts",
|
|
||||||
"test-blink": "nodemon test/blink.js"
|
"test-blink": "nodemon test/blink.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@serialport/bindings": "^9.2.9",
|
"@serialport/bindings": "^9.2.9",
|
||||||
"@serialport/list": "^12.0.0",
|
|
||||||
"@types/ip": "^1.1.3",
|
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"cors": "^2.8.5",
|
|
||||||
"dotenv": "^16.4.5",
|
|
||||||
"express": "^4.18.3",
|
"express": "^4.18.3",
|
||||||
"firmata": "^2.3.0",
|
"firmata": "^2.3.0",
|
||||||
"ip": "^2.0.1",
|
|
||||||
"johnny-five": "^2.1.0",
|
|
||||||
"nodemon": "^3.1.0",
|
"nodemon": "^3.1.0",
|
||||||
"pkg": "^5.8.1",
|
|
||||||
"serialport": "^12.0.0",
|
"serialport": "^12.0.0",
|
||||||
"socket.io": "^4.7.4"
|
"socket.io": "^4.7.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/firmata": "^0.19.8",
|
"@types/firmata": "^0.19.8",
|
||||||
"@types/johnny-five": "^2.1.9",
|
|
||||||
"@types/nodemon": "^1.19.6",
|
"@types/nodemon": "^1.19.6",
|
||||||
"@types/serialport": "^8.0.5",
|
|
||||||
"@types/socket.io": "^3.0.2",
|
"@types/socket.io": "^3.0.2",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
|
40
src/app.ts
@ -1,40 +0,0 @@
|
|||||||
import readline from "node:readline/promises";
|
|
||||||
import chalk from "chalk";
|
|
||||||
import { Board } from "johnny-five";
|
|
||||||
|
|
||||||
import { selectPort } from "./ports";
|
|
||||||
import { run } from "./server";
|
|
||||||
import { suBoard } from "./setup";
|
|
||||||
import { cfg } from "./setup/config";
|
|
||||||
import { getPublicIp } from "./utils/network";
|
|
||||||
|
|
||||||
async function questions () {
|
|
||||||
const line = readline.createInterface({
|
|
||||||
input: process.stdin,
|
|
||||||
output: process.stdout
|
|
||||||
})
|
|
||||||
|
|
||||||
const exposeHost = await line.question("Run in public network? (y/n) ");
|
|
||||||
|
|
||||||
if (exposeHost.toLowerCase() == "y") {
|
|
||||||
console.warn(chalk.yellow("Running a server on a public host may not be able to use the socket.io api"));
|
|
||||||
cfg.server.host = getPublicIp();
|
|
||||||
}
|
|
||||||
|
|
||||||
line.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function main () {
|
|
||||||
const port = await selectPort();
|
|
||||||
await questions();
|
|
||||||
|
|
||||||
console.log(`Selected port ${port}`);
|
|
||||||
|
|
||||||
cfg.port = port;
|
|
||||||
suBoard.board = new Board({
|
|
||||||
port: port,
|
|
||||||
debug: false,
|
|
||||||
repl: false
|
|
||||||
});
|
|
||||||
run();
|
|
||||||
}
|
|
Before Width: | Height: | Size: 855 KiB |
Before Width: | Height: | Size: 4.8 MiB |
Before Width: | Height: | Size: 486 KiB |
Before Width: | Height: | Size: 365 KiB |
Before Width: | Height: | Size: 4.8 KiB |
@ -1,14 +1,16 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8">
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<title>Firmata Arduino Client</title>
|
||||||
<title>Lunar Vein: Arduino</title>
|
<link rel="stylesheet" href="style/main.css">
|
||||||
<script type="module" crossorigin src="/assets/index-CfbleRJs.js"></script>
|
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-jsM6q3pf.css">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<section>
|
||||||
|
<h2>LED</h2>
|
||||||
|
<button id="toggleLed1">ON/OFF</button>
|
||||||
|
</section>
|
||||||
|
<script src="./scripts/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
17
src/client/scripts/main.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
document.getElementById('toggleLed1').addEventListener('mousedown', async () => {
|
||||||
|
const res = await fetch('/api-arduino/led/13/on', {
|
||||||
|
method: 'PATCH'
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
})
|
||||||
|
|
||||||
|
document.getElementById('toggleLed1').addEventListener('mouseup', async () => {
|
||||||
|
const res = await fetch('/api-arduino/led/13/off', {
|
||||||
|
method: 'PATCH'
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
})
|
0
src/client/style/main.css
Normal file
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,50 +0,0 @@
|
|||||||
import { Request, Response } from "express";
|
|
||||||
import { suBoard } from "../../setup";
|
|
||||||
import * as Promises from "../../promises";
|
|
||||||
|
|
||||||
|
|
||||||
interface AnalogState {
|
|
||||||
pin: string,
|
|
||||||
value: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export function analogWrite (req: Request, res: Response): Response<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
const { pin, value }: AnalogState = req.body;
|
|
||||||
|
|
||||||
try {
|
|
||||||
board.analogWrite(pin[0] == "A" ? pin.slice(1, pin.length) : 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) {
|
|
||||||
const { board } = suBoard;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
import { Request, Response } from "express";
|
|
||||||
import { suBoard } from "../../setup";
|
|
||||||
|
|
||||||
interface DigitalState {
|
|
||||||
pin: number | string,
|
|
||||||
state: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export function digitalWrite (req: Request, res: Response): Response<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
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<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
import { Request, Response } from "express";
|
|
||||||
import { suBoard } from "../../setup";
|
|
||||||
import { sPinModes } from "..";
|
|
||||||
import { Pin } from "johnny-five";
|
|
||||||
|
|
||||||
|
|
||||||
export function readPin (req: Request, res: Response): Response<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
const pin: string = req.params.p;
|
|
||||||
|
|
||||||
const { mode } = board.pins[pin];
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
pins: [
|
|
||||||
{
|
|
||||||
pin: pin,
|
|
||||||
mode: mode
|
|
||||||
}
|
|
||||||
],
|
|
||||||
message: `Pin ${pin} is ${mode}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readPins (req: Request, res: Response): Response<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
const pins: string[] = req.body.p;
|
|
||||||
const pinModes = [];
|
|
||||||
|
|
||||||
pins.forEach((pin) => {
|
|
||||||
const { mode } = board.pins[pin];
|
|
||||||
pinModes.push({
|
|
||||||
pin: pin,
|
|
||||||
mode: mode
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
pins: [ ...pinModes ]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setPin (req: Request, res: Response): Response<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
const pin: string = req.params.p;
|
|
||||||
const mode: sPinModes | string = req.params.m.toUpperCase();
|
|
||||||
|
|
||||||
board.pinMode(pin, Pin[mode]);
|
|
||||||
|
|
||||||
suBoard.PINS.digital.push(pin);
|
|
||||||
suBoard.sort();
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
pins: [
|
|
||||||
{
|
|
||||||
pin: pin,
|
|
||||||
mode: mode
|
|
||||||
}
|
|
||||||
],
|
|
||||||
message: `Pin ${pin} setted as ${mode}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setPins (req: Request, res: Response): Response<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
type PinModes = {
|
|
||||||
pin: string,
|
|
||||||
mode: sPinModes | string
|
|
||||||
}
|
|
||||||
|
|
||||||
const { pinModes }: { pinModes: PinModes[] } = req.body;
|
|
||||||
|
|
||||||
pinModes.forEach((p) => {
|
|
||||||
const { pin, mode } = p;
|
|
||||||
board.pinMode(pin, Pin[mode]);
|
|
||||||
|
|
||||||
suBoard.PINS.digital.push(pin);
|
|
||||||
suBoard.sort();
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
pins: [ ...pinModes ]
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,185 +0,0 @@
|
|||||||
import { Request, Response } from "express";
|
|
||||||
import { suBoard } from "../../setup";
|
|
||||||
import { ChannelPins, voltage } from "..";
|
|
||||||
import { Led } from "johnny-five";
|
|
||||||
|
|
||||||
export function readLed (req: Request, res: Response): Response<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
try {
|
|
||||||
const { p } = req.params;
|
|
||||||
const pin: number = Number.parseInt(p);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
console.error(err);
|
|
||||||
return res.status(500).json({
|
|
||||||
status: 200,
|
|
||||||
message: "Internal server error"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function writeLed (req: Request, res: Response): Response<string | any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
const { p, a } = req.params;
|
|
||||||
const act: string = a.toLocaleLowerCase();
|
|
||||||
const pin: number = Number.parseInt(p);
|
|
||||||
|
|
||||||
let state: voltage;
|
|
||||||
let volt: voltage;
|
|
||||||
|
|
||||||
try {
|
|
||||||
switch (act) {
|
|
||||||
case 'on' || 'high':
|
|
||||||
state = 'HIGH';
|
|
||||||
volt = 1;
|
|
||||||
break;
|
|
||||||
case 'off' || 'low':
|
|
||||||
state = 'LOW';
|
|
||||||
volt = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log(`${req.hostname} | ${pin} | LED: INVALID ACT`);
|
|
||||||
return res.status(400).json({
|
|
||||||
status: 400,
|
|
||||||
message: `Invalid act ${act}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
board.digitalWrite(pin, volt);
|
|
||||||
|
|
||||||
console.log(`${req.hostname} | ${pin} | LED: ${state}`);
|
|
||||||
|
|
||||||
res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
pin_state: {
|
|
||||||
[pin]: state
|
|
||||||
},
|
|
||||||
message: `Changed pin state ${pin} to ${state}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
res.status(500).json({
|
|
||||||
status: 500,
|
|
||||||
message: "Internal Server Error"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export function readRgbLed (req: Request, res: Response): Response<string | any> {
|
|
||||||
const r: number = Number.parseInt(req.body.r);
|
|
||||||
const g: number = Number.parseInt(req.body.g);
|
|
||||||
const b: number = Number.parseInt(req.body.b);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const rgbPins: number[] = Object.values({ r, g, b });
|
|
||||||
|
|
||||||
for (let i = 0; i < rgbPins.length; i++) {
|
|
||||||
const pin = rgbPins[i];
|
|
||||||
if (Number.isNaN(pin)) {
|
|
||||||
return res.status(400).json({
|
|
||||||
status: 400,
|
|
||||||
message: `Invalid pin ${pin} param, it should be integer`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const led = new Led.RGB({
|
|
||||||
pins: {
|
|
||||||
red: r,
|
|
||||||
green: g,
|
|
||||||
blue: b
|
|
||||||
},
|
|
||||||
isAnode: true
|
|
||||||
})
|
|
||||||
|
|
||||||
led.red = new Led(r);
|
|
||||||
led.green = new Led(g);
|
|
||||||
led.blue = new Led(b);
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
pin_state: {
|
|
||||||
[r]: led.red.isOn,
|
|
||||||
[g]: led.green.isOn,
|
|
||||||
[b]: led.blue.isOn
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return res.status(500).json({
|
|
||||||
status: 200,
|
|
||||||
message: "Internal server error"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function writeRgbLed (req: Request, res: Response): Response<string | any> {
|
|
||||||
const r: ChannelPins = req.body.r;
|
|
||||||
const g: ChannelPins = req.body.g;
|
|
||||||
const b: ChannelPins = req.body.b;
|
|
||||||
|
|
||||||
const rgbLeds: ChannelPins[] = Object.values({ r, g, b });
|
|
||||||
|
|
||||||
try {
|
|
||||||
rgbLeds.forEach(led => {
|
|
||||||
if (Number.isNaN(led.pin)) {
|
|
||||||
return res.status(400).json({
|
|
||||||
status: 400,
|
|
||||||
message: `Invalid pin ${led.pin} param, it should be integer`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const led = new Led.RGB({
|
|
||||||
pins: {
|
|
||||||
red: r.pin,
|
|
||||||
green: g.pin,
|
|
||||||
blue: b.pin
|
|
||||||
},
|
|
||||||
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 == 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}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return res.status(500).json({
|
|
||||||
status: 500,
|
|
||||||
message: "Internal Server Error"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
import { Request, Response } from "express";
|
|
||||||
import { suBoard } from "../../setup";
|
|
||||||
import { analogRead } from "../../promises";
|
|
||||||
|
|
||||||
|
|
||||||
export async function readResistor (req: Request, res: Response): Promise<Response<string, any>> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
const { p } = req.params;
|
|
||||||
const pin: string = req.params.p.startsWith("A") ? req.params.p.slice(0, p.length) : req.params.p;
|
|
||||||
|
|
||||||
const resistance = await analogRead(board, pin);
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
message: `Analog pin ${p} resistance as ${resistance}°`
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
import { Request, Response } from "express";
|
|
||||||
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);
|
|
||||||
|
|
||||||
piezo.play({
|
|
||||||
song: note.toUpperCase(),
|
|
||||||
beats: 1/2,
|
|
||||||
tempo: 100
|
|
||||||
})
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
pin_tone: {
|
|
||||||
[pin]: notePitch
|
|
||||||
},
|
|
||||||
pin_note: {
|
|
||||||
[pin]: note.toUpperCase()
|
|
||||||
},
|
|
||||||
message: `Piezo ${pin} tone note ${note}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function piezoNoTone (req: Request, res: Response): Response {
|
|
||||||
const { pin }: { pin: number } = req.body;
|
|
||||||
|
|
||||||
new Piezo(pin).noTone();
|
|
||||||
|
|
||||||
return res.sendStatus(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MusicSheet {
|
|
||||||
notes: string[];
|
|
||||||
beats: number;
|
|
||||||
tempo: 100
|
|
||||||
}
|
|
||||||
|
|
||||||
export function piezoPlayNotes (req: Request, res: Response): Response {
|
|
||||||
const { pin }: { pin: number } = req.body;
|
|
||||||
const { notes, beats, tempo }: MusicSheet = req.body;
|
|
||||||
|
|
||||||
const piezo: Piezo = new Piezo(pin);
|
|
||||||
const song: [frequency: string, duration: number][] = notes
|
|
||||||
.map((note, i): [frequency: string, duration: number] => {
|
|
||||||
const beat = notes[i+1] && notes[i+1].trim() == "-" ? beats*2 : beats;
|
|
||||||
return [note, beat]
|
|
||||||
})
|
|
||||||
.filter((note) => note[0].trim() != "-");
|
|
||||||
|
|
||||||
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}`
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
import { Request, Response } from "express";
|
|
||||||
import { suBoard } from "../../setup";
|
|
||||||
|
|
||||||
export function rotateServo (req: Request, res: Response): Response<string, any> {
|
|
||||||
const { board } = suBoard;
|
|
||||||
const { p } = req.params;
|
|
||||||
const pin: string = req.params.p.startsWith("A") ? req.params.p.slice(0, p.length) : req.params.p;
|
|
||||||
const angle: number = Number.parseInt(req.params.ang);
|
|
||||||
|
|
||||||
if (Number.isNaN(angle)) {
|
|
||||||
return res.status(400).json({
|
|
||||||
status: 400,
|
|
||||||
message: 'Invalid angle param, it should be integer'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
board.servoWrite(pin, angle);
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
status: 200,
|
|
||||||
message: `Pin ${p} rotate as ${angle}°`
|
|
||||||
});
|
|
||||||
}
|
|
6
src/controller/index.d.ts
vendored
@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
export type digitalValue = 'ON' | 'OFF';
|
export type digitalValue = 'ON' | 'OFF';
|
||||||
export type voltage = 'HIGH' | 'LOW' | 'high' | 'low' | 1 | 0;
|
export type voltage = 'HIGH' | 'LOW';
|
||||||
export type sPinModes = 'INPUT' | 'OUTPUT' | 'ANALOG' | 'PWM' | 'SERVO';
|
export type sPinModes = 'INPUT' | 'OUTPUT' | 'ANALOG' | 'PWM' | 'SERVO' |'SHIFT' |'I2C' |'ONEWIRE' |'STEPPER' |'SERIAL' |'PULLUP' |'IGNORE' |'PING_READ' | 'UNKOWN';
|
||||||
|
|
||||||
export interface ChannelPins {
|
export interface ChannelPins {
|
||||||
pin: number,
|
pin: number,
|
||||||
value: boolean
|
value: digitalValue
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ColorChannel {
|
export interface ColorChannel {
|
||||||
|
157
src/controller/led.ts
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
import { Request, Response } from "express";
|
||||||
|
import { board } from "../setup";
|
||||||
|
import { ChannelPins, digitalValue, voltage } from ".";
|
||||||
|
import { digitalRead } from "../promises";
|
||||||
|
|
||||||
|
|
||||||
|
export async function readLed (req: Request, res: Response) {
|
||||||
|
const { p } = req.params;
|
||||||
|
const pin: number = Number.parseInt(p);
|
||||||
|
|
||||||
|
if (Number.isNaN(pin)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
status: 400,
|
||||||
|
message: 'Invalid pin param, it should be integer'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const pinState: digitalValue = board.pins[pin].value == 1 ? 'ON' : 'OFF';
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
status: 200,
|
||||||
|
pin_state: {
|
||||||
|
[pin]: pinState
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function writeLed (req: Request, res: Response) {
|
||||||
|
const { p, a } = req.params;
|
||||||
|
const act: string = a.toLocaleLowerCase();
|
||||||
|
const pin: number = Number.parseInt(p);
|
||||||
|
|
||||||
|
let state: digitalValue;
|
||||||
|
let volt: voltage;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Number.isNaN(pin)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
status: 400,
|
||||||
|
message: 'Invalid pin param, it should be integer'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (act) {
|
||||||
|
case 'on':
|
||||||
|
state = 'ON';
|
||||||
|
volt = 'HIGH';
|
||||||
|
console.log(`${req.hostname} | ${pin} | LED: ${state}`);
|
||||||
|
break;
|
||||||
|
case 'off':
|
||||||
|
state = 'OFF';
|
||||||
|
volt = 'LOW';
|
||||||
|
console.log(`${req.hostname} | ${pin} | LED: ${state}`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(`${req.hostname} | ${pin} | LED: INVALID ACT`);
|
||||||
|
return res.status(400).json({
|
||||||
|
status: 400,
|
||||||
|
message: `Invalid act ${act}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
board.digitalWrite(pin, board[volt]);
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
status: 200,
|
||||||
|
message: `Success changed pin ${pin} to state ${state}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).json({
|
||||||
|
status: 500,
|
||||||
|
message: "Internal Server Error"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export async function readRgbLed (req: Request, res: Response) {
|
||||||
|
const r: number = Number.parseInt(req.body.r);
|
||||||
|
const g: number = Number.parseInt(req.body.b);
|
||||||
|
const b: number = Number.parseInt(req.body.b);
|
||||||
|
|
||||||
|
const rgbPins: number[] = Object.values({ r, g, b });
|
||||||
|
const pinStates: number[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < rgbPins.length; i++) {
|
||||||
|
const pin = rgbPins[i];
|
||||||
|
|
||||||
|
if (Number.isNaN(pin)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
status: 400,
|
||||||
|
message: `Invalid pin ${pin} param, it should be integer`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const state: number = await digitalRead(board, pin);
|
||||||
|
pinStates.push(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
status: 200,
|
||||||
|
pin_state: {
|
||||||
|
[r]: pinStates[0],
|
||||||
|
[g]: pinStates[1],
|
||||||
|
[b]: pinStates[2]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function writeRgbLed (req: Request, res: Response) {
|
||||||
|
const r: ChannelPins = req.body.r;
|
||||||
|
const g: ChannelPins = req.body.b;
|
||||||
|
const b: ChannelPins = req.body.b;
|
||||||
|
|
||||||
|
const rgbLeds: ChannelPins[] = Object.values({ r, g, b });
|
||||||
|
|
||||||
|
try {
|
||||||
|
rgbLeds.forEach((led, i) => {
|
||||||
|
if (Number.isNaN(led.pin)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
status: 400,
|
||||||
|
message: `Invalid pin ${led.pin} param, it should be integer`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (led.value) {
|
||||||
|
case 'ON':
|
||||||
|
board.analogWrite(led.pin, board.HIGH);
|
||||||
|
console.log(`${req.hostname} | ${led.pin} | LED: ${led.value}`);
|
||||||
|
break;
|
||||||
|
case 'OFF':
|
||||||
|
board.analogWrite(led.pin, board.LOW);
|
||||||
|
console.log(`${req.hostname} | ${led.pin} | LED: ${led.value}`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(`${req.hostname} | ${led.pin} | LED: INVALID VALUE`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const pins: string[] = rgbLeds.map(c => `${c.pin}, `);
|
||||||
|
const values: string[] = rgbLeds.map(c => `${c.value}, `);
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
status: 200,
|
||||||
|
message: `Success changed pins ${pins} to state ${values}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).json({
|
||||||
|
status: 500,
|
||||||
|
message: "Internal Server Error"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
46
src/controller/pin.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Request, Response } from "express";
|
||||||
|
import { board, suBoard } from "../setup";
|
||||||
|
import { sPinModes } from ".";
|
||||||
|
|
||||||
|
export function readPin (req: Request, res: Response) {
|
||||||
|
const pin: number = Number.parseInt(req.params.p);
|
||||||
|
|
||||||
|
if (Number.isNaN(pin)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
status: 400,
|
||||||
|
message: 'Invalid pin param, it should be integer'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { mode } = board.pins[pin];
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
status: 200,
|
||||||
|
state: {
|
||||||
|
used: true
|
||||||
|
},
|
||||||
|
message: `Pin ${pin} is ${mode}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setPin (req: Request, res: Response) {
|
||||||
|
const pin: number = Number.parseInt(req.params.p);
|
||||||
|
const mode: sPinModes | string = req.params.m.toUpperCase();
|
||||||
|
|
||||||
|
if (Number.isNaN(pin)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
status: 400,
|
||||||
|
message: 'Invalid pin param, it should be integer'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
board.pinMode(pin, board.MODES[mode]);
|
||||||
|
|
||||||
|
suBoard.PINS.pwm.push(pin);
|
||||||
|
suBoard.sort();
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
status: 200,
|
||||||
|
message: `Pin ${pin} setted as ${mode}`
|
||||||
|
});
|
||||||
|
}
|
@ -1,7 +0,0 @@
|
|||||||
import { Board } from "johnny-five";
|
|
||||||
import { run } from "./server";
|
|
||||||
import { defaultBoardOption, suBoard } from "./setup";
|
|
||||||
|
|
||||||
suBoard.board = new Board(defaultBoardOption);
|
|
||||||
|
|
||||||
run();
|
|
@ -1,57 +0,0 @@
|
|||||||
import { Socket } from "socket.io";
|
|
||||||
import { Pin, Sensor } from "johnny-five";
|
|
||||||
import { suBoard } from "../setup";
|
|
||||||
|
|
||||||
const { board } = suBoard;
|
|
||||||
|
|
||||||
export default (socket: Socket) => {
|
|
||||||
console.log(`${socket.id} | ${socket.client.request.headers.host} | Joined`);
|
|
||||||
|
|
||||||
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, 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}`);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
36
src/index.ts
@ -1,3 +1,35 @@
|
|||||||
import main from "./app";
|
import http from 'node:http';
|
||||||
|
import express, { Request, Response } from 'express';
|
||||||
|
import { Server } from 'socket.io';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
main();
|
import { board, suBoard, comport } from './setup';
|
||||||
|
|
||||||
|
import { isBoardConnected } from './middleware/connection';
|
||||||
|
import view from './routes/view';
|
||||||
|
import api from './routes/api';
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const server = http.createServer(app);
|
||||||
|
const io = new Server(server); // I have no experience at WebSocket, so.. forgive me :)
|
||||||
|
|
||||||
|
const host = 'localhost';
|
||||||
|
const port = 3000;
|
||||||
|
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.static('client'));
|
||||||
|
|
||||||
|
app.use('/', view);
|
||||||
|
app.use('/api-arduino', isBoardConnected, api);
|
||||||
|
|
||||||
|
app.listen(port, host, () => {
|
||||||
|
console.log(`Server is connected and running in ${host} at port ${port} 🗣️🗣️🗣️`);
|
||||||
|
console.log(`Press CTRL+C to exit`);
|
||||||
|
console.log(`URL: http://${host}:${port}/\n`);
|
||||||
|
console.log(chalk.yellow(`Connecting to Board`));
|
||||||
|
|
||||||
|
board.on('ready', () => {
|
||||||
|
console.log(chalk.green(`Board at port ${comport} Connected!! \(^o^)/`));
|
||||||
|
suBoard.connected = true;
|
||||||
|
})
|
||||||
|
});
|
@ -1,91 +0,0 @@
|
|||||||
export const Pitch = {
|
|
||||||
B0: 31,
|
|
||||||
C1: 33,
|
|
||||||
CS1: 35,
|
|
||||||
D1: 37,
|
|
||||||
DS1: 39,
|
|
||||||
E1: 41,
|
|
||||||
F1: 44,
|
|
||||||
FS1: 46,
|
|
||||||
G1: 49,
|
|
||||||
GS1: 52,
|
|
||||||
A1: 55,
|
|
||||||
AS1: 58,
|
|
||||||
B1: 62,
|
|
||||||
C2: 65,
|
|
||||||
CS2: 69,
|
|
||||||
D2: 73,
|
|
||||||
DS2: 78,
|
|
||||||
E2: 82,
|
|
||||||
F2: 87,
|
|
||||||
FS2: 93,
|
|
||||||
G2: 98,
|
|
||||||
GS2: 104,
|
|
||||||
A2: 110,
|
|
||||||
AS2: 117,
|
|
||||||
B2: 123,
|
|
||||||
C3: 131,
|
|
||||||
CS3: 139,
|
|
||||||
D3: 147,
|
|
||||||
DS3: 156,
|
|
||||||
E3: 165,
|
|
||||||
F3: 175,
|
|
||||||
FS3: 185,
|
|
||||||
G3: 196,
|
|
||||||
GS3: 208,
|
|
||||||
A3: 220,
|
|
||||||
AS3: 233,
|
|
||||||
B3: 247,
|
|
||||||
C4: 262,
|
|
||||||
CS4: 277,
|
|
||||||
D4: 294,
|
|
||||||
DS4: 311,
|
|
||||||
E4: 330,
|
|
||||||
F4: 349,
|
|
||||||
FS4: 370,
|
|
||||||
G4: 392,
|
|
||||||
GS4: 415,
|
|
||||||
A4: 440,
|
|
||||||
AS4: 466,
|
|
||||||
B4: 494,
|
|
||||||
C5: 523,
|
|
||||||
CS5: 554,
|
|
||||||
D5: 587,
|
|
||||||
DS5: 622,
|
|
||||||
E5: 659,
|
|
||||||
F5: 698,
|
|
||||||
FS5: 740,
|
|
||||||
G5: 784,
|
|
||||||
GS5: 831,
|
|
||||||
A5: 880,
|
|
||||||
AS5: 932,
|
|
||||||
B5: 988,
|
|
||||||
C6: 1047,
|
|
||||||
CS6: 1109,
|
|
||||||
D6: 1175,
|
|
||||||
DS6: 1245,
|
|
||||||
E6: 1319,
|
|
||||||
F6: 1397,
|
|
||||||
FS6: 1480,
|
|
||||||
G6: 1568,
|
|
||||||
GS6: 1661,
|
|
||||||
A6: 1760,
|
|
||||||
AS6: 1865,
|
|
||||||
B6: 1976,
|
|
||||||
C7: 2093,
|
|
||||||
CS7: 2217,
|
|
||||||
D7: 2349,
|
|
||||||
DS7: 2489,
|
|
||||||
E7: 2637,
|
|
||||||
F7: 2794,
|
|
||||||
FS7: 2960,
|
|
||||||
G7: 3136,
|
|
||||||
GS7: 3322,
|
|
||||||
A7: 3520,
|
|
||||||
AS7: 3729,
|
|
||||||
B7: 3951,
|
|
||||||
C8: 4186,
|
|
||||||
CS8: 4435,
|
|
||||||
D8: 4699,
|
|
||||||
DS8: 4978
|
|
||||||
}
|
|
@ -1,8 +1,6 @@
|
|||||||
import { NextFunction, Request, Response } from "express";
|
import { NextFunction, Request, Response } from "express";
|
||||||
import { suBoard } from "../setup";
|
import { suBoard } from "../setup";
|
||||||
|
|
||||||
const { board } = suBoard;
|
|
||||||
|
|
||||||
export function isBoardConnected (req: Request, res: Response, next: NextFunction) {
|
export function isBoardConnected (req: Request, res: Response, next: NextFunction) {
|
||||||
if (suBoard.connected) {
|
if (suBoard.connected) {
|
||||||
next();
|
next();
|
||||||
|
@ -1,19 +1,6 @@
|
|||||||
import { NextFunction, Request, Response } from "express";
|
import { NextFunction, Request, Response } from "express";
|
||||||
import { suBoard } from "../setup";
|
import { suBoard } from "../setup";
|
||||||
|
|
||||||
export function isPinNumeric (req: Request, res: Response, next: NextFunction) {
|
|
||||||
const pin: number = Number.parseInt(req.params.p);
|
|
||||||
|
|
||||||
if (Number.isNaN(pin)) {
|
|
||||||
return res.status(400).json({
|
|
||||||
status: 400,
|
|
||||||
message: 'Invalid pin param, it should be integer'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isPinBeingUsed(req: Request, res: Response, next: NextFunction) {
|
export function isPinBeingUsed(req: Request, res: Response, next: NextFunction) {
|
||||||
const pin: number = Number.parseInt(req.params.p);
|
const pin: number = Number.parseInt(req.params.p);
|
||||||
|
|
||||||
@ -24,7 +11,7 @@ export function isPinBeingUsed (req: Request, res: Response, next: NextFunction)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (suBoard.PINS.digital.indexOf(pin) != -1) {
|
if (suBoard.PINS.pwm.indexOf(pin) != -1) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
status: 400,
|
status: 400,
|
||||||
message: `Pin ${pin}, is used`
|
message: `Pin ${pin}, is used`
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import readline from 'node:readline/promises';
|
|
||||||
import { ReadPorts } from "./read";
|
|
||||||
|
|
||||||
export async function selectPort (): Promise<string | any> {
|
|
||||||
const ports = await ReadPorts();
|
|
||||||
|
|
||||||
const line = readline.createInterface({
|
|
||||||
input: process.stdin,
|
|
||||||
output: process.stdout
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Select number of ports (0-${ports.length})`);
|
|
||||||
ports.forEach((port, i) => {
|
|
||||||
console.log(`${i+1}. ${port.path} - ${port.name}${port.serialNumber ? " - Recomended" : ""}`);
|
|
||||||
})
|
|
||||||
|
|
||||||
const selectedInput: string = await line.question("Enter number: ");
|
|
||||||
const selectedNumber: number = Number.parseInt(selectedInput);
|
|
||||||
const selectedPort: { name?: string, path?: string } = ports[selectedNumber-1];
|
|
||||||
|
|
||||||
line.close();
|
|
||||||
return selectedPort.path;
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { ReadPorts } from "./read";
|
|
||||||
|
|
||||||
ReadPorts().then((ports) => {
|
|
||||||
console.log(`${ports.length} Ports available`);
|
|
||||||
ports.forEach((port, i) => {
|
|
||||||
console.log(`${i+1}. ${port.path} - ${port.name}`);
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,14 +0,0 @@
|
|||||||
import * as SerialPort from 'serialport';
|
|
||||||
|
|
||||||
export async function ReadPorts (): Promise<{ name?: string, path?: string, serialNumber?: string | number }[]> {
|
|
||||||
const ports = await SerialPort.SerialPort.list();
|
|
||||||
return ports
|
|
||||||
.filter(port => port.pnpId != null)
|
|
||||||
.map(port => {
|
|
||||||
return {
|
|
||||||
name: port['friendlyName'],
|
|
||||||
path: port.path,
|
|
||||||
serialNumber: port.serialNumber
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
import { Board } from "johnny-five";
|
import Board, { PIN_MODE } from "firmata";
|
||||||
|
|
||||||
export function digitalRead (board: Board, pin: number): Promise<number> {
|
export function digitalRead (board: Board, pin: number): Promise<PIN_MODE | number> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
board.digitalRead(pin, (val) => {
|
board.digitalRead(pin, (val) => {
|
||||||
resolve(val);
|
resolve(val);
|
||||||
@ -11,7 +11,7 @@ export function digitalRead (board: Board, pin: number): Promise<number> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function analogRead (board: Board, pin: string): Promise<number> {
|
export function analogRead (board: Board, pin: number): Promise<number> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
board.analogRead(pin, (val) => {
|
board.analogRead(pin, (val) => {
|
||||||
resolve(val);
|
resolve(val);
|
||||||
|
@ -1,55 +1,21 @@
|
|||||||
import { Response } from "express";
|
import { Response } from "express";
|
||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
|
import { readLed, readRgbLed, writeLed, writeRgbLed } from "../controller/led";
|
||||||
|
import { readPin, setPin } from "../controller/pin";
|
||||||
|
|
||||||
import { readPin, readPins, setPin, setPins } from "../controller/basic/pin";
|
const router = Router();
|
||||||
import { digitalRead, digitalWrite } from "../controller/basic/digital";
|
|
||||||
import { analogRead, analogWrite } from "../controller/basic/analog";
|
|
||||||
|
|
||||||
import { readLed, readRgbLed, writeLed, writeRgbLed } from "../controller/components/led";
|
router.get('/hello', (req, res: Response) => {
|
||||||
import { piezoNoTone, piezoNote, piezoPlayNotes, piezoTone } from "../controller/components/piezo";
|
res.status(200).send("Hello");
|
||||||
import { rotateServo } from "../controller/components/servo";
|
|
||||||
import { readResistor } from "../controller/components/photoresistor";
|
|
||||||
|
|
||||||
import { isPinNumeric } from "../middleware/pin";
|
|
||||||
|
|
||||||
const router: Router = Router();
|
|
||||||
|
|
||||||
router.get('/hello', (req, res: Response): Response<string> => {
|
|
||||||
return res.status(200).send("Hello");
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// PinMode
|
|
||||||
router.get('/pin/:p', readPin);
|
router.get('/pin/:p', readPin);
|
||||||
router.get('/pins', readPins);
|
|
||||||
router.patch('/pin/:p/:m', setPin);
|
router.patch('/pin/:p/:m', setPin);
|
||||||
router.patch('/pins', setPins);
|
|
||||||
|
|
||||||
// Digital read/write
|
router.get('/led/:p', readLed);
|
||||||
router.get('/digital/:pin', digitalRead);
|
router.patch('/led/:p/:a', writeLed);
|
||||||
router.patch('/digital', digitalWrite);
|
|
||||||
|
|
||||||
// Analog read/write
|
router.get('/rgb-led', readRgbLed);
|
||||||
router.get('/analog/:pin', analogRead);
|
|
||||||
router.patch('/analog', analogWrite);
|
|
||||||
|
|
||||||
|
|
||||||
// LED
|
|
||||||
router.get('/led/:p', isPinNumeric, readLed);
|
|
||||||
router.patch('/led/:p/:a', isPinNumeric, writeLed);
|
|
||||||
|
|
||||||
// RGB LED
|
|
||||||
router.post('/rgb-led', readRgbLed);
|
|
||||||
router.patch('/rgb-led/', writeRgbLed);
|
router.patch('/rgb-led/', writeRgbLed);
|
||||||
|
|
||||||
// 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, we're using socket.io
|
|
||||||
router.patch('/servo/:p/:m', rotateServo);
|
|
||||||
router.get('/photoresistor/:p', readResistor);
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
@ -1,73 +0,0 @@
|
|||||||
import http from 'node:http';
|
|
||||||
import path from 'node:path';
|
|
||||||
import express from 'express';
|
|
||||||
import cors from 'cors';
|
|
||||||
import { Server } from 'socket.io';
|
|
||||||
import chalk from 'chalk';
|
|
||||||
|
|
||||||
import { suBoard, comport } from './setup';
|
|
||||||
import { cfg } from './setup/config';
|
|
||||||
|
|
||||||
import { isBoardConnected } from './middleware/connection';
|
|
||||||
import view from './routes/view';
|
|
||||||
import api from './routes/api';
|
|
||||||
import socketHandler from './handlers/socketHandler';
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
const server: http.Server = http.createServer(app);
|
|
||||||
const io: Server = new Server(server, {
|
|
||||||
cors: {
|
|
||||||
origin: cfg.server.cors
|
|
||||||
}
|
|
||||||
}); // I have no experience at WebSocket, so.. forgive me :)
|
|
||||||
|
|
||||||
// Express middleware
|
|
||||||
app.use(cors({ origin: "*" }));
|
|
||||||
app.use(express.json());
|
|
||||||
app.use(express.static(path.join(__dirname, 'client')));
|
|
||||||
|
|
||||||
// Socket.io event handlers
|
|
||||||
io.on('connection', socketHandler);
|
|
||||||
|
|
||||||
// HTTP Routes
|
|
||||||
app.use('/', view);
|
|
||||||
app.use('/api-arduino', isBoardConnected, api); // Board API Controllers
|
|
||||||
|
|
||||||
// Run server
|
|
||||||
export function run () {
|
|
||||||
const { board } = suBoard;
|
|
||||||
const { port, host } = cfg.server;
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (!board) {
|
|
||||||
throw new Error("Failed to use API, process canceled. No new API boards have been declared as of yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("\nRunning Server...");
|
|
||||||
server.listen(port, () => {
|
|
||||||
console.log(`Server is connected and running in ${host} at port ${port} 🗣️🗣️🗣️`);
|
|
||||||
console.log(`* Enter ${chalk.bold(chalk.yellow("rs"))} to restart`);
|
|
||||||
console.log(`* Press ${chalk.bold(chalk.yellow("CTRL+C"))} to exit`);
|
|
||||||
console.log(`* URL: ${chalk.bold(`http://${host}:${port}/\n`)}`);
|
|
||||||
console.log(chalk.yellow(`Connecting to Board`));
|
|
||||||
|
|
||||||
board.on('ready', () => {
|
|
||||||
console.log(chalk.green(`Board at port ${comport} Connected!! \(^o^)/`));
|
|
||||||
suBoard.connected = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
board.on('error', (err) => {
|
|
||||||
console.error(chalk.red("\nError while connecting to Board"));
|
|
||||||
console.error(chalk.red(err.message));
|
|
||||||
console.log("Enter 'rs' to try again");
|
|
||||||
})
|
|
||||||
|
|
||||||
board.on('exit', () => {
|
|
||||||
console.log("Bye bye");
|
|
||||||
})
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Fatal error. ", err);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { config } from 'dotenv';
|
|
||||||
|
|
||||||
config();
|
|
||||||
|
|
||||||
export const cfg = {
|
|
||||||
port: process.env.SERIAL_PORT || '/dev/ttyUSB0',
|
|
||||||
server: {
|
|
||||||
port: 3000,
|
|
||||||
host: 'localhost',
|
|
||||||
cors: "*"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,7 @@
|
|||||||
|
import Firmata from 'firmata';
|
||||||
import { SuBoard } from './support';
|
import { SuBoard } from './support';
|
||||||
import { Board, BoardOption } from 'johnny-five';
|
|
||||||
import { config } from 'dotenv';
|
|
||||||
|
|
||||||
config();
|
export const comport: string = '/dev/ttyUSB1';
|
||||||
|
export const board: Firmata = new Firmata(comport);
|
||||||
|
|
||||||
export const comport: string = process.env.SERIAL_PORT || '/dev/ttyUSB0';
|
|
||||||
export const suBoard: SuBoard = new SuBoard();
|
export const suBoard: SuBoard = new SuBoard();
|
||||||
|
|
||||||
export const defaultBoardOption: BoardOption = {
|
|
||||||
port: comport,
|
|
||||||
debug: false,
|
|
||||||
repl: false,
|
|
||||||
};
|
|
@ -1,25 +1,20 @@
|
|||||||
import { Board } from "johnny-five";
|
|
||||||
|
|
||||||
export interface SupportBoard {
|
export interface SupportBoard {
|
||||||
port: string | null,
|
|
||||||
connected: boolean,
|
connected: boolean,
|
||||||
PINS: {
|
PINS: {
|
||||||
digital: number[],
|
pwm: number[],
|
||||||
analog: number[],
|
analog: number[],
|
||||||
}
|
}
|
||||||
sort: () => void
|
sort: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SuBoard implements SupportBoard {
|
export class SuBoard implements SupportBoard {
|
||||||
public board: Board | null;
|
|
||||||
public port = null;
|
|
||||||
public connected = false;
|
public connected = false;
|
||||||
public PINS = {
|
public PINS = {
|
||||||
digital: [],
|
pwm: [],
|
||||||
analog: []
|
analog: []
|
||||||
};
|
};
|
||||||
public sort() {
|
public sort() {
|
||||||
this.PINS.digital = this.PINS.digital.sort((a, b) => b - a);
|
this.PINS.pwm = this.PINS.pwm.sort((a, b) => b - a);
|
||||||
this.PINS.analog = this.PINS.analog.sort((a, b) => b - a);
|
this.PINS.analog = this.PINS.analog.sort((a, b) => b - a);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +0,0 @@
|
|||||||
import { address } from 'ip';
|
|
||||||
|
|
||||||
export function getPublicIp () {
|
|
||||||
return address("public", "ipv4") || '127.0.0.1';
|
|
||||||
}
|
|
17
test/serial/analogReadDigital.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import Firmata, { PIN_MODE, PIN_STATE } from 'firmata';
|
||||||
|
|
||||||
|
const board = new Firmata('/dev/ttyUSB2');
|
||||||
|
|
||||||
|
board.on('ready', async () => {
|
||||||
|
// board.analogWrite(0, 255);
|
||||||
|
// board.analogWrite(1, 255);
|
||||||
|
// board.analogWrite(2, 255);
|
||||||
|
|
||||||
|
board.analogRead(0, (val) => {
|
||||||
|
console.log(val);
|
||||||
|
})
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
await new Promise (resolve => setTimeout(resolve, 90));
|
||||||
|
}
|
||||||
|
})
|
17
test/serial/blink.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const Firmata = require('firmata');
|
||||||
|
const board = new Firmata('/dev/ttyUSB0');
|
||||||
|
|
||||||
|
board.on('ready', async () => {
|
||||||
|
const led = 12;
|
||||||
|
|
||||||
|
board.pinMode(led, board.MODES.OUTPUT);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
board.digitalWrite(led, board.HIGH);
|
||||||
|
console.log("ON");
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
|
board.digitalWrite(led, board.LOW);
|
||||||
|
console.log("OFF");
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
|
}
|
||||||
|
});
|
@ -1,13 +0,0 @@
|
|||||||
import Firmata from 'firmata';
|
|
||||||
import { Board, Pin, PinMode } from "johnny-five";
|
|
||||||
|
|
||||||
const board = new Board({
|
|
||||||
port: '/dev/ttyUSB0',
|
|
||||||
repl: false
|
|
||||||
});
|
|
||||||
|
|
||||||
board.on('ready', () => {
|
|
||||||
board.pinMode(13, Pin.OUTPUT);
|
|
||||||
|
|
||||||
board.digitalWrite(13, 1);
|
|
||||||
})
|
|
@ -1,11 +0,0 @@
|
|||||||
import { Board } from "johnny-five";
|
|
||||||
|
|
||||||
const board: Board = new Board({
|
|
||||||
port: '/dev/ttyUSB0',
|
|
||||||
debug: false,
|
|
||||||
repl: false
|
|
||||||
});
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
console.log(board.isReady);
|
|
||||||
}, 400);
|
|
@ -1,27 +0,0 @@
|
|||||||
import { Board } from "johnny-five";
|
|
||||||
|
|
||||||
const board: Board = new Board({
|
|
||||||
port: '/dev/ttyUSB1',
|
|
||||||
debug: false,
|
|
||||||
repl: false
|
|
||||||
});
|
|
||||||
|
|
||||||
board.on('ready', () => {
|
|
||||||
console.log("Board is ready");
|
|
||||||
})
|
|
||||||
|
|
||||||
board.on('close', () => {
|
|
||||||
console.log("Board is close");
|
|
||||||
})
|
|
||||||
|
|
||||||
board.on('connect', () => {
|
|
||||||
console.log("Board is connect");
|
|
||||||
})
|
|
||||||
|
|
||||||
board.on('exit', () => {
|
|
||||||
console.log("Board is exit");
|
|
||||||
})
|
|
||||||
|
|
||||||
board.on('fail', () => {
|
|
||||||
console.log("Board is fail");
|
|
||||||
})
|
|
18
test/serial/monitoringAllPins.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import Firmata from 'firmata';
|
||||||
|
|
||||||
|
const board = new Firmata('/dev/ttyUSB2');
|
||||||
|
|
||||||
|
board.on('ready', async () => {
|
||||||
|
board.analogRead(2, (val) => {
|
||||||
|
console.log(board.analogPins[2]);
|
||||||
|
const output = board.pins.map((p, i) => {
|
||||||
|
return `Pin ${i}: ${p.value}`
|
||||||
|
}).join(", ");
|
||||||
|
|
||||||
|
console.log(output);
|
||||||
|
})
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
}
|
||||||
|
})
|
@ -1,15 +0,0 @@
|
|||||||
import { Board, Pin } from "johnny-five";
|
|
||||||
|
|
||||||
const board: Board = new Board({
|
|
||||||
port: '/dev/ttyUSB0',
|
|
||||||
debug: false,
|
|
||||||
repl: false
|
|
||||||
});
|
|
||||||
|
|
||||||
board.on("ready", async () => {
|
|
||||||
board.pinMode(14, Pin.INPUT);
|
|
||||||
|
|
||||||
board.analogRead(0, (val) => {
|
|
||||||
console.log(val);
|
|
||||||
})
|
|
||||||
});
|
|
@ -1,24 +0,0 @@
|
|||||||
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);
|
|
||||||
})
|
|
||||||
})
|
|
20
test/serial/read.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const Firmata = require('firmata');
|
||||||
|
const board = new Firmata('/dev/ttyUSB0');
|
||||||
|
|
||||||
|
board.on('ready', async () => {
|
||||||
|
const led = 12;
|
||||||
|
|
||||||
|
board.pinMode(led, board.MODES.OUTPUT);
|
||||||
|
|
||||||
|
let state = board.LOW;
|
||||||
|
|
||||||
|
board.digitalWrite(led, board.HIGH);
|
||||||
|
|
||||||
|
state = board.pins[led].value;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
console.log(state);
|
||||||
|
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
}
|
||||||
|
});
|
11
test/serial/readResistor.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import Firmata from 'firmata';
|
||||||
|
|
||||||
|
const board = new Firmata('/dev/ttyUSB1');
|
||||||
|
|
||||||
|
board.on('ready', () => {
|
||||||
|
board.pinMode(0, Firmata.PIN_MODE.INPUT);
|
||||||
|
|
||||||
|
board.analogRead(0, (val) => {
|
||||||
|
console.log(val);
|
||||||
|
})
|
||||||
|
})
|
@ -1,25 +0,0 @@
|
|||||||
const { Board, Led } = require("johnny-five");
|
|
||||||
|
|
||||||
const board = new Board({
|
|
||||||
port: '/dev/ttyUSB0',
|
|
||||||
repl: false,
|
|
||||||
debug: false
|
|
||||||
})
|
|
||||||
|
|
||||||
board.on('ready', () => {
|
|
||||||
const led = new Led.RGB([7, 6, 5]);
|
|
||||||
|
|
||||||
let ins = 252;
|
|
||||||
board.loop(10, () => {
|
|
||||||
led.color("#0000FF");
|
|
||||||
led.intensity(ins);
|
|
||||||
ins--;
|
|
||||||
if (ins < 1) {
|
|
||||||
ins = 255;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
board.analogRead(0, (val) => {
|
|
||||||
console.log(val);
|
|
||||||
})
|
|
||||||
});
|
|
@ -1,28 +0,0 @@
|
|||||||
import { Board, Led } from "johnny-five";
|
|
||||||
|
|
||||||
const board = new Board({
|
|
||||||
port: '/dev/ttyUSB0',
|
|
||||||
repl: false,
|
|
||||||
debug: false
|
|
||||||
})
|
|
||||||
|
|
||||||
board.on('ready', () => {
|
|
||||||
const led = new Led.RGB({
|
|
||||||
pins: {
|
|
||||||
red: 7,
|
|
||||||
green: 6,
|
|
||||||
blue: 5,
|
|
||||||
},
|
|
||||||
isAnode: true
|
|
||||||
})
|
|
||||||
|
|
||||||
let ins = 100;
|
|
||||||
|
|
||||||
board.loop(10, () => {
|
|
||||||
led.intensity(ins);
|
|
||||||
ins--;
|
|
||||||
if (ins < 1) {
|
|
||||||
ins = 100;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
@ -1,19 +0,0 @@
|
|||||||
import { Board, Pin, PinMode } from "johnny-five";
|
|
||||||
|
|
||||||
const board: Board = new Board({
|
|
||||||
port: '/dev/ttyUSB0',
|
|
||||||
debug: true,
|
|
||||||
repl: false
|
|
||||||
});
|
|
||||||
|
|
||||||
board.on("ready", async () => {
|
|
||||||
board.pinMode(9, Pin.SERVO);
|
|
||||||
board.servoWrite(9, 0);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
board.servoWrite(9, 180);
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
||||||
board.servoWrite(9, 0);
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,19 +0,0 @@
|
|||||||
import http from 'node:http';
|
|
||||||
import express from 'express';
|
|
||||||
import { Server } from "socket.io";
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
const server = http.createServer(app);
|
|
||||||
const io = new Server(server);
|
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
|
||||||
console.log("Connected");
|
|
||||||
|
|
||||||
socket.on("message", (message) => {
|
|
||||||
console.log(message);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
server.listen(3001, "localhost", () => {
|
|
||||||
console.log("Common server is running");
|
|
||||||
})
|
|
@ -3,9 +3,8 @@
|
|||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "NodeNext",
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"sourceMap": true,
|
"sourceMap": false,
|
||||||
"outDir": "dist"
|
"outDir": "dist"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*", "test/**/*"]
|
||||||
"exclude": ["test/**/*"]
|
|
||||||
}
|
}
|