GithubHelp home page GithubHelp logo

hap-rs's People

Contributors

ewilken avatar gaelan avatar jmhodges avatar laibulle avatar m1cha avatar messense avatar mzyy94 avatar roba1993 avatar simlay avatar soundprojects avatar voider1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hap-rs's Issues

proxy with hap?

I've been digging in, but is there a way to create a proxy with hap? I have a homekit-enabled device whose behavior I would like to change and enhance by having Siri talk to a hap-created device that proxies modified messages to the original.

The crate is not debuggable

The crate doesn't implement the Debug trait anywhere, which makes it very hard to actually debug the code.

IOS Home App not showing accessory details

When adding accessories to the Ios Home app, pressing the accessory with force or touch or clicking accessory details does not make anything happen. It is like the app is experiencing some error. It only happens with the services I add with hap-rs

For example here is my custom irrigation system code:

use hap::{
    accessory::{HapAccessory, AccessoryInformation},
    service::{
        accessory_information::AccessoryInformationService,
        humidity_sensor::HumiditySensorService,
        temperature_sensor::TemperatureSensorService,
        HapService, valve::ValveService,
    },
    HapType, characteristic::HapCharacteristic,
};

use serde::{
    ser::{SerializeStruct, Serializer},
    Serialize,
};
use serde_json::{Value, Number};

/// Multi Sensor accessory.
#[derive(Debug, Default)]
pub struct HydroponicAccessory {
    /// ID of the Multi Sensor accessory.
    id: u64,

    /// Accessory Information service.
    pub accessory_information: AccessoryInformationService,
    /// Temperature Sensor service.
    pub temperature_sensor: TemperatureSensorService,
    /// TDS Sensor service.
    pub tds_sensor: HumiditySensorService,
    /// Valve service
    pub valve: ValveService
}

impl HydroponicAccessory{
    pub fn new(id: u64, acc_info: AccessoryInformation) -> Self{

        let mut hydroponic = HydroponicAccessory {
            id,
            accessory_information: acc_info.to_service(1,1).expect("Failed to create service"),
            // accessory information service ends at IID 6, so we start counting at 7
            temperature_sensor: TemperatureSensorService::new(7, 1),
            // teperature sensor service ends at IID 13, so we start counting at 14
            tds_sensor: HumiditySensorService::new(14, 1),
            // humidity sensor service ends at IID 20, so we start counting at 21
            valve: ValveService::new(21, 1)
        };

        hydroponic.valve.set_primary(true);
        hydroponic.valve.active.set_value(Value::Number(Number::from(1)));
        
        if let Some(ref mut act)  = hydroponic.temperature_sensor.status_active{
            act.set_value(Value::Number(Number::from(1)));
        }

        if let Some(ref mut act)  = hydroponic.tds_sensor.status_active{
            act.set_value(Value::Number(Number::from(1)));
        }

        hydroponic
    }
}

impl HapAccessory for HydroponicAccessory {

    fn get_id(&self) -> u64 { self.id }

    fn set_id(&mut self, id: u64) { self.id = id; }

    fn get_service(&self, hap_type: HapType) -> Option<&dyn HapService> {
        for service in self.get_services() {
            if service.get_type() == hap_type {
                return Some(service);
            }
        }
        None
    }

    fn get_mut_service(&mut self, hap_type: HapType) -> Option<&mut dyn HapService> {
        for service in self.get_mut_services() {
            if service.get_type() == hap_type {
                return Some(service);
            }
        }
        None
    }

    fn get_services(&self) -> Vec<&dyn HapService> {
        vec![
            &self.accessory_information,
            &self.temperature_sensor,
            &self.tds_sensor,
            &self.valve
        ]
    }

    fn get_mut_services(&mut self) -> Vec<&mut dyn HapService> {
        vec![
            &mut self.accessory_information,
            &mut self.temperature_sensor,
            &mut self.tds_sensor,
            &mut self.valve
        ]
    }
}

impl Serialize for HydroponicAccessory {
    fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
        let mut state = serializer.serialize_struct("HapAccessory", 2)?;
        state.serialize_field("aid", &self.get_id())?;
        state.serialize_field("services", &self.get_services())?;
        state.end()
    }
}

