diff --git a/Cargo.toml b/Cargo.toml
index cc38e65..f831da3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
categories = ["gateway", "bridge", "transport", "modemmanager"]
[dependencies]
+async-trait = "0.1.56"
mmdbus = "1.18.6"
dbus-tokio = "0.7.5"
tokio = { version = "1.19.2", features = [ "time", "macros", "rt-multi-thread" ] }
diff --git a/src/main.rs b/src/main.rs
index ff57c15..722e5f0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -13,10 +13,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use std::collections::HashMap;
-use std::error::Error as StdError;
+pub mod mm;
+use mm::modem::Modem as ModemAccess;
+
use std::fmt;
use std::sync::Arc;
+
use tokio::{
task::JoinHandle,
time::Duration,
@@ -24,16 +26,13 @@ use tokio::{
use mmdbus::{
dbus::{
- arg::{PropMap, RefArg, Variant},
- nonblock::{SyncConnection, stdintf::org_freedesktop_dbus::ObjectManager, Proxy},
- // channel::MatchingReceiver,
- // message::{MatchRule, Message},
- strings::{Path as DBusPath}, // Interface, Member,
- // Error as DBusError,
+ nonblock::{
+ SyncConnection, Proxy,
+ stdintf::org_freedesktop_dbus::ObjectManager,
+ },
+ strings::{Path as DBusPath},
+ Error as DBusError,
},
- modem::Modem as ModemAccess,
- modem_messaging::ModemMessaging,
- sms::Sms as SmsAccess,
};
use dbus_tokio::connection;
@@ -44,7 +43,6 @@ use dbus_tokio::connection;
const MM_NAME: &str = "org.freedesktop.ModemManager1";
const MM_PATH: &str = "/org/freedesktop/ModemManager1";
const TIMEOUT: Duration = Duration::from_secs(5);
-const SMSC: &str = "+33609001390"; // SFR
#[derive(Clone)]
pub struct DBus {
@@ -53,7 +51,7 @@ pub struct DBus {
}
impl DBus {
- pub fn connect() -> Result> {
+ pub fn connect() -> Result {
let (resource, conn) = connection::new_system_sync()?;
let handle: JoinHandle<()> = tokio::spawn(async {
@@ -78,22 +76,26 @@ pub struct ModemManager {
}
impl ModemManager {
- pub fn connect() -> Result> {
- Ok(DBus::connect().map(|dbus| Self { dbus })?)
+ pub fn connect() -> Result {
+ DBus::connect().map(|dbus| Self { dbus })
}
- pub async fn modems(&self) -> Result>, Box> {
+ pub async fn modems(&self) -> Result, DBusError> {
let objects = self.dbus.proxy(MM_PATH).get_managed_objects().await?;
let modems = objects
.into_iter()
- .map(|(path, _)| path )
+ .map(|(path, _)| {
+ Modem {
+ dbus: self.dbus.clone(),
+ path,
+ }
+ })
.collect();
Ok(modems)
}
}
-/*
#[derive(Clone)]
pub struct Modem {
dbus: DBus,
@@ -102,14 +104,13 @@ pub struct Modem {
impl fmt::Debug for Modem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let numbers = self.own_numbers().unwrap_or(vec![String::new()]);
- write!(f, "Modem {{ {}, {:?}, .. }}", self.path, numbers)
+ write!(f, "Modem {{ {}, {:?}, .. }}", self.path, "1234")
}
}
impl Modem {
- pub fn enabled(&self) -> Result> {
- let state: ModemState = ModemAccess::state(&self.dbus.proxy(&self.path)).map(Into::into)?;
+ pub async fn enabled(&self) -> Result {
+ let state: ModemState = ModemAccess::state(&self.dbus.proxy(&self.path)).await.map(Into::into)?;
Ok(match state {
ModemState::Enabling
| ModemState::Enabled
@@ -121,38 +122,9 @@ impl Modem {
})
}
- pub fn model(&self) -> Result> {
- Ok(ModemAccess::model(&self.dbus.proxy(&self.path))?)
+ pub async fn model(&self) -> Result {
+ ModemAccess::model(&self.dbus.proxy(&self.path)).await
}
-
- pub fn manufacturer(&self) -> Result> {
- Ok(ModemAccess::manufacturer(&self.dbus.proxy(&self.path))?)
- }
-
- pub fn own_numbers(&self) -> Result, Box> {
- Ok(ModemAccess::own_numbers(&self.dbus.proxy(&self.path))?)
- }
-
- /*
- pub fn list_sms(&self) -> Result, Box> {
- Ok(ModemMessaging::list(&self.dbus.proxy(&self.path))?
- .into_iter()
- .map(|p| Sms {
- dbus: self.dbus.clone(),
- modem: self.clone(),
- path: p,
- })
- .collect())
- }
-
- pub fn create_sms(&self, number: String, text: String) -> Result> {
- Sms::new(self, number, text)
- }
-
- pub fn delete_sms(&self, path: DBusPath) -> Result<(), Box> {
- Ok(ModemMessaging::delete(&self.dbus.proxy(&self.path), path)?)
- }
- */
}
#[repr(i32)]
@@ -203,122 +175,17 @@ impl From for ModemState {
}
}
}
-*/
-
-/*
-// include/ModemManager-enums.h MMSmsState
-/// State of a given SMS.
-#[repr(u32)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum SmsState {
- /// State unknown or not reportable.
- Unknown = 0,
- /// The message has been neither received not yet sent.
- Stored = 1,
- /// The message is being received but is not yet complete.
- Receiving = 2,
- /// The message has been completely received.
- Received = 3,
- /// The message is queued for delivery.
- Sending = 4,
- /// The message was successfully sent.
- Sent = 5,
-}
-
-impl fmt::Display for SmsState {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", match self {
- SmsState::Unknown => "unknown",
- SmsState::Stored => "stored",
- SmsState::Receiving => "receiving",
- SmsState::Received => "received",
- SmsState::Sending => "sending",
- SmsState::Sent => "sent",
- })
- }
-}
-
-impl From for SmsState {
- fn from(num: u32) -> Self {
- if num > 5 {
- Self::Unknown
- } else {
- unsafe { *(&num as *const u32 as *const Self) }
- }
- }
-}
-
-pub struct Sms {
- dbus: DBus,
- modem: Modem,
- path: DBusPath<'static>,
-}
-
-impl Sms {
- pub fn new(modem: &Modem, number: String, text: String) -> Result> {
- let props: PropMap = {
- let mut tmp = HashMap::new();
- tmp.insert(
- String::from("number"),
- Variant(Box::new(number) as Box),
- );
- tmp.insert(
- String::from("text"),
- Variant(Box::new(text) as Box),
- );
- tmp.insert(
- String::from("smsc"),
- Variant(Box::new(String::from(SMSC)) as Box),
- );
- tmp
- };
- let path = ModemMessaging::create(&modem.dbus.proxy(&modem.path), props)?;
- Ok(Sms {
- dbus: modem.dbus.clone(),
- modem: modem.clone(),
- path: path,
- })
- }
-
- pub fn state(&self) -> Result> {
- Ok(SmsAccess::state(&self.dbus.proxy(&self.path)).map(Into::into)?)
- }
-
- pub fn send(&self) -> Result<(), Box> {
- Ok(SmsAccess::send(&self.dbus.proxy(&self.path))?)
- }
-
- pub fn number(&self) -> Result> {
- Ok(SmsAccess::number(&self.dbus.proxy(&self.path))?)
- }
-
- pub fn text(&self) -> Result> {
- Ok(SmsAccess::text(&self.dbus.proxy(&self.path))?)
- }
-}
-
-impl fmt::Debug for Sms {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let state = self.state().unwrap_or(SmsState::Unknown);
- write!(f, "Sms ({}) {{ {}, {:?}, .. }}", state, self.path, self.modem)
- }
-}
-
-impl fmt::Display for Sms {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let state = self.state().unwrap_or(SmsState::Unknown);
- let number = self.number().unwrap_or(String::new());
- let text = self.text().unwrap_or(String::new());
- write!(f, "Sms ({}) {{ number: {}, text: {} }}", state, number, text)
- }
-}
-*/
#[tokio::main]
-async fn main() -> Result<(), Box> {
- let modems = ModemManager::connect()?.modems().await;
+async fn main() -> Result<(), DBusError> {
+ let modems = ModemManager::connect()?.modems().await?;
println!("Modems: {:?}", modems);
+ for modem in modems {
+ println!("Modem: {:?}", modem);
+ println!("Enabled: {:?}", modem.enabled().await);
+ println!("Model: {:?}", modem.model().await);
+ }
Ok(())
}
diff --git a/src/mm/mod.rs b/src/mm/mod.rs
new file mode 100644
index 0000000..733a648
--- /dev/null
+++ b/src/mm/mod.rs
@@ -0,0 +1,16 @@
+// Copyright (C) 2022 Maxime “pep” Buquet
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU Affero General Public License as published by the
+// Free Software Foundation, either version 3 of the License, or (at your
+// option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
+// for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+pub mod modem;
diff --git a/src/mm/modem.rs b/src/mm/modem.rs
new file mode 100644
index 0000000..4ef7ff0
--- /dev/null
+++ b/src/mm/modem.rs
@@ -0,0 +1,42 @@
+// Copyright (C) 2022 Maxime “pep” Buquet
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU Affero General Public License as published by the
+// Free Software Foundation, either version 3 of the License, or (at your
+// option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
+// for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use std::ops::Deref;
+use std::marker::Sync;
+
+use async_trait::async_trait;
+use mmdbus::dbus::{nonblock, Error as DBusError};
+
+#[async_trait]
+pub trait Modem {
+ async fn enable(&self, enable: bool) -> Result<(), DBusError>;
+ async fn state(&self) -> Result;
+ async fn model(&self) -> Result;
+}
+
+#[async_trait]
+impl<'a, T: nonblock::NonblockReply, C: Deref + Sync> Modem for nonblock::Proxy<'a, C> {
+ async fn enable(&self, enable: bool) -> Result<(), DBusError> {
+ self.method_call("org.freedesktop.ModemManager1.Modem", "Enable", (enable,)).await
+ }
+
+ async fn state(&self) -> Result {
+ ::get(&self, "org.freedesktop.ModemManager1.Modem", "State").await
+ }
+
+ async fn model(&self) -> Result {
+ ::get(&self, "org.freedesktop.ModemManager1.Modem", "Model").await
+ }
+}