[AS-IS] Insteon web socket driver

Rather than screw that up, here's my output from attempting to install:

synouser@SynoBox:/usr/local/lib/node_modules/insteon-server$ ls -l
total 48
---------- 1 synouser users   309 Apr 23 01:27 client.js
---------- 1 synouser users  2510 Apr 23 01:27 config-example.json
---------- 1 synouser users 15373 Apr 23 01:27 insteonserver.js
d--------- 2 synouser users  4096 Apr 25 21:03 insteonserver.js without Keypad support
---------- 1 synouser users   521 Apr 23 01:27 package.json
---------- 1 synouser users 15142 Apr 23 01:27 README.md
synouser@SynoBox:/usr/local/lib/node_modules/insteon-server$ sudo node -g install
node: bad option: -g
synouser@SynoBox:/usr/local/lib/node_modules/insteon-server$ sudo npm -g install
npm WARN deprecated spark@1.1.1: Use particle-api-js instead
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN rollback Rolling back ms@2.1.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-abstract/node_modules/ms'
npm WARN rollback Rolling back debug@4.3.4 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-abstract/node_modules/debug'
npm WARN rollback Rolling back @serialport/binding-abstract@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-abstract'
npm WARN rollback Rolling back ms@2.1.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-mock/node_modules/ms'
npm WARN rollback Rolling back debug@4.3.4 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-mock/node_modules/debug'
npm WARN rollback Rolling back @serialport/binding-mock@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-mock'
npm WARN rollback Rolling back ms@2.1.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/bindings/node_modules/ms'
npm WARN rollback Rolling back debug@4.3.4 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/bindings/node_modules/debug'
npm WARN rollback Rolling back @serialport/parser-byte-length@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-byte-length'
npm WARN rollback Rolling back @serialport/parser-cctalk@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-cctalk'
npm WARN rollback Rolling back @serialport/parser-delimiter@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-delimiter'
npm WARN rollback Rolling back @serialport/parser-readline@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-readline'
npm WARN rollback Rolling back @serialport/parser-ready@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-ready'
npm WARN rollback Rolling back @serialport/parser-regex@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-regex'
npm WARN rollback Rolling back ms@2.1.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/stream/node_modules/ms'
npm WARN rollback Rolling back debug@4.3.4 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/stream/node_modules/debug'
npm WARN rollback Rolling back @serialport/stream@8.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/stream'
npm WARN rollback Rolling back ansi-regex@2.1.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/ansi-regex'
npm WARN rollback Rolling back aproba@1.2.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/aproba'
npm WARN rollback Rolling back array-flatten@1.1.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/array-flatten'
npm WARN rollback Rolling back assert-plus@1.0.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/assert-plus'
npm WARN rollback Rolling back async-limiter@1.0.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/async-limiter'
npm WARN rollback Rolling back asynckit@0.4.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/asynckit'
npm WARN rollback Rolling back aws-sign2@0.7.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/aws-sign2'
npm WARN rollback Rolling back aws4@1.11.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/aws4'
npm WARN rollback Rolling back base64-js@1.5.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/base64-js'
npm WARN rollback Rolling back bytes@3.1.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/bytes'
npm WARN rollback Rolling back caseless@0.12.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/caseless'
npm WARN rollback Rolling back chownr@1.1.4 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/chownr'
npm WARN rollback Rolling back code-point-at@1.1.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/code-point-at'
npm WARN rollback Rolling back commander@7.2.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/commander'
npm WARN rollback Rolling back console-control-strings@1.1.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/console-control-strings'
npm WARN rollback Rolling back content-type@1.0.4 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/content-type'
npm WARN rollback Rolling back cookie@0.5.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/cookie'
npm WARN rollback Rolling back cookie-signature@1.0.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/cookie-signature'
npm WARN rollback Rolling back core-util-is@1.0.3 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/core-util-is'
npm WARN rollback Rolling back dashdash@1.14.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/dashdash'
npm WARN rollback Rolling back deep-extend@0.6.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/deep-extend'
npm WARN rollback Rolling back delayed-stream@1.0.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/delayed-stream'
npm WARN rollback Rolling back combined-stream@1.0.8 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/combined-stream'
npm WARN rollback Rolling back delegates@1.0.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/delegates'
npm WARN rollback Rolling back depd@2.0.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/depd'
npm WARN rollback Rolling back destroy@1.2.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/destroy'
npm WARN rollback Rolling back detect-libc@1.0.3 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/detect-libc'
npm WARN rollback Rolling back ee-first@1.1.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/ee-first'
npm WARN rollback Rolling back encodeurl@1.0.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/encodeurl'
npm WARN rollback Rolling back escape-html@1.0.3 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/escape-html'
npm WARN rollback Rolling back etag@1.8.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/etag'
npm WARN rollback Rolling back expand-template@2.0.3 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/expand-template'
npm WARN rollback Rolling back extend@3.0.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/extend'
npm WARN rollback Rolling back getpass@0.1.7 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/getpass'
npm WARN rollback Rolling back buffer@5.7.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/buffer'
npm WARN rollback Rolling back form-data@2.3.3 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/form-data'
npm WARN rollback Rolling back on-finished@2.4.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/on-finished'
npm WARN rollback Rolling back strip-ansi@3.0.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/strip-ansi'
npm WARN rollback Rolling back string-width@1.0.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/string-width'
npm WARN rollback Rolling back rc@1.2.8 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/rc'
npm WARN rollback Rolling back http-errors@2.0.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/http-errors'
npm WARN rollback Rolling back send@0.18.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/send'
npm WARN rollback Rolling back serve-static@1.15.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/serve-static'
npm WARN rollback Rolling back sshpk@1.17.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/sshpk'
npm WARN rollback Rolling back finalhandler@1.2.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/finalhandler'
npm WARN rollback Rolling back raw-body@2.5.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/raw-body'
npm WARN rollback Rolling back body-parser@1.20.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/body-parser'
npm WARN rollback Rolling back bl@4.1.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/bl'
npm WARN rollback Rolling back readable-stream@2.3.7 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/readable-stream'
npm WARN rollback Rolling back are-we-there-yet@1.1.7 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/are-we-there-yet'
npm WARN rollback Rolling back verror@1.10.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/verror'
npm WARN rollback Rolling back jsprim@1.4.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/jsprim'
npm WARN rollback Rolling back http-signature@1.2.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/http-signature'
npm WARN rollback Rolling back request@2.88.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/request'
npm WARN rollback Rolling back spark@1.1.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/spark'
npm WARN rollback Rolling back wide-align@1.1.5 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/wide-align'
npm WARN rollback Rolling back gauge@2.7.4 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/gauge'
npm WARN rollback Rolling back npmlog@4.1.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/npmlog'
npm WARN rollback Rolling back tar-stream@2.2.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/tar-stream'
npm WARN rollback Rolling back tar-fs@2.1.1 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/tar-fs'
npm WARN rollback Rolling back prebuild-install@5.3.6 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/prebuild-install'
npm WARN rollback Rolling back @serialport/bindings@8.0.8 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/bindings'
npm WARN rollback Rolling back serialport@8.0.8 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/serialport'
npm WARN rollback Rolling back express@4.18.0 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/express'
npm WARN rollback Rolling back home-controller@0.9.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/home-controller'
npm WARN rollback Rolling back ws@6.2.2 failed (this is probably harmless): ELOOP: too many symbolic links encountered, lstat '/usr/local/lib/node_modules/insteon-server/node_modules/ws'
npm WARN notsup Unsupported engine for spark@1.1.1: wanted: {"node":"^0.10.26"} (current: {"node":"12.22.7","npm":"6.14.15"})
npm WARN notsup Not compatible with your version of node/npm: spark@1.1.1
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ms@2.1.2 (node_modules/insteon-server/node_modules/@serialport/binding-abstract/node_modules/ms):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-abstract/node_modules/ms/package.json.1730728012'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: debug@4.3.4 (node_modules/insteon-server/node_modules/@serialport/binding-abstract/node_modules/debug):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-abstract/node_modules/debug/package.json.4129137472'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/binding-abstract@8.0.6 (node_modules/insteon-server/node_modules/@serialport/binding-abstract):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-abstract/package.json.3070832115'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ms@2.1.2 (node_modules/insteon-server/node_modules/@serialport/binding-mock/node_modules/ms):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-mock/node_modules/ms/package.json.604940293'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: debug@4.3.4 (node_modules/insteon-server/node_modules/@serialport/binding-mock/node_modules/debug):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-mock/node_modules/debug/package.json.1123642991'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/binding-mock@8.0.6 (node_modules/insteon-server/node_modules/@serialport/binding-mock):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/binding-mock/package.json.1779615929'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ms@2.1.2 (node_modules/insteon-server/node_modules/@serialport/bindings/node_modules/ms):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/bindings/node_modules/ms/package.json.1729513162'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: debug@4.3.4 (node_modules/insteon-server/node_modules/@serialport/bindings/node_modules/debug):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/bindings/node_modules/debug/package.json.3162219188'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/parser-byte-length@8.0.6 (node_modules/insteon-server/node_modules/@serialport/parser-byte-length):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-byte-length/package.json.509144240'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/parser-cctalk@8.0.6 (node_modules/insteon-server/node_modules/@serialport/parser-cctalk):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-cctalk/package.json.795644058'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/parser-delimiter@8.0.6 (node_modules/insteon-server/node_modules/@serialport/parser-delimiter):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-delimiter/package.json.1946189396'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/parser-readline@8.0.6 (node_modules/insteon-server/node_modules/@serialport/parser-readline):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-readline/package.json.175412842'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/parser-ready@8.0.6 (node_modules/insteon-server/node_modules/@serialport/parser-ready):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-ready/package.json.885531667'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/parser-regex@8.0.6 (node_modules/insteon-server/node_modules/@serialport/parser-regex):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/parser-regex/package.json.2509538411'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ms@2.1.2 (node_modules/insteon-server/node_modules/@serialport/stream/node_modules/ms):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/stream/node_modules/ms/package.json.3951310178'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: debug@4.3.4 (node_modules/insteon-server/node_modules/@serialport/stream/node_modules/debug):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/stream/node_modules/debug/package.json.3364955966'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @serialport/stream@8.0.6 (node_modules/insteon-server/node_modules/@serialport/stream):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/@serialport/stream/package.json.308262381'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ansi-regex@2.1.1 (node_modules/insteon-server/node_modules/ansi-regex):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/ansi-regex/package.json.4053865568'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: aproba@1.2.0 (node_modules/insteon-server/node_modules/aproba):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/aproba/package.json.1047481333'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: assert-plus@1.0.0 (node_modules/insteon-server/node_modules/assert-plus):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/assert-plus/package.json.3807576307'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: asynckit@0.4.0 (node_modules/insteon-server/node_modules/asynckit):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/asynckit/package.json.2188594471'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: aws-sign2@0.7.0 (node_modules/insteon-server/node_modules/aws-sign2):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/aws-sign2/package.json.793254962'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: aws4@1.11.0 (node_modules/insteon-server/node_modules/aws4):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/aws4/package.json.3738701832'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: base64-js@1.5.1 (node_modules/insteon-server/node_modules/base64-js):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/base64-js/package.json.2327277497'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: caseless@0.12.0 (node_modules/insteon-server/node_modules/caseless):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/caseless/package.json.1126856195'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: chownr@1.1.4 (node_modules/insteon-server/node_modules/chownr):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/chownr/package.json.4267847095'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: code-point-at@1.1.0 (node_modules/insteon-server/node_modules/code-point-at):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/code-point-at/package.json.1325186122'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: console-control-strings@1.1.0 (node_modules/insteon-server/node_modules/console-control-strings):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/console-control-strings/package.json.3066449017'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: core-util-is@1.0.3 (node_modules/insteon-server/node_modules/core-util-is):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/core-util-is/package.json.3352980513'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: dashdash@1.14.1 (node_modules/insteon-server/node_modules/dashdash):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/dashdash/package.json.2292094255'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: deep-extend@0.6.0 (node_modules/insteon-server/node_modules/deep-extend):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/deep-extend/package.json.1752084337'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: delayed-stream@1.0.0 (node_modules/insteon-server/node_modules/delayed-stream):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/delayed-stream/package.json.4226236093'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: combined-stream@1.0.8 (node_modules/insteon-server/node_modules/combined-stream):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/combined-stream/package.json.1960449190'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: delegates@1.0.0 (node_modules/insteon-server/node_modules/delegates):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/delegates/package.json.891728507'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: detect-libc@1.0.3 (node_modules/insteon-server/node_modules/detect-libc):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/detect-libc/package.json.2213407932'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: expand-template@2.0.3 (node_modules/insteon-server/node_modules/expand-template):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/expand-template/package.json.2944665730'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: extend@3.0.2 (node_modules/insteon-server/node_modules/extend):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/extend/package.json.3586061648'