It connects properly but the valve is absent from the configuration and pressing the accessory to show its details does not do anything at all.

What would be a good starting point to look into this? The dnssd seems to work properly. Debug shows that TCP streams are setup. How can you verify that what the service needs to send as configuration is what the ios app is expecting?

Thanks

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

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.

Bridge is not pairing with multiple accessories

Hi,

the pairing is not working when in the config a bridge (or lightbulb) is defined and multiple accessories are added.
Do you have an idea where this needs to be addressed in the code?

Thanks,
Robert

Evaluate using `HomeKitDaemon.framework` for codegen

Extensive definitions of HomeKit categories, services and characteristics can be found in the /System/Library/PrivateFrameworks/HomeKitDaemon.framework/Resources/plain-metadata.config file on macOS. That file might be better suited for codegen than the stale simulator app definitions currently used.

Implement accessories for missing categories

There are some accessory categories that aren't covered by this crate yet:

  • Audio Receiver
  • AirPort
  • Apple TV
  • HomePod
  • IP Camera
  • Target Control
  • Television Set Top Box
  • Television Streaming Stick
  • Video Doorbell
  • Wi-Fi Router
  • Wi-Fi Satellite

Some of them might be impossible, but some of them might be worth looking into.

IP Camera and Video Doorbell are currently blocked by #47.

Multiple instances with same service

When trying to run the same code on two different clients, they both fight over the same name
Shouldn't hap-rs rename the service to 'service (1)' and so on?

And should this also mean that the c# number should be incremented when adding the second service? Now they have the same id's?

Rustling issue with the examples

Hey all! I am a rust beginner. I've been thru rustlings, and feel like I've got a small bit figured out. So, of course, one then jumps into the deep end.

