homebridge-vivint icon indicating copy to clipboard operation
homebridge-vivint copied to clipboard

Add support for light switches

Open mceres opened this issue 5 years ago • 49 comments

[4/18/2019, 4:14:37 AM] [Vivint] Do not know how to handle device! ID: 75 Data.t: multilevel_switch_device data.ec: undefined Data.n: Living Room [4/18/2019, 4:14:37 AM] [Vivint] Do not know how to handle device! ID: 79 Data.t: binary_switch_device data.ec: undefined Data.n: Garage [4/18/2019, 4:14:37 AM] [Vivint] Do not know how to handle device! ID: 85 Data.t: multilevel_switch_device data.ec: undefined Data.n: Garage Entrance [4/18/2019, 4:14:37 AM] [Vivint] Do not know how to handle device! ID: 89 Data.t: binary_switch_device data.ec: undefined Data.n: Play Area

This is the message that comes across when turning on and off the switches

[4/18/2019, 4:17:04 AM] [Vivint] {"_id":"0000000000000000|1","da":{"d":[{"_id":75,"s":true}],"plctx":{"context_carrier":{"previous_handler":"Subscriber Update Handler","tracing_context":{"uber-trace-id":"68c03ea59ab42378:68c03ea59ab42378:0:1"}},"ctxd":null,"ctxid":"5bf05d0878b4d449811a228b","ctxt":20,"mid":"5cb7fa3f9681f1005b837115","ts":"2019-04-18T04:17:04.253","validation":{"args":{"value":[100,true]},"method":["on_property_updated"],"module":["binary_switch_device","multilevel_switch_device"],"timestamp":1555561023.972614}}},"op":"u","panid":0000000000000000,"parid":1,"t":"account_partition"} [4/18/2019, 4:17:11 AM] [Vivint] received pubNub msg [4/18/2019, 4:17:11 AM] [Vivint] {"_id":"0000000000000000|1","da":{"d":[{"_id":75,"val":0}],"plctx":{"context_carrier":{"previous_handler":"Subscriber Update Handler","tracing_context":{"uber-trace-id":"be1f781f661677a:be1f781f661677a:0:1"}},"ctxd":null,"ctxid":"5bf05d0878b4d449811a228b","ctxt":20,"mid":"5cb7fa47d593cf3b720af265","ts":"2019-04-18T04:17:11.729","validation":{"args":{"value":[0,false]},"method":["on_property_updated"],"module":["binary_switch_device","multilevel_switch_device"],"timestamp":1555561031.536903}}},"op":"u","panid":0000000000000000,"parid":1,"t":"account_partition"} [4/18/2019, 4:17:12 AM] [Vivint] received pubNub msg [4/18/2019, 4:17:12 AM] [Vivint] {"_id":"0000000000000000|1","da":{"d":[{"_id":75,"s":false}],"plctx":{"context_carrier":{"previous_handler":"Subscriber Update Handler","tracing_context":{"uber-trace-id":"36be93225eda0f1b:36be93225eda0f1b:0:1"}},"ctxd":null,"ctxid":"5bf05d0878b4d449811a228b","ctxt":20,"mid":"5cb7fa47d593cf3b720af265","ts":"2019-04-18T04:17:11.801","validation":{"args":{"value":[0,false]},"method":["on_property_updated"],"module":["binary_switch_device","multilevel_switch_device"],"timestamp":1555561031.536903}}},"op":"u","panid":0000000000000000,"parid":1,"t":"account_partition"}