npm ERR! code ELOOP
npm ERR! syscall open
npm ERR! path /usr/local/lib/node_modules/insteon-server/node_modules/array-flatten/package.json.2862293524
npm ERR! errno -40
npm ERR! ELOOP: too many symbolic links encountered, open '/usr/local/lib/node_modules/insteon-server/node_modules/array-flatten/package.json.2862293524'

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-04-26T05_13_34_925Z-debug.log

Sorry. Busy morning so I'm just looking at this quickly. Maybe a couple of things to try here.

β€’ Make sure npm is updated.

β€’ Try without the -g option

β€’ Install the dependencies first (e.g. npm -g install home-controller, npm -g install express and npm install -g ws)

β€’ Make sure your RPi account has root privileges
after logging into your account, type sudo su

2 Likes

I re-wrote the instructions with a focus on installation to a Raspberry Pi. I've gone through the steps twice and had success both times.

My suggestion would be to just image the microSD card for your Raspberry Pi again and start over. I made a mistake in the installation as I was writing the instructions, and I found fixing it was much harder than just starting over from the beginning.

You'll find the new instructions in the first post.

1 Like

Thanks! The re-written instructions help a lot, however, I still get stuck on step 28. Let me know if these changes I made to resolve cause any problems...

When I attempt to run node insteonserver.js it cannot find the home-controller. All the npm installs default to /usr/lib/node_modules (rather than /usr/local/lib/node_modules) which means I need to go to that directory to re-attempt. When I do this, it then asks for insteonserver.js which I need to copy to this directory. After this change, I attempt "node insteonserver.js" again and get an error "Cannot find module 'underscore'. So I install (sudo npm install -g underscore) in /usr/lib/node_modules and run node insteonserver.js

