forked from thirtythreeforty/neolink
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
222 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
use super::{BcCamera, Error, Result, RX_TIMEOUT}; | ||
use crate::bc::{model::*, xml::*}; | ||
|
||
/// Motion Status that the callback can send | ||
pub enum MotionStatus { | ||
/// Sent when motion is first detected | ||
Start, | ||
/// Sent when motion stops | ||
Stop, | ||
/// Sent when an Alarm about something other than motion was received | ||
NoChange, | ||
} | ||
|
||
/// This is a conveince type for the error of the MotionOutput callback | ||
pub type MotionOutputError = Result<bool>; | ||
|
||
/// Trait used as part of [`listen_on_motion`] to send motion messages | ||
pub trait MotionOutput { | ||
/// This is the callback used when motion is received | ||
/// | ||
/// If result is `Ok(true)` more messages will be sent | ||
/// | ||
/// If result if `Ok(false)` then message will be stopped | ||
/// | ||
/// If result is `Err(E)` then motion messages be stopped | ||
/// and an error will be thrown | ||
fn motion_recv(&mut self, motion_status: MotionStatus) -> MotionOutputError; | ||
} | ||
|
||
impl BcCamera { | ||
/// This message tells the camera to send the motion events to us | ||
/// Which are the recieved on msgid 33 | ||
fn start_motion_query(&self) -> Result<()> { | ||
let connection = self | ||
.connection | ||
.as_ref() | ||
.expect("Must be connected to listen to messages"); | ||
|
||
let sub = connection.subscribe(MSG_ID_MOTION_REQUEST)?; | ||
let msg = Bc { | ||
meta: BcMeta { | ||
msg_id: MSG_ID_MOTION_REQUEST, | ||
channel_id: self.channel_id, | ||
msg_num: self.new_message_num(), | ||
stream_type: 0, | ||
response_code: 0, | ||
class: 0x6414, | ||
}, | ||
body: BcBody::ModernMsg(ModernMsg { | ||
..Default::default() | ||
}), | ||
}; | ||
|
||
sub.send(msg)?; | ||
|
||
let msg = sub.rx.recv_timeout(RX_TIMEOUT)?; | ||
|
||
if let BcMeta { | ||
response_code: 200, .. | ||
} = msg.meta | ||
{ | ||
Ok(()) | ||
} else { | ||
Err(Error::UnintelligibleReply { | ||
reply: msg, | ||
why: "The camera did not accept the request to start motion", | ||
}) | ||
} | ||
} | ||
|
||
/// This requests that motion messages be listen to and sent to the | ||
/// output struct. | ||
/// | ||
/// The output structure must implement the [`MotionCallback`] trait | ||
pub fn listen_on_motion<T: MotionOutput>(&self, data_out: &mut T) -> Result<()> { | ||
self.start_motion_query()?; | ||
|
||
let connection = self | ||
.connection | ||
.as_ref() | ||
.expect("Must be connected to listen to messages"); | ||
|
||
// After start_motion_query (MSG_ID 31) the camera sends motion messages | ||
// when whenever motion is detected. | ||
let sub = connection.subscribe(MSG_ID_MOTION)?; | ||
|
||
loop { | ||
// Mostly ignore when timout is reached because these messages are only | ||
// sent when motion is detected which might means hours between messages | ||
// being received | ||
let msg = sub.rx.recv_timeout(RX_TIMEOUT); | ||
let status = match msg { | ||
Ok(motion_msg) => { | ||
if let BcBody::ModernMsg(ModernMsg { | ||
payload: | ||
Some(BcPayloads::BcXml(BcXml { | ||
alarm_event_list: Some(alarm_event_list), | ||
.. | ||
})), | ||
.. | ||
}) = motion_msg.body | ||
{ | ||
let mut result = MotionStatus::NoChange; | ||
for alarm_event in &alarm_event_list.alarm_events { | ||
if alarm_event.channel_id == self.channel_id { | ||
if alarm_event.status == "MD" { | ||
result = MotionStatus::Start; | ||
break; | ||
} else if alarm_event.status == "none" { | ||
result = MotionStatus::Stop; | ||
break; | ||
} | ||
} | ||
} | ||
Ok(result) | ||
} else { | ||
Ok(MotionStatus::NoChange) | ||
} | ||
} | ||
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => Ok(MotionStatus::NoChange), | ||
// On connection drop we stop | ||
Err(e @ std::sync::mpsc::RecvTimeoutError::Disconnected) => Err(e), | ||
}?; | ||
|
||
match data_out.motion_recv(status) { | ||
Ok(true) => {} | ||
Ok(false) => return Ok(()), | ||
Err(e) => return Err(e), | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.