I don't understand how the examples are supposed to work. I've setup a new project, and listed hap = "0.0.10" in my cargo.toml, but when I try to use one of the examples as my main program, it fails to compile at all. (Example in question: https://github.com/ewilken/hap-rs/blob/master/examples/lightbulb.rs)

➜ cargo build
   Compiling virtual_hap v0.1.0 (/home/anoldguy/code/virtual_hap)
error[E0432]: unresolved imports `hap::accessory::lightbulb::LightbulbAccessory`, `hap::accessory::AccessoryCategory`, `hap::server`, `hap::storage`, `hap::tokio`, `hap::MacAddress`, `hap::Pin`
  --> src/main.rs:4:17
   |
4  |     accessory::{lightbulb::LightbulbAccessory, AccessoryCategory, AccessoryInformation},
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^ no `AccessoryCategory` in `accessory`
   |                 |
   |                 no `LightbulbAccessory` in `accessory::lightbulb`
5  |     server::{IpServer, Server},
   |     ^^^^^^ could not find `server` in `hap`
6  |     storage::{FileStorage, Storage},
   |     ^^^^^^^ could not find `storage` in `hap`
7  |     tokio,
   |     ^^^^^ no `tokio` in the root
8  |     Config,
9  |     MacAddress,
   |     ^^^^^^^^^^ no `MacAddress` in the root
10 |     Pin,
   |     ^^^
   |     |
   |     no `Pin` in the root
   |     help: a similar name exists in the module: `pin`

error[E0433]: failed to resolve: use of undeclared type or module `pnet`
  --> src/main.rs:16:22
   |
16 |         for iface in pnet::datalink::interfaces() {
   |                      ^^^^ use of undeclared type or module `pnet`

error[E0433]: failed to resolve: use of undeclared type or module `env_logger`
  --> src/main.rs:59:5
   |
59 |     env_logger::init();
   |     ^^^^^^^^^^ use of undeclared type or module `env_logger`

error[E0603]: type alias `AccessoryInformation` is private
 --> src/main.rs:4:67
  |
4 |     accessory::{lightbulb::LightbulbAccessory, AccessoryCategory, AccessoryInformation},
  |                                                                   ^^^^^^^^^^^^^^^^^^^^ private type alias
  |
note: the type alias `AccessoryInformation` is defined here
 --> /home/anoldguy/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.10/src/accessory/mod.rs:8:39
  |
8 |         accessory_information::{self, AccessoryInformation},
  |                                       ^^^^^^^^^^^^^^^^^^^^

error[E0560]: struct `hap::config::Config` has no field named `socket_addr`
  --> src/main.rs:41:17
   |
41 |                 socket_addr: SocketAddr::new(current_ipv4().unwrap(), 32000),
   |                 ^^^^^^^^^^^ `hap::config::Config` does not have this field
   |
   = note: available fields are: `storage_path`, `ip`, `port`, `pin`, `name` ... and 10 others

error[E0277]: `main` has invalid return type `impl std::future::Future`
  --> src/main.rs:14:17
   |
14 | async fn main() {
   |                 ^ `main` can only return types that implement `std::process::Termination`
   |
   = help: consider using `()`, or a `Result`

error[E0752]: `main` function is not allowed to be `async`
  --> src/main.rs:14:1
   |
14 | async fn main() {
   | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`

error: aborting due to 7 previous errors

Some errors have detailed explanations: E0277, E0432, E0433, E0560, E0603, E0752.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `virtual_hap`.

I clearly need to understand more of rust's basics before diving in, but I don't even know where to start. For example, the last error error[E0752]: mainfunction is not allowed to beasync`` indicates that I'm supposed to be calling these from some larger parent program, I think?

Are these examples supposed to run out of the box? My goal was to expose a virtual garage door so I could test some logic, but I'm completely out of my depth here.

I also realize this isn't your issue, but maybe just a plea to include a full example somewhere to help make things easier for folks new to rust?

Feel free to close this if it's not inline with your project goals or time constraints!

thread 'main' panicked at 'couldn't send event response: ()'

This seems to happen in response to an accessory being removed and re-added.

reproduce

  1. Add Outlet accessory (paired successfully)
  2. Remove Outlet accessory
  3. Re-add same Outlet accessory (paired successfully)
  4. Return to Home app accessory list
  5. Panic

test code

(mostly taken straight out of the hap-rs docs)

extern crate hap;
extern crate failure;

use failure::Error;

use hap::{
    transport::{Transport, IpTransport},
    accessory::{Category, Information, outlet},
    characteristic::{Readable, Updatable},
    Config,
    HapType,
};

#[derive(Debug, Clone)]
pub struct VirtualOutlet {
    on: bool,
}


impl Readable<bool> for VirtualOutlet {
    fn on_read(&mut self, _: HapType) -> Option<bool> {
        println!("On read.");
        Some(self.on)
    }
}

impl Updatable<bool> for VirtualOutlet {
    fn on_update(&mut self, old_val: &bool, new_val: &bool, _: HapType) {
        println!("On updated from {} to {}.", old_val, new_val);
        if new_val != old_val { self.on = new_val.clone(); }
    }
}


fn main() -> Result<(), Error> {
    let info = Information {
        name: "Outlet".into(),
        ..Default::default()
    };

    let mut outlet = outlet::new(info).unwrap();

    let virtual_outlet = VirtualOutlet { on: false };
    outlet.inner.outlet.inner.on.set_readable(virtual_outlet.clone()).unwrap();
    outlet.inner.outlet.inner.on.set_updatable(virtual_outlet).unwrap();

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

    let mut ip_transport = IpTransport::new(config).unwrap();
    ip_transport.add_accessory(outlet).unwrap();
    ip_transport.start().unwrap();

    Ok(())
}

backtrace

$ RUST_BACKTRACE=1 cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.25s
     Running `target/debug/hap-fun`
On read.
On updated from false to false.
On updated from false to true.
On updated from true to false.
On updated from false to true.
On read.
On updated from true to false.
On read.
On updated from false to false.
On updated from false to true.
thread 'main' panicked at 'couldn't send event response: ()', libcore/result.rs:945:5
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:211
   3: std::panicking::default_hook
             at libstd/panicking.rs:227
   4: <std::panicking::begin_panic::PanicPayload<A> as core::panic::BoxMeUp>::get
             at libstd/panicking.rs:511
   5: std::panicking::continue_panic_fmt
             at libstd/panicking.rs:426
   6: std::panicking::try::do_call
             at libstd/panicking.rs:337
   7: <T as core::any::Any>::get_type_id
             at libcore/panicking.rs:92
   8: tokio_threadpool::worker::entry::WorkerEntry::set_next_sleeper
             at /Users/travis/build/rust-lang/rust/src/libcore/macros.rs:26
   9: std::thread::panicking
             at /Users/travis/build/rust-lang/rust/src/libcore/result.rs:809
  10: hap::transport::http::server::serve::{{closure}}::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/transport/http/server.rs:224
  11: hap::pin::new
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/event.rs:26
  12: core::alloc::Layout::align
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/characteristic/mod.rs:150
  13: core::alloc::Layout::align
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/characteristic/mod.rs:364
  14: hap::db::accessory_list::AccessoryList::write_characteristic
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/db/accessory_list.rs:162
  15: hap::transport::http::handlers::characteristics::UpdateCharacteristics::new
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/transport/http/handlers/characteristics.rs:151
  16: hap::transport::http::server::serve::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/transport/http/handlers/mod.rs:112
  17: <hap::transport::http::server::Api as tokio_service::Service>::call::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/transport/http/server.rs:163
  18: <hap::characteristic::Format as core::cmp::PartialEq>::eq
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/future/and_then.rs:34
  19: std::thread::panicking
             at /Users/travis/build/rust-lang/rust/src/libcore/result.rs:468
  20: <hap::characteristic::Format as core::cmp::PartialEq>::eq
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/future/and_then.rs:33
  21: <hyper::method::Method as core::clone::Clone>::clone
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/future/chain.rs:39
  22: <hap::characteristic::Format as core::cmp::PartialEq>::eq
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/future/and_then.rs:32
  23: <core::cmp::Ordering as core::cmp::PartialEq>::eq
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/future/mod.rs:113
  24: <hap::db::accessory_list::AccessoryList as core::clone::Clone>::clone
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.11.27/src/proto/h1/dispatch.rs:343
  25: <hyper::header::raw::RawLines<'a> as core::iter::iterator::Iterator>::next
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.11.27/src/proto/h1/dispatch.rs:230
  26: <hyper::header::raw::RawLines<'a> as core::iter::iterator::Iterator>::next
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.11.27/src/proto/h1/dispatch.rs:97
  27: <hyper::header::raw::RawLines<'a> as core::iter::iterator::Iterator>::next
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.11.27/src/proto/h1/dispatch.rs:85
  28: <hyper::header::raw::RawLines<'a> as core::iter::iterator::Iterator>::next
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.11.27/src/proto/h1/dispatch.rs:73
  29: <hap::db::accessory_list::AccessoryList as core::clone::Clone>::clone
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.11.27/src/proto/h1/dispatch.rs:316
  30: futures::task_impl::core::get_ptr
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.11.27/src/server/conn.rs:112
  31: <hyper::header::raw::RawLines<'a> as core::iter::iterator::Iterator>::next
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/future/map_err.rs:30
  32: futures::task_impl::core::get_ptr
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/future/map.rs:30
  33: <std::time::Instant as core::cmp::PartialOrd>::gt
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/future/mod.rs:113
  34: tokio_current_thread::CURRENT::__init
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/task_impl/mod.rs:289
  35: tokio_current_thread::CURRENT::__init
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/task_impl/mod.rs:363
  36: futures::task_impl::std::BorrowedUnpark::new
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/task_impl/std/mod.rs:78
  37: tokio_current_thread::CURRENT::__init
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/task_impl/mod.rs:363
  38: tokio_current_thread::CURRENT::__init
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/task_impl/mod.rs:289
  39: <core::cell::BorrowRefMut<'b> as core::ops::drop::Drop>::drop
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/scheduler.rs:353
  40: <core::cell::BorrowRefMut<'b> as core::ops::drop::Drop>::drop
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/scheduler.rs:332
  41: core::sync::atomic::fence
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/lib.rs:747
  42: tokio_core::reactor::CURRENT_LOOP::FOO::__getit
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/lib.rs:783
  43: core::sync::atomic::fence
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/lib.rs:746
  44: futures::task_impl::core::get_ptr
             at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:294
  45: futures::task_impl::core::get_ptr
             at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:248
  46: core::sync::atomic::fence
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/lib.rs:745
  47: <core::cell::BorrowRefMut<'b> as core::ops::drop::Drop>::drop
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/scheduler.rs:332
  48: core::sync::atomic::fence
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/lib.rs:591
  49: core::sync::atomic::fence
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-current-thread-0.1.1/src/lib.rs:517
  50: tokio_core::reactor::Core::poll::{{closure}}::{{closure}}::{{closure}}::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.17/src/reactor/mod.rs:298
  51: <libmdns::dns_parser::enums::QueryClass as core::cmp::PartialEq>::eq
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/scoped-tls-0.1.2/src/lib.rs:155
  52: tokio_core::reactor::Core::poll::{{closure}}::{{closure}}::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.17/src/reactor/mod.rs:297
  53: tokio_core::net::udp::UdpSocket::poll_read::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-timer-0.2.6/src/timer/handle.rs:94
  54: futures::task_impl::core::get_ptr
             at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:294
  55: futures::task_impl::core::get_ptr
             at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:248
  56: tokio_core::net::udp::UdpSocket::poll_read::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-timer-0.2.6/src/timer/handle.rs:81
  57: tokio_core::reactor::Core::poll::{{closure}}::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.17/src/reactor/mod.rs:275
  58: core::num::<impl usize>::overflowing_add
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-executor-0.1.4/src/global.rs:173
  59: futures::task_impl::core::get_ptr
             at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:294
  60: futures::task_impl::core::get_ptr
             at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:248
  61: core::num::<impl usize>::overflowing_add
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-executor-0.1.4/src/global.rs:143
  62: tokio_core::reactor::Core::poll::{{closure}}
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.17/src/reactor/mod.rs:274
  63: tokio_timer::timer::handle::CURRENT_TIMER::__init
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-reactor-0.1.5/src/lib.rs:232
  64: futures::task_impl::core::get_ptr
             at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:294
  65: futures::task_impl::core::get_ptr
             at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:248
  66: tokio_timer::timer::handle::CURRENT_TIMER::__init
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-reactor-0.1.5/src/lib.rs:215
  67: <core::cmp::Ordering as core::cmp::PartialEq>::eq
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.17/src/reactor/mod.rs:273
  68: <alloc::vec::SetLenOnDrop<'a> as core::ops::drop::Drop>::drop
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.17/src/reactor/mod.rs:248
  69: hap::transport::http::server::serve
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/transport/http/server.rs:238
  70: hap::transport::http::handlers::characteristics::UpdateCharacteristics::new
             at /Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hap-0.0.2/src/transport/ip.rs:150
  71: hap_fun::main
             at src/main.rs:55
  72: std::rt::lang_start::{{closure}}
             at /Users/travis/build/rust-lang/rust/src/libstd/rt.rs:74
  73: std::panicking::try::do_call
             at libstd/rt.rs:59
             at libstd/panicking.rs:310
  74: panic_unwind::dwarf::eh::read_encoded_pointer
             at libpanic_unwind/lib.rs:105
  75: std::sys_common::at_exit_imp::push
             at libstd/panicking.rs:289
             at libstd/panic.rs:392
             at libstd/rt.rs:58
  76: std::rt::lang_start
             at /Users/travis/build/rust-lang/rust/src/libstd/rt.rs:74
  77: <hap_fun::VirtualOutlet as core::clone::Clone>::clone

Add accessory from other threads.

Hi,

I am a Rust beginner and want to use Rust to implement a HomeKit to MQTT bridge. Currently, I want to receive a list of devices in JSON format from MQTT broker and create accessories accordingly. But I am struggling to get it done.

The MQTT client is running on a separate thread, so it cannot mutate the IpTransport struct. I tried with Mutex like this

let mut ip_transport = Arc::new(Mutex::new(IpTransport::new(config).unwrap()));

and run the event loop by using this command

ip_transport.lock().unwrap().start().unwrap();

But the command never release the mutex and doesn't led me add a new accessory. Note that, I added an accessory by using this command:

transport_clone.lock().unwrap().add_accessory(sw).unwrap();

I tried channels but I don't have any idea about how to receive from a channel continuously without spawning a new Thread.

Could you give me any advice to get what I want? Thank you so much.

Bump Tokio to 1.0

Tokio released v1.0 recently and lots of libraries have switched to it. I'm trying to use this with a different library that uses Tokio 1.0 already and that obviously doesn't work.

Can we bump Tokio?

Thanks

Update examples to properly reflect target states

Some services have current and target versions of characteristics. Controller set the target value and expect the current value to update accordingly. Otherwise the controller might assume the accessory being unresponsive.

With this implementation, this behavior has to be implemented explicitly by a consumer of the library:

  1. Set an on_update callback to the target value.
  2. In it, update the current value to the target value the controller expects.

Accessory examples that might need this treatment:

  • Cooler
  • Dehumidifier
  • Door
  • Faucet
  • Heater
  • Humidifier
  • Irrigation System
  • Lock
  • Security System
  • Shower Head
  • Smart Speaker
  • Window Covering
  • Window

Raspbian speed

Hi

Did you get this managed to work on a fresh raspbian installation on a pi 3?
I am running one of your examples but there is much lag in the responses when pairing it seems, both in debug and release...

Any ideas?

could not compile pnet_packet

Thank you for this nice lib ❤️
Unfortunately I have problems getting it to work:

➜  hapfoo git:(master) ✗ cargo run
   Compiling hap v0.0.9
   Compiling pnet_packet v0.22.0
error[E0599]: no method named `to_primitive_values` found for type `pnet_base::MacAddr` in the current scope
   --> /Users/kofi/innoq/hapfoo/target/debug/build/pnet_packet-e7d624a3a67e0e17/out/ethernet.rs:442:24
    |
442 |         let vals = val.to_primitive_values();
    |                        ^^^^^^^^^^^^^^^^^^^ method not found in `pnet_base::MacAddr`

error[E0599]: no method named `to_primitive_values` found for type `pnet_base::MacAddr` in the current scope
   --> /Users/kofi/innoq/hapfoo/target/debug/build/pnet_packet-e7d624a3a67e0e17/out/ethernet.rs:499:24
    |
499 |         let vals = val.to_primitive_values();
    |                        ^^^^^^^^^^^^^^^^^^^ method not found in `pnet_base::MacAddr`

error[E0599]: no method named `to_primitive_values` found for type `pnet_base::MacAddr` in the current scope
   --> /Users/kofi/innoq/hapfoo/target/debug/build/pnet_packet-e7d624a3a67e0e17/out/arp.rs:776:24
    |
776 |         let vals = val.to_primitive_values();
    |                        ^^^^^^^^^^^^^^^^^^^ method not found in `pnet_base::MacAddr`

error[E0599]: no method named `to_primitive_values` found for type `pnet_base::MacAddr` in the current scope
   --> /Users/kofi/innoq/hapfoo/target/debug/build/pnet_packet-e7d624a3a67e0e17/out/arp.rs:874:24
    |
874 |         let vals = val.to_primitive_values();
    |                        ^^^^^^^^^^^^^^^^^^^ method not found in `pnet_base::MacAddr`

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0599`.
error: could not compile `pnet_packet`.
warning: build failed, waiting for other jobs to finish...
error: build failed

I tried with hap v0.0.9:
rustc 1.40.0 (73528e339 2019-12-16) on macOS and
rustc 1.39.0 (4560ea788 2019-11-04) on arm

no_std support

Would be amazing to be able to use this on embedded devices, for that we need no_std support though.

State of the project

Hello,

I am quite interested in your HAP implementation for my home automation server. But for now, I know nothing about HAP and I am quite a newbie with Rust.

So before spending a lot of time understanding the behaviour of the the protocol, I would like to know if your library is at least partially functional. Do you have some sample code to help people using the library?

Thanks a lot for your work.

Help with setting values on characteristics

Hello!

I'm having trouble conceptualizing how to code up an accessory like a contact sensor, where I'm tracking a value and pushing updates on its current status "out to homekit". I'm guessing example in the current readme of "Setting a characteristic value directly" is more for pre-setup and not what I should be trying to build around. What I'm seeing is that add_accessory takes ownership and returns a pointer, so I can't store or access the actual service & characteristic directly anymore like the example.

An alternative I see is to handle my own shared state somewhere else and use an on_read callback to update the Homekit state when its actually attempting to be read. Is this how Homekit should be operating? I'm definitely just poking around and not fully sure, but in my tests this only triggers when I'm actively using the Home app and it is reading data.

I was expecting that set_value would be "sending out" status update messages to the system so they could be triggering notifications, automations, etc. The other idea I had but haven't followed through with yet is trying to use the pointer::Acessory returned from add_accessory to try and get to the characteristic to set values on it. Is that what I'm supposed to be doing? If so I can figure that out and propose a readme addition for it, just looking for some guidance.

The example I've been trying to write is a door using a tokio interval to simulate being opened/closed every 10s, just to figure out how push state in to the system and watch those notifications from my phone.

make API easier to use with concurrent programs

Hi, I'm trying to implement some code that'd execute on each characteristic update, but unfortunately it's quite complicated to use .on_update(...) right now,

Here's my code:
Screenshot 2021-12-28 at 22 29 02

and unfortunately it won't compile because closure might outlive current function.

is there some approach that you use in this case?

maybe it'd be easier to expose some channels such as mpsc or broadcast from tokio crate?

FnMut instead of Fn for on_update_async

Is it possible for the on_update_async() function of characteristics to allow for functions that can change a variable outside of the function? I am currently trying to use these functions to change something when a characteristic changes but because it is Fn it doesn't allow me to 🙂

Struggling get demo to work.

Hi,

im quite new to rust & homexit so apologies in advance if this is something obvious but id really appreciate any pointers / help.

Im trying to get the demo code working between my map & my phone. However when trying to add the device, after adding the PIN the home iOS app just hangs with a spinner.

ive managed to enable logging and this is what i get

[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::io] read 0 bytes
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::conn] read eof
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::io] read 161 bytes
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::io] parsed 3 headers
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::conn] incoming body is content-length (37 bytes)
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::conn] incoming body completed
[2019-06-26T12:09:27Z DEBUG hap::transport::http::handler::pair_verify] M1: Got Verify Start Request
[2019-06-26T12:09:27Z DEBUG hap::transport::http::handler::pair_verify] M2: Sending Verify Start Response
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::io] flushed 117 bytes
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::io] flushed 140 bytes
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::io] read 250 bytes
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::io] parsed 3 headers
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::conn] incoming body is content-length (125 bytes)
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::conn] incoming body completed
[2019-06-26T12:09:27Z DEBUG hap::transport::http::handler::pair_verify] M3: Got Verify Finish Request
[2019-06-26T12:09:27Z DEBUG hap::transport::http::handler::pair_verify] M4: Sending Verify Finish Response
[2019-06-26T12:09:27Z DEBUG hyper::proto::h1::io] flushed 118 bytes