All these changes get me to Step 29. Figured you would want to know. I also noticed there are instances where insteon-server.zip changes to capital "I" (Insteon-server.zip) which tripped me initially.

So now, I installed the drivers as instructed but I cannot seem to get to a device preference screen like the one shown. I create a virtual device and make type Insteon WS Parent, click save, but I only see IP and port options. I noted this is a difference between WS Parent without Keypad support preferences in the driver code vs Insteon WS Parent. Does Insteon WS Parent also need these preferences to connect?

Update:
I was able to setup WS Parent without Keypad support and have switches working!!! Not clear still if I should use both versions of the parent or one or the other? I would like keypad support but I cannot complete the install steps with the other parent file. Probably missing a step that may seem obvious to more experienced peeps. Thanks again for all the guidance.

One or the other, not both. You must change our the insteonserver.js file if you use the WS parent file for keypads.

I've heard from some that the keypad support works, but it's slow. I've heard from some that when you use the insteonserver.js file and the WS parent file with keypad support, that it doesn't create the child devices. The latter, I have experienced myself. However, I don't own a keypad. Had one for initial testing, but returned it when we were finished testing. Insteon keypads are not really my thing. I'm guessing (and this is a complete guess) that those that have it working have added devices with the two files that don't support keypads, so they get the child devices, then they swapped out the keypad files and got support for keypads. Just a hypothesis though. No way to test that without a keypad.

