lego_powered_up/
iodevice.rs1use tokio::sync::broadcast;
2
3use crate::hubs::{Channels, Tokens};
4use crate::notifications::{
5 DatasetType, NetworkCommand, PortOutputCommandFeedbackFormat,
6 PortValueCombinedFormat, PortValueSingleFormat,
7};
8use crate::IoTypeId;
9use crate::{Error, Result};
10use basic::Basic;
11use definition::Definition;
12use hubled::HubLed;
13use motor::EncoderMotor;
14use remote::RcDevice;
15use sensor::GenericSensor;
16use visionsensor::VisionSensor;
17
18pub mod basic;
19pub mod definition;
20pub mod headlight;
21pub mod hubled;
22pub mod modes;
23pub mod motor;
24pub mod remote;
25pub mod sensor;
26pub mod visionsensor;
27
28#[derive(Debug, Clone)]
29pub struct IoDevice {
30 pub def: Definition,
31 tokens: Tokens,
32 channels: Channels,
33}
34
35impl IoDevice {
36 pub fn kind(&self) -> &IoTypeId {
37 self.def.kind()
38 }
39 pub fn def(&self) -> &Definition {
40 &self.def
41 }
42 pub fn port(&self) -> u8 {
43 self.def.port()
44 }
45 pub fn channels(&self) -> &Channels {
46 &self.channels
47 }
48 pub fn new(kind: IoTypeId, port: u8, tokens: Tokens) -> Self {
49 Self {
50 def: Definition::new(kind, port),
51 tokens,
52 channels: Default::default(),
53 }
54 }
55 pub fn cache_channels(&mut self, channels: Channels) {
56 self.channels = channels;
57 }
58}
59
60impl Basic for IoDevice {
62 fn port(&self) -> u8 {
63 self.def.port()
64 }
65 fn tokens(&self) -> Tokens {
66 self.tokens.clone()
67 }
68 fn get_rx(&self) -> Result<broadcast::Receiver<PortValueSingleFormat>> {
69 if let Some(sender) = &self.channels.singlevalue_sender {
70 Ok(sender.subscribe())
71 } else {
72 Err(Error::NoneError(String::from("Sender not found")))
73 }
74 }
75}
76impl GenericSensor for IoDevice {
77 fn check(&self) -> Result<()> {
78 Ok(())
79 }
80 fn check_dataset(&self, mode: u8, datasettype: DatasetType) -> Result<()> {
81 if let Some(pm) = self.def.modes().get(&mode) {
82 let vf = pm.value_format;
83 if datasettype == vf.dataset_type {
84 Ok(())
85 } else {
86 Err(Error::NoneError(String::from("Incorrect dataset type")))
87 }
88 } else {
89 Err(Error::NoneError(String::from("Mode not found")))
90 }
91 }
92}
93
94impl RcDevice for IoDevice {
95 fn get_rx_pvs(&self) -> Result<broadcast::Receiver<PortValueSingleFormat>> {
96 if let Some(sender) = &self.channels.singlevalue_sender {
97 Ok(sender.subscribe())
98 } else {
99 Err(Error::NoneError(String::from("Sender not found")))
100 }
101 }
102 fn get_rx_nwc(&self) -> Result<broadcast::Receiver<NetworkCommand>> {
103 if let Some(sender) = &self.channels.networkcmd_sender {
104 Ok(sender.subscribe())
105 } else {
106 Err(Error::NoneError(String::from("Sender not found")))
107 }
108 }
109 fn check(&self) -> Result<()> {
110 match self.def.kind() {
111 IoTypeId::RemoteButtons => Ok(()),
112 _ => Err(Error::HubError(String::from(
113 "Not a remote control device",
114 ))),
115 }
116 }
117}
118
119impl EncoderMotor for IoDevice {
120 fn get_rx_combined(
121 &self,
122 ) -> Result<broadcast::Receiver<PortValueCombinedFormat>> {
123 if let Some(sender) = &self.channels.combinedvalue_sender {
124 Ok(sender.subscribe())
125 } else {
126 Err(Error::NoneError(String::from("Sender not found")))
127 }
128 }
129 fn get_rx_feedback(
130 &self,
131 ) -> Result<broadcast::Receiver<PortOutputCommandFeedbackFormat>> {
132 if let Some(sender) = &self.channels.commandfeedback_sender {
133 Ok(sender.subscribe())
134 } else {
135 Err(Error::NoneError(String::from("Sender not found")))
136 }
137 }
138 fn check(&self) -> Result<()> {
139 match self.def.kind() {
140 IoTypeId::TechnicLargeLinearMotor
141 | IoTypeId::TechnicXLargeLinearMotor
142 | IoTypeId::TechnicMediumAngularMotorGrey
143 | IoTypeId::TechnicLargeAngularMotorGrey
144 | IoTypeId::InternalMotorTacho => Ok(()),
145 _ => Err(Error::HubError(String::from("Not an Encoder Motor"))),
146 }
147 }
148}
149
150impl HubLed for IoDevice {
151 fn check(&self) -> Result<()> {
152 match self.def.kind() {
153 IoTypeId::HubLed => Ok(()),
154 _ => Err(Error::HubError(String::from("Not a Hub LED device"))),
155 }
156 }
157}
158
159impl VisionSensor for IoDevice {
160 fn check(&self) -> Result<()> {
161 match self.def.kind() {
162 IoTypeId::VisionSensor => Ok(()),
163 _ => {
164 Err(Error::HubError(String::from("Not a Vision sensor Motor")))
165 }
166 }
167 }
168}
169
170#[macro_export]
171macro_rules! device_trait {
172 ($name:tt, [$( $b:item ),*]) => {
173 #[async_trait]
174 pub trait $name: Debug + Send + Sync + Basic {
175 fn check(&self) -> Result<()>;
176 $(
177 $b
178 )*
179 }
180 }
181}