It seems like maybe something in the M4 step isn't working correctly maybe?? Im unsure how to debug from this point onward.

also the program I'm trying to get working

#[macro_use] extern crate log;
extern crate env_logger;
use env_logger::Env;
use hap::{
    transport::{Transport, IpTransport},
    accessory::{Category, Information, outlet},
    characteristic::{Readable, Updatable},
    Config,
    HapType,
};

use log::Level;

#[derive(Clone)]
pub struct VirtualOutlet {
    on: bool,
}

impl Readable<bool> for VirtualOutlet {
    fn on_read(&mut self, _: HapType) -> Option<bool> {
        println!("On read.");
        Some(self.on)
    }
}

impl Updatable<bool> for VirtualOutlet {
    fn on_update(&mut self, old_val: &bool, new_val: &bool, _: HapType) {
        println!("On updated from {} to {}.", old_val, new_val);
        if new_val != old_val { self.on = *new_val; }
    }
}

fn main() {
    env_logger::from_env(Env::default().default_filter_or("hap=debug,tokio=warn")).init();

    debug!("this is a debug {}", "message");

    let info = Information {
        name: "My Plug".into(),
        ..Default::default()
    };

    let mut outlet = outlet::new(info).unwrap();

    let virtual_outlet = VirtualOutlet { on: false };
    outlet.inner.outlet.inner.on.set_readable(virtual_outlet.clone()).unwrap();
    outlet.inner.outlet.inner.on.set_updatable(virtual_outlet).unwrap();

    let config = Config {
        name: "My Plug".into(),
        category: Category::Outlet,
        ..Default::default()
    };

    let mut ip_transport = IpTransport::new(config).unwrap();
    ip_transport.add_accessory(outlet).unwrap();
    ip_transport.start().unwrap();
}

