Skip to main content

edgehog_device_runtime/telemetry/status/
runtime_info.rs

1// This file is part of Edgehog.
2//
3// Copyright 2022 - 2025 SECO Mind Srl
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9//    http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
17// SPDX-License-Identifier: Apache-2.0
18
19use std::borrow::Cow;
20
21use serde::Deserialize;
22
23use crate::data::set_property;
24use crate::Client;
25
26const INTERFACE: &str = "io.edgehog.devicemanager.RuntimeInfo";
27
28pub const RUNTIME_INFO: RuntimeInfo<'static> = RuntimeInfo::read();
29
30#[derive(Debug, Clone, Deserialize)]
31pub struct RuntimeInfo<'a> {
32    pub name: Cow<'a, str>,
33    pub url: Cow<'a, str>,
34    pub version: Cow<'a, str>,
35    pub environment: Cow<'a, str>,
36}
37
38impl RuntimeInfo<'static> {
39    /// Get structured data for `io.edgehog.devicemanager.RuntimeInfo` interface
40    pub const fn read() -> Self {
41        Self {
42            name: Cow::Borrowed(env!("CARGO_PKG_NAME")),
43            url: Cow::Borrowed(env!("CARGO_PKG_HOMEPAGE")),
44            version: Cow::Borrowed(env!("CARGO_PKG_VERSION")),
45            environment: Cow::Borrowed(env!("EDGEHOG_RUSTC_VERSION")),
46        }
47    }
48
49    pub async fn send<C>(self, client: &mut C)
50    where
51        C: Client,
52    {
53        let values = [
54            ("/name", self.name),
55            ("/url", self.url),
56            ("/version", self.version),
57            ("/environment", self.environment),
58        ];
59
60        for (path, data) in values {
61            set_property(client, INTERFACE, path, data.as_ref()).await;
62        }
63    }
64}
65
66#[cfg(test)]
67pub(crate) mod tests {
68    use astarte_device_sdk::store::SqliteStore;
69    use astarte_device_sdk::transport::mqtt::Mqtt;
70    use astarte_device_sdk::AstarteData;
71    use astarte_device_sdk_mock::MockDeviceClient;
72    use mockall::{predicate, Sequence};
73
74    use super::*;
75
76    pub(crate) fn mock_runtime_info_telemetry(
77        client: &mut MockDeviceClient<Mqtt<SqliteStore>>,
78        seq: &mut Sequence,
79    ) {
80        client
81            .expect_set_property()
82            .with(
83                predicate::eq("io.edgehog.devicemanager.RuntimeInfo"),
84                predicate::eq("/name"),
85                predicate::eq(AstarteData::from(env!("CARGO_PKG_NAME"))),
86            )
87            .once()
88            .in_sequence(seq)
89            .returning(|_, _, _| Ok(()));
90
91        client
92            .expect_set_property()
93            .with(
94                predicate::eq("io.edgehog.devicemanager.RuntimeInfo"),
95                predicate::eq("/url"),
96                predicate::eq(AstarteData::from(env!("CARGO_PKG_HOMEPAGE"))),
97            )
98            .once()
99            .in_sequence(seq)
100            .returning(|_, _, _| Ok(()));
101
102        client
103            .expect_set_property()
104            .with(
105                predicate::eq("io.edgehog.devicemanager.RuntimeInfo"),
106                predicate::eq("/version"),
107                predicate::eq(AstarteData::from(env!("CARGO_PKG_VERSION"))),
108            )
109            .once()
110            .in_sequence(seq)
111            .returning(|_, _, _| Ok(()));
112
113        client
114            .expect_set_property()
115            .with(
116                predicate::eq("io.edgehog.devicemanager.RuntimeInfo"),
117                predicate::eq("/environment"),
118                predicate::eq(AstarteData::from(env!("EDGEHOG_RUSTC_VERSION"))),
119            )
120            .once()
121            .in_sequence(seq)
122            .returning(|_, _, _| Ok(()));
123    }
124
125    #[tokio::test]
126    async fn should_send_runtime_info() {
127        let mut client = MockDeviceClient::<Mqtt<SqliteStore>>::new();
128        let mut seq = Sequence::new();
129
130        mock_runtime_info_telemetry(&mut client, &mut seq);
131
132        RUNTIME_INFO.send(&mut client).await;
133    }
134}