Maybe you don't need this for your keypads though... :man_shrugging:

Thanks. I might just link the keypad scenes manually. I am only using them for various zone controls with other Insteon devices. For example, all on/off, all dim, zone1 on/off, zone2 on/off. I can accomplish this with the local programming in multi-link mode.

Question: After configuring my Insteon devices on my Pi, I powered off the Pi and Hubitat continued controlling these devices via Google Home (which is my user-level UI for home control). Do I need the Pi running continuously in the background after setup? Would it make sense to configure a bunch of fake devices just to generate several childs for future use in the Hubitat interface? I ask because I only have one Pi and it is dedicated to Home Assistant which I will need again.

You will not get status update or be able to use input devices such as Insteon contact sensors, leak sensors or motion sensors without the node.js server and client listener running. Also cannot get new child devices without it running.

What you experienced was that part of the driver that Chris wrote to control device via http;// get commands. There are earlier drivers that do the same thing without node,js, but they don't give you status of the light, so things can get out of sync when you manually control switches if the node.js server isn't used.

Do you want a keypad? Ill take one out of my wall and send it to you. The keypad is the most important part of my insteon install. Unless there is a 8 button z-wave switch that is affordable. Ill send you one to test with and maybe get a more transparent way of switching insteon to hubitat. As a matter of fact I can send several switches, motion sensors etc to test with. I have bought many extra except key pads and as I replace old switches for z-wave I have plenty to offer if you can make a difference for easier and better migration. Eg. have a pie, download this, run it and start adding. PM me if your interested.

I’m not the developer of this driver or the node.js code. Would not know how to improve it. I tested all that I could and @cwwilson08 coded to the best of his abilities at the time. We tested, it worked.

The code is there for anyone that knows how to improve on it and has the motivation to do so. Sorry, but I cannot help make this into more than it is today.

1 Like

Hmm. Considering I need Home Assistant (w/ Insteon control panel) to configure Insteon devices and I have HE, wouldn't it make more sense to control these Insteon devices using Home Assistant Device Bridge?

Am I missing something?

It’s great that they can control the device settings, but it’s not as good for controlling the devices themselves. See my reply here for detail around that.

1 Like

Hello,

New user to the Hubitat community, picked one up in hopes of getting control back to my Inteson devices.

By using the documentation on these forms I was able to get Machine Rules created to control my dimmer switches but wasn't able to set it up as a Device to turn it on / off.

