Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot pair with thermostat, ip_camera, light_sensor, or video_doorbell accessories #11

Open
sbruton opened this issue Oct 12, 2018 · 7 comments
Labels
bug Something isn't working

Comments

@sbruton
Copy link

sbruton commented Oct 12, 2018

Pairing fails whenever a thermostat accessory is added.

To reproduce:

extern crate hap;

use hap::{
    accessory::{bridge, thermostat, Category, Information},
    transport::{IpTransport, Transport},
    Config,
};

fn main() {
    pretty_env_logger::init();
    let bridge = bridge::new(Information {
        name: "Bridge".into(),
        ..Default::default()
    })
    .unwrap();

    let thermostat = thermostat::new(Information {
        name: "Thermostat".into(),
        ..Default::default()
    })
    .unwrap();

    let config = Config {
        name: "Test".into(),
        category: Category::Bridge,
        ..Default::default()
    };

    let mut ip_transport = IpTransport::new(config).unwrap();
    ip_transport.add_accessory(bridge).unwrap();
    ip_transport.add_accessory(thermostat).unwrap();

    ip_transport.start().unwrap();
}

attempt to pair with code 11122333 fails with message "Home couldn't connect to this accessory". No errors are logged via the service.

changing the thermostat accessory to Outlet or Valve and pairing is successful.

@sbruton sbruton changed the title Cannot pair with thermostat accessory Cannot pair with thermostat, ip_camera, light_sensor, or video_doorbell accessories Oct 12, 2018
@sbruton
Copy link
Author

sbruton commented Oct 12, 2018

Looks like this behavior is also present with ip_camera, light_sensor, and video_doorbell. Uncommenting any of the add_accessory() lines below will result in failure to pair.

extern crate hap;

use hap::{
    accessory::{
        air_purifier, air_quality_sensor, bridge, carbon_dioxide_sensor, carbon_monoxide_sensor,
        contact_sensor, door, fan, fan_v2, garage_door_opener, heater_cooler,
        humidifier_dehumidifier, humidity_sensor, ip_camera, leak_sensor, light_sensor, lightbulb,
        lock, motion_sensor, occupancy_sensor, outlet, security_system, smoke_sensor,
        stateless_programmable_switch, switch, temperature_sensor, thermostat, valve,
        video_doorbell, window, window_covering, Category, Information,
    },
    transport::{IpTransport, Transport},
    Config, Error,
};

fn main() -> Result<(), Error> {
    let config = Config {
        name: "Test".into(),
        category: Category::Bridge,
        ..Default::default()
    };

    let mut ipt = IpTransport::new(config)?;

    ipt.add_accessory(air_purifier::new(Information::default())?)?;
    ipt.add_accessory(air_quality_sensor::new(Information::default())?)?;
    ipt.add_accessory(bridge::new(Information::default())?)?;
    ipt.add_accessory(carbon_dioxide_sensor::new(Information::default())?)?;
    ipt.add_accessory(carbon_monoxide_sensor::new(Information::default())?)?;
    ipt.add_accessory(contact_sensor::new(Information::default())?)?;
    ipt.add_accessory(door::new(Information::default())?)?;
    ipt.add_accessory(fan::new(Information::default())?)?;
    ipt.add_accessory(fan_v2::new(Information::default())?)?;
    ipt.add_accessory(garage_door_opener::new(Information::default())?)?;
    ipt.add_accessory(heater_cooler::new(Information::default())?)?;
    ipt.add_accessory(humidifier_dehumidifier::new(Information::default())?)?;
    ipt.add_accessory(humidity_sensor::new(Information::default())?)?;
    // ipt.add_accessory(ip_camera::new(Information::default())?)?;
    ipt.add_accessory(leak_sensor::new(Information::default())?)?;
    // ipt.add_accessory(light_sensor::new(Information::default())?)?;
    ipt.add_accessory(lightbulb::new(Information::default())?)?;
    ipt.add_accessory(lock::new(Information::default())?)?;
    ipt.add_accessory(motion_sensor::new(Information::default())?)?;
    ipt.add_accessory(occupancy_sensor::new(Information::default())?)?;
    ipt.add_accessory(outlet::new(Information::default())?)?;
    ipt.add_accessory(security_system::new(Information::default())?)?;
    ipt.add_accessory(smoke_sensor::new(Information::default())?)?;
    ipt.add_accessory(stateless_programmable_switch::new(Information::default())?)?;
    ipt.add_accessory(switch::new(Information::default())?)?;
    ipt.add_accessory(temperature_sensor::new(Information::default())?)?;
    // ipt.add_accessory(thermostat::new(Information::default())?)?;
    ipt.add_accessory(valve::new(Information::default())?)?;
    // ipt.add_accessory(video_doorbell::new(Information::default())?)?;
    ipt.add_accessory(window::new(Information::default())?)?;
    ipt.add_accessory(window_covering::new(Information::default())?)?;

    ipt.start()?;

    Ok(())
}

