fundamentum_sdk_mqtt/models/
action.rs1use cloud_proto::{action_request::Action as CloudAction, action_response::Status as CloudStatus};
2use fundamentum_iot_mqtt_proto::com::fundamentum::actions::v1 as cloud_proto;
3use prost::{Message as _, bytes::Bytes};
4
5use crate::{
6 Device, PublishOptions, Publishable,
7 error::Error,
8 models::actions::{ClientAction, FileTransferAction},
9};
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub struct ActionRequest {
14 pub id: u64,
16 pub target_devices: Vec<String>,
20 pub action: Action,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub enum Action {
27 ClientAction(ClientAction),
29 FileTransferAction(FileTransferAction),
31}
32
33impl TryFrom<Bytes> for ActionRequest {
34 type Error = Error;
35
36 fn try_from(data: Bytes) -> Result<Self, Self::Error> {
37 cloud_proto::ActionRequest::decode(data)?.try_into()
38 }
39}
40
41impl TryFrom<cloud_proto::ActionRequest> for ActionRequest {
42 type Error = Error;
43
44 fn try_from(action_request: cloud_proto::ActionRequest) -> Result<Self, Self::Error> {
45 let action = match action_request.action {
46 Some(CloudAction::ClientAction(a)) => Action::ClientAction(a.into()),
47 Some(CloudAction::FileTransferAction(a)) => Action::FileTransferAction(a.try_into()?),
48 _ => {
49 return Err(Error::InvalidRequest(format!(
50 "Action is not supported: {action_request:?}"
51 )));
52 }
53 };
54
55 Ok(Self {
56 id: action_request.id,
57 target_devices: action_request.target_devices,
58 action,
59 })
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Hash)]
66pub struct ActionResponse {
67 pub id: u64,
69 pub serial_numbers: Vec<String>,
73 pub message: String,
75 pub payload: Vec<u8>,
78 pub status: Status,
80}
81
82impl Publishable for ActionResponse {
83 type Error = Error;
84
85 fn topic(&self, device: &Device) -> impl Into<String> + Send {
86 format!(
87 "registries/{}/devices/{}/actions/{}/response",
88 device.registry_id(),
89 device.serial(),
90 self.id
91 )
92 }
93
94 fn payload(&self) -> Result<impl Into<Bytes> + Send, Error> {
95 Ok(cloud_proto::ActionResponse::from(self.clone()).encode_to_vec())
96 }
97
98 fn publish_overrides(&self) -> PublishOptions {
99 PublishOptions::default()
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, Hash)]
105pub enum Status {
106 Success,
108 Failure,
110 Ongoing {
113 progress: u32,
115 },
116 Deferred,
119}
120
121impl From<ActionResponse> for cloud_proto::ActionResponse {
122 fn from(action_response: ActionResponse) -> Self {
123 Self {
124 serial_numbers: action_response.serial_numbers,
125 message: action_response.message,
126 payload: action_response.payload,
127 status: Some(action_response.status.into()),
128 }
129 }
130}
131
132impl From<Status> for CloudStatus {
133 fn from(status: Status) -> Self {
134 match status {
135 Status::Success => Self::Success(cloud_proto::SuccessStatus {}),
136 Status::Failure => Self::Failure(cloud_proto::FailureStatus {}),
137 Status::Ongoing { progress } => Self::Ongoing(cloud_proto::OngoingStatus { progress }),
138 Status::Deferred => Self::Deferred(cloud_proto::DeferredStatus {}),
139 }
140 }
141}