In some environments, such as MagicMirror modules, the WebSocket class is not defined. This is apparently a client-only class and generally only exists in browsers, but I'm confused how the unit tests were passing when run against just node. Either way, this means we have to disable the test again since ws is not compatible with jest-websocket-mock, and I haven't found an alternative mock server that is.
This replaces the 'ws' library with built-in websockets so that we can mock a server and successfully connect to it. A simple test verifies that Unit is handling a message request and response as we expect it to.
I was trying to make a websocket test, but the "ws" library doesn't appear to be easily mocked and I prefer to use it over the built-in WebSocket. So we'll see what I can do in the future.
I've seen this STATUS parameter have different values with some messages, so it no longer makes sense to attempt to lock in the type to one of these strings.
This can be used to find all the controllable circuits in your system.
When invoked with `npm run list-objects` or `node esm/list-objects.js` it will search for units, then request and format+display the objects to the user. There are a few arguments available:
* --controllerAddr=1.2.3.4
* Specifies the IntelliCenter controller's address directly which skips the searching phase.
* --controllerPort=1234
* Specifies the port to use when connecting to the controller (probably should never use this; does nothing if --controllerAddr is not specified)
* --multicastAddr=1.2.3.4
* Specifies the address of the network interface to send the multicast search packet on (useful if you have multiple adapters/interfaces and the system is picking the wrong one; does nothing if --controllerAddr is specified)
* --onlyToggleable
* Only displays objects which can be toggled on or off
Note that if you are invoking this with `npm run list-objects` then the arguments must be specified after an empty `--` so that they are given to the script rather than npm itself. Example: `npm run list-objects -- --controllerAddr=10.0.0.41 --onlyToggleable`
This allows require() and import to work for even better compatibility between CJS and ESM consumers.
I dislike that this kills our ability for top-level awaits in example.ts, but seeing as how my primary use case for this library is a commonjs module, I think this is a fair trade-off.
Also changed "messages" to not encapsulate its export under the name "messages" to remove some repetition in importing "messages" and still needing to do "messages." to get the methods out. Now it's simple to import each message by name or group them under something like "messages" as desired on a per-library-user basis.
Refs:
* https://www.kravchyk.com/typescript-npm-package-json-exports/
* https://arethetypeswrong.github.io/
* https://evertpot.com/universal-commonjs-esm-typescript-packages/
This gives better control over importing in non-module environments and removes the example code as the default import which was running when loading up the library.
When you have multiple network adapters/interfaces, the system can choose the wrong one. This allows you to be explicit about which one you broadcast on.
Using SubscribeToUpdates() will cause the Unit to trigger a "notify" event any time the subscribed property changes, containing the new value of the property.
I don't know how/if you can unsubscribe from something as I don't see the official app ever doing that.
This adds a bunch of messages to retrieve and set various things on the controller. It also groups the messages under one export to simplify the process of using and discovering many of them from one location.
Some of these are WIP/probably not portable to other systems.
This also adds the ability to set multiple circuits at once.
Getting a feel for how the development experience is with this setup. With the previous idea of abstracting the request into a getSystemInfo() function on the Unit itself, the documentation for what to expect from GetSystemInfo either had to live in two places or be presented as a link to the canonical location. Neither felt great, so I think the caller can just call send(GetRequest()) themselves.
Also added the first "set" message which is capable of toggling a body or circuit.
No idea if this will be the best way to represent this stuff long-term, but it's working at the moment. I have some reservations about attempting to list all the possible ResponseParam keys, but I'm already this far in and it would be nice if it worked out...
This can correctly find and return IntelliCenter units on the local network now.
Cleaned up a bunch of Finder code and added back in "debug" module logging.
Fixed up types in Dns module so we can use instanceof
Add a field for the raw ipv4 address of an A record (encoded in an int)
Rename "remaining data" to "rdata" since that's what the dns spec calls it
Update Srv record rdata block to be handled the same as other records
Fix A record endOffset to have the correct value