[4/18/2019, 4:20:18 AM] [Vivint] received pubNub msg [4/18/2019, 4:20:18 AM] [Vivint] {"_id":"0000000000000000|1","da":{"d":[{"_id":79,"val":100}],"plctx":{"context_carrier":{"previous_handler":"Subscriber Update Handler","tracing_context":{"uber-trace-id":"6aec278a1b9a41d6:6aec278a1b9a41d6:0:1"}},"mid":"5cb7fb028acbfd0001a0c521","ts":"2019-04-18T04:20:18.530"}},"op":"u","panid":0000000000000000,"parid":1,"t":"account_partition"} [4/18/2019, 4:20:18 AM] [Vivint] received pubNub msg [4/18/2019, 4:20:18 AM] [Vivint] {"_id":"0000000000000000|1","da":{"d":[{"_id":79,"val":100}],"plctx":{"context_carrier":{"previous_handler":"Subscriber Update Handler","tracing_context":{"uber-trace-id":"6aec278a1b9a41d6:6aec278a1b9a41d6:0:1"}},"mid":"5cb7fb028acbfd0001a0c521","ts":"2019-04-18T04:20:18.530"}},"op":"u","panid":0000000000000000,"parid":1,"t":"account_partition"} [4/18/2019, 4:20:18 AM] [Vivint] received pubNub msg [4/18/2019, 4:20:18 AM] [Vivint] {"_id":"0000000000000000|1","da":{"d":[{"_id":79,"s":true}],"plctx":{"context_carrier":{"previous_handler":"Subscriber Update Handler","tracing_context":{"uber-trace-id":"a2bd097ee304022:a2bd097ee304022:0:1"}},"mid":"5cb7fb02975a7600014604ca","ts":"2019-04-18T04:20:18.613"}},"op":"u","panid":0000000000000000,"parid":1,"t":"account_partition"} [4/18/2019, 4:20:21 AM] [Vivint] received pubNub msg [4/18/2019, 4:20:21 AM] [Vivint] {"_id":"0000000000000000|1","da":{"d":[{"_id":79,"val":0}],"plctx":{"context_carrier":{"previous_handler":"Subscriber Update Handler","tracing_context":{"uber-trace-id":"3d741e60348fe717:3d741e60348fe717:0:1"}},"ctxd":null,"ctxid":"5bf05d0878b4d449811a228b","ctxt":20,"mid":"5cb7fb05d593cf3b720afbc7","ts":"2019-04-18T04:20:21.695","validation":{"args":{"value":[0]},"method":["on_property_updated"],"module":["binary_switch_device","multilevel_switch_device"],"timestamp":1555561221.500922}}},"op":"u","panid":0000000000000000,"parid":1,"t":"account_partition"} [4/18/2019, 4:20:21 AM] [Vivint] received pubNub msg [4/18/2019, 4:20:21 AM] [Vivint] {"_id":"0000000000000000|1","da":{"d":[{"_id":79,"s":false}],"plctx":{"context_carrier":{"previous_handler":"Subscriber Update Handler","tracing_context":{"uber-trace-id":"4618e58f7bb2b66c:4618e58f7bb2b66c:0:1"}},"ctxd":null,"ctxid":"5bf05d0878b4d449811a228b","ctxt":20,"mid":"5cb7fb05d593cf3b720afbc7","ts":"2019-04-18T04:20:21.799","validation":{"args":{"value":[0]},"method":["on_property_updated"],"module":["binary_switch_device","multilevel_switch_device"],"timestamp":1555561221.500922}}},"op":"u","panid":0000000000000000,"parid":1,"t":"account_partition"}

mceres avatar Apr 18 '19 04:04 mceres

Is Id 79 (garage) a dimmer switch or normal on/off switch? I presume binary device designates it as having only an on/off state? What about the multilevel switches (id 85/garage entrance)

daymondm avatar Apr 22 '19 03:04 daymondm

Living Room (75) and garage entrance (85) are dimmers.

Garage (79) and Play Area (89) are just on and off.

mceres avatar Apr 22 '19 03:04 mceres

Are you able to control the switches through the Vivint app itself? I don't know why I had in my mind that this was simply adding a contact sensor. I'm not sure how the api handles a put request to a switch.

For example, to control a lock the Homebridge app sends a "PUT" request to https://vivintsky.com/api/locks/24 (assuming 24 is the ID# of the lock) with the following body: {id: 24, s:true}.

So without actually having compatible switches, its impossible to guess what Vivint would replace "/locks/" with.

That being said, we can utilize an app to sniff out the api, but it only works if you're able to control the switches directly from the Vivint app (or more specifically, from vivintsky.com).

The app that I've used in this project is called Postman.. I'll try to post a walkthrough on how to set this up:

When the app loads, click on the templates tab, and select "Reverse Engineering an API" Screen Shot 2019-04-23 at 11 33 45 PM

Click on "Use this template" -> "Create"

Click on the "Capture API requests" icon:

Screen Shot 2019-04-24 at 12 07 12 AM

Note the proxy port number, 5555 by default, select the reverse engineering profile as the target and click "Connect":

Screen Shot 2019-04-23 at 11 39 59 PM

You should get a pop up saying something to the effect of the connection has been established. Now you need to set up your browser to use postman as a proxy.. I am on a Mac and use safari so I'll show how its done with Mac:

Screen Shot 2019-04-23 at 11 41 38 PM

Click on the "advanced" tab, and click "Change Settings" under "Proxies":

Screen Shot 2019-04-23 at 11 42 54 PM

Check the box next to HTTP and HTTPS, set server to localhost, and port to 5555 (or whatever you set previously in postman) and click ok:

Screen Shot 2019-04-23 at 11 44 31 PM

Click Apply on the network screen (if you just close it, it will prompt you to apply)

....

open vivintsky.com in safari, and things should start populating in the postman log. On the vivintsky website, operate the light switch on and off, and look back at the postman log. You are looking for any "PUT" requests. Next pic is an example of a PUT request that I got for unlocking my backdoor (id 42):

Screen Shot 2019-04-23 at 11 47 55 PM

Don't post the string of numbers that I have blocked out in the picture above, I just need to see what the /1/locks/42 part says for you when the switch is controlled.

If you could post that information, I think I ought to be able to write the code for it!

