fxbox / foxbox Goto Github PK
View Code? Open in Web Editor NEWThe FoxBox daemon
License: Mozilla Public License 2.0
The FoxBox daemon
License: Mozilla Public License 2.0
Changing one single unit test takes about 30s to compile and execute; even if you changed a simple assertion.
Split FoxBox into many small crates.
Reason: As infered above, FoxBox lives in a single crate. If one line changes (test included), the whole crate is recompiled, no matter if file is a deep dependency or not. A crate is a compilation unit. This means every module is merged within 1 file before being compiled. You can see the generated file by adding -Z unstable-options --pretty expanded
to the rustc command line. As a consequence and if I understood correctly, you can only use multi-threading to compile the dependency of a crate, and not the crate itself.
rustc
has gotten a perf regression for about a year: rust-lang/rust#25069 . There has been no activity on this bug for the last 8 months, though.
Here below, the default steps are:
cargo test
)assert!(true)
)time cargo test
Comment out all the tests but one. That one should be simple, and redo the process detailed above. After 5 tries, the average time decreased from 30s to ±27s.
Take the simple test you had in the previous part. Transform it to use the standard way of define tests. E.g.:
#[test]
fn my_test() {
assert!(true);
}
As a consequence, the time remains about the same as in the part above.
time cargo test -j4
takes the same time as if -j1
was used. After looking up, 1 crate is compiled in 1 thread.
Fast way: Checkout this branch.
Longer way:
src/main.rs
to src/lib.rs
tests/foo.rs
foxbox
as an extern crate and use it in a simple test.For each test defined under tests/
, a new binary is create. Then, cargo can use more than 1 thread. I'm not sure if this speeds up the compilation. Like said above, the compiler crashed the first time. When it happens, I remain at something around 24s.
I just wanted to voice a concern about using features that require us to use nightly Rust. I'd prefer us to only use features available in stable Rust so we can make cutting releases easy and not end up in a situation where we have to refactor (backwards).
For example in #29 we chose to use the docopt!
macro when we could've just kept the original semantics and got the same functionality.
It's not only the docopt!
macro. There are features in the serde_json
crate too IIRC. I was planning to remove serde_json
and use rustc_serialize::json
instead.
Now that a lot of us are adding code I think we should be aware and agree how best to handle this, even if that decision is to keep nightly Rust.
Thoughts?
We'll need to:
Not necessarily in this order.
Developing here: https://github.com/michielbdejong/foxbox/tree/add-selenium
To get started with the "Discovering the Foxbox (includes setup app to foxbox)", I will try to implement the following super-basic and non-secure FTU flow:
To do:
registration::get_ip_addr() doesn't support IPv6
Because it only get the IPv4 address.
Also get_if_addrs() doesn't support interfaces with two addresses....
Currently the pairing token is generated from unique but ultimately predictable data.
In #58 we added the client side to connect to the registry service to allow discovery.
In the case of multiple interfaces connected to internet (weird but possible specially if we are in a rpi2), we should provide a way to hook the discovery of the ip to a selected interface specified by the user via command line parameters.
The Foxbox is supposed to run for several years. So we need to survive crashes – and fix them.
This means:
This bug will probably be split in sub-bugs once we have a clearer idea how to do both.
Currently user management, router/controller, and adapters each have their own error response format. Let's move all of them to https://github.com/fxbox/users/blob/master/doc/API.md#response-format which is already employed by user management.
From #36 (comment):
About the foxbox.local name setting, it should be set by the daemon itself to reflect the --name command line argument. We'll need the avahi bindings that @azasypkin is working on and implement something similar to http://www.avahi.org/wiki/Examples/PythonPublishAlias (without dbus).
We should remember to change https://github.com/fxbox/foxbox/pull/36/files#diff-dae553a6502782625ac1a8979c781526R18 back when this is done.
I could crash the hue adapter by running multiple discos in parallel over a packet-lossy WiFi link for several minutes. I didn't run with a backtrace, so I'm just leaving the error message here for now:
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: "PoisonError { inner: .. }"', ../src/libcore/result.rs:746
After it first appeared, it kept repeating and no more API requests would be handled until restart.
Many use cases rely on the local time, foxbox-side. This means that we need to be able to set the local time.
We shouldn't be showing the setup or login screen depending on the session token that is stored in the browser. Instead, the server should decide which flow to show based on the existence of an admin account.
Building on #13, switch from http to https.
After I get that working, I'll look at improving it further, e.g. avoid bad UX of adding the exception for the self-signed cert, and not requiring the connection to the router to be via ethernet.
Consider a IoT heater. Setting it to 100ºF or 100ºC will cause very different results and possibly life-threatening accidents.
So when dealing with temperature, we'll need to know which unit is expected by the device and which unit is entered through the UX, then perform conversions as needed.
I'm not sure at which layer we need to do this.
We need to make Thinkerbell usable from the FoxBox, and hey, while we're at it, let's make it an Adapter
, with the following services:
Upon executing fxbox, following error message is shown:
ERROR:foxbox::config_store: Unable to open configuration file foxbox.conf: No such file or directory (os error 2). According to fabrice, this is actually not an error.
ccing @cr for resolution.
I'm seeing quite a lot of intermittent failures from kcov. It looks like sometimes it can't find the foxbox executable. @JohanLorenzo does that ring a bell?
Here's a log extract with such a failure:
Scanning dependencies of target kcov
[ 25%] Building CXX object src/CMakeFiles/kcov.dir/capabilities.cc.o
[ 27%] Building CXX object src/CMakeFiles/kcov.dir/collector.cc.o
[ 30%] Building CXX object src/CMakeFiles/kcov.dir/configuration.cc.o
[ 32%] Building CXX object src/CMakeFiles/kcov.dir/engine-factory.cc.o
[ 35%] Building CXX object src/CMakeFiles/kcov.dir/engines/bash-engine.cc.o
[ 37%] Building CXX object src/CMakeFiles/kcov.dir/engines/gcov-engine.cc.o
[ 40%] Building CXX object src/CMakeFiles/kcov.dir/engines/python-engine.cc.o
[ 42%] Building CXX object src/CMakeFiles/kcov.dir/filter.cc.o
[ 45%] Building CXX object src/CMakeFiles/kcov.dir/gcov.cc.o
[ 47%] Building CXX object src/CMakeFiles/kcov.dir/main.cc.o
[ 50%] Building CXX object src/CMakeFiles/kcov.dir/merge-file-parser.cc.o
[ 52%] Building CXX object src/CMakeFiles/kcov.dir/output-handler.cc.o
[ 55%] Building CXX object src/CMakeFiles/kcov.dir/parsers/dummy-address-verifier.cc.o
[ 57%] Building CXX object src/CMakeFiles/kcov.dir/parser-manager.cc.o
[ 60%] Building CXX object src/CMakeFiles/kcov.dir/reporter.cc.o
[ 62%] Building CXX object src/CMakeFiles/kcov.dir/utils.cc.o
[ 65%] Building CXX object src/CMakeFiles/kcov.dir/writers/cobertura-writer.cc.o
[ 67%] Building CXX object src/CMakeFiles/kcov.dir/writers/coveralls-writer.cc.o
[ 70%] Building CXX object src/CMakeFiles/kcov.dir/writers/html-writer.cc.o
[ 72%] Building CXX object src/CMakeFiles/kcov.dir/writers/writer-base.cc.o
[ 75%] Building CXX object src/CMakeFiles/kcov.dir/engines/ptrace.cc.o
[ 77%] Building CXX object src/CMakeFiles/kcov.dir/engines/kernel-engine.cc.o
[ 80%] Building CXX object src/CMakeFiles/kcov.dir/parsers/elf-parser.cc.o
[ 82%] Building CXX object src/CMakeFiles/kcov.dir/solib-handler.cc.o
[ 85%] Building C object src/CMakeFiles/kcov.dir/solib-parser/phdr_data.c.o
[ 87%] Building CXX object src/CMakeFiles/kcov.dir/library.cc.o
[ 90%] Building CXX object src/CMakeFiles/kcov.dir/bash-redirector-library.cc.o
[ 92%] Building CXX object src/CMakeFiles/kcov.dir/python-helper.cc.o
[ 95%] Building CXX object src/CMakeFiles/kcov.dir/bash-helper.cc.o
[ 97%] Building CXX object src/CMakeFiles/kcov.dir/html-data-files.cc.o
[100%] Building C object src/CMakeFiles/kcov.dir/version.c.o
Linking CXX executable kcov
[100%] Built target kcov
+cd -
/home/travis/build/fxbox/foxbox
+compile_foxbox_with_dead_code
++cargo test --no-run --verbose
++sed --quiet 's/.*`\(rustc .* --test .*\)`.*/\1/p'
src/controller.rs:207:5: 207:23 warning: struct field is never used: `controller`, #[warn(dead_code)] on by default
src/controller.rs:207 controller: FoxBox,
^~~~~~~~~~~~~~~~~~
+RUSTC_COMMAND='rustc src/main.rs --crate-name foxbox --crate-type bin -g --test --cfg feature=\"default\" --cfg feature=\"authentication\" -C metadata=a9cabe0dc62944c7 -C extra-filename=-a9cabe0dc62944c7 --out-dir /home/travis/build/fxbox/foxbox/target/debug --emit=dep-info,link -L dependency=/home/travis/build/fxbox/foxbox/target/debug -L dependency=/home/travis/build/fxbox/foxbox/target/debug/deps --extern iron_test=/home/travis/build/fxbox/foxbox/target/debug/deps/libiron_test-1e845ce178cfe460.rlib --extern mount=/home/travis/build/fxbox/foxbox/target/debug/deps/libmount-354041ca4f0dc0b3.rlib --extern stainless=/home/travis/build/fxbox/foxbox/target/debug/deps/libstainless-ba9d17ed65ee54dc.so --extern crypto=/home/travis/build/fxbox/foxbox/target/debug/deps/libcrypto-97872ea539a059cd.rlib --extern ws=/home/travis/build/fxbox/foxbox/target/debug/deps/libws-d2f82be550680a28.rlib --extern xml=/home/travis/build/fxbox/foxbox/target/debug/deps/libxml-7f9311e89a955d7f.rlib --extern multicast_dns=/home/travis/build/fxbox/foxbox/target/debug/deps/libmulticast_dns-3de45b741afde594.rlib --extern serde_json=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde_json-53d3e106cfb5207d.rlib --extern env_logger=/home/travis/build/fxbox/foxbox/target/debug/deps/libenv_logger-1963490441847a73.rlib --extern staticfile=/home/travis/build/fxbox/foxbox/target/debug/deps/libstaticfile-b1081474074fbce3.rlib --extern docopt_macros=/home/travis/build/fxbox/foxbox/target/debug/deps/libdocopt_macros-c07846471a9a5fbf.so --extern serde=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde-50d4f336f4dbf399.rlib --extern unicase=/home/travis/build/fxbox/foxbox/target/debug/deps/libunicase-f807684b8c0dd9b5.rlib --extern clippy=/home/travis/build/fxbox/foxbox/target/debug/deps/libclippy-ab1b8e06a6a9105d.so --extern iron=/home/travis/build/fxbox/foxbox/target/debug/deps/libiron-291b005d9cf352e3.rlib --extern regex=/home/travis/build/fxbox/foxbox/target/debug/deps/libregex-1a3a0af90d20fdaf.rlib --extern router=/home/travis/build/fxbox/foxbox/target/debug/deps/librouter-eafcd78868655893.rlib --extern log=/home/travis/build/fxbox/foxbox/target/debug/deps/liblog-35b3ccf0458f5f8d.rlib --extern hyper=/home/travis/build/fxbox/foxbox/target/debug/deps/libhyper-93452a301949bf5b.rlib --extern rustc_serialize=/home/travis/build/fxbox/foxbox/target/debug/deps/librustc_serialize-ee878f05d7532512.rlib --extern foxbox_users=/home/travis/build/fxbox/foxbox/target/debug/deps/libfoxbox_users-b57eb8ad4eab3730.rlib --extern url=/home/travis/build/fxbox/foxbox/target/debug/deps/liburl-f77b9d6b20364f2d.rlib --extern uuid=/home/travis/build/fxbox/foxbox/target/debug/deps/libuuid-541c72a101b6b06d.rlib --extern serde_macros=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde_macros-1109154aa8830403.so --extern time=/home/travis/build/fxbox/foxbox/target/debug/deps/libtime-1aeb304d6ae03c62.rlib --extern docopt=/home/travis/build/fxbox/foxbox/target/debug/deps/libdocopt-584bf737f155d9e1.rlib --extern get_if_addrs=/home/travis/build/fxbox/foxbox/target/debug/deps/libget_if_addrs-8d1ccb2dabd39bd9.rlib --extern mio=/home/travis/build/fxbox/foxbox/target/debug/deps/libmio-b7b0ae0672144946.rlib --extern libc=/home/travis/build/fxbox/foxbox/target/debug/deps/liblibc-f1a4f924481a5b7d.rlib -L native=/home/travis/build/fxbox/foxbox/target/debug/build/openssl-0c4b4a6cb21fd5d4/out -L native=/home/travis/build/fxbox/foxbox/target/debug/build/openssl-sys-extras-3867c37901e58a23/out -L native=/usr/lib/x86_64-linux-gnu -L native=/home/travis/build/fxbox/foxbox/target/debug/build/rust-crypto-97872ea539a059cd/out -L native=/usr/lib/x86_64-linux-gnu'
+eval rustc src/main.rs --crate-name foxbox --crate-type bin -g --test --cfg 'feature=\"default\"' --cfg 'feature=\"authentication\"' -C metadata=a9cabe0dc62944c7 -C extra-filename=-a9cabe0dc62944c7 --out-dir /home/travis/build/fxbox/foxbox/target/debug --emit=dep-info,link -L dependency=/home/travis/build/fxbox/foxbox/target/debug -L dependency=/home/travis/build/fxbox/foxbox/target/debug/deps --extern iron_test=/home/travis/build/fxbox/foxbox/target/debug/deps/libiron_test-1e845ce178cfe460.rlib --extern mount=/home/travis/build/fxbox/foxbox/target/debug/deps/libmount-354041ca4f0dc0b3.rlib --extern stainless=/home/travis/build/fxbox/foxbox/target/debug/deps/libstainless-ba9d17ed65ee54dc.so --extern crypto=/home/travis/build/fxbox/foxbox/target/debug/deps/libcrypto-97872ea539a059cd.rlib --extern ws=/home/travis/build/fxbox/foxbox/target/debug/deps/libws-d2f82be550680a28.rlib --extern xml=/home/travis/build/fxbox/foxbox/target/debug/deps/libxml-7f9311e89a955d7f.rlib --extern multicast_dns=/home/travis/build/fxbox/foxbox/target/debug/deps/libmulticast_dns-3de45b741afde594.rlib --extern serde_json=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde_json-53d3e106cfb5207d.rlib --extern env_logger=/home/travis/build/fxbox/foxbox/target/debug/deps/libenv_logger-1963490441847a73.rlib --extern staticfile=/home/travis/build/fxbox/foxbox/target/debug/deps/libstaticfile-b1081474074fbce3.rlib --extern docopt_macros=/home/travis/build/fxbox/foxbox/target/debug/deps/libdocopt_macros-c07846471a9a5fbf.so --extern serde=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde-50d4f336f4dbf399.rlib --extern unicase=/home/travis/build/fxbox/foxbox/target/debug/deps/libunicase-f807684b8c0dd9b5.rlib --extern clippy=/home/travis/build/fxbox/foxbox/target/debug/deps/libclippy-ab1b8e06a6a9105d.so --extern iron=/home/travis/build/fxbox/foxbox/target/debug/deps/libiron-291b005d9cf352e3.rlib --extern regex=/home/travis/build/fxbox/foxbox/target/debug/deps/libregex-1a3a0af90d20fdaf.rlib --extern router=/home/travis/build/fxbox/foxbox/target/debug/deps/librouter-eafcd78868655893.rlib --extern log=/home/travis/build/fxbox/foxbox/target/debug/deps/liblog-35b3ccf0458f5f8d.rlib --extern hyper=/home/travis/build/fxbox/foxbox/target/debug/deps/libhyper-93452a301949bf5b.rlib --extern rustc_serialize=/home/travis/build/fxbox/foxbox/target/debug/deps/librustc_serialize-ee878f05d7532512.rlib --extern foxbox_users=/home/travis/build/fxbox/foxbox/target/debug/deps/libfoxbox_users-b57eb8ad4eab3730.rlib --extern url=/home/travis/build/fxbox/foxbox/target/debug/deps/liburl-f77b9d6b20364f2d.rlib --extern uuid=/home/travis/build/fxbox/foxbox/target/debug/deps/libuuid-541c72a101b6b06d.rlib --extern serde_macros=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde_macros-1109154aa8830403.so --extern time=/home/travis/build/fxbox/foxbox/target/debug/deps/libtime-1aeb304d6ae03c62.rlib --extern docopt=/home/travis/build/fxbox/foxbox/target/debug/deps/libdocopt-584bf737f155d9e1.rlib --extern get_if_addrs=/home/travis/build/fxbox/foxbox/target/debug/deps/libget_if_addrs-8d1ccb2dabd39bd9.rlib --extern mio=/home/travis/build/fxbox/foxbox/target/debug/deps/libmio-b7b0ae0672144946.rlib --extern libc=/home/travis/build/fxbox/foxbox/target/debug/deps/liblibc-f1a4f924481a5b7d.rlib -L native=/home/travis/build/fxbox/foxbox/target/debug/build/openssl-0c4b4a6cb21fd5d4/out -L native=/home/travis/build/fxbox/foxbox/target/debug/build/openssl-sys-extras-3867c37901e58a23/out -L native=/usr/lib/x86_64-linux-gnu -L native=/home/travis/build/fxbox/foxbox/target/debug/build/rust-crypto-97872ea539a059cd/out -L native=/usr/lib/x86_64-linux-gnu -C link-dead-code
++rustc src/main.rs --crate-name foxbox --crate-type bin -g --test --cfg 'feature="default"' --cfg 'feature="authentication"' -C metadata=a9cabe0dc62944c7 -C extra-filename=-a9cabe0dc62944c7 --out-dir /home/travis/build/fxbox/foxbox/target/debug --emit=dep-info,link -L dependency=/home/travis/build/fxbox/foxbox/target/debug -L dependency=/home/travis/build/fxbox/foxbox/target/debug/deps --extern iron_test=/home/travis/build/fxbox/foxbox/target/debug/deps/libiron_test-1e845ce178cfe460.rlib --extern mount=/home/travis/build/fxbox/foxbox/target/debug/deps/libmount-354041ca4f0dc0b3.rlib --extern stainless=/home/travis/build/fxbox/foxbox/target/debug/deps/libstainless-ba9d17ed65ee54dc.so --extern crypto=/home/travis/build/fxbox/foxbox/target/debug/deps/libcrypto-97872ea539a059cd.rlib --extern ws=/home/travis/build/fxbox/foxbox/target/debug/deps/libws-d2f82be550680a28.rlib --extern xml=/home/travis/build/fxbox/foxbox/target/debug/deps/libxml-7f9311e89a955d7f.rlib --extern multicast_dns=/home/travis/build/fxbox/foxbox/target/debug/deps/libmulticast_dns-3de45b741afde594.rlib --extern serde_json=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde_json-53d3e106cfb5207d.rlib --extern env_logger=/home/travis/build/fxbox/foxbox/target/debug/deps/libenv_logger-1963490441847a73.rlib --extern staticfile=/home/travis/build/fxbox/foxbox/target/debug/deps/libstaticfile-b1081474074fbce3.rlib --extern docopt_macros=/home/travis/build/fxbox/foxbox/target/debug/deps/libdocopt_macros-c07846471a9a5fbf.so --extern serde=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde-50d4f336f4dbf399.rlib --extern unicase=/home/travis/build/fxbox/foxbox/target/debug/deps/libunicase-f807684b8c0dd9b5.rlib --extern clippy=/home/travis/build/fxbox/foxbox/target/debug/deps/libclippy-ab1b8e06a6a9105d.so --extern iron=/home/travis/build/fxbox/foxbox/target/debug/deps/libiron-291b005d9cf352e3.rlib --extern regex=/home/travis/build/fxbox/foxbox/target/debug/deps/libregex-1a3a0af90d20fdaf.rlib --extern router=/home/travis/build/fxbox/foxbox/target/debug/deps/librouter-eafcd78868655893.rlib --extern log=/home/travis/build/fxbox/foxbox/target/debug/deps/liblog-35b3ccf0458f5f8d.rlib --extern hyper=/home/travis/build/fxbox/foxbox/target/debug/deps/libhyper-93452a301949bf5b.rlib --extern rustc_serialize=/home/travis/build/fxbox/foxbox/target/debug/deps/librustc_serialize-ee878f05d7532512.rlib --extern foxbox_users=/home/travis/build/fxbox/foxbox/target/debug/deps/libfoxbox_users-b57eb8ad4eab3730.rlib --extern url=/home/travis/build/fxbox/foxbox/target/debug/deps/liburl-f77b9d6b20364f2d.rlib --extern uuid=/home/travis/build/fxbox/foxbox/target/debug/deps/libuuid-541c72a101b6b06d.rlib --extern serde_macros=/home/travis/build/fxbox/foxbox/target/debug/deps/libserde_macros-1109154aa8830403.so --extern time=/home/travis/build/fxbox/foxbox/target/debug/deps/libtime-1aeb304d6ae03c62.rlib --extern docopt=/home/travis/build/fxbox/foxbox/target/debug/deps/libdocopt-584bf737f155d9e1.rlib --extern get_if_addrs=/home/travis/build/fxbox/foxbox/target/debug/deps/libget_if_addrs-8d1ccb2dabd39bd9.rlib --extern mio=/home/travis/build/fxbox/foxbox/target/debug/deps/libmio-b7b0ae0672144946.rlib --extern libc=/home/travis/build/fxbox/foxbox/target/debug/deps/liblibc-f1a4f924481a5b7d.rlib -L native=/home/travis/build/fxbox/foxbox/target/debug/build/openssl-0c4b4a6cb21fd5d4/out -L native=/home/travis/build/fxbox/foxbox/target/debug/build/openssl-sys-extras-3867c37901e58a23/out -L native=/usr/lib/x86_64-linux-gnu -L native=/home/travis/build/fxbox/foxbox/target/debug/build/rust-crypto-97872ea539a059cd/out -L native=/usr/lib/x86_64-linux-gnu -C link-dead-code
src/controller.rs:207:5: 207:23 warning: struct field is never used: `controller`, #[warn(dead_code)] on by default
src/controller.rs:207 controller: FoxBox,
^~~~~~~~~~~~~~~~~~
+run_tests_and_coverage
++find /home/travis/build/fxbox/foxbox/tools/../target/debug -maxdepth 1 -executable -name 'foxbox-*'
+FOXBOX_UNIT_TEST_BINARY='/home/travis/build/fxbox/foxbox/tools/../target/debug/foxbox-5fe0ccd2f25574e9
/home/travis/build/fxbox/foxbox/tools/../target/debug/foxbox-a9cabe0dc62944c7'
+RUST_BACKTRACE=1
+/home/travis/build/fxbox/foxbox/tools/../target/kcov/kcov-30/src/kcov '--exclude-path=~/.cargo, /home/travis/build/fxbox/foxbox/tools/../src/stubs, /home/travis/build/fxbox/foxbox/tools/../target' --coveralls-id=114424535 /home/travis/build/fxbox/foxbox/tools/../target/coverage-report/ '/home/travis/build/fxbox/foxbox/tools/../target/debug/foxbox-5fe0ccd2f25574e9
/home/travis/build/fxbox/foxbox/tools/../target/debug/foxbox-a9cabe0dc62944c7'
kcov: error: Can't find or open /home/travis/build/fxbox/foxbox/tools/../target/debug/foxbox-5fe0ccd2f25574e9
/home/travis/build/fxbox/foxbox/tools/../target/debug/foxbox-a9cabe0dc62944c7
The command "$TRAVIS_BUILD_DIR/tools/execute-unit-tests-with-coverage" exited with 1.
$ jshint static/main/js/*.js static/setup/js/*.js test/selenium/*.js
The command "jshint static/main/js/*.js static/setup/js/*.js test/selenium/*.js" exited with 0.
$ (cargo run -- -n $BOX_HOST_NAME -p $BOX_PORT &> /dev/null &) ; npm test
> [email protected] test /home/travis/build/fxbox/foxbox
> rm -f *sqlite && ./node_modules/.bin/mocha test/selenium/*_test.js
We use the crate get_if_addrs. Its license is GPL-3. It is my understanding it is not OK.
The D-Link cameras that we're supporting don't seem to support IPv6, but when we have support for a Raspberry Pi as a camera, then we need to make sure that everything works properly using IPv6 addresses for the camera.
Most Apps (both Control and Monitor) will need to monitor changes to device properties.
For instance:
To implement any of these apps, we need an API that will monitor a set of properties of devices and callback each time the value of a given property of a given device enter/leaves some interval (or at each change if no interval is specified).
We need this API at least in WebSocket, as all consumers can be built on top of WebSocket. Ideally, we'd like to provide a concise JS API on top of the WebSocket API. It would be useful to have this API available to Rust code, too, for the sake of the rules engine and Monitor Workers.
I'll describe a pseudo-API in Rust, because I have attempted to do it in other languages and it was actually more complicated:
trait Watcher {
/// Create a new watcher.
pub fn new() -> Watcher;
/// Watch a property of a device.
///
/// If the device is smart enough,
///
/// # Example
///
/// let witness = watcher.add(&the_terminator,
/// &InputCapability::DetectSarahConnor,
/// &Range::any(),
/// &tx);
///
/// Until `witness` is dropped, whenever property `DetectSarahConnor` of `the_terminator`
/// changes, the watcher will send a message on `tx`.
///
/// let witness_2 = watcher.add(&the_terminator,
/// &InputCapability::Ammo,
/// &Range::boundary(100),
/// &tx_2);
///
/// Until `witness_2` is dropped, whenever property `Ammo` of `the_terminator` goes
/// above/beyond 100, the watcher will send a message on `tx_2`.
pub fn<T> add(&mut self, &Device, &InputCapability<T>, &Range<T>, &Sender<T>) -> Witness;
}
/// A structure used to stop watching a property once it is dropped.
pub struct Witness {
// ...
}
This depends heavily on our ongoing efforts on Taxonomy.
Note that JS versions of this API will most likely use a addEventListener
/removeEventListener
pair, rather than channels (unless streams have been standardized by then). The server will monitor WebSocket disconnection to ensure garbage-collection of Watcher
.
Cc @mcav, @jedireza, @davidflanagan .
We should persist the discovered cameras in a database so that we don't need to wait for upnp before needing to access a camera.
The database would also need to store the username and password needed to access the camera, as well as a user-friendly name for the UI.
If the IP address of an IP Camera changes, we need to detect that and update our internal database and the persisted database.
That'd be nice to have the name of the manufacturer and the model ID of each services in list.json.
This can be used to display specific icon to help users to identify devices quicker.
cc @fabricedesre and @cr
Surfaced in: #149
Ideally, we'd like to be able to install drivers/adapters just like apps, using a SmartDevice, perhaps with a reboot.
Following is the JSON info of the dimmable light sent from the philips hub:
"1":{
"state": {
"on":false,
"bri":0,
"alert":"none",
"reachable":false
},
"type": "Dimmable light",
"name": "Hue white lamp 1",
"modelid": "LWB006",
"manufacturername": "Philips",
"uniqueid":"00:17:88:01:10:34:95:dd-0b",
"swversion": "",
"pointsymbol": {
"1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none"
}
And this is the JSON info of a color light:
"1": {
"state": {
"on": true,
"bri": 254,
"hue": 14910,
"sat": 144,
"effect": "none",
"xy": [
0.4596,
0.4105
],
"ct": 370,
"alert": "none",
"colormode": "ct",
"reachable": false
},
"type": "Extended color light",
"name": "Hue color lamp 1",
"modelid": "LCT007",
"manufacturername": "Philips",
"uniqueid": "00:17:88:01:10:41:87:79-0b",
"swversion": "66014919"
}
because the dimmable light is missing some fields compared to the color light, it will cause foxbox to have a JSON parse error since it appears that there is only one SettingsLightState in src/adapters/philips_hue/hub_api/structs.rs
Right now this is a manual step in https://public.etherpad-mozilla.org/p/project-link-discovery#lineNumber=10
Make use of the authentication middleware from https://github.com/fxbox/users#authenticating-endpoints to authenticate the GET /services endpoint.
CR mentioned that nupnp server address is currently hardcoded and there is no simple mechanism to pass down command arguments to adapters. However, the plan is to have the option to store it in a global config parameter which could relatively easily be overridden.
After fxbox/users#32 we give the consumer a session token to use in following requests to authenticated endpoints. We need to save this token after the user creates the admin account.
Currently, if you take enough snapshots then it will eventually fill the disk.
Instead we should have something like keep the last N snapshots for each camera (simplest) or implement a max storage (per camera or globally).
Authorization to 3rd party apps is outside of the scope of the prototype. However, we know that we don't want 3rd party apps asking users to enter their username & password (iif we finally use user&pass...), so we can at least mock an authorization flow where the user is redirected to the box to enter her credentials and we redirect the user back to the app with a fake auth token.
The docopt crate seems like a nice way to manage command line args:
https://github.com/docopt/docopt.rs
Related to: #3
Deploy-time:
a.<hash>.knilxof.org
, b.<hash>.knilxof.org
, local.<hash>.knilxof.org
, and remote.<hash>.knilxof.org
.a.<hash>.knilxof.org
and local.<hash>.knilxof.org
A records to current local IP address.remote.<hash>.knilxof.org
A record to the tunnel's public IP address.a.<hash>.knilxof.org
(see below).Run-time when certs are about to expire:
a.<hash>.knilxof.org
, b.<hash>.knilxof.org
, local.<hash>.knilxof.org
, and remote.<hash>.knilxof.org
.Run-time when local IP address changes (if current preferred mirror is a.
):
b.<hash>.knilxof.org
and local.<hash>.knilxof.org
A record to new local IP address.b.<hash>.knilxof.org
.a.<hash>.knilxof.org
.Run-time when local IP address changes (if current preferred mirror is b.
):
a.<hash>.knilxof.org
and local.<hash>.knilxof.org
A record to new local IP address.a.<hash>.knilxof.org
.b.<hash>.knilxof.org
.On https://local.<hash>.knilxof.org/
we just publish the list of mirrors (a.
and b.
), and which of them is currently live, and the client remembers this, then redirects to the live one.
When the Box becomes unreachable on the current mirror, the client tries another one from the list.
This way, the client only queries DNS for local.
when scanning the QR code, and not during normal operation, so by the next time the Box's IP address changes, it will have been flushed from DNS cache.
When using the registration server instead of the QR code, the Box could even announce the current preferred mirror directly to the registration-server.
If we see the IP switches too often, we could also rotate >2 mirrors .
I did a git clean -x -d -f to remove all files not checked into github
I then did a cargo build
I then browsed to http://localhost:3000 and was asked to enter my admin password (rather than the ask/confirm). Checking the filesystem, users_db.sqlite doesn't even exist yet. And of course, because I haven't set a password, all passwords come back as unauthorized.
So something about authentication seems totally broken.
Tagging @ferjm so that he sees this.
Running with RUST_LOG=foxbox=trace cargo run yields no interesting information.
If I enter a password and click Signin then I get back an Unauthorized error, and an empty users_db.sqlite is created. If I browse the database using sqlitebrowser it shows no rows in the table.
We don't have a shutdown sequence, but we really should have one. Would be useful to stop/restart when updating for instance.
@mcav is that something you would be interested in?
We need to provide an API that lets applications find out which devices are available for a specific purpose. This API will be used both server-side (in the rules engine, in Monitor Workers) and client-side (in client web apps).
We need this API at least in REST, as all consumers can be built on top of REST. Ideally, we'd like to provide a concise JS API on top of the REST API. It would be useful to have this API available to Rust code, too, for the sake of the rules engine and possibly Monitor Workers.
I'll describe a possible API in Rust, because I have attempted to do it in other languages and it was actually more complicated:
/// Get the list of all available devices that can fulfill a service.
///
/// # Example
///
/// let devices = get_devices(DeviceKind::RobotFromTheFuture,
/// &vec![InputCapability::DetectSarahConnor, InputCapability::DetectJohnConnor, InputCapability::IsControlledBySkynet],
/// &vec![OutputCapability::Terminate]);
///
/// for terminator in devices {
/// // ...
/// }
fn get_devices(&DeviceKind, &Vec<InputCapability>, &Vec<OutputCapability>) -> Vec<Device>
This depends heavily on our ongoing efforts on Taxonomy.
Note that JS versions of this API will return a Promise
, rather than blocking.
Right now they end up in the directory foxbox was launched from.
Right now the dummyservice is just printing to the console (https://github.com/fxbox/foxbox/blob/master/src/dummy_adapter.rs#L58) but it should actually send that to websocket listeners.
We need to add a new event kind in events.rs and go from there.
@jedireza, it's all yours.
At first, the App connects to the Box on its local IP (as discovered through nupnp). Once the App has successfully authenticated, it should have some way to ask the Box for its tunnel address (if any).
This is a build on OS X:
$ rustc -V
rustc 1.8.0-nightly (c92e910c1 2016-02-21)
$ cargo build
Compiling multicast_dns v0.1.0 (https://github.com/fxbox/multicast-dns.git?rev=b87f76a#b87f76af)
/Users/cruetten/.multirust/toolchains/nightly-2016-02-22/cargo/git/checkouts/multicast-dns-d51af2fa146824d6/b87f76a/src/adapters/fake/adapter.rs:76:5: 78:6 error: method `add_name_alias` has an incompatible type for trait:
expected (),
found struct `collections::string::String` [E0053]
/Users/cruetten/.multirust/toolchains/nightly-2016-02-22/cargo/git/checkouts/multicast-dns-d51af2fa146824d6/b87f76a/src/adapters/fake/adapter.rs:76 fn add_name_alias(&self, host_name: &str) -> String {
/Users/cruetten/.multirust/toolchains/nightly-2016-02-22/cargo/git/checkouts/multicast-dns-d51af2fa146824d6/b87f76a/src/adapters/fake/adapter.rs:77 host_name.to_owned()
/Users/cruetten/.multirust/toolchains/nightly-2016-02-22/cargo/git/checkouts/multicast-dns-d51af2fa146824d6/b87f76a/src/adapters/fake/adapter.rs:78 }
/Users/cruetten/.multirust/toolchains/nightly-2016-02-22/cargo/git/checkouts/multicast-dns-d51af2fa146824d6/b87f76a/src/adapters/fake/adapter.rs:76:5: 78:6 help: run `rustc --explain E0053` to see a detailed explanation
error: aborting due to previous error
Could not compile `multicast_dns`.
To learn more, run the command again with --verbose.
I need to revert to commit 85ca6d9 be able to build.
We need to implement the client side of https://github.com/fxbox/users/blob/master/doc/API.md#post-login
I'm getting intermittent test failures running cargo test
:
test service_router::service_router::services::should_make_service_available ... FAILED
test service_router::service_router::services::should_return_an_error_if_no_service_was_found ... FAILED
test service_router::service_router::services::should_create_list.json ... FAILED
The error is always:
thread 'service_router::service_router::services::should_make_service_available' panicked at 'called
Result::unwrap()on an
Err value: IronError { error: StringError("Unauthorized"), response: HTTP/1.1 401 Unauthorized Unauthorized
Looks like another init race condition.
*
is very fragile and is on its way out anyway.
A service
should probably run in a separate process - easy upgrades, safety from crashes etc. See brief discussion on #22.
We should use https://github.com/servo/ipc-channel, it probably needs extending though:
Servers only accept one client at a time.
These processes probably need some sort of supervisor to keep them alive. As will the tunnel_controller
, which will control the lifecycle of the tunnel process.
service
service
and controller
- probably CSP based on ipc-channelA 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.