0.1.14 go back to using super.read

improve examples including home assistant coordination
master
David Kebler 2019-09-08 20:34:11 -07:00
parent 779f762cc4
commit d1305a0250
8 changed files with 79 additions and 51 deletions

View File

@ -5,25 +5,25 @@
// uses main broker socket but formats incoming and outgoing packets for HA convention
// TODO Make sure subscribed topics includes 'lighting/set/#'
const TOPIC = 'relays'
const TOPIC = 'relay'
function register(name) {
this.beforeProcessHook(async (packet) => {
console.log('incoming mqtt packet to modify')
console.dir(packet)
// console.log('incoming mqtt packet to modify')
// console.dir(packet)
let cmd = packet.cmd.split('/')
packet.cmd = `${packet.data.toLowerCase()}`
packet.pins = cmd[2]
delete packet.data
console.log('translated to uci packet')
console.dir(packet)
// console.log('translated to uci packet')
// console.dir(packet)
return packet
},
{name:name})
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) {
let npacket = {}
npacket.cmd = 'error'
@ -36,14 +36,14 @@ function register(name) {
{name:name})
this.beforeSendHook(async (packet) => {
console.log('beforeSendHook', packet)
// console.log('beforeSendHook', packet)
if (packet.cmd === 'status') {
let num = Object.keys(packet.pins)[0]
packet.cmd = `${TOPIC}/status/${num}`
packet.payload = packet.pins[num] ? 'on' : 'off'
console.log('=============modified packet sent to broker================')
console.dir(packet)
console.log('================')
let pin = packet.pins || packet.pin || packet.gpios || packet.gpio || packet.ids || packet.id
packet.cmd = `${TOPIC}/status/${pin}`
packet.payload = (packet.state[pin]!=null ? packet.state[pin] : packet.state ) ? 'on' : 'off'
// console.log('=============modified packet sent to broker================')
// console.dir(packet)
// console.log('================')
}
return packet
},

View File

@ -1,21 +1,31 @@
import Gpios from '../src/gpios'
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 TCP_PORT = 9075
const WS_PORT = 8090
;
(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')
await relays.addSocket('tcp','s','t', {port:TCP_PORT})
await relays.addSocket('web','s','w')
await relays.init()
relays.announce()
// await relays.getSocket('mqs').subscribe(['relays/#'])
})().catch(err => {

View File

@ -1,12 +1,12 @@
{
"name": "@uci/gpio",
"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",
"scripts": {
"client": "node -r esm examples/client",
"multi": "node --require esm examples/multi",
"multilog": "UCI_ENV=dev node --require esm examples/multi"
"client:tcp": "node -r esm examples/tcp-client",
"relays": "node --r esm examples/relays",
"relays:dev": "UCI_ENV=dev ./node_modules/.bin/nodemon -r esm examples/relays"
},
"author": "David Kebler",
"license": "MIT",
@ -26,16 +26,16 @@
},
"homepage": "https://github.com/uCOMmandIt/uci-interrrupt#readme",
"dependencies": {
"@uci-utils/logger": "0.0.14",
"@uci/base": "^0.1.23",
"@uci-utils/logger": "^0.0.15",
"@uci/base": "^0.1.27",
"death": "^1.1.0",
"onoff": "^4.1.1",
"onoff": "^4.1.4",
"p-settle": "^3.1.0"
},
"devDependencies": {
"chai": "^4.1.2",
"chai": "^4.2.0",
"esm": "^3.2.25",
"mocha": "^5.0.1",
"nodemon": "^1.14.3"
"mocha": "^6.2.0",
"nodemon": "^1.19.2"
}
}

View File

@ -5,7 +5,7 @@ let log = logger({package:'@uci/gpio', file:'/src/commands.js'})
export default {
on: async function(packet) {
packet.pinCmd = 'on'
this.commands.set(packet)
await this.commands.set(packet)
return packet
},
off: async function(packet) {
@ -20,28 +20,40 @@ export default {
},
set: async function(packet) {
packet.pinCmd = packet.pinCmd || 'set'
let pins = parsePins.call(this, packet.pins || packet.pin)
packet.res = await pSettle(
pins.map(pin => {
return this.pins[pin][packet.pinCmd](packet.value)
})
)
packet = await this.commands.get(packet)
log.debug({msg:'packet set request', packet:packet})
let pins = parsePins.call(this, packet.pins || packet.pin || packet.gpios || packet.gpio || packet.ids || packet.id )
log.debug({msg:'pins to set', packet:packet, pins:pins})
// 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 => {
// 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.push(packet) // will push on any socket
return packet
},
get: async function(packet) {
let pins = parsePins.call(this,packet.pins || packet.pin)
packet.pins = {}
pins.forEach(pin => packet.pins[pin] = this.pins[pin].value)
let pins = parsePins.call(this, this, packet.pins || packet.pin || packet.gpios || packet.gpio || packet.ids || packet.id)
packet.state = {}
pins.forEach(pin => packet.state[pin] = this.pins[pin].get(packet.read))
packet.cmd = 'status'
return packet
}
}
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==='string') {
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))
}
}
// TODO plain object is pin and value pairs
if (pins.some(pin => !(pin in this.pins),this)) console.log('pin not available')
return pins
}

View File

@ -22,7 +22,7 @@ class Pin extends Gpio {
} // end constructor
async init() {
this.set(this.value)
await this.set(this.value)
DeadJim((signal,err) => {
log.warn({signal:signal, method:'init', line:56, error:err, msg:'gpio process was killed, unexporting pin'})
this.unexport() // kill the kernel entry
@ -34,6 +34,8 @@ class Pin extends Gpio {
async toggle() { return await this.set(!this.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))
if (err) {
log.warn({error:err, pin:this.number, msg:'error reading gpio pin'})
@ -45,17 +47,19 @@ class Pin extends Gpio {
}
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) {
log.warn({error:err, pin:this.pin, msg:'error reading gpio pin'})
return err
}
this.value=res
this.state = res ? 'on' : 'off'
return res
return this.value
}
async get() { return this.value }
async get() {
return this.value
}
} // end Class

View File

@ -19,7 +19,7 @@ class Gpios extends Base {
log = logger({ name: 'gpios', id: this.id, package:'@uci/gpios', file:'src/gpios.js'})
pins.forEach(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}`})
this.pins[pin] = new Gpio(pin, opts[pin])
})
@ -28,15 +28,15 @@ class Gpios extends Base {
}
async init() {
console.log('init')
for (let pin of Object.keys(this.pins)) {
log.debug({msg:`initializing pin ${pin} with ${this.pins[pin].value}`})
await this.pins[pin].init()
}
await super.init()
return Promise.all(
Object.keys(this.pins).map(pin => {
return this.pins[pin].init()
})
)
return 'ready'
}
// register same hook to all pins
registerHook(func) {
this.pins.forEach(async pin => {

View File

@ -1,7 +1,9 @@
'use strict'
// just a starting template
const
Gpio = require('../src/interrupt'),
Gpio = require('../src/gpios'),
expect = require('chai').expect
// TODO finish simple test of a pin as interrupt