crazyflie_lib/subsystems/
platform.rs1use std::convert::TryFrom;
8
9use crate::{crtp_utils::crtp_channel_dispatcher, Error, Result};
10use crazyflie_link::Packet;
11use flume::{Receiver, Sender};
12use futures::{lock::Mutex, stream, Sink, SinkExt, Stream, StreamExt};
13
14use crate::crazyflie::PLATFORM_PORT;
15
16const PLATFORM_COMMAND: u8 = 0;
17const VERSION_CHANNEL: u8 = 1;
18const APP_CHANNEL: u8 = 2;
19
20const PLATFORM_SET_CONT_WAVE: u8 = 0;
21const PLATFORM_REQUEST_ARMING: u8 = 1;
22const PLATFORM_REQUEST_CRASH_RECOVERY: u8 = 2;
23
24const VERSION_GET_PROTOCOL: u8 = 0;
25const VERSION_GET_FIRMWARE: u8 = 1;
26const VERSION_GET_DEVICE_TYPE: u8 = 2;
27
28pub const APPCHANNEL_MTU: usize = 31;
30
31pub struct Platform {
35 version_comm: Mutex<(Sender<Packet>, Receiver<Packet>)>,
36 appchannel_comm: Mutex<Option<(Sender<Packet>, Receiver<Packet>)>>,
37 uplink: Sender<Packet>,
38}
39impl Platform {
41 pub(crate) fn new(uplink: Sender<Packet>, downlink: Receiver<Packet>) -> Self {
42 let (_, version_downlink, appchannel_downlink, _) = crtp_channel_dispatcher(downlink);
43
44 Self {
45 version_comm: Mutex::new((uplink.clone(), version_downlink)),
46 appchannel_comm: Mutex::new(Some((uplink.clone(), appchannel_downlink))),
47 uplink,
48 }
49 }
50
51 pub async fn protocol_version(&self) -> Result<u8> {
59 let (uplink, downlink) = &*self.version_comm.lock().await;
60
61 let pk = Packet::new(PLATFORM_PORT, VERSION_CHANNEL, vec![VERSION_GET_PROTOCOL]);
62 uplink.send_async(pk).await?;
63
64 let pk = downlink.recv_async().await?;
65
66 if pk.get_data()[0] != VERSION_GET_PROTOCOL {
67 return Err(Error::ProtocolError("Wrong version answer".to_owned()));
68 }
69
70 Ok(pk.get_data()[1])
71 }
72
73 pub async fn firmware_version(&self) -> Result<String> {
79 let (uplink, downlink) = &*self.version_comm.lock().await;
80
81 let pk = Packet::new(PLATFORM_PORT, VERSION_CHANNEL, vec![VERSION_GET_FIRMWARE]);
82 uplink.send_async(pk).await?;
83
84 let pk = downlink.recv_async().await?;
85
86 if pk.get_data()[0] != VERSION_GET_FIRMWARE {
87 return Err(Error::ProtocolError("Wrong version answer".to_owned()));
88 }
89
90 let version = String::from_utf8_lossy(&pk.get_data()[1..]);
91
92 Ok(version.to_string())
93 }
94
95 pub async fn device_type_name(&self) -> Result<String> {
100 let (uplink, downlink) = &*self.version_comm.lock().await;
101
102 let pk = Packet::new(
103 PLATFORM_PORT,
104 VERSION_CHANNEL,
105 vec![VERSION_GET_DEVICE_TYPE],
106 );
107 uplink.send_async(pk).await?;
108
109 let pk = downlink.recv_async().await?;
110
111 if pk.get_data()[0] != VERSION_GET_DEVICE_TYPE {
112 return Err(Error::ProtocolError("Wrong device type answer".to_owned()));
113 }
114
115 let version = String::from_utf8_lossy(&pk.get_data()[1..]);
116
117 Ok(version.to_string())
118 }
119
120 pub async fn get_app_channel(
128 &self,
129 ) -> Option<(
130 impl Sink<AppChannelPacket> + use<>,
131 impl Stream<Item = AppChannelPacket> + use<>,
132 )> {
133 match self.appchannel_comm.lock().await.take() { Some((tx, rx)) => {
134 let app_tx = Box::pin(tx.into_sink().with_flat_map(|app_pk: AppChannelPacket| {
137 stream::once(async { Ok(Packet::new(PLATFORM_PORT, APP_CHANNEL, app_pk.0)) })
138 }));
139
140 let app_rx = rx
141 .into_stream()
142 .map(|pk: Packet| AppChannelPacket(pk.get_data().to_vec()))
143 .boxed();
144
145 Some((app_tx, app_rx))
146 } _ => {
147 None
148 }}
149 }
150
151 pub async fn set_cont_wave(&self, activate: bool) -> Result<()> {
162 let command = if activate { 1 } else { 0 };
163 self.uplink
164 .send_async(Packet::new(
165 PLATFORM_PORT,
166 PLATFORM_COMMAND,
167 vec![PLATFORM_SET_CONT_WAVE, command],
168 ))
169 .await?;
170 Ok(())
171 }
172
173 pub async fn send_arming_request(&self, do_arm: bool) -> Result<()> {
181 let command = if do_arm { 1 } else { 0 };
182 self.uplink
183 .send_async(Packet::new(
184 PLATFORM_PORT,
185 PLATFORM_COMMAND,
186 vec![PLATFORM_REQUEST_ARMING, command],
187 ))
188 .await?;
189 Ok(())
190 }
191
192 pub async fn send_crash_recovery_request(&self) -> Result<()> {
196 self.uplink
197 .send_async(Packet::new(
198 PLATFORM_PORT,
199 PLATFORM_COMMAND,
200 vec![PLATFORM_REQUEST_CRASH_RECOVERY],
201 ))
202 .await?;
203 Ok(())
204 }
205}
206
207#[derive(Debug, PartialEq, Eq)]
239pub struct AppChannelPacket(Vec<u8>);
240
241impl TryFrom<Vec<u8>> for AppChannelPacket {
242 type Error = Error;
243
244 fn try_from(value: Vec<u8>) -> Result<Self> {
245 if value.len() <= APPCHANNEL_MTU {
246 Ok(AppChannelPacket(value))
247 } else {
248 Err(Error::AppchannelPacketTooLarge)
249 }
250 }
251}
252
253impl TryFrom<&[u8]> for AppChannelPacket {
254 type Error = Error;
255
256 fn try_from(value: &[u8]) -> Result<Self> {
257 if value.len() <= APPCHANNEL_MTU {
258 Ok(AppChannelPacket(value.to_vec()))
259 } else {
260 Err(Error::AppchannelPacketTooLarge)
261 }
262 }
263}
264
265impl From<AppChannelPacket> for Vec<u8> {
266 fn from(pk: AppChannelPacket) -> Self {
267 pk.0
268 }
269}
270
271macro_rules! from_impl {
275 ($n:expr_2021) => {
276 impl From<[u8; $n]> for AppChannelPacket {
277 fn from(v: [u8; $n]) -> Self {
278 AppChannelPacket(v.to_vec())
279 }
280 }
281 };
282}
283
284from_impl!(0);
285from_impl!(1);
286from_impl!(2);
287from_impl!(3);
288from_impl!(4);
289from_impl!(5);
290from_impl!(6);
291from_impl!(7);
292from_impl!(8);
293from_impl!(9);
294from_impl!(10);
295from_impl!(11);
296from_impl!(12);
297from_impl!(13);
298from_impl!(14);
299from_impl!(15);
300from_impl!(16);
301from_impl!(17);
302from_impl!(18);
303from_impl!(19);
304from_impl!(20);
305from_impl!(21);
306from_impl!(22);
307from_impl!(23);
308from_impl!(24);
309from_impl!(25);
310from_impl!(26);
311from_impl!(27);
312from_impl!(28);
313from_impl!(29);
314from_impl!(30);