0.1.14 go back to using super.read
improve examples including home assistant coordinationmaster
parent
779f762cc4
commit
d1305a0250
|
@ -5,25 +5,25 @@
|
||||||
// uses main broker socket but formats incoming and outgoing packets for HA convention
|
// uses main broker socket but formats incoming and outgoing packets for HA convention
|
||||||
// TODO Make sure subscribed topics includes 'lighting/set/#'
|
// TODO Make sure subscribed topics includes 'lighting/set/#'
|
||||||
|
|
||||||
const TOPIC = 'relays'
|
const TOPIC = 'relay'
|
||||||
|
|
||||||
function register(name) {
|
function register(name) {
|
||||||
|
|
||||||
this.beforeProcessHook(async (packet) => {
|
this.beforeProcessHook(async (packet) => {
|
||||||
console.log('incoming mqtt packet to modify')
|
// console.log('incoming mqtt packet to modify')
|
||||||
console.dir(packet)
|
// console.dir(packet)
|
||||||
let cmd = packet.cmd.split('/')
|
let cmd = packet.cmd.split('/')
|
||||||
packet.cmd = `${packet.data.toLowerCase()}`
|
packet.cmd = `${packet.data.toLowerCase()}`
|
||||||
packet.pins = cmd[2]
|
packet.pins = cmd[2]
|
||||||
delete packet.data
|
delete packet.data
|
||||||
console.log('translated to uci packet')
|
// console.log('translated to uci packet')
|
||||||
console.dir(packet)
|
// console.dir(packet)
|
||||||
return packet
|
return packet
|
||||||
},
|
},
|
||||||
{name:name})
|
{name:name})
|
||||||
|
|
||||||
this.afterProcessHook(async (packet) => {
|
this.afterProcessHook(async (packet) => {
|
||||||
console.log('processed packet available to modify again', packet)
|
// console.log('processed packet available to modify again', packet)
|
||||||
if (packet.error) {
|
if (packet.error) {
|
||||||
let npacket = {}
|
let npacket = {}
|
||||||
npacket.cmd = 'error'
|
npacket.cmd = 'error'
|
||||||
|
@ -36,14 +36,14 @@ function register(name) {
|
||||||
{name:name})
|
{name:name})
|
||||||
|
|
||||||
this.beforeSendHook(async (packet) => {
|
this.beforeSendHook(async (packet) => {
|
||||||
console.log('beforeSendHook', packet)
|
// console.log('beforeSendHook', packet)
|
||||||
if (packet.cmd === 'status') {
|
if (packet.cmd === 'status') {
|
||||||
let num = Object.keys(packet.pins)[0]
|
let pin = packet.pins || packet.pin || packet.gpios || packet.gpio || packet.ids || packet.id
|
||||||
packet.cmd = `${TOPIC}/status/${num}`
|
packet.cmd = `${TOPIC}/status/${pin}`
|
||||||
packet.payload = packet.pins[num] ? 'on' : 'off'
|
packet.payload = (packet.state[pin]!=null ? packet.state[pin] : packet.state ) ? 'on' : 'off'
|
||||||
console.log('=============modified packet sent to broker================')
|
// console.log('=============modified packet sent to broker================')
|
||||||
console.dir(packet)
|
// console.dir(packet)
|
||||||
console.log('================')
|
// console.log('================')
|
||||||
}
|
}
|
||||||
return packet
|
return packet
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,21 +1,31 @@
|
||||||
import Gpios from '../src/gpios'
|
import Gpios from '../src/gpios'
|
||||||
import hahooks from './homeassistant.js'
|
import hahooks from './homeassistant.js'
|
||||||
|
|
||||||
const PINS = [80,73,69,230,229,361,75,74,70]
|
const PINS = [80,73,69,230,229,75,74,70]
|
||||||
|
const ALL_PIN_OPTS = {activeLow:true, init:1}
|
||||||
|
|
||||||
let relays = new Gpios(PINS, {pinOpts:{activeLow:true}})
|
let relays = new Gpios(PINS, {pinOpts:ALL_PIN_OPTS,69:{init:0}})
|
||||||
|
|
||||||
|
relays.announce = function () {
|
||||||
|
for (let pin of Object.keys(relays.pins)) {
|
||||||
|
relays.push({cmd:'status', pin:pin, state:relays.pins[pin].value})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const BROKER = 'nas.kebler.net'
|
const BROKER = 'nas.kebler.net'
|
||||||
const TCP_PORT = 9075
|
const TCP_PORT = 9075
|
||||||
|
const WS_PORT = 8090
|
||||||
|
|
||||||
;
|
;
|
||||||
(async () => {
|
(async () => {
|
||||||
await relays.addSocket('mqs','s','m', {host:BROKER, topics:['relays/set/+']})
|
await relays.addSocket('web','s','w',{ wsport:WS_PORT })
|
||||||
|
await relays.addSocket('mqs','s','m', {host:BROKER, topics:['relay/set/+']})
|
||||||
hahooks.call(relays,'mqs')
|
hahooks.call(relays,'mqs')
|
||||||
await relays.addSocket('tcp','s','t', {port:TCP_PORT})
|
await relays.addSocket('tcp','s','t', {port:TCP_PORT})
|
||||||
await relays.addSocket('web','s','w')
|
|
||||||
await relays.init()
|
await relays.init()
|
||||||
|
|
||||||
|
relays.announce()
|
||||||
|
|
||||||
// await relays.getSocket('mqs').subscribe(['relays/#'])
|
// await relays.getSocket('mqs').subscribe(['relays/#'])
|
||||||
|
|
||||||
})().catch(err => {
|
})().catch(err => {
|
20
package.json
20
package.json
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@uci/gpio",
|
"name": "@uci/gpio",
|
||||||
"main": "src",
|
"main": "src",
|
||||||
"version": "0.1.13",
|
"version": "0.1.14",
|
||||||
"description": "a class for adding simple on/off read of GPIO pins on SBCs including Raspberry Pi",
|
"description": "a class for adding simple on/off read of GPIO pins on SBCs including Raspberry Pi",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"client": "node -r esm examples/client",
|
"client:tcp": "node -r esm examples/tcp-client",
|
||||||
"multi": "node --require esm examples/multi",
|
"relays": "node --r esm examples/relays",
|
||||||
"multilog": "UCI_ENV=dev node --require esm examples/multi"
|
"relays:dev": "UCI_ENV=dev ./node_modules/.bin/nodemon -r esm examples/relays"
|
||||||
},
|
},
|
||||||
"author": "David Kebler",
|
"author": "David Kebler",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -26,16 +26,16 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/uCOMmandIt/uci-interrrupt#readme",
|
"homepage": "https://github.com/uCOMmandIt/uci-interrrupt#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uci-utils/logger": "0.0.14",
|
"@uci-utils/logger": "^0.0.15",
|
||||||
"@uci/base": "^0.1.23",
|
"@uci/base": "^0.1.27",
|
||||||
"death": "^1.1.0",
|
"death": "^1.1.0",
|
||||||
"onoff": "^4.1.1",
|
"onoff": "^4.1.4",
|
||||||
"p-settle": "^3.1.0"
|
"p-settle": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.2.0",
|
||||||
"esm": "^3.2.25",
|
"esm": "^3.2.25",
|
||||||
"mocha": "^5.0.1",
|
"mocha": "^6.2.0",
|
||||||
"nodemon": "^1.14.3"
|
"nodemon": "^1.19.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ let log = logger({package:'@uci/gpio', file:'/src/commands.js'})
|
||||||
export default {
|
export default {
|
||||||
on: async function(packet) {
|
on: async function(packet) {
|
||||||
packet.pinCmd = 'on'
|
packet.pinCmd = 'on'
|
||||||
this.commands.set(packet)
|
await this.commands.set(packet)
|
||||||
return packet
|
return packet
|
||||||
},
|
},
|
||||||
off: async function(packet) {
|
off: async function(packet) {
|
||||||
|
@ -20,28 +20,40 @@ export default {
|
||||||
},
|
},
|
||||||
set: async function(packet) {
|
set: async function(packet) {
|
||||||
packet.pinCmd = packet.pinCmd || 'set'
|
packet.pinCmd = packet.pinCmd || 'set'
|
||||||
let pins = parsePins.call(this, packet.pins || packet.pin)
|
log.debug({msg:'packet set request', packet:packet})
|
||||||
packet.res = await pSettle(
|
let pins = parsePins.call(this, packet.pins || packet.pin || packet.gpios || packet.gpio || packet.ids || packet.id )
|
||||||
pins.map(pin => {
|
log.debug({msg:'pins to set', packet:packet, pins:pins})
|
||||||
return this.pins[pin][packet.pinCmd](packet.value)
|
// TODO could use this but need a way to know which res item is for what pin
|
||||||
})
|
// packet.res = await pSettle(
|
||||||
)
|
// pins.map(async pin => {
|
||||||
packet = await this.commands.get(packet)
|
// return this.pins[pin][packet.pinCmd](packet.value)
|
||||||
|
// }), {concurrency:1}
|
||||||
|
// )
|
||||||
|
packet.state = {}
|
||||||
|
for (let pin of pins) {
|
||||||
|
packet.state[pin] = await this.pins[pin][packet.pinCmd](packet.value)
|
||||||
|
}
|
||||||
|
log.info({msg:'pin(s) set result', packet:packet})
|
||||||
|
packet.cmd='status'
|
||||||
this.emit('gpios',packet) // emit locally
|
this.emit('gpios',packet) // emit locally
|
||||||
this.push(packet) // will push on any socket
|
this.push(packet) // will push on any socket
|
||||||
return packet
|
return packet
|
||||||
},
|
},
|
||||||
|
|
||||||
get: async function(packet) {
|
get: async function(packet) {
|
||||||
let pins = parsePins.call(this,packet.pins || packet.pin)
|
let pins = parsePins.call(this, this, packet.pins || packet.pin || packet.gpios || packet.gpio || packet.ids || packet.id)
|
||||||
packet.pins = {}
|
packet.state = {}
|
||||||
pins.forEach(pin => packet.pins[pin] = this.pins[pin].value)
|
pins.forEach(pin => packet.state[pin] = this.pins[pin].get(packet.read))
|
||||||
packet.cmd = 'status'
|
packet.cmd = 'status'
|
||||||
return packet
|
return packet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsePins = function(pins) {
|
const parsePins = function(pins) {
|
||||||
|
if (!pins) {
|
||||||
|
console.log('no pins supplied aborting')
|
||||||
|
throw new Error('no pins specified in command')
|
||||||
|
}
|
||||||
if (typeof pins==='number') pins = [pins]
|
if (typeof pins==='number') pins = [pins]
|
||||||
if (typeof pins==='string') {
|
if (typeof pins==='string') {
|
||||||
if (pins==='all') pins = Object.keys(this.pins)
|
if (pins==='all') pins = Object.keys(this.pins)
|
||||||
|
@ -49,6 +61,6 @@ const parsePins = function(pins) {
|
||||||
pins = pins.split(/[,:\s]+/).map(Number).filter( (x) => !Number.isNaN(x))
|
pins = pins.split(/[,:\s]+/).map(Number).filter( (x) => !Number.isNaN(x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO plain object is pin and value pairs
|
if (pins.some(pin => !(pin in this.pins),this)) console.log('pin not available')
|
||||||
return pins
|
return pins
|
||||||
}
|
}
|
||||||
|
|
12
src/gpio.js
12
src/gpio.js
|
@ -22,7 +22,7 @@ class Pin extends Gpio {
|
||||||
} // end constructor
|
} // end constructor
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
this.set(this.value)
|
await this.set(this.value)
|
||||||
DeadJim((signal,err) => {
|
DeadJim((signal,err) => {
|
||||||
log.warn({signal:signal, method:'init', line:56, error:err, msg:'gpio process was killed, unexporting pin'})
|
log.warn({signal:signal, method:'init', line:56, error:err, msg:'gpio process was killed, unexporting pin'})
|
||||||
this.unexport() // kill the kernel entry
|
this.unexport() // kill the kernel entry
|
||||||
|
@ -34,6 +34,8 @@ class Pin extends Gpio {
|
||||||
async toggle() { return await this.set(!this.value) }
|
async toggle() { return await this.set(!this.value) }
|
||||||
|
|
||||||
async set(value) {
|
async set(value) {
|
||||||
|
log.debug({msg:'set a pin', value:value, number:this.number})
|
||||||
|
// this.write(parseInt(value) || 0).then(res => console.log('returning from write'))
|
||||||
let [err] = await to(this.write(parseInt(value) || 0))
|
let [err] = await to(this.write(parseInt(value) || 0))
|
||||||
if (err) {
|
if (err) {
|
||||||
log.warn({error:err, pin:this.number, msg:'error reading gpio pin'})
|
log.warn({error:err, pin:this.number, msg:'error reading gpio pin'})
|
||||||
|
@ -45,17 +47,19 @@ class Pin extends Gpio {
|
||||||
}
|
}
|
||||||
|
|
||||||
async read() {
|
async read() {
|
||||||
let [err, res] = await to(super.read())
|
let [err, res] = await to(super.read()) // super.read here just calls this.read making an infinite loop and blowing the stack, should call onoff's read
|
||||||
if (err) {
|
if (err) {
|
||||||
log.warn({error:err, pin:this.pin, msg:'error reading gpio pin'})
|
log.warn({error:err, pin:this.pin, msg:'error reading gpio pin'})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
this.value=res
|
this.value=res
|
||||||
this.state = res ? 'on' : 'off'
|
this.state = res ? 'on' : 'off'
|
||||||
return res
|
return this.value
|
||||||
}
|
}
|
||||||
|
|
||||||
async get() { return this.value }
|
async get() {
|
||||||
|
return this.value
|
||||||
|
}
|
||||||
|
|
||||||
} // end Class
|
} // end Class
|
||||||
|
|
||||||
|
|
16
src/gpios.js
16
src/gpios.js
|
@ -19,7 +19,7 @@ class Gpios extends Base {
|
||||||
log = logger({ name: 'gpios', id: this.id, package:'@uci/gpios', file:'src/gpios.js'})
|
log = logger({ name: 'gpios', id: this.id, package:'@uci/gpios', file:'src/gpios.js'})
|
||||||
pins.forEach(pin => {
|
pins.forEach(pin => {
|
||||||
if (typeof pin !=='number') pin = parseInt(pin)
|
if (typeof pin !=='number') pin = parseInt(pin)
|
||||||
opts[pin] = opts[pin] ? opts[pin] : opts.pinOpts
|
opts[pin] = Object.assign({},opts.pinOpts || {}, opts[pin] || {})
|
||||||
log.debug({ opts: opts[pin], line:27, msg:`pin options for pin ${pin}`})
|
log.debug({ opts: opts[pin], line:27, msg:`pin options for pin ${pin}`})
|
||||||
this.pins[pin] = new Gpio(pin, opts[pin])
|
this.pins[pin] = new Gpio(pin, opts[pin])
|
||||||
})
|
})
|
||||||
|
@ -28,14 +28,14 @@ class Gpios extends Base {
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
await super.init()
|
console.log('init')
|
||||||
return Promise.all(
|
for (let pin of Object.keys(this.pins)) {
|
||||||
Object.keys(this.pins).map(pin => {
|
log.debug({msg:`initializing pin ${pin} with ${this.pins[pin].value}`})
|
||||||
return this.pins[pin].init()
|
await this.pins[pin].init()
|
||||||
})
|
}
|
||||||
)
|
await super.init()
|
||||||
|
return 'ready'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// register same hook to all pins
|
// register same hook to all pins
|
||||||
registerHook(func) {
|
registerHook(func) {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
// just a starting template
|
||||||
|
|
||||||
const
|
const
|
||||||
Gpio = require('../src/interrupt'),
|
Gpio = require('../src/gpios'),
|
||||||
expect = require('chai').expect
|
expect = require('chai').expect
|
||||||
|
|
||||||
// TODO finish simple test of a pin as interrupt
|
// TODO finish simple test of a pin as interrupt
|
||||||
|
|
Loading…
Reference in New Issue