@sbruton
Copy link
Author

sbruton commented Oct 12, 2018

So far I've found that the service is getting to the /pair-verify - M4: Sending Verify Finish Response where it sends back the following response for the accessory w/ thermostat service:

{
   "accessories":[
      {
         "aid":1,
         "services":[
            {
               "iid":1,
               "type":"3E",
               "hidden":false,
               "primary":false,
               "characteristics":[
                  {
                     "iid":2,
                     "type":"14",
                     "format":"bool",
                     "perms":[
                        "pw"
                     ]
                  },
                  {
                     "iid":3,
                     "type":"20",
                     "format":"string",
                     "perms":[
                        "pr"
                     ],
                     "value":"undefined"
                  },
                  {
                     "iid":4,
                     "type":"21",
                     "format":"string",
                     "perms":[
                        "pr"
                     ],
                     "value":"undefined"
                  },
                  {
                     "iid":5,
                     "type":"23",
                     "format":"string",
                     "perms":[
                        "pr"
                     ],
                     "value":"undefined"
                  },
                  {
                     "iid":6,
                     "type":"30",
                     "format":"string",
                     "perms":[
                        "pr"
                     ],
                     "value":"undefined",
                     "maxLen":64
                  },
                  {
                     "iid":7,
                     "type":"52",
                     "format":"string",
                     "perms":[
                        "pr"
                     ],
                     "value":"undefined"
                  }
               ]
            },
            {
               "iid":8,
               "type":"4A",
               "hidden":false,
               "primary":true,
               "characteristics":[
                  {
                     "iid":9,
                     "type":"F",
                     "format":"uint8",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "value":0,
                     "valid-values":[
                        0,
                        1,
                        2
                     ]
                  },
                  {
                     "iid":10,
                     "type":"33",
                     "format":"uint8",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "value":0,
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ]
                  },
                  {
                     "iid":11,
                     "type":"11",
                     "format":"float",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "value":0.0,
                     "unit":"celsius",
                     "maxValue":100.0,
                     "minStep":0.1
                  },
                  {
                     "iid":12,
                     "type":"35",
                     "format":"float",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "value":0.0,
                     "unit":"celsius",
                     "maxValue":38.0,
                     "minValue":10.0,
                     "minStep":0.1
                  },
                  {
                     "iid":13,
                     "type":"36",
                     "format":"uint8",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "value":0,
                     "valid-values":[
                        0,
                        1
                     ]
                  }
               ]
            }
         ]
      }
   ]
}

immediately thereafter an unpairing request comes through, whereas a working pairing next queries characteristics

@ewilken
Copy link
Owner

ewilken commented Oct 14, 2018

Thanks a lot for testing & reporting! The unpairing request seems to be the the expected behaviour of an iOS controller getting an invalid accessories JSON, e.g. with required characteristics missing or forbidden characteristics included in an accessory. I will look into this.

@ewilken
Copy link
Owner

ewilken commented Oct 21, 2018

So this is a weird one.

I discovered a bug causing zeroes as characteristic min_values not to be rendered into the auto-generated characteristics, but fixing it didn't change anything about the thermostat and light sensor accessories being invalid. The invalidity of the IP camera and video doorbell is obvious, as video streams aren't implemented in this crate yet.

Currently, I'm generating the accessories, services and characteristics from the HomeKit Accessory Simulator from the Additional Tools for Xcode 10.1 Beta 3.

I will publish the fix for the min_values as soon as the upcoming version of handlebars-rs it depends on is published and keep investigating the invalidity of the two accessories, but unfortunately I don't have much time for it at the moment.

Thanks for your patience and feel free to contribute if you find out anything about this issue in the meantime.

@ewilken ewilken added the bug Something isn't working label Feb 21, 2020
@nusairat
Copy link

@ewilken Hey i was curious sine the above is over a year old, do you have video streams working yet? I see the use of CameraRTPStreamManagement but it's auto generated type. Just cant tell.

@soundprojects
Copy link
Contributor

In the example above, it at least looks like IID 12 should have a minimum value of 10.0 but has a value of 0.0
That doesn't look right

@soundprojects
Copy link
Contributor

Perhaps we should compare values with the values that the simulator sets on a 'fresh' set up of these accessories and that the default values should mimic them to an extent that they seem to have some influence on the pairing process?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants