ewilken / hap-rs Goto Github PK
View Code? Open in Web Editor NEWRust implementation of the Apple HomeKit Accessory Protocol (HAP)
License: Apache License 2.0
Rust implementation of the Apple HomeKit Accessory Protocol (HAP)
License: Apache License 2.0
Would be amazing to be able to use this on embedded devices, for that we need no_std support though.
In our house, we have many devices that can function as HomeKit controllers—several Macs, several iPhones, and an Apple TV. When hap-rs comes online, they all try to open persistent TCP connections. Unfortunately, HttpServer
seems to only process one connection at a time, so all but one of these devices fails to communicate with the accessory.
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.
This could be useful to e.g. persist accessory state data that lives outside of HomeKit next to the HomeKit data.
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.
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
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.
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:
on_update
callback to the target
value.current
value to the target
value the controller expects.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.
you can find that here
https://github.com/ewilken/hap-rs/blob/main/src/service/generated/battery.rs#L34-L37
There are some accessory categories that aren't covered by this crate yet:
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.
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
Hey,
the WindowCoverings
have no functions/events to be used when something is changing with these devices.
Could you add these kind of support?
Thanks,
Robert
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.
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 ?
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.
The crate doesn't implement the Debug
trait anywhere, which makes it very hard to actually debug the code.
A lot of the doc comments are missing or outdated. We're gonna have to revisit them.
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 be
async`` 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!
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.
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
Hey 👋🏻
As there is no action since mid last year, do you plan on maintaining this crate?
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:
hap-rs/src/storage/file_storage.rs
Line 68 in 596e70b
You need to add .truncate(true)
.
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.
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();
}
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.
Hello. Sorry to bother you. Just wanted to ask if there are any plans to switch to Tokyo 1 in the near future?
We need to validate it being possible with the currently exported API and add an example for it.
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
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 🙂
Currently, all optional characteristics default to None
on the accessories emitted by the codegen
. We should evaluate defaulting to Some
.
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
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.
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,
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?
Looks like doc.rs had a build error while creating the docs for the new 0.0.10.
https://docs.rs/crate/hap/0.0.10/builds/223151
Not sure what the deal is
This seems to happen in response to an accessory being removed and re-added.
(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(())
}
$ 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
I found generated characteristics for hue, saturation and brightness, but couldn't find examples on how to use that.
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?
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.