apearson / insteon-plm Goto Github PK
View Code? Open in Web Editor NEWInsteon PLM is a TypeScript/JavaScript library for the Insteon PowerLinc Modem family of devices.
License: BSD 3-Clause "New" or "Revised" License
Insteon PLM is a TypeScript/JavaScript library for the Insteon PowerLinc Modem family of devices.
License: BSD 3-Clause "New" or "Revised" License
Right now levels must be passed to class methods as a hex value. The problem is that some methods have different ranges (see LightOn
vs LightOnAtRate
). Having the method convert a range from 0 - 100% would normalize the input.
If we convert levels to a percentage, then we should also convert ramp rates to seconds.
These two methods return two different objects. Is there a reason not to have the device.getDeviceInfo
call the static method PowerLincModem.getDeviceInfo
?
The first issue is that if linkDevice
doesn't seem to work with battery operated devices. I put the battery device in awake mode (press and hold the set button so the LED flashes), then tried to run await linkDevice
. The modem LED begins flashing, but the program never progresses passed this point.
The second thing I noticed if an invalid address, or a device is otherwise unresponsive is given to the linkDevice
command, the modem becomes stuck in this state and is unresponsive to any other commands. After a while the modem will give a long buzz, and then it seems to work again.
Attempting to link an invalid device address on my other home controller results in a message that says "Unable to determine insteon engine", so possibly we need to send a query message first before putting the modem into link mode?
The status packet for outlets are different than switches and dimmers.
Request:
Response:
In testing clearDatabaseRecord
, it seems that the device in the link record is changed to zeros as expected, but the record's active flag is still true (expected false).
Here is what my link record looks like after clearing it:
{
"address": [
15,
175
],
"type": 186,
"Type": {
"active": true,
"control": 0,
"smartHop": 3,
"highWater": false
},
"group": 0,
"device": [
0,
0,
0
],
"onLevel": 0,
"rampRate": 0
}
I don't yet know if this is an issue with the library, or just an unexpected Insteon behavior.
let device = await getDeviceInstance(address, { debug: false, syncInfo: true, syncLinks: true });
console.log(device.links); // [] -> IT's Empty!!
The device.links are empty even when asking the constructor to syncLinks
. syncLinks
is being called, but something is not awaiting correctly.
At first I thought it was because we are returning a new device without await
:
default: return new DimmableLightingDevice(deviceID, this, options);
But this did not fix the problem either:
default: return await new DimmableLightingDevice(deviceID, this, options);
If both syncInfo
and syncLinks
are false, the ready
event never fires. If either of them is true, the ready
event fires just fine.
const outlet = [0x2F,0x98,0xA4];
let myOutlet = await modem.getDeviceInstance(outlet, {debug: true, syncInfo: false, syncLinks: false});
console.log(`constructor: ${myOutlet.constructor.name}`);
// This event is never triggered
myOutlet.once('ready', async () => {
console.log("Outlet is ready");
});
This really makes no sense. If you comment out lines 103 - 108 in insteonDevice.ts
you get the same behavior where the 'ready' event never fires.
My goal is to be able to make a GUI in Node-RED that allows you to manage your insteon network.
In order to do that, I think it's necessary to document a list of use cases or actions that would be needed in order to build a fully functional GUI.
I will try and keep this list updated. If something gets implemented, I'll update the example (and link to the documentation). If an idea is rejected, I'll explain why.
User wants to add a new device to their insteon eco system. Give option to factory reset delete the links database of the device before linking it to the PLM.
device = plm.addDevice('hexID', {
clearAllLinks: true, // erase all the links from the device before linking it to the PLM
waitForButtonPress: false // wireless devices need a button press to wake them up
});
To do: Investigate whether we need to link the groups for Motion Sensors, Leak Sensors, etc where they broadcast other commands (such as dawn/dusk, low battery, heartbeat, etc)
Returns the instance of the device's object
device = plm.getDevice('hexID');
User wants to remove a device from the eco system, which means all links which reference the device on all remote devices should be flagged as deleted.
plm.removeDevice(device);
Returns an array of instances of all of the devices
deviceList = plm.getAllDevices();
The constructor should take a hexID and then interrogate the device to find out what it is and what it's current state is.
Depending on the device type, it should emit different events (e.g. on
|off
for switches, motion
, for motion sensors, open
|closed
for door sensors, etc). The device should also have properties to keep track of it's current state (e.g. current brightness level, current on/off state).
This seems to be the only way to completely clear a device's links table, and is required to get a clean slate.
device.eraseDB();
Return the full list of links that are in the specified device's database. This is also a time intensive task, so include a cache.
device.getLinks(options: {
reloadCache: true // Get the links from the device instead of from nodeJS memory
});
This has been implemented as SyncLinks()
. No cache option yet.
Update the device's links database to make it a controller of the list of devices provided.
Should automatically make devices listed responders?
device.makeControllerOf(
[device2, device3, device4],
group: 1,
options: {
onLevel = 50,
rampRate = 10,
button = 0
}
);
Delete the link in the controller's database. Also delete the corresponding links in the responder's database?
device.stopControlling([device3,device4]);
This might be a private method, unless there is a valid use case for having a device be a responder without the other device being a controller. Otherwise we should just automatically call makeResponderOf
from within makeControllerOf
.
The makeResponder will make the device respond to commands from the list of devices provided.
device.makeResponderOf(
[device2, device3, device4],
options: {
onLevel = 50,
rampRate = 10,
button = 0
}
Self explanatory
device.stopRespondingTo([device3,device4]);
This is to get the current state of the device - is it on/off, what is the brightness level. Motion sensors seem to also be able to send the battery level.
device.query();
This is needed so we can make a NodeRED Node that allows the user to pick which events to subscribe to, which would then trigger a flow. Since each main device type has different capabilities, we need to be able to list which events are available to listen to.
possibleEvents = device.getEvents();
TBD
This is some weird behavior with Insteon traffic where sometimes the device repeats or resends the data on the same link address more than one time.
To handle this, we should make the readDatabase
method only return unique link addresses. Suggest checking the return array to see if the link is already in the array, and if so, overwrite it.
After unlinking a device, the list from syncLinks
seems to be incomplete. The list also still contains the device that was unlinked.
for(var address in devices){
let links = await devices[address].syncLinks();
data.devices.push({
address,
links
});
}
Need to separate the device specific information and command into their own classes.
This will simply the modem interface quite a bit, allowing each device to keep track of their own request queues, timeouts, and link databases. The modem class already contains some device specific commands that are useless on other devices.
If you attempt to send multiple commands to devices rapidly, they begin to timeout requiring a restart of the docker container. Incidentally, I'm not quite sure why restarting the container unhangs the modem**.
Simply sending "on" commands to two devices simultaneously is enough to break it.
**EDIT: I believe the modem isn't actually hung, its the modem's process queue which is hung - which is why the restart of docker fixes it.
The handle response function is getting large and will only get larger.
Need to move these handlers to a different file and index them like packets are indexed on the parser.
Requests should not be allowed to take forever
The device queues seem to be working correctly but it seems like the modem has to get a reply before sending another message. Or the device messages need to be sent with a certain time between them. Maybe 16 ms?
Device Links DB does not get updated when a PLM link is deleted.
We need a clamp function added to the utilities.
The existing methods in the device classes that check upper/lower limits should be adapted to use the clamp utility.
Some of the utilities for address manipulation are needed in the Node-RED package.
Modem echos will be in the request queue identified by the modem id
Device replies will be in the request queue identified by the device's id
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.