automategreen / home-controller Goto Github PK
View Code? Open in Web Editor NEWA node package to control Insteon home automation devices
License: MIT License
A node package to control Insteon home automation devices
License: MIT License
I'm trying to work out how to remove links previously associated with the controller. The docs are a tad vague ;p
For example, some of the output from "links" is below:
{ "flags": "a2", "controller": false, "isInUse": true, "hasBeenUsed": true, "isLast": false, "group": 1, "id": "0651df", "data": [ "00", "00", "ff" ], "onLevel": 0, "rampRate": 2000 }, { "flags": "e2", "controller": true, "isInUse": true, "hasBeenUsed": true, "isLast": false, "group": 254, "id": "0651df", "data": [ "01", "07", "28" ], "onLevel": 1, "rampRate": 480000 }
....how would I go about calling unlink()
to remove those two links?
I realize a scene is the preferred mechanism for turning multiple devices on/off, but I am nonetheless sending the on/off to three lights at the same time (well in a single threaded node application). This causes the first command to fire, then the second to wait commandTimeout seconds long, then firing the 2nd, then waiting commandTimeout seconds long, then firing the 3rd. This causes 4 lamp 'on' messages to take 20 seconds with default configuration!
Here's the debug output during one of these events:
Connected to Insteon PLM
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Send: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622367AC0F1300","id":"2367AC"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Already running a command - queuing command: undefined
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Rcvd: 1443574234186 02622367ac0f130006
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - buffer: 02622367ac0f130006
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622367AC0F1300","id":"2367AC"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - Direct Command
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622367AC0F1300","id":"2367AC"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Already running a command - queuing command: undefined
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Already running a command - queuing command: undefined
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Rcvd: 1443574234488 02502367ac1eb2fb2f1300
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - buffer: 02502367ac1eb2fb2f1300
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622367AC0F1300","id":"2367AC"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - Standard Command
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Parsed command: {"standard":{"type":"50","id":"2367ac","gatewayId":"1eb2fb","extended":0,"messageType":1,"hopsLeft":3,"maxHops":3,"command1":"13","command2":"00","raw":"02502367ac1eb2fb2f1300"}}
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622367AC0F1300","id":"2367AC"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Devices: ["216645","236810","257096","306962","30666D","2367AC","231A8D","25A873","259E9F","25A403","259DDF","240B8E","240CC8","2113E2","1FC9FE"]
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Handle Command for device: 2367AC
Sent off
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622367AC0F1300","id":"2367AC"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false,"response":{"standard":{"type":"50","id":"2367ac","gatewayId":"1eb2fb","extended":0,"messageType":1,"hopsLeft":3,"maxHops":3,"command1":"13","command2":"00","raw":"02502367ac1eb2fb2f1300"}},"success":true}
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Send: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: Rcvd: 1443574234550 15
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - buffer: 15
Tue Sep 29 2015 17:50:34 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000}
5 seconds
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: sendCommandTimout - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Resend: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Rcvd: 1443574239553 0262240cc80f130006
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - buffer: 150262240cc80f130006
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - Direct Command
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Rcvd: 1443574239899 0250240cc81eb2fb2b1300
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - buffer: 0250240cc81eb2fb2b1300
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - Standard Command
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Parsed command: {"standard":{"type":"50","id":"240cc8","gatewayId":"1eb2fb","extended":0,"messageType":1,"hopsLeft":2,"maxHops":3,"command1":"13","command2":"00","raw":"0250240cc81eb2fb2b1300"}}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Devices: ["216645","236810","257096","306962","30666D","2367AC","231A8D","25A873","259E9F","25A403","259DDF","240B8E","240CC8","2113E2","1FC9FE"]
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Handle Command for device: 240CC8
Sent off
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"0262240CC80F1300","id":"240CC8"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false,"response":{"standard":{"type":"50","id":"240cc8","gatewayId":"1eb2fb","extended":0,"messageType":1,"hopsLeft":2,"maxHops":3,"command1":"13","command2":"00","raw":"0250240cc81eb2fb2b1300"}},"success":true}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Send: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: Rcvd: 1443574239955 15
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - buffer: 15
Tue Sep 29 2015 17:50:39 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000}
5 seconds
Tue Sep 29 2015 17:50:44 GMT-0700 (PDT) ::: sendCommandTimout - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:44 GMT-0700 (PDT) ::: Resend: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:44 GMT-0700 (PDT) ::: Rcvd: 1443574244964 02622570960f130006
Tue Sep 29 2015 17:50:44 GMT-0700 (PDT) ::: checkStatus - buffer: 1502622570960f130006
Tue Sep 29 2015 17:50:44 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:44 GMT-0700 (PDT) ::: checkStatus - Direct Command
Tue Sep 29 2015 17:50:44 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: Rcvd: 1443574245316 02502570961eb2fb2b1300
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: checkStatus - buffer: 02502570961eb2fb2b1300
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: checkStatus - Standard Command
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: Parsed command: {"standard":{"type":"50","id":"257096","gatewayId":"1eb2fb","extended":0,"messageType":1,"hopsLeft":2,"maxHops":3,"command1":"13","command2":"00","raw":"02502570961eb2fb2b1300"}}
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: Status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: Devices: ["216645","236810","257096","306962","30666D","2367AC","231A8D","25A873","259E9F","25A403","259DDF","240B8E","240CC8","2113E2","1FC9FE"]
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: Handle Command for device: 257096
Sent off
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622570960F1300","id":"257096"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false,"response":{"standard":{"type":"50","id":"257096","gatewayId":"1eb2fb","extended":0,"messageType":1,"hopsLeft":2,"maxHops":3,"command1":"13","command2":"00","raw":"02502570961eb2fb2b1300"}},"success":true}
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: Send: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: Rcvd: 1443574245373 1515
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: checkStatus - buffer: 1515
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:45 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000}
5 seconds
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: sendCommandTimout - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: Resend: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: Rcvd: 1443574250380 02622368100f130006
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: checkStatus - buffer: 02622368100f130006
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000}
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: checkStatus - Direct Command
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: Rcvd: 1443574250690 02502368101eb2fb2f1300
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: checkStatus - buffer: 02502368101eb2fb2f1300
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: checkStatus - status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: checkStatus - Standard Command
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: Parsed command: {"standard":{"type":"50","id":"236810","gatewayId":"1eb2fb","extended":0,"messageType":1,"hopsLeft":3,"maxHops":3,"command1":"13","command2":"00","raw":"02502368101eb2fb2f1300"}}
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: Status: {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false}
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: Devices: ["216645","236810","257096","306962","30666D","2367AC","231A8D","25A873","259E9F","25A403","259DDF","240B8E","240CC8","2113E2","1FC9FE"]
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: Handle Command for device: 236810
Sent off
Tue Sep 29 2015 17:50:50 GMT-0700 (PDT) ::: checkStatus - status (after parsing): {"command":{"cmd1":"13","cmd2":"00","type":"62","raw":"02622368100F1300","id":"236810"},"deferred":{"promise":{}},"timeout":5000,"ack":true,"nack":false,"response":{"standard":{"type":"50","id":"236810","gatewayId":"1eb2fb","extended":0,"messageType":1,"hopsLeft":3,"maxHops":3,"command1":"13","command2":"00","raw":"02502368101eb2fb2f1300"}},"success":true}
Hi guys!
Is it possible to utilize the Insteon KeyPads using this library?
I'd like to
Can this be done? If yes, are there any examples or docs that would help me on that?
Thanks! :)
Firstly, thanks for this awesome API.
Is there anyway to toggle a light, without first querying it's state?
Currently I have to check if device level === 0 to tell if its off, then I can turn it on.
Is there a better way to simply toggle from off to on or on to off?
although i personally prefer to use a hub or SmartLinc, there are folks out there with a USB interface to their Insteon network.
could we extend the Insteon constructor to allow the caller to either pass arguments suitable for a call to serialPort.SerialPort(), or pass a stream argument.
the protocol is the same regarding of whether one is using TCP/IP or USB/serial ...
hello again. this is marshall rose, one of the curators of #thethingsystem -- http://thethingsystem.com -- https://github.com/TheThingSystem -- a home autonomy server. i'm thinking of dropping our home made insteon gateway code and using the home-controller package instead.
are you happy with the home-controller package? we've got a small, but fairly vocal community of insteon folks who are using #thethingsystem to integrate with their non-insteon things, so i'm interested in taking things to the next level.
what's your thinking?
thanks!
On startup, I am getting:
/Users/user/dev/node_modules/home-controller/lib/Insteon.js:80
this.buffer = '';
^
TypeError: Cannot set property 'buffer' of undefined
My entire node application is:
var Insteon = require('home-controller').Insteon;
var gw = Insteon();
var gw = gw.connect('my.home.com');
var gw = gw.connect('192.168.10.10', 9761);
var gw = gw.connect('192.168.10.10', function(){
console.log('Connected!');
});
Why does Insteon.connect()
and Insteon.serial()
not return (err, result)
as a callback args?
When I call light.level(1-100)
it works great.
When I call light.turnOff()
it also works great.
However, when I call light.level(0) when the level is currently > 1 ... it does nothing, no err and the light stays at its level.
Hi, first of all, thanks for the useful package!
Is there a way to set a name when linking a device, to get this name when listing the links?
Something like the Insteon App for Hub does.
Thanks!
there's a "boatload" of different insteon gear available, i'm thinking that support for insteon sensors is probably the biggest bang for the buck. what's your thinking?
we should have another thermostat user in a few days. i have to add the driver to the steward, but hopefully that's straight-forward...
All unit tests have mock data (sending/receiving), which all lower-cased. However, Insteon PLM sends all data in upper case. In some case (e.g. type, id, etc) library explicitly does toUpperCase()
, but not in all cases (e.g. cmd1, cmd2, etc). I ran into this problem writing a test for Light class.
Proposal 1 (simple): call toUpperCase in socket's data
handler.
Proposal 2 (slight more complicated): change all mock data in tests to be upper case.
@brandongoode what do you think?
Events are emitted by the light object (such as 'turnOn' , 'dimmed', etc.) on physical button presses and commands sent via home-controller, but they don't appear to be emitted when manipulating lights by using scene commands such as insteon.sceneOn form home-controller.
Is this expected?
Hey @brandongoode !
First, I want to thank you for putting this together. It has been an amazing help when trying to interface with my Insteon hub.
In working with the current build, I found a few bugs I want to discuss and fix (notably rampRateToHexHalfByte() doesn't work).
I'll give you a pull request with the tiny fixes I noticed.
Bug Hunt:
gw.link()
-> I get an error from status.response.link
. It doesn't exist and causes an error when next() tries to pass this 'undefined' thing. Did this used to work??rampRateToHexHalfByte()
, which it depends on. More or less, I cannot define a custom rampRate when also trying to change a light level.In addition to bug hunting, I've also been looking at the design of the api, and I wanted to discuss a few ideas with you.
Design Notes:
socket.setKeepAlive(true, 30000)
on line 86 causes the crash by design. I don't understand the benefit of needing to close the socket after a moment of commands have finished.if(!!{obj} [|| obj === 0]){};
. The optiontional OR is for when {int} 0 is a possible value. The !! is better at understanding if something isn't null, undefined, 'undefined', 0
, etc.I would love to have a chat about this and understand how you approached designing this api. It would help me greatly with a project I'm working on and I also hope we'll both learn a lot from it.
There is also a hard to catch bug where the .level command will sometimes return {int} 0, when that is just not correct. This happens when I interact with the hub frequently (every 2 seconds) Here's an example of what I put in a setInterval:
console.time("insteonLightSwitch" + data.settings.devID);
var Insteon = require('home-controller').Insteon;
var gw = new Insteon();
gw.connect(data.settings.hubIp, function(){
gw.level(data.settings.devID, function(err, result){
gw.close();
console.timeEnd("insteonLightSwitch" + data.settings.devID);
});
})
Is it posible to use it with phonegap?
It would make it and interesting library, since you can share the same code for all the clients web, desktop (node-webkit) and mobile (via phonegap)
Could it be browserified?
automategreen/home-controller/lib/Insteon/index.js:415
if(raw.length < status.command.raw.length + 2) {
^
TypeError: Cannot read property 'command' of undefined
at Insteon.checkStatus (/Users/bgoode/automategreen/home-controller/lib/Insteon/index.js:415:27)
at Insteon.checkStatus (/Users/bgoode/automategreen/home-controller/lib/Insteon/index.js:500:10)
at Socket. (/Users/bgoode/automategreen/home-controller/lib/Insteon/index.js:60:10)
at Socket.EventEmitter.emit (events.js:107:17)
at readableAddChunk (_stream_readable.js:159:16)
at Socket.Readable.push (_stream_readable.js:126:10)
at TCP.onread (net.js:514:20)
I'm getting command
, turnOn
, turnOff
events from the light, but no brightening
, brightened
, dimming
, or dimmed
events. No events trigger after physically dimming the light switch.
Powerline Modem is 2413u
and device firmware is 41 (i2CS engine)
I'm using node-q in my own project that also uses home-controller as a dependency.
TypeError: object is not a function
Looking at the version of Q in home-controller v1.0.x vs the most current version out... v1.2.0
I'm about to try npm shrinkwrap
to see if I can have the two versions used respectively.
I was unable to install home-controller 0.4.2 on windows 7. npm would not build serialport 1.1.3.
I was able to install serialport 1.4.0 so I modified home-controller package.json to require 1.4.0. This gave rise to another serialport problem where access to the port (COM3) was denied. Turns out that home-controller was opening the port twice. Removing the line "this.socket.open();" at the end of the insteon.serial function fixed the problem.
I know this is probably due to a change in serialport functionality but I thought I would let you know.
Cheers,
Ken
It's entirely possible I'm missing something - but is there a way (either via defined function, or raw Insteon) to turn a KeypadLinc LED on or off directly?
i'm testing an 010e lamplinc dimmer, dual-band
when i manually adjust the level, i get the message event for the insteon gateway:
event=command, type=50, id=219727, gatewayId=20d246, extended=0, messageType=2, hopsLeft=0, maxHops=1, command1=11, command2=01, raw=025021972720d246411101
it seems to me that things like this ought to get redirected to the Light object and it should raise an event instead, e.g.,
.emit('update', { level: 100 })
or whatever. does that make sense?
Hey, I ran across an issue sending the turnOn()
command when I didn't specify the level or rate. If I specify a level, it will turn on as normal.
Looking at the Light
class, it will guard against functions being the first or second argument, but nothing will be done if there are no arguments at all.
https://github.com/automategreen/home-controller/blob/master/lib/Insteon/Light.js#L15
Adding an extra guard against an undefined level
was enough to fix it.
This might not happen for all devices, it appears that some devices will actually parse the level while others will ignore it. Since the level
is 0 it will turn it off.
From the specs:
http://imgur.com/HJkbpA2
Example code to trigger bug:
https://gist.github.com/2fast2fourier/0b01cd20bec10738f0fc
It would be really nice to have node-red nodes which mapped the Insteon functionality of this project to node-red. I'm interested in swapping Misterhouse for node-red but the big thing keeping me on Misterhouse is the great Insteon support it has. If I can find some time I might work on this, but given my project list right now that could be a long while... As a starting point it would be worthwhile I think to see how this was done with the ZWave nodes.
Now I could be way wrong on this...but I'm finding that the links()
function does not seem to work like many other typical functions of other popular libs. Eg. fs.readFile()
when using FRP lib like Bacon.js.
It's entirely possible that I'm doing something wrong, but something just doesn't seem right. Please bare with me since in order to explain, I need to mention things specific to Bacon.
Something like this works... (non-home-controller)
var Bacon = require('baconjs').Bacon,
fs = require('fs');
var read = Bacon.fromNodeCallback(fs.readFile, 'input.txt');
read.onError(function(error) { console.log("Reading failed: " + error); });
read.onValue(function(value) { console.log("Read contents: " + value); });
Also, this DOES work (home-controller)
plm.serial(PLM_SERIAL_COM, function(){
console.log('CONNECTED!');
plm.links(null, function(error, link){
console.log(link);
})
});
However, this does NOT work (home-controller)
plm.serial(PLM_SERIAL_COM, function(){
console.log('CONNECTED!');
var linksStream = Bacon.fromNodeCallback(plm.links, null);
linksStream.onValue(function(link){
console.log(link);
});
});
The error is the more interesting thing to me...
TypeError: Cannot call method 'firstLink' of null
at Insteon.links (/Users/me/Projects/leaf-box/node_modules/home-controller/lib/Insteon/index.js:1113:17)
When I go into /lib/Insteon/index.html adding console.log(this)
consoles out null
. However, when I console the same in the typical, non-FRP version of home-controller it of course consoles out the plm/Insteon instance.
Any idea why this would happen?
The PLM hardware and Insteon infra is pretty slow, but people's expectations for UI are very high.
Consider a UI where the user can use a 0-100 slider bar to control their light.level() in realtime. Not just wait till the user stops dragging and releases.... but control the levels as the scrub the bar.
I've simulated this with my UI and home-controller
and I think it's choking on the calls rather then handling them. It seems it just tries to have them all queued up regardless of how many.
Mocha has been updated to v3.x which breaks test coverage reporting: they removed html reporter. I suggest we switch to istambuljs (actively supported and maintained) that has built-in report formatters (including html). I already did the conversion locally in a branch, and it works great. I can create a PR if you agree.
Abstraction of thermostat control.
I have been hacking code together and and a simple setup with 3 dimmable switches and using the Insteon USB controller to control.
I can control each of the lights separately just fine, but I cannot get scenes to work no matter what I do.
Could someone post some simple example code to see what I'm doing wrong?
This is what I'm currently using.
var Insteon = require('home-controller').Insteon
var insteon = new Insteon()
const CONTROLLER = '3118b5'
const HOUSE_RIGHT = '3de6c1'
const HOUSE_LEFT = '40d6a4'
const SCONCES = '3dad15'
...
// connect via serial USB
...
// Does not work
insteon.scene('gw', [
SCONCES, HOUSE_RIGHT, HOUSE_LEFT
], {
group: 2
}).then(function () {
insteon.sceneOn(2)
})
// Works
var sconces = insteon.light(SCONCES)
sconces.turnOn()
If in "getter" mode, those two functions use Light.info
and return relevant parameter (as int) in the callback.
If in "setter" mode, they return promise
in the callback which is inconsistent.
It should be consistent and return the value.
Relevant code fix: https://github.com/automategreen/home-controller/blob/unit-testing-improvements/lib/Insteon/Light.js#L345-L361
Another possible solution is to rewrite .info
function to accept additional parameters (make it common) and then onLevel
and rampRate
become the aliases of it.
Sometimes when two messages come in right after each other, second messages can be cut off and thus not processed (discarded).
Relevant line: https://github.com/automategreen/home-controller/blob/master/lib/Insteon/index.js#L820
In the while
loop, there is a check for a start message signature, but there is not check for the length of the message. Example, 02629999990f117f060250999999ffffff2f117f
<- two incoming messages from a light. In some cases I experienced when Serial port returned a partial response 02629999990f117f060250
(and is still in the process of receiving the rest 999999ffffff2f117f
). While loop will iterate twice because there are two message start signatures: 0262
and 0250
. However, there will be no check performed if second message is complete or still buffering. Thus it will fail to parse it and return "null" for all fields, and then discard it.
It happens not often enough to cause problems, but often enough to notice it in the logs.
Fix is easy: change while
to if
thus making function return after first message, and then waiting for rerun of checkStatus
function which does perform message length validation.
What do you think?
Both the PLM and the Dimmer Switch give their typical squak noises that I think means, things worked. However, no links are ever returned. Can you see something I'm doing wrong? Should I be reseting the PLM or the Dimmer first?
var Insteon = require('home-controller').Insteon;
var hub = new Insteon();
var express = require('express');
var app = express();
var deviceMid = '[devicenum]';
var deviceBack = '[devicenum]';
var PLM_SERIAL = '/dev/tty.usbserial-[id]';
hub.serial(PLM_SERIAL, function () {
hub.link(deviceBack, {}, function(links){
console.log(links);
hub.cancelLinking(function(){
console.log('linking canceled');
});
});
});
I'm fighting the unintelligible Insteon command tables - is there a reason you didn't include support for "scene on at level" and "scene on at level with rate" type options?
It looks like it should be as simple as replacing the '00' in your sendAllLinkCmd function with the appropriate level (or half level / half rate) but that didn't seem to work.
Any thoughts / comments?
i'm using an insteon hub. the package recognizes it fine.
i have an appliancelinc (an on/off switch), which is not recognized, presumably because it doesn't do extended responses.
the insteon code in the steward knows about the devices below, and i'm pretty sure that the logic in buildInfo doesn't really account for this. rather than "do surgery" on that function, i thought it best to check with you as to how we should extend the function to be able to distinguish between dimmable bulbs, on/off switches, and dimmer switches.
steward.actors.device.lighting.insteon.bulb.$info.type = '/device/lighting/insteon/bulb';
devices.makers['Insteon.013a'] = Insteon_Bulb;
devices.makers['Insteon.013b'] = Insteon_Bulb;
devices.makers['Insteon.013c'] = Insteon_Bulb;
devices.makers['Insteon.014c'] = Insteon_Bulb;
devices.makers['Insteon.014d'] = Insteon_Bulb;
devices.makers['Insteon.0151'] = Insteon_Bulb;
steward.actors.device.lighting.insteon.downlight.$info.type = '/device/lighting/insteon/downlight';
devices.makers['Insteon.0149'] = Insteon_Bulb;
devices.makers['Insteon.014a'] = Insteon_Bulb;
devices.makers['Insteon.014b'] = Insteon_Bulb;
devices.makers['Insteon.014e'] = Insteon_Bulb;
devices.makers['Insteon.014f'] = Insteon_Bulb;
steward.actors.device['switch'].insteon.onoff.$info.type = '/device/switch/insteon/onoff';
devices.makers['Insteon.0209'] = Insteon_OnOff;
devices.makers['Insteon.022d'] = Insteon_OnOff;
devices.makers['Insteon.0230'] = Insteon_OnOff;
devices.makers['Insteon.0235'] = Insteon_OnOff;
devices.makers['Insteon.0236'] = Insteon_OnOff;
steward.actors.device['switch'].insteon.dimmer.$info.type = '/device/switch/insteon/dimmer';
devices.makers['Insteon.0100'] = Insteon_Dimmer;
devices.makers['Insteon.010e'] = Insteon_Dimmer;
devices.makers['Insteon.010f'] = Insteon_Dimmer;
devices.makers['Insteon.0111'] = Insteon_Dimmer;
devices.makers['Insteon.0112'] = Insteon_Dimmer;
devices.makers['Insteon.01ef'] = Insteon_Dimmer;
devices.makers['Insteon.0120'] = Insteon_Dimmer;
insteon.serial() does not seem to return a promise?
Are there certain methods that do not return promises in home-controller?
Hey Brandon, there appears to be a problem with how 0262 replies are handled when they did not originate from home-controller in an app like connect.insteon.com
Steps to reproduce:
Error is as follows
/home/ben/SHS/hydra-insteon/node_modules/home-controller/lib/Insteon.js:374
if(raw.length < status.command.raw.length + 2) {
^
TypeError: Cannot read property 'command' of undefined
at Insteon.checkStatus (/home/ben/SHS/hydra-insteon/node_modules/home-controller/lib/Insteon.js:374:27)
at Socket.<anonymous> (/home/ben/SHS/hydra-insteon/node_modules/home-controller/lib/Insteon.js:99:10)
at Socket.EventEmitter.emit (events.js:95:17)
at Socket.<anonymous> (_stream_readable.js:746:14)
at Socket.EventEmitter.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:408:10)
at emitReadable (_stream_readable.js:404:5)
at readableAddChunk (_stream_readable.js:165:9)
at Socket.Readable.push (_stream_readable.js:127:10)
at TCP.onread (net.js:526:21)
I think it is essentially an iolink, but it would be nice to get open/close status rather than on/off.
I am in the process of acquiring one so should be able to test/add soon.
When extended command is sent to change current mode of a thermostat, it replies with a standard command to confirm the change.
Hello, thanks again for writing this library. I am running into a little difficulty. I am trying to auto-detect as much as possible about the home automation network starting only with the IDs in the .links() command of the controller. I query every single one, and of course lights consistently return that they are lights, but my battery powered devices do not, so I use a raw command handler to detect the first time that device makes any call, and upon seeing that call, I immediately try initializing it as an Insteon.motion device, and then issue the motion.status() command which normally gives me info on the motion sensor. I don't know how I'd do this better (not blindly assuming things that don't respond right away are motion sensors), and the door sensor object seems to lack a .status() command similar to the motion sensor. How would you recommend that I achieve something like this?
First of all pardon me if this is a dumb question.
however Insteon hub 2012 does not have a REST API , since i know from the dev notes for insteon hub 2012.
Nice library by the way!
Just thought I would give a shout-out for a new hub package I developed specifically to call home-controller functions. I need this because I have a media center app I've written that needs to control lights and an HVAC app to control the thermostat. I am also considering developing a third app with lets you manage scenes in a web-page. I don't like monolithic apps that provide a lot of unrelated functions.
https://github.com/mark-hahn/insteon-hub
As the readme says it is not tested with lights yet, but since it just passes the URLs through as function calls I expect lights to work.
I will be adding websockets to receive events soon. I need the HVAC app to act as a responder for commands from a wireless controller.
Edit: It should be able to drive ALL calls including low-level ones.
on some conditions the status.command comes undefined in Insteon.prototype.checkStatus function. the switch() is failing with an exception:
/Users/vital/node_modules/home-controller/lib/Insteon.js:327
switch(status.command.type) {
^
TypeError: Cannot read property 'type' of undefined
at onGet (/Users/vital/node_modules/home-controller/lib/Insteon.js:327:26)
at IncomingMessage.onEnd (/Users/vital/node_modules/home-controller/lib/Insteon.js:118:9)
at IncomingMessage.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:920:16
at process._tickCallback (node.js:415:13)
not sure where its coming from, but as a quick fix set to skip this status check call.
I was working with home-controller a fair bit a few weeks ago. Came back to it and now I feel like I'm back to square one. Can't seem to get the array of links off the PLM.
var Insteon = require('home-controller').Insteon;
module.exports.bootstrap = function(cb) {
var plm = new Insteon();
var PLM_SERIAL_COM = '/dev/tty.usbserial-A901M7UC';
plm.serial(PLM_SERIAL_COM);
plm.links(null, function(err, links){
console.log('LINKS:', links);
});
};
What am I doing wrong? Also, I could not find one single example for using home-controller with serial()
Looking for a simple way to listen for light events in general and not have to listen to EACH light for ALL of its events.
So the event would bubble the event type, the action and the device. This way you can listen for sweeping wide events.
?
Abstract the scene/group command (ALL-Link Commands)
I have be using home-controller for almost two years. I've been controlling light bulbs and relays.
I just tried controlling a new wall dimmer switch, a 2477D, using the same code I've been using for light bulbs. The switch works manually but I can't get dimming to work from home-controller. Shouldn't a bulb and wall switch behave the same?
I've tried light.turnOn(25,'fast')
and light.level(25)
. I know the light
instance is good because it works with turnOn()
and turnOff()
.
The switch is brand new so it shouldn't have any link cruft in it. I had to link from the PLM to the switch of course.
Any ideas?
Is there a way to get information about device information without creating an object of the corresponding type? I'm looking for basic reporting of events that happen on the device network. I'm running the USB PLM, and I see that its pretty trivial to connect to it and listen for commands, but the payload is rather cryptic.
The scenario that I'm dealing with is that I've received a generic "command" event from the PLM, and I want to translate it back into "The upstairs overhead light was turned on". At this point I'm not actually storing the list of devices in a database in a way that I could create instances of their various classes and listen to specific events, is there a way to map the generic event back to a device specific format?
When I run this... this the "Light On!" gets consoled the one time since I'm programmatically turning on the light. However, if I then walk over to the switch and turn it off and on... nothing happens. I'm not getting the "Light On!" anymore... nor am I seeming to get any of the "command" events at all.
var plm = new Insteon();
var PLM_SERIAL_COM = '/dev/tty.usbserial-A6028O1E'; // /dev/tty.usbserial-A901M7UD
plm.serial(PLM_SERIAL_COM);
var frontrow = plm.light('2a330a');
frontrow.on('turnOn', function(){
console.log("Light ON!");
});
frontrow.turnOn();
plm.on('command', function(command){
console.log(command);
});
Recently, I noticed a lot of errors in my log file that look like this:
No event for command - 00
So apparently, when you request a light level (direct command '19'), it will respond with ACK containing the level. But since it's a known device, it will also try to "handleAck" it. "handleAck" will log the error because returned message will have Command1 = '00' (it's actualy Database Delta according to the docs). Basically, ACK will not reference original command ('19').
I propose a small "filter" that will check if arriving message is a response to the '19' command, and then ignore it (like this df0b63a)
@brandongoode what do you think?
I'm using a PLM right now, but may want to switch to my hub in the future.
I've successfully controlled a Switchlinc dimmer and utilized a motion sensor with the library. Its not immediately apparent how I would control a Fanlinc though. Any guidance?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.