1use alloc::{string::String, vec::Vec};
4
5use crate::extend::ExtendableThing;
6use serde::{Deserialize, Serialize};
7use serde_with::{serde_as, skip_serializing_none, OneOrMany};
8
9#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash)]
11pub enum ControlPacket {
12 #[serde(rename = "mqv:publish")]
13 Publish,
14 #[serde(rename = "mqv:subscribe")]
15 Subscribe,
16 #[serde(rename = "mqv:unsubscribe")]
17 Unsubscribe,
18}
19
20#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash)]
22pub enum QoS {
23 #[serde(rename = "quality:0")]
24 AtMostOnce,
25 #[serde(rename = "quality:1")]
26 AtLeastOnce,
27 #[serde(rename = "quality:2")]
28 ExactlyOnce,
29}
30
31#[serde_as]
33#[skip_serializing_none]
34#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash, Default)]
35pub struct Form {
36 #[serde(
37 rename = "mqv:retain",
38 skip_serializing_if = "core::ops::Not::not",
39 default
40 )]
41 pub retain: bool,
42 #[serde(rename = "mqv:controlPacket")]
43 pub control_packet: Option<ControlPacket>,
44 #[serde(rename = "mqv:qos")]
45 pub qos: Option<QoS>,
46 #[serde(rename = "mqv:topic")]
47 pub topic: Option<String>,
48 #[serde(rename = "mqv:filter", skip_serializing_if = "Vec::is_empty", default)]
49 #[serde_as(as = "OneOrMany<_>")]
50 pub filter: Vec<String>,
51}
52
53#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
55pub struct MqttProtocol {}
56
57impl ExtendableThing for MqttProtocol {
58 type InteractionAffordance = ();
59 type PropertyAffordance = ();
60 type ActionAffordance = ();
61 type EventAffordance = ();
62 type Form = Form;
63 type ExpectedResponse = ();
64 type DataSchema = ();
65 type ObjectSchema = ();
66 type ArraySchema = ();
67}
68
69#[cfg(test)]
70mod test {
71 use alloc::vec;
72
73 use super::MqttProtocol;
74 use crate::thing::Form;
75 use crate::thing::{DefaultedFormOperations::Custom, FormOperation::*};
76
77 fn deserialize_form(s: &str, r: Form<MqttProtocol>) {
78 let f: crate::thing::Form<MqttProtocol> = serde_json::from_str(s).unwrap();
79 assert_eq!(f, r);
80 }
81
82 #[test]
83 fn simple_filter() {
84 let s = r#"{
85 "href": "mqtt://broker.com:1883",
86 "op": [
87 "subscribeevent",
88 "unsubscribeevent"
89 ],
90 "mqv:filter": "thing1/events/overheating"
91 }"#;
92
93 let expected = Form {
94 op: Custom(vec![SubscribeEvent, UnsubscribeEvent]),
95 href: "mqtt://broker.com:1883".into(),
96 other: super::Form {
97 filter: vec!["thing1/events/overheating".into()],
98 ..Default::default()
99 },
100 ..Default::default()
101 };
102
103 deserialize_form(s, expected);
104 }
105
106 #[test]
107 fn complex_filter() {
108 let s = r#"{
109 "href": "mqtt://broker.com:1883",
110 "op": [
111 "readproperty",
112 "observeproperty"
113 ],
114 "mqv:qos": "quality:1",
115 "mqv:retain" : true,
116 "mqv:filter": "application/devices/thing1/properties/test"
117 }"#;
118
119 let expected = Form {
120 op: Custom(vec![ReadProperty, ObserveProperty]),
121 href: "mqtt://broker.com:1883".into(),
122 other: super::Form {
123 qos: Some(super::QoS::AtLeastOnce),
124 retain: true,
125 filter: vec!["application/devices/thing1/properties/test".into()],
126 ..Default::default()
127 },
128 ..Default::default()
129 };
130
131 deserialize_form(s, expected);
132 }
133}