daymondm avatar Apr 24 '19 04:04 daymondm

Great, thanks for the tip. I was able to do this on a Windows PC. Here is the info

This is on a dimmer

image

This is on an on/off switch

image

Let me know if you need any other info.

mceres avatar Apr 24 '19 16:04 mceres

Switches I guess it wouldn’t have been impossible to guess. Looks easy enough, I’ll update the fork when I get home

daymondm avatar Apr 24 '19 21:04 daymondm

ok so lets try this... add the following code to the deviceset class, after the // mischief managed comment (line 678 of device_set.js):

  // Binary switch has only on and off states
  class LightSwitch extends Device {
    constructor(accessory) {
      super(accessory)
      this.service = accessory.getServiceByUUIDAndSubType(Service.Lightbulb)

      this.service
        .getCharacteristic(Characteristic.On)
        .on('get', (next) => next(null,this.switchCurrentValue()))
        .on('set', this.setSwitchCurrentValue.bind(this))
    }

    switchCurrentValue() {
      return this.data.s
    }

    setSwitchCurrentValue(targetState, next) {
      if (targetState) {
        // turn switch on
        vivintApi.putDevice('switches', this.id, {s: true, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      } else {
        // turn switch off
        vivintApi.putDevice('switches', this.id, {s: false, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      }
    }

    notify() {
      if (this.service) {
        this.service.getCharacteristic(Characteristic.On)
          .updateValue(this.switchCurrentValue())
      }
    }
  }

  extend(LightSwitch, {
    appliesTo: (data) => { return data.t == "binary_switch_device"},
    addServices: (accessory) => {
      accessory.addService(new Service.Lightbulb(accessory.context.name))
    }
  })

and change the let Devices = line to:

let Devices = [ContactSensor, MotionSensor, Lock, Thermostat, GarageDoor, Panel, PIVMotion, LightSwitch]

daymondm avatar Apr 25 '19 05:04 daymondm

Also for the dimmer switches.. can you tell me if you always get a PubNub message stating s: true and s:false when the light is switched on and off? or does it send you a val: 0 when the switch is turned off?

It looks like, based on what you had pasted before, that it always sends two separate messages, one with the s true/false stating whether or not the light is on, as well as one with a val argument. I'm curious as to what messages are sent when you change the dim level without turning the bulb completely off?

daymondm avatar Apr 25 '19 05:04 daymondm

For on/off it goes to false {"s":false,"_id":79}

For dimmer it goes to 0 or if its being dimmed to a diff value Off {"val":0,"_id":85} Dimmed {"val":40,"_id":85}

ill give the code a try.

Thank You :)

mceres avatar Apr 25 '19 14:04 mceres

Nice, you did it. Thank you!

My on/off switches are working perfectly. My dimmers are not being passed to homekit yet.

[4/26/2019, 3:41:47 AM] [Vivint] Do not know how to handle device! ID: 75 Data.t: multilevel_switch_device data.ec: undefined Data.n: Living Room

[4/26/2019, 3:41:47 AM] [Vivint] Do not know how to handle device! ID: 85 Data.t: multilevel_switch_device data.ec: undefined Data.n: Garage Entrance

[4/26/2019, 3:41:47 AM] [Vivint] Adding 2 new accessories [4/26/2019, 3:41:47 AM] [Vivint] { name: 'Garage', id: 79, deviceClassName: 'LightSwitch' } [4/26/2019, 3:41:47 AM] [Vivint] { name: 'Play Area', id: 89, deviceClassName: 'LightSwitch' }

mceres avatar Apr 26 '19 03:04 mceres

excellent, I added a couple things I was hoping you would try.. so first off for the binary switches, I added some code to infer whether or not they are light switches, fan switches, or just plan old switches. My assumption is that you'll get a light icon if it identifies as a lightbulb, fan icon for a fan, and just a normal switch which is what you are seeing now. I'm pretty confident that that code will work so I'm not necessarily needing you to test it, but if you add the word "light" somewhere into the name of the device it will register as a lightbulb in HomeKit instead of just a switch.

Now for the dimmer... I've wrote some code for you to test!

for the let Devices line (note the change from LightSwitch to BinarySwitch):

let Devices = [ContactSensor, MotionSensor, Lock, Thermostat, GarageDoor, Panel, PIVMotion, BinarySwitch, DimmerSwitch]

and the good stuff (replace the previous code with this, this updates to more intelligently define the binary switches as well as add support for the dimmer switch):

  class BinarySwitch extends Device {
    constructor(accessory) {
      super(accessory)

      this.service = accessory.getServiceByUUIDAndSubType(Service.Lightbulb) || accessory.getServiceByUUIDAndSubType(Service.Fan) || accessory.getServiceByUUIDAndSubType(Service.Switch)

      this.service
        .getCharacteristic(Characteristic.On)
        .on('get', (next) => next(null,this.switchCurrentValue()))
        .on('set', this.setSwitchCurrentValue.bind(this))
    }

    switchCurrentValue() {
      return this.data.s
    }

    setSwitchCurrentValue(targetState, next) {
      if (targetState) {
        // turn switch on
        vivintApi.putDevice('switches', this.id, {s: true, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      } else {
        // turn switch off
        vivintApi.putDevice('switches', this.id, {s: false, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      }
    }

    notify() {
      if (this.service) {
        this.service.getCharacteristic(Characteristic.On)
          .updateValue(this.switchCurrentValue())
      }
    }
  }

  extend(BinarySwitch, {
    appliesTo: (data) => { return data.t == "binary_switch_device"},
    addServices: (accessory) => {
      if (accessory.context.name.match(/\blight\b/i)) {
        accessory.addService(new Service.Lightbulb(accessory.context.name))
      }
      else if (accessory.context.name.match(/\bfan\b/i)) {
        accessory.addService(new Service.Fan(accessory.context.name))
      }
      else {
        accessory.addService(new Service.Switch(accessory.context.name))
      }
    }
  })

  // dimmer switch {s: true/false, val: 0-100}
  class DimmerSwitch extends Device {
    constructor(accessory) {
      super(accessory)

      this.service = accessory.getServiceByUUIDAndSubType(Service.Lightbulb)

      this.service
        .getCharacteristic(Characteristic.On)
        .on('get', (next) => next(null,this.switchCurrentValue()))
        .on('set', this.setSwitchCurrentValue.bind(this))

      this.service
        .getCharacteristic(Characteristic.Brightness)
        .on('get', (next) => next(null, this.switchBrightnessValue()))
        .on('set', this.setBrightnessValue.bind(this))
    }

    switchCurrentValue() {
      return this.data.s
    }

    setSwitchCurrentValue(targetState, next) {
      if (targetState) {
        // turn switch on
        vivintApi.putDevice('switches', this.id, {s: true, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      } else {
        // turn switch off
        vivintApi.putDevice('switches', this.id, {s: false, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      }
    }

    switchBrightnessValue() {
      return this.data.val
    }

    setBrightnessValue(targetState,next) {
      vivintApi.putDevice('switches', this.id, {val: targetState, _id: this.id})
        .then(
          (success) => next(),
          (failure) => {
            log("failure " + failure)
            next(failure)
          })
    }

    notify() {
      if (this.service) {
        if (this.data.val >= 0) {
          this.service
           .getCharacteristic(Characteristic.Brightness)
           .updateValue(this.data.val)
        }

        if (this.data.s == true || this.data.s == false) {
          this.service
            .getCharacteristic(Characteristic.On)
            .updateValue(this.data.s)
        }
        //this.service.getCharacteristic(Characteristic.On)
        //  .updateValue(this.switchCurrentValue())
      }
    }
  }

  extend(DimmerSwitch, {
    appliesTo: (data) => { return data.t == "multilevel_switch_device"},
    addServices: (accessory) => {
      //assuming this is a dimmer switch controlling a light
      accessory.addService(new Service.Lightbulb(accessory.context.name))
    }
  })

daymondm avatar Apr 26 '19 04:04 daymondm

im getting this

[4/26/2019, 4:18:23 AM] [Vivint] Error while bootstrapping accessories [4/26/2019, 4:18:23 AM] [Vivint] Unknown device class name LightSwitch

mceres avatar Apr 26 '19 04:04 mceres

ok lets change the device class name back to LightSwitch instead of BinarySwitch:

let Devices = [ContactSensor, MotionSensor, Lock, Thermostat, GarageDoor, Panel, PIVMotion, LightSwitch, DimmerSwitch]

and:

  // Binary switch has only on and off states
  class LightSwitch extends Device {
    constructor(accessory) {
      super(accessory)

      this.service = accessory.getServiceByUUIDAndSubType(Service.Lightbulb) || accessory.getServiceByUUIDAndSubType(Service.Fan) || accessory.getServiceByUUIDAndSubType(Service.Switch)

      this.service
        .getCharacteristic(Characteristic.On)
        .on('get', (next) => next(null,this.switchCurrentValue()))
        .on('set', this.setSwitchCurrentValue.bind(this))
    }

    switchCurrentValue() {
      return this.data.s
    }

    setSwitchCurrentValue(targetState, next) {
      if (targetState) {
        // turn switch on
        vivintApi.putDevice('switches', this.id, {s: true, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      } else {
        // turn switch off
        vivintApi.putDevice('switches', this.id, {s: false, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      }
    }

    notify() {
      if (this.service) {
        this.service.getCharacteristic(Characteristic.On)
          .updateValue(this.switchCurrentValue())
      }
    }
  }

  extend(LightSwitch, {
    appliesTo: (data) => { return data.t == "binary_switch_device"},
    addServices: (accessory) => {
      if (accessory.context.name.match(/\blight\b/i)) {
        accessory.addService(new Service.Lightbulb(accessory.context.name))
      }
      else if (accessory.context.name.match(/\bfan\b/i)) {
        accessory.addService(new Service.Fan(accessory.context.name))
      }
      else {
        accessory.addService(new Service.Switch(accessory.context.name))
      }
    }
  })

  // dimmer switch {s: true/false, val: 0-100}
  class DimmerSwitch extends Device {
    constructor(accessory) {
      super(accessory)

      this.service = accessory.getServiceByUUIDAndSubType(Service.Lightbulb)

      this.service
        .getCharacteristic(Characteristic.On)
        .on('get', (next) => next(null,this.switchCurrentValue()))
        .on('set', this.setSwitchCurrentValue.bind(this))

      this.service
        .getCharacteristic(Characteristic.Brightness)
        .on('get', (next) => next(null, this.switchBrightnessValue()))
        .on('set', this.setBrightnessValue.bind(this))
    }

    switchCurrentValue() {
      return this.data.s
    }

    setSwitchCurrentValue(targetState, next) {
      if (targetState) {
        // turn switch on
        vivintApi.putDevice('switches', this.id, {s: true, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      } else {
        // turn switch off
        vivintApi.putDevice('switches', this.id, {s: false, _id: this.id})
          .then(
            (success) => next(),
            (failure) => {
              log("failure " + failure)
              next(failure)
            })
      }
    }

    switchBrightnessValue() {
      return this.data.val
    }

    setBrightnessValue(targetState,next) {
      vivintApi.putDevice('switches', this.id, {val: targetState, _id: this.id})
        .then(
          (success) => next(),
          (failure) => {
            log("failure " + failure)
            next(failure)
          })
    }

    notify() {
      if (this.service) {
        if (this.data.val >= 0) {
          this.service
           .getCharacteristic(Characteristic.Brightness)
           .updateValue(this.data.val)
        }

        if (this.data.s == true || this.data.s == false) {
          this.service
            .getCharacteristic(Characteristic.On)
            .updateValue(this.data.s)
        }
        //this.service.getCharacteristic(Characteristic.On)
        //  .updateValue(this.switchCurrentValue())
      }
    }
  }

  extend(DimmerSwitch, {
    appliesTo: (data) => { return data.t == "multilevel_switch_device"},
    addServices: (accessory) => {
      //assuming this is a dimmer switch controlling a light
      accessory.addService(new Service.Lightbulb(accessory.context.name))
    }
  })

daymondm avatar Apr 26 '19 04:04 daymondm

[4/26/2019, 4:26:04 AM] Error: listen EADDRINUSE :::51826 at Object._errnoException (util.js:1022:11) at _exceptionWithHostPort (util.js:1044:20) at Server.setupListenHandle [as _listen2] (net.js:1367:14) at listenInCluster (net.js:1408:12) at Server.listen (net.js:1492:7) at EventedHTTPServer.listen (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/util/eventedhttp.js:60:19) at HAPServer.listen (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/HAPServer.js:158:20) at Bridge.Accessory.publish (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:616:16) at Server._publish (/usr/local/lib/node_modules/homebridge/lib/server.js:132:16) at Server.run (/usr/local/lib/node_modules/homebridge/lib/server.js:101:10) [4/26/2019, 4:26:04 AM] Got SIGTERM, shutting down Homebridge... [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 5 Data.t: energy_service data.ec: undefined Data.n: undefined [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 12 Data.t: network_hosts_service data.ec: undefined Data.n: undefined [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 13 Data.t: panel_diagnostics_service data.ec: undefined Data.n: undefined [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 35 Data.t: wireless_sensor data.ec: 1248 Data.n: Bedroom Glass Break [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 36 Data.t: wireless_sensor data.ec: 1248 Data.n: Living Room Glass Break [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 44 Data.t: phillips_hue_bridge_device data.ec: undefined Data.n: Philips hue [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 45 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Front Outdoor [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 46 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Front Door Lights [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 47 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Belen's [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 48 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Cristian's [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 49 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Master Bedroom [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 20003 Data.t: scheduler_service data.ec: undefined Data.n: undefined [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 70 Data.t: controller_device data.ec: undefined Data.n: Wink [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 84 Data.t: wireless_sensor data.ec: 1269 Data.n: Master Hall Fire Alert [4/26/2019, 4:26:05 AM] [Vivint] Do not know how to handle device! ID: 94 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Bathroom [4/26/2019, 4:26:05 AM] [Vivint] Adding 0 new accessories HAP Warning: Characteristic 00000008-0000-1000-8000-0026BB765291 not in required or optional characteristics for service 00000043-0000-1000-8000-0026BB765291. Adding anyway. HAP Warning: Characteristic 00000008-0000-1000-8000-0026BB765291 not in required or optional characteristics for service 00000043-0000-1000-8000-0026BB765291. Adding anyway. [4/26/2019, 4:26:05 AM] [Vivint] Handling incoming device snapshot for timestamp 2019-04-26T04:24:35.749000

mceres avatar Apr 26 '19 04:04 mceres

I don't see id 75/85 in the unknown devices list, did those devices add to homekit? Living Room and Garage Entrance were the device names

daymondm avatar Apr 26 '19 04:04 daymondm

also those devices that are marked as multilevel_switch_ip_device.. do those behave the same way within postman? (s: true/false for when the switch is turned on and off, and val: 0-100 when the dim level is changed)

daymondm avatar Apr 26 '19 04:04 daymondm

It actually did, but something is stopping homebridge

received cached accessory PlatformAccessory { displayName: 'Living Room', UUID: '28ea52bf-3ecf-4d94-8aee-7d18ebbd0d24', category: 1, services: [ Service { displayName: undefined, UUID: '0000003E-0000-1000-8000-0026BB765291', subtype: undefined, iid: null, characteristics: [Array], optionalCharacteristics: [], isHiddenService: false, isPrimaryService: false, linkedServices: [] }, Service { displayName: 'Living Room', UUID: '00000043-0000-1000-8000-0026BB765291', subtype: undefined, iid: null, characteristics: [Array], optionalCharacteristics: [], isHiddenService: false, isPrimaryService: false, linkedServices: [] } ], reachable: false, context: { name: 'Living Room', id: 75, deviceClassName: 'DimmerSwitch' }, _associatedPlugin: 'homebridge-vivint', _associatedPlatform: 'Vivint' } received cached accessory PlatformAccessory { displayName: 'Garage Entrance', UUID: 'ba6172b2-376a-4166-9a3d-ca282f33de29', category: 1, services: [ Service { displayName: undefined, UUID: '0000003E-0000-1000-8000-0026BB765291', subtype: undefined, iid: null, characteristics: [Array], optionalCharacteristics: [], isHiddenService: false, isPrimaryService: false, linkedServices: [] }, Service { displayName: 'Garage Entrance', UUID: '00000043-0000-1000-8000-0026BB765291', subtype: undefined, iid: null, characteristics: [Array], optionalCharacteristics: [], isHiddenService: false, isPrimaryService: false, linkedServices: [] } ], reachable: false, context: { name: 'Garage Entrance', id: 85, deviceClassName: 'DimmerSwitch' }, _associatedPlugin: 'homebridge-vivint', _associatedPlatform: 'Vivint' }

mceres avatar Apr 26 '19 04:04 mceres

the multilevel_switch_ip_device are hue lights... ill need to see how the message looks on those. Also i already have Hue integrated with homekit so im not in a hurry to make those work for now.... but to continue to grow the plugin we can take a look.

any idea why is my homebridge stopping?

mceres avatar Apr 26 '19 04:04 mceres

ok no need to add the extra step through Vivint if it can be controlled directly from HomeKit, they'll be much more reliable that way.

does the log file show any more detail?

daymondm avatar Apr 26 '19 04:04 daymondm

this is all its showing right after loading the accessories and displaying the pairing code

[4/26/2019, 4:42:36 AM] Error: listen EADDRINUSE :::51826 at Object._errnoException (util.js:1022:11) at _exceptionWithHostPort (util.js:1044:20) at Server.setupListenHandle [as _listen2] (net.js:1367:14) at listenInCluster (net.js:1408:12) at Server.listen (net.js:1492:7) at EventedHTTPServer.listen (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/util/eventedhttp.js:60:19) at HAPServer.listen (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/HAPServer.js:158:20) at Bridge.Accessory.publish (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:616:16) at Server._publish (/usr/local/lib/node_modules/homebridge/lib/server.js:132:16) at Server.run (/usr/local/lib/node_modules/homebridge/lib/server.js:101:10) [4/26/2019, 4:42:37 AM] Got SIGTERM, shutting down Homebridge... [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 5 Data.t: energy_service data.ec: undefined Data.n: undefined [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 12 Data.t: network_hosts_service data.ec: undefined Data.n: undefined [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 13 Data.t: panel_diagnostics_service data.ec: undefined Data.n: undefined [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 35 Data.t: wireless_sensor data.ec: 1248 Data.n: Bedroom Glass Break [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 36 Data.t: wireless_sensor data.ec: 1248 Data.n: Living Room Glass Break [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 44 Data.t: phillips_hue_bridge_device data.ec: undefined Data.n: Philips hue [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 45 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Front Outdoor [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 46 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Front Door Lights [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 47 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Belen's [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 48 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Cristian's [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 49 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Master Bedroom [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 20003 Data.t: scheduler_service data.ec: undefined Data.n: undefined [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 70 Data.t: controller_device data.ec: undefined Data.n: Wink [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 84 Data.t: wireless_sensor data.ec: 1269 Data.n: Master Hall Fire Alert [4/26/2019, 4:42:38 AM] [Vivint] Do not know how to handle device! ID: 94 Data.t: multilevel_switch_ip_device data.ec: undefined Data.n: Bathroom [4/26/2019, 4:42:38 AM] [Vivint] Adding 0 new accessories HAP Warning: Characteristic 00000008-0000-1000-8000-0026BB765291 not in required or optional characteristics for service 00000043-0000-1000-8000-0026BB765291. Adding anyway. HAP Warning: Characteristic 00000008-0000-1000-8000-0026BB765291 not in required or optional characteristics for service 00000043-0000-1000-8000-0026BB765291. Adding anyway. [4/26/2019, 4:42:38 AM] [Vivint] Handling incoming device snapshot for timestamp 2019-04-26T04:41:01.308000 status { category: 'PNConnectedCategory', operation: 'PNSubscribeOperation', affectedChannels: [ 'PlatformChannel#H4nf3iAXnxFdsSkptxuv51GZc7eLBpwQ' ], subscribedChannels: [ 'PlatformChannel#H4nf3iAXnxFdsSkptxuv51GZc7eLBpwQ' ], affectedChannelGroups: [], lastTimetoken: 0, currentTimetoken: '15562530192086688' }

mceres avatar Apr 26 '19 04:04 mceres

the first line in the log seems like there might be two instances of Homebridge running?

if not.. lets try commenting out the following lines and seeing if its the notify code that is causing problems (add /* and */ to comment out the code):

    notify() {
      /*
      if (this.service) {
        if (this.data.val >= 0) {
          this.service
           .getCharacteristic(Characteristic.Brightness)
           .updateValue(this.data.val)
        }

        if (this.data.s == true || this.data.s == false) {
          this.service
            .getCharacteristic(Characteristic.On)
            .updateValue(this.data.s)
        }
        //this.service.getCharacteristic(Characteristic.On)
        //  .updateValue(this.switchCurrentValue())
      }
      */
    }

daymondm avatar Apr 26 '19 04:04 daymondm

got it, there were other homebridge processes running.

the are working :)

only thing i am finding is that when i when i change a light, lets say from on to off... i see the accessory in homekit going to off status and then to on and back to off.. not sure if i am describing this correctly to you.. but like if its getting a status update before doing what is told.

mceres avatar Apr 26 '19 04:04 mceres

interesting.. maybe because the Vivint api is sending two messages each time the switch is operated, one with just the brightness value and then another with whether or not the light is on or off. Do you mean when you press the button in HomeKit from your phone or when you physically control the switch?

Also, does the HomeKit show you that this is a dimmable light and are you able to dim the bulb from HomeKit?

daymondm avatar Apr 26 '19 05:04 daymondm

the dimmer lights show correctly i can dim them in homekit and the on/off also show correctly.

its when i control them in homekit... it might be an issue with having a wink hub connected to the vivint panel. I will be removing the wink hub and do some more testing. Ill do that tomorrow.

Before coming across this plugin i had to add the wink hub to the vivint panel as a zwave device and then added the wink hub to hassio to be able to pass the light switches to homekit. But now its all working :)

im pretty sure that wink hub has something to do with what i am experiencing.

Thanks for all your help, ill report back once i remove the wink hub from the panel.

mceres avatar Apr 26 '19 05:04 mceres

hey try this real quick if you don't mind and see if it corrects that issue:

    notify() {
      if (this.service) {
        if (this.data.val >= 0) {
          this.service
           .getCharacteristic(Characteristic.Brightness)
           .updateValue(this.data.val)
        }

        if (this.data.s == true || this.data.s == false) {
          if (this.data.s == true && this.data.val == 0) this.service.getCharacteristic(Characteristic.On).updateValue(false)
          else {
            this.service
              .getCharacteristic(Characteristic.On)
              .updateValue(this.data.s)
          }
        }
        //this.service.getCharacteristic(Characteristic.On)
        //  .updateValue(this.switchCurrentValue())
      }

daymondm avatar Apr 26 '19 05:04 daymondm

where do you want me to add that.. i didnt comment out what you asked when i was having problems running homebridge

this is what i currently have

// Binary switch has only on and off states class LightSwitch extends Device { constructor(accessory) { super(accessory)

  this.service = accessory.getServiceByUUIDAndSubType(Service.Lightbulb) || accessory.getServiceByUUIDAndSubType(Service.Fan) || accessory.getServiceByUUIDAndSubType(Service.Switch)

  this.service
    .getCharacteristic(Characteristic.On)
    .on('get', (next) => next(null,this.switchCurrentValue()))
    .on('set', this.setSwitchCurrentValue.bind(this))
}

switchCurrentValue() {
  return this.data.s
}

setSwitchCurrentValue(targetState, next) {
  if (targetState) {
    // turn switch on
    vivintApi.putDevice('switches', this.id, {s: true, _id: this.id})
      .then(
        (success) => next(),
        (failure) => {
          log("failure " + failure)
          next(failure)
        })
  } else {
    // turn switch off
    vivintApi.putDevice('switches', this.id, {s: false, _id: this.id})
      .then(
        (success) => next(),
        (failure) => {
          log("failure " + failure)
          next(failure)
        })
  }
}

notify() {
  if (this.service) {
    this.service.getCharacteristic(Characteristic.On)
      .updateValue(this.switchCurrentValue())
  }
}

}

extend(LightSwitch, { appliesTo: (data) => { return data.t == "binary_switch_device"}, addServices: (accessory) => { if (accessory.context.name.match(/\blight\b/i)) { accessory.addService(new Service.Lightbulb(accessory.context.name)) } else if (accessory.context.name.match(/\bfan\b/i)) { accessory.addService(new Service.Fan(accessory.context.name)) } else { accessory.addService(new Service.Switch(accessory.context.name)) } } })

// dimmer switch {s: true/false, val: 0-100} class DimmerSwitch extends Device { constructor(accessory) { super(accessory)

  this.service = accessory.getServiceByUUIDAndSubType(Service.Lightbulb)

  this.service
    .getCharacteristic(Characteristic.On)
    .on('get', (next) => next(null,this.switchCurrentValue()))
    .on('set', this.setSwitchCurrentValue.bind(this))

  this.service
    .getCharacteristic(Characteristic.Brightness)
    .on('get', (next) => next(null, this.switchBrightnessValue()))
    .on('set', this.setBrightnessValue.bind(this))
}

switchCurrentValue() {
  return this.data.s
}

setSwitchCurrentValue(targetState, next) {
  if (targetState) {
    // turn switch on
    vivintApi.putDevice('switches', this.id, {s: true, _id: this.id})
      .then(
        (success) => next(),
        (failure) => {
          log("failure " + failure)
          next(failure)
        })
  } else {
    // turn switch off
    vivintApi.putDevice('switches', this.id, {s: false, _id: this.id})
      .then(
        (success) => next(),
        (failure) => {
          log("failure " + failure)
          next(failure)
        })
  }
}

switchBrightnessValue() {
  return this.data.val
}

setBrightnessValue(targetState,next) {
  vivintApi.putDevice('switches', this.id, {val: targetState, _id: this.id})
    .then(
      (success) => next(),
      (failure) => {
        log("failure " + failure)
        next(failure)
      })
}

notify() {
  if (this.service) {
    if (this.data.val >= 0) {
      this.service
       .getCharacteristic(Characteristic.Brightness)
       .updateValue(this.data.val)
    }

    if (this.data.s == true || this.data.s == false) {
      this.service
        .getCharacteristic(Characteristic.On)
        .updateValue(this.data.s)
    }
    //this.service.getCharacteristic(Characteristic.On)
    //  .updateValue(this.switchCurrentValue())
  }
}

}

extend(DimmerSwitch, { appliesTo: (data) => { return data.t == "multilevel_switch_device"}, addServices: (accessory) => { //assuming this is a dimmer switch controlling a light accessory.addService(new Service.Lightbulb(accessory.context.name)) } })

mceres avatar Apr 26 '19 05:04 mceres

replace that last bit of code (the notify function):

notify() {
  if (this.service) {
    if (this.data.val >= 0) {
      this.service
       .getCharacteristic(Characteristic.Brightness)
       .updateValue(this.data.val)
    }

    if (this.data.s == true || this.data.s == false) {
      this.service
        .getCharacteristic(Characteristic.On)
        .updateValue(this.data.s)
    }
    //this.service.getCharacteristic(Characteristic.On)
    //  .updateValue(this.switchCurrentValue())
  }
}

with:

    notify() {
      if (this.service) {
        if (this.data.val >= 0) {
          this.service
           .getCharacteristic(Characteristic.Brightness)
           .updateValue(this.data.val)
        }

        if (this.data.s == true || this.data.s == false) {
          if (this.data.s == true && this.data.val == 0) this.service.getCharacteristic(Characteristic.On).updateValue(false)
          else {
            this.service
              .getCharacteristic(Characteristic.On)
              .updateValue(this.data.s)
          }
        }
        //this.service.getCharacteristic(Characteristic.On)
        //  .updateValue(this.switchCurrentValue())
      }
   }

daymondm avatar Apr 26 '19 05:04 daymondm

sorry I edited that last post hopefully before you saw it, I forgot a }, there should be two of them at the end after the two // lines

daymondm avatar Apr 26 '19 05:04 daymondm

i catch the edit... still behaving the same way.

mceres avatar Apr 26 '19 05:04 mceres

copy that, thanks for trying!

daymondm avatar Apr 26 '19 05:04 daymondm

if i turn on the light it goes to 100% -> off ->100%.... if i turn it off it seems to go to off and stays there

mceres avatar Apr 26 '19 05:04 mceres