I believe I should be using the instructions in this document to accomplish this. I had a few questions for clarification (wasn't able to find the answers in the comments, they are probably pretty basic questions):

  1. If I have the hubitat hub do I still require another device to run the Insteon Server Node.js?
  2. In the section for "Installing the Insteon WS Parent and Child device drivers", I am stuck at where I could find the link for the actual Parent and Child Driver code to copy?

Thanks for the assistance.

Yes.

You can get them from @SmartHomePrimer's GitHub repository; available here:

1 Like

Thank you!

1 Like

I am having trouble with adding a motion sensor. I don't see any support for type "motionsensor" in the insteonserver.js file so I think it is being ignored in my config.json file. This is how I have it set up in the config file:

{
"name": "Bonus Room Motion Sensor",
"deviceID": "2D3DA0",
"dimmable": "no",
"deviceType": "motionsensor"
}

Maybe I have the wrong version of insteonserver.js?

So sorry for the long delay in responding. Please try removing "dimmable": "no", from your config.json file. I just checked how I have my contact sensor setup and it doesn't include the dimmable type for that device. Save and restart the server and client listener.

I do not personally own an Insteon motion sensor, so I've no way to test this. Motion sensors were included in the original Homecontroller code that sits at the base of all this, so it technically should work, but I cannot recall if we ever tested it with this specific integration. I am personally considering just retiring my one Insteon contact sensor. I thought I would go ahead and use it, because it was working perfectly as a sensor for closed physical contacts, but now that I've converted it back to using the internal reed switch, I find I have to restart the server and client listener every week or so. Not worth it to me and I have several more Aqara and Mijia contact sensors that are rock solid using Home Assistant with Home Assistant Device Bridge to bring them back into HE.

Looks like we may have either abandoned the attempt because we didn't have a motion sensor to test with, or just forgot to finish adding it. Part of the code was in the ws parent file, but not all of it, and as you mentioned, nothing was in the insteonserver.js file. I'm not sure I did it right, but give these a try and see if they work for you.

Insteonserver.js (with motion sensor - no keypad support)

'use strict'
var Insteon = require('home-controller').Insteon
var hub = new Insteon()
var express = require('express')
var app = express()
var fs = require('fs')
var _ = require('underscore')

var websocket = require('ws')
var wss = new websocket.Server({port: 8080})

var configFile = fs.readFileSync('./config.json')
var configJSON = JSON.parse(configFile)
var platformIndex = configJSON.platforms.findIndex(function(item){return item.platform =='InsteonLocal'})
var config = configJSON.platforms[platformIndex]

InsteonServer()

function InsteonServer() {
	var devices = config.devices
	var deviceIDs = []
	var deviceJSON = []

	devices.forEach(function(device){
		deviceIDs.push(device.deviceID)
	})

	devices.forEach(function(device){
		var devJSON = {name: device.name, deviceID: device.deviceID, dimmable: device.dimmable, deviceType: device.deviceType}
		deviceJSON.push(devJSON)
	})

	var host = config.host
	var port = config.port
	var user = config.user
	var pass = config.pass
	var model = config.model
	var server_port = config.server_port || 3000

	var hubConfig = {
		host: host,
		port: port,
		user: user,
		password: pass
	}

	connectToHub()
	init()

	app.get('/light/:id/on', function(req, res) {
		var id = req.params.id.toUpperCase()
		hub.light(id).turnOn().then(function(status) {
			if (status.response) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/light/:id/off', function(req, res) {
		var id = req.params.id.toUpperCase()
		hub.light(id).turnOff().then(function(status) {
			if (status.response) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/light/:id/faston', function(req, res) {
		var id = req.params.id.toUpperCase()
		hub.light(id).turnOnFast().then(function(status) {
			if (status.response) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/light/:id/fastoff', function(req, res) {
		var id = req.params.id.toUpperCase()
		hub.light(id).turnOffFast().then(function(status) {
			if (status.response) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/light/:id/status', function(req, res) {
		var id = req.params.id
		hub.light(id).level(function(err, level) {
			res.json({
				'level': level
			})
		})
	})

	app.get('/light/:id/level/:targetLevel', function(req, res) {
		var id = req.params.id
		var targetLevel = req.params.targetLevel

		hub.light(id).level(targetLevel).then(function(status) {
			if (status.response) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/scene/:group/on', function(req, res) {
		var group = parseInt(req.params.group)
		hub.sceneOn(group).then(function(status) {
			if (status.aborted) {
				res.sendStatus(404)
			}
			if (status.completed) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/scene/:group/off', function(req, res) {
		var group = parseInt(req.params.group)
		hub.sceneOff(group).then(function(status) {
			if (status.aborted) {
				res.sendStatus(404)
			}
			if (status.completed) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/links', function(req, res) {
		hub.links(function(err, links) {
			res.json(links)
		})
	})

	app.get('/links/:id', function(req, res) {
		var id = req.params.id
		hub.links(id, function(err, links) {
			res.json(links)
		})
	})

	app.get('/info/:id', function(req, res) {
		var id = req.params.id
		hub.info(id, function(err, info) {
			res.json(info)
		})
	})

	app.get('/iolinc/:id/relay_on', function(req, res) {
		var id = req.params.id
		hub.ioLinc(id).relayOn().then(function(status) {
			if (status.response) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/iolinc/:id/relay_off', function(req, res) {
		var id = req.params.id
		hub.ioLinc(id).relayOff().then(function(status) {
			if (status.response) {
				res.sendStatus(200)

			} else {
				res.sendStatus(404)
			}
		})
	})

	app.get('/iolinc/:id/sensor_status', function(req, res) {
		var id = req.params.id
		hub.ioLinc(id).status(function(err, status) {
			res.json(status.sensor)
		})
	})

	app.get('/iolinc/:id/relay_status', function(req, res) {
		var id = req.params.id
		hub.ioLinc(id).status(function(err, status) {
			res.json(status.relay)
		})
	})

	app.listen(server_port)

	function connectToHub() {
		console.log('Model: ' + model)

		if (model == '2245') {
			console.log('Connecting to Insteon Model 2245 Hub...')
			hub.httpClient(hubConfig, function() {
				console.log('Connected to Insteon Model 2245 Hub...')
				connectedToHub = true
			})
		} else if (model == '2243') {
			console.log('Connecting to Insteon "Hub Pro" Hub...')
			connectingToHub = true
			hub.serial('/dev/ttyS4',{baudRate:19200}, function() {
				console.log('Connected to Insteon "Hub Pro" Hub...')
				connectedToHub = true

			})
		} else if (model == '2242') {
			console.log('Connecting to Insteon Model 2242 Hub...')
			hub.connect(host, function() {
				console.log('Connected to Insteon Model 2242 Hub...')
				connectedToHub = true
			})
		} else {
			console.log('Connecting to Insteon PLM...')
			hub.serial(host,{baudRate:19200}, function() {
				console.log('Connected to Insteon PLM...')
				connectedToHub = true
			})
		}
	}

	function init() {
		console.log('Initiating websocket...')
		var message

		wss.on('connection', function (ws) {
			console.log('Client connected to websocket')
			ws.isAlive = true

			ws.on('close', function(){
				console.log('Websocket closed by client')
				ws.isAlive = false
			})

			ws.send('Connected to Insteon Server')

			ws.on('message', function (message) {
				if(message == 'getDevices'){
					console.log(deviceJSON)
					if(ws.isAlive){ws.send(JSON.stringify(deviceJSON))}
				}
			})

			devices.forEach(function(device){
				switch (device.deviceType) {
				case 'doorsensor':
				case 'windowsensor':
				case 'contactsensor':
				case 'motionsensor':


					device.door = hub.door(device.deviceID)

					device.door.on('opened', function(){
						console.log('Got open for ' + device.name)
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: 'open'}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})

					device.door.on('closed', function(){
						console.log('Got closed for ' + device.name)
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: 'closed'}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})

					break

					case 'leaksensor':
					device.leak = hub.leak(device.deviceID)

					device.leak.on('dry', function(){
						console.log('Got dry for ' + device.name)
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: 'dry'}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})

					device.leak.on('wet', function(){
						console.log('Got wet for ' + device.name)
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: 'wet'}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})

					break

					case 'motionsensor':
					device.motion = hub.motion(device.deviceID)

					device.motion.on('inactive', function(){
						console.log('Got inactive for ' + device.name)
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: 'inactive'}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})

					device.motion.on('active', function(){
						console.log('Got active for ' + device.name)
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: 'active'}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})

					break

				case 'switch':
					device.light = hub.light(device.deviceID)

					device.light.on('turnOn', function (group, level) {
						console.log(device.name + ' turned on')
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: level}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})

					device.light.on('turnOff', function () {
						console.log(device.name + ' turned off')
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: 0}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})

					break

				case 'lightbulb':
				case 'dimmer':
					device.light = hub.light(device.deviceID)
					device.light.level().then(function(level) {
						message = {name: device.name, id: device.deviceID, deviceType: device.deviceType, state: level}
						if(ws.isAlive){ws.send(JSON.stringify(message))}
					})
					break
				}
			})

			eventListener()

			function eventListener() {
				console.log('Insteon event listener started...')

				hub.on('command', function(data) {

					if (typeof data.standard !== 'undefined') {
						//console.log('Received command for ' + data.standard.id)

						var info = JSON.stringify(data)
						var id = data.standard.id.toUpperCase()
						var command1 = data.standard.command1
						var command2 = data.standard.command2
						var messageType = data.standard.messageType

						var isDevice = _.contains(deviceIDs, id, 0)
						var message

						if (isDevice) {
							var foundDevices = devices.filter(function(item) {
								return item.deviceID == id
							})

							console.log('Found ' + foundDevices.length + ' accessories matching ' + id)
							console.log('Hub command: ' + info)

							for (var i = 0, len = foundDevices.length; i < len; i++) {
								var foundDevice = foundDevices[i]
								console.log('Got event for ' + foundDevice.name + ' (' + foundDevice.deviceID + ')')

								switch (foundDevice.deviceType) {
								case 'lightbulb':
								case 'dimmer':
									if (command1 == '19' || command1 == '03' || command1 == '04' || (command1 == '00' && command2 != '00') || (command1 == '06' && messageType == '1')) { //19 = status
										var level_int = parseInt(command2, 16) * (100 / 255)
										var level = Math.ceil(level_int)

										console.log('Got updated status for ' + foundDevice.name)
										message = {name: foundDevice.name, id: foundDevice.deviceID, deviceType: foundDevice.deviceType, state: level}
										if(ws.isAlive){ws.send(JSON.stringify(message))}
									}

									if (command1 == 11) { //11 = on
										var level_int = parseInt(command2, 16)*(100/255)
										var level = Math.ceil(level_int)

										console.log('Got on event for ' + foundDevice.name)
										message = {name: foundDevice.name, id: foundDevice.deviceID, deviceType: foundDevice.deviceType, state: level}
										if(ws.isAlive){ws.send(JSON.stringify(message))}
									}

									if (command1 == 12) { //fast on
										console.log('Got fast on event for ' + foundDevice.name)
										message = {name: foundDevice.name, id: foundDevice.deviceID, deviceType: foundDevice.deviceType, state: 100}
										if(ws.isAlive){ws.send(JSON.stringify(message))}
									}

									if (command1 == 13 || command1 == 14) { //13 = off, 14= fast off
										if (command1 == 13) {
											console.log('Got off event for ' + foundDevice.name)
										} else {console.log('Got fast off event for ' + foundDevice.name)}
										message = {name: foundDevice.name, id: foundDevice.deviceID, deviceType: foundDevice.deviceType, state: 0}
										if(ws.isAlive){ws.send(JSON.stringify(message))}
									}

									if (command1 == 18) { //stop dimming
										console.log('Got dim event for ' + foundDevice.name)
										foundDevice.light.level().then(function(level) {
											message = {name: foundDevice.name, id: foundDevice.deviceID, deviceType: foundDevice.deviceType, state: level}
											if(ws.isAlive){ws.send(JSON.stringify(message))}
										})
									}

									break
								}
							}
						}
					}
				})
			}
		}
		)}
}

ws parent (with motion sensor - no keypad support)

/**
 *  Insteon WS Parent
 *
 *  Copyright 2019 Chris Wilson
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 *  
 *  
 *
 *  Original Author     : ethomasii@gmail.com
 *  Creation Date       : 2013-12-08
 *
 *  Rewritten by        : idealerror
 *  Last Modified Date  : 2016-12-13 
 *
 *  Rewritten by        : kuestess
 *  Last Modified Date  : 2017-09-30
 * 
 *  Hubitat port by    @cwwilson08
 *  Last Modified Date  : 2019-06-24
 *
 * 
 *  Changelog:
 *  2019-06-24: Merge functions of original Insteon Direct dimmer code with WS so all calls are completed by parent device
 *  2019-06-23: Convert to async http calls - major code cleanup
 *  2019-06-23: Utilize ogiewon's websocket reconncet code
 *  2018-10-01: Added ability to disable auto refresh in driver
 *  2018-09-14: Added Fast ON/OFF & Refresh setting in driver
 *  2018-09-09: Initial release for Hubitat Elevation Hub
 *  2016-12-13: Added polling for Hub2
 *  2016-12-13: Added background refreshing every 3 minutes
 *  2016-11-21: Added refresh/polling functionality
 *  2016-10-15: Added full dimming functions
 *  2016-10-01: Redesigned interface tiles
 * 
 */


import hubitat.helper.InterfaceUtils
import groovy.json.JsonSlurper

metadata {
definition (name: "Insteon WS Parent", namespace: "cw", author: "Chris Wilson") {
    capability "Initialize"
    capability "Switch"
    attribute "connection", ""
    
}
}

preferences {
input("ip", "text", title: "Websocket IP Address", description: "Websocket IP Address", required: true)
	input("wsPort", "text", title: "WS Port", description: "Websocket Port", required: true)
    input("host", "text", title: "URL", description: "The URL of your Insteon Hub (without http:// example: my.hub.com ")
    input("instPort", "text", title: "Insteon Hub Port", description: "The insteon hub port.")
    input("username", "text", title: "Username", description: "The hub username (found in app)")
    input("password", "text", title: "Password", description: "The hub password (found in app)")
    input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
}


def parse(String description) {
    if (logEnable)log.debug "data from websocketparsed here"
    if (logEnable)log.debug "description: ${description}"
    if (description.startsWith("Connected to Insteon Server")) {
    sendEvent(name: "connection", value: "connected")
		return
   }
	

	def jsonSlurper = new JsonSlurper()
	def msg = jsonSlurper.parseText(description)

if (msg.dimmable){
    createDevices(msg)
    return
}

if (msg.id != null){
    if(state.childDevice.contains(msg.id)){
	child = getChildDevice(msg.id)
       // log.debug "Got event for Device ${child} with a value of ${msg.state}"   
if (msg.deviceType == "motionsensor") {childMotion(child, msg.state)}
if (msg.deviceType == "contactsensor") {childContact(child, msg.state)}
if (msg.deviceType == "dimmer") {childDimmer(child, msg.state)}
if (msg.deviceType == "lightbulb") {childDimmer(child, msg.state)}        
if (msg.deviceType == "leaksensor") {childLeakSensor(child, msg.state)}

                                          } 
 }
}

def childMotion(child, state){
if (logEnable) log.debug "child motion = ${child}"
if (logEnable) log.debug "child state = ${state}"
child.sendEvent(name: "motion", value: state)}

                                                          
def childContact(child, state){
if (logEnable) log.debug "child conact = ${child}"
if (logEnable) log.debug "child state = ${state}"
child.sendEvent(name: "contact", value: state)}

def childLeakSensor(child, state){
if (logEnable) log.debug "child leak = ${child}"
if (logEnable)log.debug "child state = ${state}"
child.sendEvent(name: "water", value: state)}


def childDimmer(child, state){
if (state == 0){
    child.sendEvent(name: "level", value: state)
    child.sendEvent(name: "switch", value: "off")
}
   
if (state > 0){
   if (logEnable) log.debug state
    child.sendEvent(name: "level", value: state)
    child.sendEvent(name: "switch", value: "on")
}
}


def initialize() {
   log.info "initialize() called"
   if (!ip) {
    log.warn "Please enter an IP"
    return
}

	try {
		
   
		InterfaceUtils.webSocketConnect(device, "ws://${ip}:${wsPort}")
} 
catch(e) {
    if (logEnable) log.debug "initialize error: ${e.message}"
    log.error "WebSocket connect failed"
    sendEvent(name: "connection", value: "disconnected")
}

}

def updated() {
log.info "updated() called"
//Unschedule any existing schedules
unschedule()

//Create a 30 minute timer for debug logging
if (logEnable) runIn(1800,logsOff)

//Connect the webSocket
    initialize()
    runIn(2, listChild)
    runIn(4, getDevices)
    
}

def logsOff(){
log.warn "debug logging disabled..."
device.updateSetting("logEnable",[value:"false",type:"bool"])
}


def getDevices() {
	if (logEnable) log.debug "getDevices sent"
	sendMsg ("getDevices")
}


def createDevices(msg){ msg.each { it->
    namespace = "cw"
    if (it.deviceType == "motionsensor") {type = "Insteon Motion Child"}
	if (it.deviceType == "contactsensor") {type = "Insteon Contact Child"}
    if (it.deviceType == "dimmer") {type = "Insteon Dimmer Child"}
    if (it.deviceType == "leaksensor") {type = "Insteon Leak Child"}
    if (it.deviceType == "lightbulb") {type = "Insteon Dimmer Child"}
    if (logEnable)log.debug type
    if (logEnable)log.debug it.deviceID
    if (logEnable)log.debug it.name
    if(!state.childDevice.contains(it.deviceID)){
    log.debug "creating device: ${it.name}"
	addChildDevice (namespace, type, it.deviceID, [label: it.name, isComponent: false, name: type])
}

}
listChild()

}
def listChild (){
def myMap =[]
	if (logEnable)log.debug "listChild called"
	childDevices.each{ it ->
        if (logEnable)log.debug "child: ${it.deviceNetworkId}"
        myMap << it.deviceNetworkId
        
        
}
if (logEnable)log.debug myMap
state.childDevice = myMap

}

def sendMsg(String s) {
InterfaceUtils.sendWebSocketMessage(device, s)
}



def webSocketStatus(String status){
if (logEnable)log.debug "webSocketStatus- ${status}"

if(status.startsWith('failure: ')) {
    log.warn("failure message from web socket ${status}")
    sendEvent(name: "connection", value: "disconnected")
    reconnectWebSocket()
} 
else if(status == 'status: open') {
    sendEvent(name: "connection", value: "connected")    
    log.info "websocket is open"
    if (logEnable)log.debug "Resetting reconnect delay"
    // success! reset reconnect delay
    pauseExecution(1000)
    state.reconnectDelay = 1
} 
else if (status == "status: closing"){
    log.warn "WebSocket connection closing."
    sendEvent(name: "connection", value: "disconnected")
} 
else {
    log.warn "WebSocket error, reconnecting."
    reconnectWebSocket()
}
}

def reconnectWebSocket() {
// first delay is 2 seconds, doubles every time
state.reconnectDelay = (state.reconnectDelay ?: 1) * 2
// don't let delay get too crazy, max it out at 10 minutes
if(state.reconnectDelay > 600) state.reconnectDelay = 600

   
runIn(state.reconnectDelay, initialize)
}


////control functions here


def setLevel(value, deviceid) {

    if (logEnable)log.debug "setLevel >> value: $value"
    
    // Max is 255
    def percent = value / 100
    def realval = percent * 255
    def valueaux = realval as Integer
    def level = Math.max(Math.min(valueaux, 255), 0)
    if (level > 0) {
        sendEvent(name: "switch", value: "on")
    } else {
        sendEvent(name: "switch", value: "off")
    }
    if (logEnable)log.debug "dimming value is $valueaux"
    if (logEnable)log.debug "dimming to $level"
    dim(level,value, deviceid)
}

def setLevel(value, rate, deviceid) {

    if (logEnable)log.debug "setLevel >> value: $value"
    
    // Max is 255
    def percent = value / 100
    def realval = percent * 255
    def valueaux = realval as Integer
    def level = Math.max(Math.min(valueaux, 255), 0)
    if (level > 0) {
        sendEvent(name: "switch", value: "on")
    } else {
        sendEvent(name: "switch", value: "off")
    }
    if (logEnable)log.debug "dimming value is $valueaux"
    if (logEnable)log.debug "dimming to $level"
    dim(level,value)
}

def dim(level, real, deviceid) {
    String hexlevel = level.toString().format( '%02x', level.toInteger() )
   
    if (logEnable)log.debug "Dimming Device: ${deviceid} to hex $hexlevel"
    sendCmd("11",hexlevel, deviceid)
}

def sendCmd(num, level, deviceid){
    
    def requestParams = [ uri: "http://${settings.username}:${settings.password}@${settings.host}:${settings.instPort}//3?0262${deviceid}0F${num}${level}=I=3" ]
    if(logEnable)log.debug requestParams
    if(logEnable)log.debug "Sending command to Device: ${device} with parameters Command: ${num} Level ${level}"
	asynchttpGet("cmdHandler", requestParams)
}

def cmdHandler(resp, data) {
	if(resp.getStatus() == 200 || resp.getStatus() == 207) {
        if (logEnable) "Command Sent successfully"
    
        } else {
        
		    log.error "Error sending command to device"
	}
}

motion sensor child

/**
 *  Insteon Motion Child
 *
 *  Copyright 2022 Logname
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 *  
 *
 
 * 
 */

metadata {
	definition (name: "Insteon Motion Child", namespace: "ln", author: "logname") {
		
		capability "Motion Sensor"
        command "active"
        command "inactive"
        			
	}   
}


def installed() {
}

def open() {
    sendEvent(name: "motion", value: "active")
}

def close() {
    sendEvent(name: "motion", value: "inactive")
}

[Update 6/7/2022] Insteon servers are back online. Hurry up and make your hub and device changes!

1 Like

What?!!!!! She lives!!!

1 Like

It might not last. Insteon users should get while the gettin's good, then go local for life.

1 Like