IOS Home App does not see accessories any longer

Running hap-rs with a sprinkler accessory added

Things worked instantly the first time but after deletion the accessory does not show up when pressing 'Add Accessory' in the IOS home app

when running dns-sd command in the terminal and running Discovery bonjour application all the services show up perfectly

I resetted the whole homekit home and added all the accessories back but still the hap-rs ones do not show up.

Illegal Double declaration

in the file "src/characteristic/mod.rs" there is an double declaration of Deserialize. Somehow this compiles for me on Rust version 1.35. But this shouldn't be legal at all as far as I know.

Bug in FileStorage

FileStorage has a bug: when overwriting an existing file with a shorter string, it fails to truncate the end, resulting in config.json looking something like this:

{"socket_addr":"10.0.1.25:32000","pin":{"pin":[3,1,4,1,5,9,2,6]},"name":"Patio Heater","device_id":"30-18-31-41-00-00","device_ed25519_keypair":[245,41,240,83,254,253,1,8,2,237,61,117,97,67,53,117,130,70,148,135,56,158,9,132,174,48,147,103,59,160,244,236,179,231,26,227,82,107,115,144,30,112,96,96,109,12,248,103,4,78,110,151,220,84,35,18,171,88,25,37,63,42,131,254],"configuration_number":2,"state_number":1,"category":"Heater","protocol_version":"1.0","status_flag":"NotPaired","feature_flag":"Zero","max_peers":null}ers":null}

