You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
5.0KB

  1. use futures::Future;
  2. use qmetaobject::*;
  3. #[derive(QObject, Default)]
  4. pub struct PairingManager {
  5. base: qt_base_class!(trait QObject),
  6. discovered_bridges: qt_signal!(count: usize),
  7. errored: qt_signal!(err: String),
  8. authenticated: qt_signal!(address: String, username: String),
  9. start_searching: qt_method!(fn(&self)),
  10. }
  11. impl PairingManager {
  12. fn start_searching(&self) {
  13. let callback_discovered = {
  14. let ptr = QPointer::from(&*self);
  15. queued_callback(move |count| {
  16. ptr.as_ref().map(|x| x.discovered_bridges(count));
  17. })
  18. };
  19. let callback_errored_1 = {
  20. let ptr = QPointer::from(&*self);
  21. queued_callback(move |err| {
  22. ptr.as_ref().map(|x| x.errored(err));
  23. })
  24. };
  25. let callback_errored_2 = callback_errored_1.clone();
  26. let callback_authenticated = {
  27. let ptr = QPointer::from(&*self);
  28. queued_callback(move |(address, username)| {
  29. ptr.as_ref().map(|x| x.authenticated(address, username));
  30. })
  31. };
  32. tokio::spawn(huey::bridge_discovery::discover()
  33. .then(move |result| {
  34. println!("{:?}", result);
  35. match result {
  36. Ok(bridges) => {
  37. if bridges.len() == 0 {
  38. callback_errored_1("Couldn't find a bridge.".to_owned());
  39. Err(())
  40. }
  41. else {
  42. callback_discovered(bridges.len());
  43. Ok(bridges)
  44. }
  45. },
  46. Err(err) => {
  47. eprintln!("{:?}", err);
  48. callback_errored_1(format!("{}", err));
  49. Err(())
  50. }
  51. }
  52. })
  53. .and_then(move |bridges| {
  54. fn run(bridges: Vec<huey::bridge_discovery::DiscoveredBridge>, i: usize) -> Box<Future<Item=(huey::bridge_discovery::DiscoveredBridge, String), Error=(Vec<huey::bridge_discovery::DiscoveredBridge>, usize, huey::HueError)> + Send> {
  55. let bridge: &huey::bridge_discovery::DiscoveredBridge = &bridges[i];
  56. Box::new(huey::registration::register(&bridge.internalipaddress, "radiate")
  57. .then(move |res| {
  58. match res {
  59. Ok(username) => Ok((bridges.into_iter().nth(i).unwrap(), username)),
  60. Err(err) => Err((bridges, i, err)),
  61. }
  62. })
  63. .or_else(|(bridges, i, err)| {
  64. match err {
  65. huey::HueError::LinkButtonNotPressed => {
  66. if i + 1 < bridges.len() {
  67. run(bridges, i + 1)
  68. } else {
  69. Box::new(tokio::timer::Delay::new(std::time::Instant::now() + std::time::Duration::from_millis(400))
  70. .or_else(|err| {
  71. eprintln!("Timer failed: {:?}", err);
  72. Ok(())
  73. })
  74. .and_then(|_| run(bridges, 0)))
  75. }
  76. },
  77. other_err => {
  78. Box::new(futures::future::err((bridges, i, other_err)))
  79. }
  80. }
  81. }))
  82. }
  83. run(bridges, 0)
  84. .then(move |res| {
  85. match res {
  86. Ok((bridge, username)) => {
  87. callback_authenticated((bridge.internalipaddress, username));
  88. },
  89. Err((_, _, err)) => {
  90. eprintln!("{:?}", err);
  91. callback_errored_2(format!("{}", err));
  92. },
  93. }
  94. Ok(())
  95. })
  96. }));
  97. }
  98. }