Merge remote-tracking branch 'weave/master' into aosp-master2

* weave/master:
  Fix behavior of bootstrap manager after monitoring timeout was reached
  Added instruction for checking examples/daemon/README for details.
  Include cmath, needed for FP std::abs.
  examples/daemon: split daemon into seperate binaries
diff --git a/README b/README
index b62b547..bf9b70b 100644
--- a/README
+++ b/README
@@ -56,7 +56,7 @@
 
   examples/build.sh
 
-Execute example:
+Execute example (check examples/daemon/README for details):
 
   sudo out/Debug/weave_daemon
 
diff --git a/examples/build.sh b/examples/build.sh
index 2bd398ef..e4c412d 100755
--- a/examples/build.sh
+++ b/examples/build.sh
@@ -8,7 +8,7 @@
 
 cd $ROOT_DIR
 
-gyp -Ilibweave_common.gypi --toplevel-dir=. --depth=. -f ninja $DIR/daemon/daemon.gyp
+gyp -Ilibweave_common.gypi --toplevel-dir=. --depth=. -f ninja $DIR/daemon/examples.gyp
 
 if [ -z "$BUILD_CONFIG" ]; then
    export BUILD_CONFIG=Debug
@@ -16,7 +16,7 @@
 
 export BUILD_TARGET=$*
 if [ -z "$BUILD_TARGET" ]; then
-   export BUILD_TARGET="weave_daemon libweave_testrunner libweave_exports_testrunner"
+   export BUILD_TARGET="weave_daemon_examples libweave_testrunner libweave_exports_testrunner"
 fi
 
 export CORES=`cat /proc/cpuinfo | grep processor | wc -l`
diff --git a/examples/daemon/README b/examples/daemon/README
index 4743883..287459f 100644
--- a/examples/daemon/README
+++ b/examples/daemon/README
@@ -84,16 +84,16 @@
         Enter request body:
         {
           "deviceId": "0f8a5ff5-1ef0-ec39-f9d8-66d1caeb9e3d",
-          "name": "_greeter._greet",
+          "name": "_sample._hello",
           "parameters": { "_name": "cloud user" }
         }
    "Send the request", you command will be "queued" as its "state"
 
   - verify the command execution with weave daemon
        in terminal running the daemon, observe something similar to
-         New command '_greeter._greet' arrived, ...
-         received command: _greeter._greet
-         _greeter._greet command: finished
+         New command '_sample._hello' arrived, ...
+         received command: _sample._hello
+         _sample._hello command: finished
   - verify the command history with oauthplayground
        Similar to "Acquire Registration Ticket" section in this document,
        except in "step 3", do:
@@ -104,9 +104,9 @@
        "Send the request", you get all of the commands executed on your
        device, find something like
           "kind": "clouddevices#command",
-          "name": "_greeter._greet",
+          "name": "_sample._hello",
           "results": {
-            "_greeting": "Hello cloud user"
+            "_reply": "Hello cloud user"
           },
           ...
 
diff --git a/examples/daemon/common/daemon.h b/examples/daemon/common/daemon.h
new file mode 100644
index 0000000..0e05b88
--- /dev/null
+++ b/examples/daemon/common/daemon.h
@@ -0,0 +1,124 @@
+// Copyright 2015 The Weave Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <weave/device.h>
+#include <weave/error.h>
+
+#include <base/bind.h>
+
+#include "examples/provider/avahi_client.h"
+#include "examples/provider/bluez_client.h"
+#include "examples/provider/curl_http_client.h"
+#include "examples/provider/event_http_server.h"
+#include "examples/provider/event_network.h"
+#include "examples/provider/event_task_runner.h"
+#include "examples/provider/file_config_store.h"
+#include "examples/provider/wifi_manager.h"
+
+class Daemon {
+ public:
+  struct Options {
+    bool force_bootstrapping_ = false;
+    bool disable_security_ = false;
+    bool disable_privet_ = false;
+    std::string registration_ticket_;
+
+    static void ShowUsage(const std::string& name) {
+      LOG(ERROR) << "\nUsage: " << name << " <option(s)>"
+                 << "\nOptions:\n"
+                 << "\t-h,--help                    Show this help message\n"
+                 << "\t--v=LEVEL                    Logging level\n"
+                 << "\t-b,--bootstrapping           Force WiFi bootstrapping\n"
+                 << "\t-d,--disable_security        Disable privet security\n"
+                 << "\t--registration_ticket=TICKET Register device with the "
+                    "given ticket\n"
+                 << "\t--disable_privet             Disable local privet\n";
+    }
+
+    bool Parse(int argc, char** argv) {
+      for (int i = 1; i < argc; ++i) {
+        std::string arg = argv[i];
+        if (arg == "-h" || arg == "--help") {
+          return false;
+        } else if (arg == "-b" || arg == "--bootstrapping") {
+          force_bootstrapping_ = true;
+        } else if (arg == "-d" || arg == "--disable_security") {
+          disable_security_ = true;
+        } else if (arg == "--disable_privet") {
+          disable_privet_ = true;
+        } else if (arg.find("--registration_ticket") != std::string::npos) {
+          auto pos = arg.find("=");
+          if (pos == std::string::npos) {
+            return false;
+          }
+          registration_ticket_ = arg.substr(pos + 1);
+        } else if (arg.find("--v") != std::string::npos) {
+          auto pos = arg.find("=");
+          if (pos == std::string::npos) {
+            return false;
+          }
+          logging::SetMinLogLevel(-std::stoi(arg.substr(pos + 1)));
+        } else {
+          return false;
+        }
+      }
+      return true;
+    }
+  };
+
+  Daemon(const Options& opts)
+      : config_store_{new weave::examples::FileConfigStore(
+            opts.disable_security_)},
+        task_runner_{new weave::examples::EventTaskRunner},
+        http_client_{new weave::examples::CurlHttpClient(task_runner_.get())},
+        network_{new weave::examples::EventNetworkImpl(task_runner_.get())},
+        bluetooth_{new weave::examples::BluetoothImpl} {
+    if (!opts.disable_privet_) {
+      network_->SetSimulateOffline(opts.force_bootstrapping_);
+
+      dns_sd_.reset(new weave::examples::AvahiClient);
+      http_server_.reset(
+          new weave::examples::HttpServerImpl{task_runner_.get()});
+      if (weave::examples::WifiImpl::HasWifiCapability())
+        wifi_.reset(
+            new weave::examples::WifiImpl{task_runner_.get(), network_.get()});
+    }
+    device_ = weave::Device::Create(config_store_.get(), task_runner_.get(),
+                                    http_client_.get(), network_.get(),
+                                    dns_sd_.get(), http_server_.get(),
+                                    wifi_.get(), bluetooth_.get());
+
+    if (!opts.registration_ticket_.empty()) {
+      device_->Register(opts.registration_ticket_,
+                        base::Bind(&OnRegisterDeviceDone, device_.get()));
+    }
+  }
+
+  void Run() { task_runner_->Run(); }
+
+  weave::Device* GetDevice() const { return device_.get(); }
+
+  weave::examples::EventTaskRunner* GetTaskRunner() const {
+    return task_runner_.get();
+  }
+
+ private:
+  static void OnRegisterDeviceDone(weave::Device* device,
+                                   weave::ErrorPtr error) {
+    if (error)
+      LOG(ERROR) << "Fail to register device: " << error->GetMessage();
+    else
+      LOG(INFO) << "Device registered: " << device->GetSettings().cloud_id;
+  }
+
+  std::unique_ptr<weave::examples::FileConfigStore> config_store_;
+  std::unique_ptr<weave::examples::EventTaskRunner> task_runner_;
+  std::unique_ptr<weave::examples::CurlHttpClient> http_client_;
+  std::unique_ptr<weave::examples::EventNetworkImpl> network_;
+  std::unique_ptr<weave::examples::BluetoothImpl> bluetooth_;
+  std::unique_ptr<weave::examples::AvahiClient> dns_sd_;
+  std::unique_ptr<weave::examples::HttpServerImpl> http_server_;
+  std::unique_ptr<weave::examples::WifiImpl> wifi_;
+  std::unique_ptr<weave::Device> device_;
+};
diff --git a/examples/daemon/examples.gyp b/examples/daemon/examples.gyp
new file mode 100644
index 0000000..8fee90d
--- /dev/null
+++ b/examples/daemon/examples.gyp
@@ -0,0 +1,14 @@
+{
+  'targets': [
+    {
+      'target_name': 'weave_daemon_examples',
+      'type': 'none',
+      'dependencies': [
+        'sample/daemon.gyp:weave_daemon_sample',
+        'light/daemon.gyp:weave_daemon_light',
+        'lock/daemon.gyp:weave_daemon_lock',
+        'ledflasher/daemon.gyp:weave_daemon_ledflasher'
+      ]
+    }
+  ]
+}
diff --git a/examples/daemon/daemon.gyp b/examples/daemon/ledflasher/daemon.gyp
similarity index 84%
copy from examples/daemon/daemon.gyp
copy to examples/daemon/ledflasher/daemon.gyp
index c6f8837..5abfcd6 100644
--- a/examples/daemon/daemon.gyp
+++ b/examples/daemon/ledflasher/daemon.gyp
@@ -4,10 +4,10 @@
 {
   'targets': [
     {
-      'target_name': 'weave_daemon',
+      'target_name': 'weave_daemon_ledflasher',
       'type': 'executable',
       'sources': [
-        'main.cc',
+        'ledflasher.cc',
       ],
       'dependencies': [
         '<@(DEPTH)/libweave_standalone.gyp:libweave',
diff --git a/examples/daemon/ledflasher_handler.h b/examples/daemon/ledflasher/ledflasher.cc
similarity index 78%
rename from examples/daemon/ledflasher_handler.h
rename to examples/daemon/ledflasher/ledflasher.cc
index 812a3d4..38314f5 100644
--- a/examples/daemon/ledflasher_handler.h
+++ b/examples/daemon/ledflasher/ledflasher.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "examples/daemon/common/daemon.h"
+
 #include <weave/device.h>
 
 #include <base/bind.h>
@@ -9,10 +11,6 @@
 
 #include <bitset>
 
-namespace weave {
-namespace examples {
-namespace daemon {
-
 namespace {
 // Supported LED count on this device
 const size_t kLedCount = 3;
@@ -23,7 +21,7 @@
 class LedFlasherHandler {
  public:
   LedFlasherHandler() {}
-  void Register(Device* device) {
+  void Register(weave::Device* device) {
     device_ = device;
 
     device->AddStateDefinitionsFromJson(R"({
@@ -60,7 +58,7 @@
   }
 
  private:
-  void OnFlasherSetCommand(const std::weak_ptr<Command>& command) {
+  void OnFlasherSetCommand(const std::weak_ptr<weave::Command>& command) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -84,13 +82,13 @@
       cmd->Complete({}, nullptr);
       return;
     }
-    ErrorPtr error;
-    Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
-                 "Invalid parameters");
+    weave::ErrorPtr error;
+    weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+                        "Invalid parameters");
     cmd->Abort(error.get(), nullptr);
   }
 
-  void OnFlasherToggleCommand(const std::weak_ptr<Command>& command) {
+  void OnFlasherToggleCommand(const std::weak_ptr<weave::Command>& command) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -105,13 +103,13 @@
       cmd->Complete({}, nullptr);
       return;
     }
-    ErrorPtr error;
-    Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
-                 "Invalid parameters");
+    weave::ErrorPtr error;
+    weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+                        "Invalid parameters");
     cmd->Abort(error.get(), nullptr);
   }
 
-  void UpdateLedState(void) {
+  void UpdateLedState() {
     base::ListValue list;
     for (uint32_t i = 0; i < led_status_.size(); i++)
       list.AppendBoolean(led_status_[i] ? true : false);
@@ -119,7 +117,7 @@
     device_->SetStateProperty("_ledflasher._leds", list, nullptr);
   }
 
-  Device* device_{nullptr};
+  weave::Device* device_{nullptr};
 
   // Simulate LED status on this device so client app could explore
   // Each bit represents one device, indexing from LSB
@@ -127,6 +125,15 @@
   base::WeakPtrFactory<LedFlasherHandler> weak_ptr_factory_{this};
 };
 
-}  // namespace daemon
-}  // namespace examples
-}  // namespace weave
+int main(int argc, char** argv) {
+  Daemon::Options opts;
+  if (!opts.Parse(argc, argv)) {
+    Daemon::Options::ShowUsage(argv[0]);
+    return 1;
+  }
+  Daemon daemon{opts};
+  LedFlasherHandler handler;
+  handler.Register(daemon.GetDevice());
+  daemon.Run();
+  return 0;
+}
diff --git a/examples/daemon/daemon.gyp b/examples/daemon/light/daemon.gyp
similarity index 86%
copy from examples/daemon/daemon.gyp
copy to examples/daemon/light/daemon.gyp
index c6f8837..e8bb646 100644
--- a/examples/daemon/daemon.gyp
+++ b/examples/daemon/light/daemon.gyp
@@ -4,10 +4,10 @@
 {
   'targets': [
     {
-      'target_name': 'weave_daemon',
+      'target_name': 'weave_daemon_light',
       'type': 'executable',
       'sources': [
-        'main.cc',
+        'light.cc',
       ],
       'dependencies': [
         '<@(DEPTH)/libweave_standalone.gyp:libweave',
diff --git a/examples/daemon/light_handler.h b/examples/daemon/light/light.cc
similarity index 68%
rename from examples/daemon/light_handler.h
rename to examples/daemon/light/light.cc
index 33b440a..484b9e1 100644
--- a/examples/daemon/light_handler.h
+++ b/examples/daemon/light/light.cc
@@ -2,21 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "examples/daemon/common/daemon.h"
+
 #include <weave/device.h>
 
 #include <base/bind.h>
 #include <base/memory/weak_ptr.h>
 
-namespace weave {
-namespace examples {
-namespace daemon {
-
 // LightHandler is a command handler example that shows
 // how to handle commands for a Weave light.
 class LightHandler {
  public:
   LightHandler() = default;
-  void Register(Device* device) {
+  void Register(weave::Device* device) {
     device_ = device;
 
     device->AddStateDefinitionsFromJson(R"({
@@ -50,18 +48,16 @@
         }
       }
     })");
-    device->AddCommandHandler(
-        "onOff.setConfig",
-        base::Bind(&LightHandler::OnOnOffSetConfig,
-                   weak_ptr_factory_.GetWeakPtr()));
-    device->AddCommandHandler(
-        "brightness.setConfig",
-         base::Bind(&LightHandler::OnBrightnessSetConfig,
-                    weak_ptr_factory_.GetWeakPtr()));
+    device->AddCommandHandler("onOff.setConfig",
+                              base::Bind(&LightHandler::OnOnOffSetConfig,
+                                         weak_ptr_factory_.GetWeakPtr()));
+    device->AddCommandHandler("brightness.setConfig",
+                              base::Bind(&LightHandler::OnBrightnessSetConfig,
+                                         weak_ptr_factory_.GetWeakPtr()));
   }
 
  private:
-  void OnBrightnessSetConfig(const std::weak_ptr<Command>& command) {
+  void OnBrightnessSetConfig(const std::weak_ptr<weave::Command>& command) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -78,13 +74,13 @@
       cmd->Complete({}, nullptr);
       return;
     }
-    ErrorPtr error;
-    Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
-                 "Invalid parameters");
+    weave::ErrorPtr error;
+    weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+                        "Invalid parameters");
     cmd->Abort(error.get(), nullptr);
   }
 
-  void OnOnOffSetConfig(const std::weak_ptr<Command>& command) {
+  void OnOnOffSetConfig(const std::weak_ptr<weave::Command>& command) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -103,20 +99,20 @@
       cmd->Complete({}, nullptr);
       return;
     }
-    ErrorPtr error;
-    Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
-                 "Invalid parameters");
+    weave::ErrorPtr error;
+    weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+                        "Invalid parameters");
     cmd->Abort(error.get(), nullptr);
   }
 
-  void UpdateLightState(void) {
+  void UpdateLightState() {
     base::DictionaryValue state;
     state.SetString("onOff.state", light_status_ ? "on" : "standby");
     state.SetInteger("brightness.brightness", brightness_state_);
     device_->SetStateProperties(state, nullptr);
   }
 
-  Device* device_{nullptr};
+  weave::Device* device_{nullptr};
 
   // Simulate the state of the light.
   bool light_status_;
@@ -124,6 +120,15 @@
   base::WeakPtrFactory<LightHandler> weak_ptr_factory_{this};
 };
 
-}  // namespace daemon
-}  // namespace examples
-}  // namespace weave
+int main(int argc, char** argv) {
+  Daemon::Options opts;
+  if (!opts.Parse(argc, argv)) {
+    Daemon::Options::ShowUsage(argv[0]);
+    return 1;
+  }
+  Daemon daemon{opts};
+  LightHandler handler;
+  handler.Register(daemon.GetDevice());
+  daemon.Run();
+  return 0;
+}
diff --git a/examples/daemon/daemon.gyp b/examples/daemon/lock/daemon.gyp
similarity index 86%
rename from examples/daemon/daemon.gyp
rename to examples/daemon/lock/daemon.gyp
index c6f8837..0402a29 100644
--- a/examples/daemon/daemon.gyp
+++ b/examples/daemon/lock/daemon.gyp
@@ -4,10 +4,10 @@
 {
   'targets': [
     {
-      'target_name': 'weave_daemon',
+      'target_name': 'weave_daemon_lock',
       'type': 'executable',
       'sources': [
-        'main.cc',
+        'lock.cc',
       ],
       'dependencies': [
         '<@(DEPTH)/libweave_standalone.gyp:libweave',
diff --git a/examples/daemon/lock_handler.h b/examples/daemon/lock/lock.cc
similarity index 63%
rename from examples/daemon/lock_handler.h
rename to examples/daemon/lock/lock.cc
index b2fd9b5..e1ca2d9 100644
--- a/examples/daemon/lock_handler.h
+++ b/examples/daemon/lock/lock.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "examples/daemon/common/daemon.h"
+
 #include <weave/device.h>
 #include <weave/enum_to_string.h>
 
@@ -9,29 +11,26 @@
 #include <base/memory/weak_ptr.h>
 
 namespace weave {
-
 namespace lockstate {
 enum class LockState { kUnlocked, kLocked, kPartiallyLocked };
 
 const weave::EnumToStringMap<LockState>::Map kLockMapMethod[] = {
-  {LockState::kLocked, "locked"},
-  {LockState::kUnlocked, "unlocked"},
-  {LockState::kPartiallyLocked, "partiallyLocked"}};
+    {LockState::kLocked, "locked"},
+    {LockState::kUnlocked, "unlocked"},
+    {LockState::kPartiallyLocked, "partiallyLocked"}};
 }  // namespace lockstate
 
 template <>
 EnumToStringMap<lockstate::LockState>::EnumToStringMap()
-  : EnumToStringMap(lockstate::kLockMapMethod) {}
-
-namespace examples {
-namespace daemon {
+    : EnumToStringMap(lockstate::kLockMapMethod) {}
+}  // namespace weave
 
 // LockHandler is a command handler example that shows
 // how to handle commands for a Weave lock.
 class LockHandler {
  public:
   LockHandler() = default;
-  void Register(Device* device) {
+  void Register(weave::Device* device) {
     device_ = device;
 
     device->AddStateDefinitionsFromJson(R"({
@@ -52,14 +51,13 @@
           }
         }
     })");
-    device->AddCommandHandler(
-        "lock.setConfig",
-        base::Bind(&LockHandler::OnLockSetConfig,
-                   weak_ptr_factory_.GetWeakPtr()));
+    device->AddCommandHandler("lock.setConfig",
+                              base::Bind(&LockHandler::OnLockSetConfig,
+                                         weak_ptr_factory_.GetWeakPtr()));
   }
 
  private:
-  void OnLockSetConfig(const std::weak_ptr<Command>& command) {
+  void OnLockSetConfig(const std::weak_ptr<weave::Command>& command) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -68,13 +66,13 @@
     if (cmd->GetParameters()->GetString("lockedState", &requested_state)) {
       LOG(INFO) << cmd->GetName() << " state: " << requested_state;
 
-      lockstate::LockState new_lock_status;
+      weave::lockstate::LockState new_lock_status;
 
       if (!weave::StringToEnum(requested_state, &new_lock_status)) {
         // Invalid lock state was specified.
-        ErrorPtr error;
-        Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
-                     "Invalid parameters");
+        weave::ErrorPtr error;
+        weave::Error::AddTo(&error, FROM_HERE, "example",
+                            "invalid_parameter_value", "Invalid parameters");
         cmd->Abort(error.get(), nullptr);
         return;
       }
@@ -88,26 +86,35 @@
       cmd->Complete({}, nullptr);
       return;
     }
-    ErrorPtr error;
-    Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
-                 "Invalid parameters");
+    weave::ErrorPtr error;
+    weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
+                        "Invalid parameters");
     cmd->Abort(error.get(), nullptr);
   }
 
-  void UpdateLockState(void) {
+  void UpdateLockState() {
     base::DictionaryValue state;
     std::string updated_state = weave::EnumToString(lock_state_);
     state.SetString("lock.lockedState", updated_state);
     device_->SetStateProperties(state, nullptr);
   }
 
-  Device* device_{nullptr};
+  weave::Device* device_{nullptr};
 
   // Simulate the state of the light.
-  lockstate::LockState lock_state_{lockstate::LockState::kLocked};
+  weave::lockstate::LockState lock_state_{weave::lockstate::LockState::kLocked};
   base::WeakPtrFactory<LockHandler> weak_ptr_factory_{this};
 };
 
-}  // namespace daemon
-}  // namespace examples
-}  // namespace weave
+int main(int argc, char** argv) {
+  Daemon::Options opts;
+  if (!opts.Parse(argc, argv)) {
+    Daemon::Options::ShowUsage(argv[0]);
+    return 1;
+  }
+  Daemon daemon{opts};
+  LockHandler handler;
+  handler.Register(daemon.GetDevice());
+  daemon.Run();
+  return 0;
+}
diff --git a/examples/daemon/main.cc b/examples/daemon/main.cc
deleted file mode 100644
index a4ec366..0000000
--- a/examples/daemon/main.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <weave/device.h>
-#include <weave/error.h>
-
-#include <base/bind.h>
-
-#include "examples/daemon/ledflasher_handler.h"
-#include "examples/daemon/light_handler.h"
-#include "examples/daemon/lock_handler.h"
-#include "examples/daemon/sample_handler.h"
-
-#include "examples/provider/avahi_client.h"
-#include "examples/provider/bluez_client.h"
-#include "examples/provider/curl_http_client.h"
-#include "examples/provider/event_http_server.h"
-#include "examples/provider/event_network.h"
-#include "examples/provider/event_task_runner.h"
-#include "examples/provider/file_config_store.h"
-#include "examples/provider/wifi_manager.h"
-
-namespace {
-
-// Supported LED count on this device
-const size_t kLedCount = 3;
-
-void ShowUsage(const std::string& name) {
-  LOG(ERROR) << "\nUsage: " << name << " <option(s)>"
-             << "\nOptions:\n"
-             << "\t-h,--help                    Show this help message\n"
-             << "\t--v=LEVEL                    Logging level\n"
-             << "\t-b,--bootstrapping           Force WiFi bootstrapping\n"
-             << "\t-d,--disable_security        Disable privet security\n"
-             << "\t--registration_ticket=TICKET Register device with the "
-                "given ticket\n"
-             << "\t--disable_privet             Disable local privet\n"
-             << "\t--type=UIDEVICEKIND          Create a device with the "
-                "specified ui device kind\n";
-}
-
-void OnRegisterDeviceDone(weave::Device* device, weave::ErrorPtr error) {
-  if (error)
-    LOG(ERROR) << "Fail to register device: " << error->GetMessage();
-  else
-    LOG(INFO) << "Device registered: " << device->GetSettings().cloud_id;
-}
-
-}  // namespace
-
-int main(int argc, char** argv) {
-  bool force_bootstrapping = false;
-  bool disable_security = false;
-  bool disable_privet = false;
-  std::string registration_ticket;
-  std::string ui_device_kind;
-  for (int i = 1; i < argc; ++i) {
-    std::string arg = argv[i];
-    if (arg == "-h" || arg == "--help") {
-      ShowUsage(argv[0]);
-      return 0;
-    } else if (arg == "-b" || arg == "--bootstrapping") {
-      force_bootstrapping = true;
-    } else if (arg == "-d" || arg == "--disable_security") {
-      disable_security = true;
-    } else if (arg == "--disable_privet") {
-      disable_privet = true;
-    } else if (arg.find("--registration_ticket") != std::string::npos) {
-      auto pos = arg.find("=");
-      if (pos == std::string::npos) {
-        ShowUsage(argv[0]);
-        return 1;
-      }
-      registration_ticket = arg.substr(pos + 1);
-    } else if (arg.find("--v") != std::string::npos) {
-      auto pos = arg.find("=");
-      if (pos == std::string::npos) {
-        ShowUsage(argv[0]);
-        return 1;
-      }
-      logging::SetMinLogLevel(-std::stoi(arg.substr(pos + 1)));
-    } else if (arg.find("--type") != std::string::npos) {
-      auto pos = arg.find("=");
-      if (pos == std::string::npos) {
-        ShowUsage(argv[0]);
-        return 1;
-      }
-      ui_device_kind = arg.substr(pos + 1);
-    } else {
-      ShowUsage(argv[0]);
-      return 1;
-    }
-  }
-
-  weave::examples::FileConfigStore config_store{disable_security};
-  weave::examples::EventTaskRunner task_runner;
-  weave::examples::CurlHttpClient http_client{&task_runner};
-  weave::examples::EventNetworkImpl network{&task_runner};
-  weave::examples::BluetoothImpl bluetooth;
-  std::unique_ptr<weave::examples::AvahiClient> dns_sd;
-  std::unique_ptr<weave::examples::HttpServerImpl> http_server;
-  std::unique_ptr<weave::examples::WifiImpl> wifi;
-
-  if (!disable_privet) {
-    network.SetSimulateOffline(force_bootstrapping);
-
-    dns_sd.reset(new weave::examples::AvahiClient);
-    http_server.reset(new weave::examples::HttpServerImpl{&task_runner});
-    if (weave::examples::WifiImpl::HasWifiCapability())
-      wifi.reset(new weave::examples::WifiImpl{&task_runner, &network});
-  }
-  std::unique_ptr<weave::Device> device{weave::Device::Create(
-      &config_store, &task_runner, &http_client, &network, dns_sd.get(),
-      http_server.get(), wifi.get(), &bluetooth)};
-
-  if (!registration_ticket.empty()) {
-    device->Register(registration_ticket,
-                     base::Bind(&OnRegisterDeviceDone, device.get()));
-  }
-
-  weave::examples::daemon::SampleHandler sample{&task_runner};
-  weave::examples::daemon::LedFlasherHandler ledFlasher;
-  sample.Register(device.get());
-  ledFlasher.Register(device.get());
-
-  // If the caller specified a particular ui device kind, register the
-  // correspoinding device handlers
-  // TODO: move this to before device registration, as this should also
-  // cause a particular model manifest to be used.
-  weave::examples::daemon::LightHandler lightHandler;
-  weave::examples::daemon::LockHandler lockHandler;
-  if (!ui_device_kind.empty()) {
-    if (ui_device_kind == "light") {
-      lightHandler.Register(device.get());
-    } else if (ui_device_kind == "lock") {
-      lockHandler.Register(device.get());
-    }
-  }
-
-  task_runner.Run();
-
-  LOG(INFO) << "exit";
-  return 0;
-}
diff --git a/examples/daemon/daemon.gyp b/examples/daemon/sample/daemon.gyp
similarity index 86%
copy from examples/daemon/daemon.gyp
copy to examples/daemon/sample/daemon.gyp
index c6f8837..29d8235 100644
--- a/examples/daemon/daemon.gyp
+++ b/examples/daemon/sample/daemon.gyp
@@ -4,10 +4,10 @@
 {
   'targets': [
     {
-      'target_name': 'weave_daemon',
+      'target_name': 'weave_daemon_sample',
       'type': 'executable',
       'sources': [
-        'main.cc',
+        'sample.cc',
       ],
       'dependencies': [
         '<@(DEPTH)/libweave_standalone.gyp:libweave',
diff --git a/examples/daemon/sample_handler.h b/examples/daemon/sample/sample.cc
similarity index 80%
rename from examples/daemon/sample_handler.h
rename to examples/daemon/sample/sample.cc
index eca3452..905a977 100644
--- a/examples/daemon/sample_handler.h
+++ b/examples/daemon/sample/sample.cc
@@ -2,16 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "examples/daemon/common/daemon.h"
+
 #include <weave/device.h>
 #include <weave/provider/task_runner.h>
 
 #include <base/bind.h>
 #include <base/memory/weak_ptr.h>
 
-namespace weave {
-namespace examples {
-namespace daemon {
-
 // SampleHandler is a command handler example.
 // It implements the following commands:
 // - _hello: handle a command with an argument and set its results.
@@ -19,9 +17,9 @@
 // - _countdown: handle long running command and report progress.
 class SampleHandler {
  public:
-  SampleHandler(provider::TaskRunner* task_runner)
+  SampleHandler(weave::provider::TaskRunner* task_runner)
       : task_runner_{task_runner} {}
-  void Register(Device* device) {
+  void Register(weave::Device* device) {
     device_ = device;
 
     device->AddCommandDefinitionsFromJson(R"({
@@ -69,7 +67,7 @@
   }
 
  private:
-  void OnHelloCommand(const std::weak_ptr<Command>& command) {
+  void OnHelloCommand(const std::weak_ptr<weave::Command>& command) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -77,9 +75,9 @@
 
     std::string name;
     if (!cmd->GetParameters()->GetString("_name", &name)) {
-      ErrorPtr error;
-      Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value",
-                   "Name is missing");
+      weave::ErrorPtr error;
+      weave::Error::AddTo(&error, FROM_HERE, "example",
+                          "invalid_parameter_value", "Name is missing");
       cmd->Abort(error.get(), nullptr);
       return;
     }
@@ -90,7 +88,7 @@
     LOG(INFO) << cmd->GetName() << " command finished: " << result;
   }
 
-  void OnPingCommand(const std::weak_ptr<Command>& command) {
+  void OnPingCommand(const std::weak_ptr<weave::Command>& command) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -107,7 +105,7 @@
     LOG(INFO) << cmd->GetName() << " command finished: " << result;
   }
 
-  void OnCountdownCommand(const std::weak_ptr<Command>& command) {
+  void OnCountdownCommand(const std::weak_ptr<weave::Command>& command) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -121,7 +119,7 @@
     DoTick(cmd, seconds);
   }
 
-  void DoTick(const std::weak_ptr<Command>& command, int seconds) {
+  void DoTick(const std::weak_ptr<weave::Command>& command, int seconds) {
     auto cmd = command.lock();
     if (!cmd)
       return;
@@ -148,13 +146,22 @@
     LOG(INFO) << cmd->GetName() << " command finished: " << result;
   }
 
-  Device* device_{nullptr};
-  provider::TaskRunner* task_runner_{nullptr};
+  weave::Device* device_{nullptr};
+  weave::provider::TaskRunner* task_runner_{nullptr};
 
   int ping_count_{0};
   base::WeakPtrFactory<SampleHandler> weak_ptr_factory_{this};
 };
 
-}  // namespace daemon
-}  // namespace examples
-}  // namespace weave
+int main(int argc, char** argv) {
+  Daemon::Options opts;
+  if (!opts.Parse(argc, argv)) {
+    Daemon::Options::ShowUsage(argv[0]);
+    return 1;
+  }
+  Daemon daemon{opts};
+  SampleHandler handler{daemon.GetTaskRunner()};
+  handler.Register(daemon.GetDevice());
+  daemon.Run();
+  return 0;
+}
diff --git a/src/commands/schema_utils.h b/src/commands/schema_utils.h
index 826bab8..0c1d1b3 100644
--- a/src/commands/schema_utils.h
+++ b/src/commands/schema_utils.h
@@ -5,6 +5,7 @@
 #ifndef LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_
 #define LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_
 
+#include <cmath>
 #include <limits>
 #include <map>
 #include <memory>
diff --git a/src/privet/wifi_bootstrap_manager.cc b/src/privet/wifi_bootstrap_manager.cc
index 4f46ea4..292622d 100644
--- a/src/privet/wifi_bootstrap_manager.cc
+++ b/src/privet/wifi_bootstrap_manager.cc
@@ -20,7 +20,10 @@
 
 namespace {
 
+const int kMonitoringWithSsidTimeoutSeconds = 15;
 const int kMonitoringTimeoutSeconds = 120;
+const int kBootstrapTimeoutSeconds = 600;
+const int kConnectingTimeoutSeconds = 180;
 
 const EnumToStringMap<WifiBootstrapManager::State>::Map kWifiSetupStateMap[] = {
     {WifiBootstrapManager::State::kDisabled, "disabled"},
@@ -55,7 +58,8 @@
                  lifetime_weak_factory_.GetWeakPtr()));
   if (config_->GetSettings().last_configured_ssid.empty()) {
     // Give implementation some time to figure out state.
-    StartMonitoring(base::TimeDelta::FromSeconds(15));
+    StartMonitoring(
+        base::TimeDelta::FromSeconds(kMonitoringWithSsidTimeoutSeconds));
   } else {
     StartMonitoring(base::TimeDelta::FromSeconds(kMonitoringTimeoutSeconds));
   }
@@ -80,28 +84,30 @@
     task_runner_->PostDelayedTask(
         FROM_HERE, base::Bind(&WifiBootstrapManager::OnBootstrapTimeout,
                               tasks_weak_factory_.GetWeakPtr()),
-        base::TimeDelta::FromMinutes(10));
+        base::TimeDelta::FromSeconds(kBootstrapTimeoutSeconds));
   }
   // TODO(vitalybuka): Add SSID probing.
   privet_ssid_ = GenerateSsid();
   CHECK(!privet_ssid_.empty());
+
+  VLOG(1) << "Starting AP with SSID: " << privet_ssid_;
   wifi_->StartAccessPoint(privet_ssid_);
 }
 
 void WifiBootstrapManager::EndBootstrapping() {
+  VLOG(1) << "Stopping AP";
   wifi_->StopAccessPoint();
   privet_ssid_.clear();
 }
 
 void WifiBootstrapManager::StartConnecting(const std::string& ssid,
                                            const std::string& passphrase) {
-  VLOG(1) << "WiFi is attempting to connect. (ssid=" << ssid
-          << ", pass=" << passphrase << ").";
+  VLOG(1) << "Attempting connect to SSID:" << ssid;
   UpdateState(State::kConnecting);
   task_runner_->PostDelayedTask(
       FROM_HERE, base::Bind(&WifiBootstrapManager::OnConnectTimeout,
                             tasks_weak_factory_.GetWeakPtr()),
-      base::TimeDelta::FromMinutes(3));
+      base::TimeDelta::FromSeconds(kConnectingTimeoutSeconds));
   wifi_->Connect(ssid, passphrase,
                  base::Bind(&WifiBootstrapManager::OnConnectDone,
                             tasks_weak_factory_.GetWeakPtr(), ssid));
@@ -110,6 +116,11 @@
 void WifiBootstrapManager::EndConnecting() {}
 
 void WifiBootstrapManager::StartMonitoring(const base::TimeDelta& timeout) {
+  monitor_until_ = {};
+  ContinueMonitoring(timeout);
+}
+
+void WifiBootstrapManager::ContinueMonitoring(const base::TimeDelta& timeout) {
   VLOG(1) << "Monitoring connectivity.";
   // We already have a callback in place with |network_| to update our
   // connectivity state.  See OnConnectivityChange().
@@ -134,8 +145,8 @@
 void WifiBootstrapManager::EndMonitoring() {}
 
 void WifiBootstrapManager::UpdateState(State new_state) {
-  VLOG(3) << "Switching state from " << static_cast<int>(state_) << " to "
-          << static_cast<int>(new_state);
+  VLOG(3) << "Switching state from " << EnumToString(state_) << " to "
+          << EnumToString(new_state);
   // Abort irrelevant tasks.
   tasks_weak_factory_.InvalidateWeakPtrs();
 
@@ -227,29 +238,26 @@
 }
 
 void WifiBootstrapManager::OnConnectivityChange() {
-  VLOG(3) << "ConnectivityChanged: "
-          << EnumToString(network_->GetConnectionState());
   UpdateConnectionState();
 
-  if (state_ == State::kMonitoring ||  // Reset monitoring timeout.
+  if (state_ == State::kMonitoring ||
       (state_ != State::kDisabled &&
        network_->GetConnectionState() == Network::State::kOnline)) {
-    StartMonitoring(base::TimeDelta::FromSeconds(kMonitoringTimeoutSeconds));
+    ContinueMonitoring(base::TimeDelta::FromSeconds(kMonitoringTimeoutSeconds));
   }
 }
 
 void WifiBootstrapManager::OnMonitorTimeout() {
-  VLOG(1) << "Spent too long offline.  Entering bootstrap mode.";
+  VLOG(1) << "Spent too long offline. Entering bootstrap mode.";
   // TODO(wiley) Retrieve relevant errors from shill.
   StartBootstrapping();
 }
 
 void WifiBootstrapManager::UpdateConnectionState() {
   connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
-  if (config_->GetSettings().last_configured_ssid.empty())
-    return;
 
   Network::State service_state{network_->GetConnectionState()};
+  VLOG(3) << "New network state: " << EnumToString(service_state);
   switch (service_state) {
     case Network::State::kOffline:
       connection_state_ = ConnectionState{ConnectionState::kOffline};
diff --git a/src/privet/wifi_bootstrap_manager.h b/src/privet/wifi_bootstrap_manager.h
index 71dbb49..62a77c2 100644
--- a/src/privet/wifi_bootstrap_manager.h
+++ b/src/privet/wifi_bootstrap_manager.h
@@ -74,6 +74,7 @@
   void EndConnecting();
 
   void StartMonitoring(const base::TimeDelta& timeout);
+  void ContinueMonitoring(const base::TimeDelta& timeout);
   void EndMonitoring();
 
   // Update the current state, post tasks to notify listeners accordingly to
diff --git a/src/weave_unittest.cc b/src/weave_unittest.cc
index 6ff3f6d..fb00cc9 100644
--- a/src/weave_unittest.cc
+++ b/src/weave_unittest.cc
@@ -21,13 +21,14 @@
 #include "src/bind_lambda.h"
 
 using testing::_;
+using testing::AtLeast;
 using testing::AtMost;
 using testing::HasSubstr;
+using testing::InSequence;
 using testing::Invoke;
 using testing::InvokeWithoutArgs;
 using testing::MatchesRegex;
 using testing::Mock;
-using testing::AtLeast;
 using testing::Return;
 using testing::ReturnRefOfCopy;
 using testing::StartsWith;
@@ -266,10 +267,13 @@
 
   void NotifyNetworkChanged(provider::Network::State state,
                             base::TimeDelta delay) {
-    EXPECT_CALL(network_, GetConnectionState()).WillRepeatedly(Return(state));
-    for (const auto& cb : network_callbacks_) {
-      task_runner_.PostDelayedTask(FROM_HERE, cb, delay);
-    }
+    auto task = [this, state] {
+      EXPECT_CALL(network_, GetConnectionState()).WillRepeatedly(Return(state));
+      for (const auto& cb : network_callbacks_)
+        cb.Run();
+    };
+
+    task_runner_.PostDelayedTask(FROM_HERE, base::Bind(task), delay);
   }
 
   std::map<std::string, provider::HttpServer::RequestHandlerCallback>
@@ -460,4 +464,67 @@
   StartDevice();
 }
 
+TEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithNoSsid) {
+  EXPECT_CALL(network_, GetConnectionState())
+      .WillRepeatedly(Return(Network::State::kOffline));
+  NotifyNetworkChanged(provider::Network::State::kOnline,
+                       base::TimeDelta::FromHours(15));
+
+  {
+    InSequence s;
+    auto time_stamp = task_runner_.GetClock()->Now();
+
+    EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
+        .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
+          EXPECT_LE(task_runner_.GetClock()->Now() - time_stamp,
+                    base::TimeDelta::FromMinutes(1));
+          time_stamp = task_runner_.GetClock()->Now();
+        }));
+
+    EXPECT_CALL(wifi_, StopAccessPoint())
+        .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
+          EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
+                    base::TimeDelta::FromMinutes(5));
+          time_stamp = task_runner_.GetClock()->Now();
+          task_runner_.Break();
+        }));
+  }
+
+  StartDevice();
+}
+
+TEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithSsid) {
+  EXPECT_CALL(config_store_, LoadSettings())
+      .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
+  EXPECT_CALL(network_, GetConnectionState())
+      .WillRepeatedly(Return(Network::State::kOffline));
+  NotifyNetworkChanged(provider::Network::State::kOnline,
+                       base::TimeDelta::FromHours(15));
+
+  {
+    InSequence s;
+    auto time_stamp = task_runner_.GetClock()->Now();
+    for (size_t i = 0; i < 10; ++i) {
+      EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
+          .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
+            EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
+                      base::TimeDelta::FromMinutes(1));
+            time_stamp = task_runner_.GetClock()->Now();
+          }));
+
+      EXPECT_CALL(wifi_, StopAccessPoint())
+          .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
+            EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
+                      base::TimeDelta::FromMinutes(5));
+            time_stamp = task_runner_.GetClock()->Now();
+          }));
+    }
+
+    EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
+        .WillOnce(InvokeWithoutArgs([this]() { task_runner_.Break(); }));
+  }
+
+  StartDevice();
+}
+
 }  // namespace weave