(note the end)

The issue is here:

let file = fs::OpenOptions::new().write(true).create(true).open(file_path)?;

You need to add .truncate(true).

cannot discover on network

I cannot discover any homekit accessories using the homekit app on my iphone. Have tried with my prototype app as well as running the example as cargo run --example bridged_accessories. I have tried with the default pin of 11122333 as well as a custom pin set in the Config struct.

Have tried with the firewall disabled on my iMac and confirmed that iPhone and iMac are both on the same wireless network and can otherwise communicate between each other. I see MDNS queries come through via Wireshark on the iMac, though I don't see any responses from the app going out.

Not sure if there's anything else that needs to be done to make the accessory discoverable, beyond the example code.

Status of this crate

Hey 👋🏻

As there is no action since mid last year, do you plan on maintaining this crate?

No Response from accessory after restart

Example: television

I was able to add Acme TV accessory in the Home app and I can see its status. However, if I restart the example, the Home app displays a No Response from the accessory. Is it possible to keep track of the accessories between application restart ?

Value Type check for Characteristics

I think it would be good to have a value type check for characteristics in some way

Now a characteristic value only has to be of a Json Value type but that does allow the user to set a bool where the specification excepts a number, resulting in a panic

Can't build pnet_packet dependency

When building hap = "0.0.3" (and version from git master too) on MacOS, one of dependencies can't be built, with following error:

   Compiling pnet_packet v0.21.0
error[E0599]: no method named `to_primitive_values` found for type `pnet_base::MacAddr` in the current scope
   --> /Users/kolen/items/pm_sensor/logging_node/target/debug/build/pnet_packet-3048cc3df534cf77/out/ethernet.rs:442:24
    |
442 |         let vals = val.to_primitive_values();
    |                        ^^^^^^^^^^^^^^^^^^^

Related issue in pnet: libpnet/libpnet#361

Updating pnet dependency version to 0.22.0 (from 0.21.0) fixes it. It builds and basic example from readme works (tried connecting with phone). Not thoroughly tested, however.

Tokio 1

Hello. Sorry to bother you. Just wanted to ask if there are any plans to switch to Tokyo 1 in the near future?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.