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;
21
22const VERSION_GET_PROTOCOL: u8 = 0;
23const VERSION_GET_FIRMWARE: u8 = 1;
24const VERSION_GET_DEVICE_TYPE: u8 = 2;
25
26pub const APPCHANNEL_MTU: usize = 31;
28
29pub struct Platform {
33 version_comm: Mutex<(Sender<Packet>, Receiver<Packet>)>,
34 appchannel_comm: Mutex<Option<(Sender<Packet>, Receiver<Packet>)>>,
35 uplink: Sender<Packet>,
36}
37impl Platform {
39 pub(crate) fn new(uplink: Sender<Packet>, downlink: Receiver<Packet>) -> Self {
40 let (_, version_downlink, appchannel_downlink, _) = crtp_channel_dispatcher(downlink);
41
42 Self {
43 version_comm: Mutex::new((uplink.clone(), version_downlink)),
44 appchannel_comm: Mutex::new(Some((uplink.clone(), appchannel_downlink))),
45 uplink,
46 }
47 }
48
49 pub async fn protocol_version(&self) -> Result<u8> {
57 let (uplink, downlink) = &*self.version_comm.lock().await;
58
59 let pk = Packet::new(PLATFORM_PORT, VERSION_CHANNEL, vec![VERSION_GET_PROTOCOL]);
60 uplink.send_async(pk).await?;
61
62 let pk = downlink.recv_async().await?;
63
64 if pk.get_data()[0] != VERSION_GET_PROTOCOL {
65 return Err(Error::ProtocolError("Wrong version answer".to_owned()));
66 }
67
68 Ok(pk.get_data()[1])
69 }
70
71 pub async fn firmware_version(&self) -> Result<String> {
77 let (uplink, downlink) = &*self.version_comm.lock().await;
78
79 let pk = Packet::new(PLATFORM_PORT, VERSION_CHANNEL, vec![VERSION_GET_FIRMWARE]);
80 uplink.send_async(pk).await?;
81
82 let pk = downlink.recv_async().await?;
83
84 if pk.get_data()[0] != VERSION_GET_FIRMWARE {
85 return Err(Error::ProtocolError("Wrong version answer".to_owned()));
86 }
87
88 let version = String::from_utf8_lossy(&pk.get_data()[1..]);
89
90 Ok(version.to_string())
91 }
92
93 pub async fn device_type_name(&self) -> Result<String> {
98 let (uplink, downlink) = &*self.version_comm.lock().await;
99
100 let pk = Packet::new(
101 PLATFORM_PORT,
102 VERSION_CHANNEL,
103 vec![VERSION_GET_DEVICE_TYPE],
104 );
105 uplink.send_async(pk).await?;
106
107 let pk = downlink.recv_async().await?;
108
109 if pk.get_data()[0] != VERSION_GET_DEVICE_TYPE {
110 return Err(Error::ProtocolError("Wrong device type answer".to_owned()));
111 }
112
113 let version = String::from_utf8_lossy(&pk.get_data()[1..]);
114
115 Ok(version.to_string())
116 }
117
118 pub async fn get_app_channel(
126 &self,
127 ) -> Option<(
128 impl Sink<AppChannelPacket>,
129 impl Stream<Item = AppChannelPacket>,
130 )> {
131 if let Some((tx, rx)) = self.appchannel_comm.lock().await.take() {
132 let app_tx = Box::pin(tx.into_sink().with_flat_map(|app_pk: AppChannelPacket| {
135 stream::once(async { Ok(Packet::new(PLATFORM_PORT, APP_CHANNEL, app_pk.0)) })
136 }));
137
138 let app_rx = rx
139 .into_stream()
140 .map(|pk: Packet| AppChannelPacket(pk.get_data().to_vec()))
141 .boxed();
142
143 Some((app_tx, app_rx))
144 } else {
145 None
146 }
147 }
148
149 pub async fn set_cont_wave(&self, activate: bool) -> Result<()> {
160 let command = if activate { 1 } else { 0 };
161 self.uplink
162 .send_async(Packet::new(
163 PLATFORM_PORT,
164 PLATFORM_COMMAND,
165 vec![PLATFORM_SET_CONT_WAVE, command],
166 ))
167 .await?;
168 Ok(())
169 }
170}
171
172#[derive(Debug, PartialEq, Eq)]
204pub struct AppChannelPacket(Vec<u8>);
205
206impl TryFrom<Vec<u8>> for AppChannelPacket {
207 type Error = Error;
208
209 fn try_from(value: Vec<u8>) -> Result<Self> {
210 if value.len() <= APPCHANNEL_MTU {
211 Ok(AppChannelPacket(value))
212 } else {
213 Err(Error::AppchannelPacketTooLarge)
214 }
215 }
216}
217
218impl TryFrom<&[u8]> for AppChannelPacket {
219 type Error = Error;
220
221 fn try_from(value: &[u8]) -> Result<Self> {
222 if value.len() <= APPCHANNEL_MTU {
223 Ok(AppChannelPacket(value.to_vec()))
224 } else {
225 Err(Error::AppchannelPacketTooLarge)
226 }
227 }
228}
229
230impl From<AppChannelPacket> for Vec<u8> {
231 fn from(pk: AppChannelPacket) -> Self {
232 pk.0
233 }
234}
235
236macro_rules! from_impl {
240 ($n:expr) => {
241 impl From<[u8; $n]> for AppChannelPacket {
242 fn from(v: [u8; $n]) -> Self {
243 AppChannelPacket(v.to_vec())
244 }
245 }
246 };
247}
248
249from_impl!(0);
250from_impl!(1);
251from_impl!(2);
252from_impl!(3);
253from_impl!(4);
254from_impl!(5);
255from_impl!(6);
256from_impl!(7);
257from_impl!(8);
258from_impl!(9);
259from_impl!(10);
260from_impl!(11);
261from_impl!(12);
262from_impl!(13);
263from_impl!(14);
264from_impl!(15);
265from_impl!(16);
266from_impl!(17);
267from_impl!(18);
268from_impl!(19);
269from_impl!(20);
270from_impl!(21);
271from_impl!(22);
272from_impl!(23);
273from_impl!(24);
274from_impl!(25);
275from_impl!(26);
276from_impl!(27);
277from_impl!(28);
278from_impl!(29);
279from_impl!(30);