mirror of
https://github.com/zyphlar/easy-usb-relay.git
synced 2024-03-08 07:57:47 +00:00
First pass at the API 🦄
This commit is contained in:
commit
729693f0d1
2
.eslintignore
Normal file
2
.eslintignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dist
|
||||||
|
node_modules
|
23
.eslintrc.yml
Normal file
23
.eslintrc.yml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
parser: babel-eslint
|
||||||
|
parserOptions:
|
||||||
|
ecmaVersion: 6
|
||||||
|
sourceType: module
|
||||||
|
ecmaFeatures:
|
||||||
|
impliedStrict: true
|
||||||
|
experimentalObjectRestSpread: true
|
||||||
|
globals:
|
||||||
|
Promise: true
|
||||||
|
env:
|
||||||
|
browser: true
|
||||||
|
jest: true
|
||||||
|
node: true
|
||||||
|
commonjs: true
|
||||||
|
extends:
|
||||||
|
- eslint:recommended
|
||||||
|
rules:
|
||||||
|
no-empty: warn
|
||||||
|
no-console: off
|
||||||
|
semi:
|
||||||
|
- error
|
||||||
|
- never
|
44
.gitignore
vendored
Normal file
44
.gitignore
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#-----------------------------------
|
||||||
|
# Application specific files
|
||||||
|
#-----------------------------------
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------
|
||||||
|
# Build artifacts
|
||||||
|
#-----------------------------------
|
||||||
|
|
||||||
|
.cache
|
||||||
|
.awcache
|
||||||
|
*.bk
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------
|
||||||
|
# Editor files
|
||||||
|
#-----------------------------------
|
||||||
|
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------
|
||||||
|
# Logs/database files
|
||||||
|
#-----------------------------------
|
||||||
|
|
||||||
|
*.log
|
||||||
|
*.sql
|
||||||
|
*.sqlite
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------
|
||||||
|
# OS generated files
|
||||||
|
#-----------------------------------
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
4
.prettierignore
Normal file
4
.prettierignore
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.vscode
|
||||||
|
dist
|
||||||
|
node_modules
|
||||||
|
package-lock.json
|
5
.prettierrc
Normal file
5
.prettierrc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
64
README.md
Normal file
64
README.md
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# usbrelay
|
||||||
|
|
||||||
|
**THIS IS CURRENTLY IN AN EXPERIMENTAL STATE:** It does not yet support multiple boards or other manufacturers. Coming soon...
|
||||||
|
|
||||||
|
> A Node.js library to control USB connected relays
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save usbrelay
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { Board } = require('usbrelay')
|
||||||
|
|
||||||
|
const numRelays = 2
|
||||||
|
const relays = new Board(numRelays)
|
||||||
|
|
||||||
|
// Turn all relays off:
|
||||||
|
relays.allOff()
|
||||||
|
|
||||||
|
// Turn all relays on:
|
||||||
|
relays.allOn()
|
||||||
|
|
||||||
|
// Turn relay #1 on:
|
||||||
|
relays.on(1)
|
||||||
|
|
||||||
|
// Turn relay #1 off:
|
||||||
|
relays.off(1)
|
||||||
|
```
|
||||||
|
|
||||||
|
Please see [examples directory](/examples) for more examples on using `usbrelay`
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### `relays.allOff()`
|
||||||
|
|
||||||
|
Turn all relays off.
|
||||||
|
|
||||||
|
### `relays.allOn()`
|
||||||
|
|
||||||
|
Turn all relays on.
|
||||||
|
|
||||||
|
### `relays.on(index)`
|
||||||
|
|
||||||
|
Turn relay with `index` on. Index starts at `1` and goes to the number of available relays. Throws an exception if the relay `index` is greater than the available number of relays.
|
||||||
|
|
||||||
|
### `relays.off(index)`
|
||||||
|
|
||||||
|
Turn relay with `index` off. Index starts at `1` and goes to the number of available relays. Throws an exception if the relay `index` is greater than the available number of relays.
|
||||||
|
|
||||||
|
## Contribute
|
||||||
|
|
||||||
|
Contributions welcome! Please submit a Pull Request and make sure to format your code with Prettier and write tests!
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
© [Dana Woodman](http://danawoodman.com) 2018
|
13
examples/simple.js
Normal file
13
examples/simple.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
const { Board } = require('../src/relays')
|
||||||
|
|
||||||
|
const numRelays = 2
|
||||||
|
const relays = new Board(numRelays)
|
||||||
|
|
||||||
|
// Make sure the relay defaults to off
|
||||||
|
relays.allOff()
|
||||||
|
|
||||||
|
relays.on(1)
|
||||||
|
setTimeout(() => relays.off(1), 500)
|
||||||
|
setTimeout(() => relays.on(2), 500)
|
||||||
|
setTimeout(() => relays.allOn(), 1000)
|
||||||
|
setTimeout(() => relays.allOff(), 2000)
|
6951
package-lock.json
generated
Normal file
6951
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
39
package.json
Normal file
39
package.json
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"name": "usbrelay",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "A USB relay support library",
|
||||||
|
"main": "src/relay.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "github.com/danawoodman/usbrelay"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"usb",
|
||||||
|
"relay",
|
||||||
|
"arduino",
|
||||||
|
"rpi",
|
||||||
|
"raspberry",
|
||||||
|
"pi",
|
||||||
|
"linux",
|
||||||
|
"switch",
|
||||||
|
"control",
|
||||||
|
"iot",
|
||||||
|
"electronics",
|
||||||
|
"diy"
|
||||||
|
],
|
||||||
|
"author": "Dana Woodman <dana@danawoodman.com> (http://danawoodman.com/)",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-hid": "0.7.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-eslint": "8.2.6",
|
||||||
|
"eslint": "5.1.0",
|
||||||
|
"jest": "23.4.1",
|
||||||
|
"nodemon": "1.18.3",
|
||||||
|
"prettier": "1.13.7"
|
||||||
|
}
|
||||||
|
}
|
85
src/board.js
Normal file
85
src/board.js
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* Control a USB relay board using USB.
|
||||||
|
*
|
||||||
|
* This code helped a lot in the understanding of what they boards
|
||||||
|
* expect for hex inputs:
|
||||||
|
* https://github.com/jaketeater/Very-Simple-USB-Relay/blob/master/relay.py
|
||||||
|
*/
|
||||||
|
const HID = require('node-hid')
|
||||||
|
|
||||||
|
const ALL_ON = 0xfe
|
||||||
|
const ALL_OFF = 0xfc
|
||||||
|
const ON = 0xff
|
||||||
|
const OFF = 0xfd
|
||||||
|
const VENDOR_ID = 5824
|
||||||
|
const PRODUCT_ID = 1503
|
||||||
|
|
||||||
|
// convert integer to binary representation
|
||||||
|
const itob = num => Number(parseInt(num, 10).toString(2))
|
||||||
|
|
||||||
|
class Board {
|
||||||
|
constructor(numRelays = 1, debug = true) {
|
||||||
|
if (debug) console.log('NUMBER OF RELAYS:', numRelays)
|
||||||
|
|
||||||
|
this.debug = debug
|
||||||
|
|
||||||
|
this.numRelays = numRelays
|
||||||
|
this.relays = Array.from(Array(this.numRelays).keys())
|
||||||
|
|
||||||
|
this.board = new HID.HID(VENDOR_ID, PRODUCT_ID)
|
||||||
|
if (!this.board) throw new Error('No device found!')
|
||||||
|
|
||||||
|
this.board.on('data', data => console.log('DATA:', data))
|
||||||
|
this.board.on('error', error => console.error('ERROR:', error))
|
||||||
|
|
||||||
|
this.logState()
|
||||||
|
}
|
||||||
|
|
||||||
|
getState() {
|
||||||
|
const binaryState = itob(this.board.getFeatureReport(1, 8)[7])
|
||||||
|
const state = String(binaryState)
|
||||||
|
.split('')
|
||||||
|
.map(Number)
|
||||||
|
.map(v => (v === 0 ? OFF : ON))
|
||||||
|
return this.relays.map(index => state[index] || state[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
logState() {
|
||||||
|
if (!this.debug) return
|
||||||
|
|
||||||
|
console.log('STATE:')
|
||||||
|
this.getState().map((state, index) =>
|
||||||
|
console.log('-> RELAY:', index, 'STATE:', state === OFF ? 'OFF' : 'ON')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkIndex(index) {
|
||||||
|
if (index && !this.relays[index])
|
||||||
|
throw new Error('Provided index is invalid')
|
||||||
|
}
|
||||||
|
|
||||||
|
on(index) {
|
||||||
|
this.checkIndex()
|
||||||
|
this.trigger([ON, index])
|
||||||
|
}
|
||||||
|
|
||||||
|
off(index) {
|
||||||
|
this.checkIndex()
|
||||||
|
this.trigger([OFF, index])
|
||||||
|
}
|
||||||
|
|
||||||
|
allOn() {
|
||||||
|
this.trigger([ALL_ON])
|
||||||
|
}
|
||||||
|
|
||||||
|
allOff() {
|
||||||
|
this.trigger([ALL_OFF])
|
||||||
|
}
|
||||||
|
|
||||||
|
trigger(state) {
|
||||||
|
this.logState()
|
||||||
|
this.board.sendFeatureReport(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Board
|
3
src/relays.js
Normal file
3
src/relays.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
// TODO: enumerate on all USB relay boards
|
||||||
|
const Board = require('./board')
|
||||||
|
module.exports = { Board }
|
Loading…
Reference in New Issue
Block a user