Applied clippy rules
This commit is contained in:
@@ -142,7 +142,7 @@ impl PresenceDeviceConfig {
|
||||
fn generate_topic(mut self, class: &str, identifier: &str, config: &Config) -> Result<PresenceDeviceConfig, MissingWildcard> {
|
||||
if self.mqtt.is_none() {
|
||||
if !has_wildcards(&config.presence.topic) {
|
||||
return Err(MissingWildcard::new(&config.presence.topic).into());
|
||||
return Err(MissingWildcard::new(&config.presence.topic));
|
||||
}
|
||||
|
||||
// TODO: This is not perfect, if the topic is some/+/thing/# this will fail
|
||||
@@ -243,17 +243,17 @@ impl Device {
|
||||
let device = match self {
|
||||
Device::IkeaOutlet { info, mqtt, outlet_type, timeout } => {
|
||||
trace!(id = identifier, "IkeaOutlet [{} in {:?}]", info.name, info.room);
|
||||
IkeaOutlet::build(&identifier, info, mqtt, outlet_type, timeout, client).await
|
||||
IkeaOutlet::build(identifier, info, mqtt, outlet_type, timeout, client).await
|
||||
.map(device_box)?
|
||||
},
|
||||
Device::WakeOnLAN { info, mqtt, mac_address, broadcast_ip } => {
|
||||
trace!(id = identifier, "WakeOnLan [{} in {:?}]", info.name, info.room);
|
||||
WakeOnLAN::build(&identifier, info, mqtt, mac_address, broadcast_ip, client).await
|
||||
WakeOnLAN::build(identifier, info, mqtt, mac_address, broadcast_ip, client).await
|
||||
.map(device_box)?
|
||||
},
|
||||
Device::KasaOutlet { ip } => {
|
||||
trace!(id = identifier, "KasaOutlet [{}]", identifier);
|
||||
device_box(KasaOutlet::new(&identifier, ip))
|
||||
device_box(KasaOutlet::new(identifier, ip))
|
||||
}
|
||||
Device::AudioSetup { mqtt, mixer, speakers } => {
|
||||
trace!(id = identifier, "AudioSetup [{}]", identifier);
|
||||
@@ -263,16 +263,16 @@ impl Device {
|
||||
let speakers_id = format!("{}.speakers", identifier);
|
||||
let speakers = (*speakers).create(&speakers_id, config, client.clone()).await?;
|
||||
|
||||
AudioSetup::build(&identifier, mqtt, mixer, speakers, client).await
|
||||
AudioSetup::build(identifier, mqtt, mixer, speakers, client).await
|
||||
.map(device_box)?
|
||||
},
|
||||
Device::ContactSensor { mqtt, presence } => {
|
||||
trace!(id = identifier, "ContactSensor [{}]", identifier);
|
||||
let presence = presence
|
||||
.map(|p| p.generate_topic("contact", &identifier, &config))
|
||||
.map(|p| p.generate_topic("contact", identifier, config))
|
||||
.transpose()?;
|
||||
|
||||
ContactSensor::build(&identifier, mqtt, presence, client).await
|
||||
ContactSensor::build(identifier, mqtt, presence, client).await
|
||||
.map(device_box)?
|
||||
},
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn start(mut presence_rx: presence::Receiver, mut light_sensor_rx: light_sen
|
||||
loop {
|
||||
tokio::select! {
|
||||
res = presence_rx.changed() => {
|
||||
if !res.is_ok() {
|
||||
if res.is_err() {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ pub fn start(mut presence_rx: presence::Receiver, mut light_sensor_rx: light_sen
|
||||
debug_bridge.on_presence(presence).await;
|
||||
}
|
||||
res = light_sensor_rx.changed() => {
|
||||
if !res.is_ok() {
|
||||
if res.is_err() {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ pub fn start(mut mqtt_rx: mqtt::Receiver, mut presence_rx: presence::Receiver, m
|
||||
}
|
||||
});
|
||||
|
||||
return DevicesHandle { tx };
|
||||
DevicesHandle { tx }
|
||||
}
|
||||
|
||||
impl Devices {
|
||||
|
||||
@@ -76,11 +76,11 @@ impl Request {
|
||||
encrypted.put_u32(data.len() as u32);
|
||||
|
||||
for c in data {
|
||||
key = key ^ c;
|
||||
key ^= c;
|
||||
encrypted.put_u8(key);
|
||||
}
|
||||
|
||||
return encrypted.freeze();
|
||||
encrypted.freeze()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ impl Response {
|
||||
.map(|_| sysinfo.relay_state == 1);
|
||||
}
|
||||
|
||||
return Err(ResponseError::SysinfoNotFound);
|
||||
Err(ResponseError::SysinfoNotFound)
|
||||
}
|
||||
|
||||
fn check_set_relay_success(&self) -> Result<(), ResponseError> {
|
||||
@@ -165,13 +165,13 @@ impl Response {
|
||||
return set_relay_state.err_code.ok();
|
||||
}
|
||||
|
||||
return Err(ResponseError::RelayStateNotFound);
|
||||
Err(ResponseError::RelayStateNotFound)
|
||||
}
|
||||
|
||||
fn decrypt(mut data: bytes::Bytes) -> Result<Self, ResponseError> {
|
||||
let mut key: u8 = 171;
|
||||
if data.len() < 4 {
|
||||
return Err(ResponseError::ToShort.into());
|
||||
return Err(ResponseError::ToShort);
|
||||
}
|
||||
|
||||
let length = data.get_u32();
|
||||
@@ -189,10 +189,10 @@ impl Response {
|
||||
|
||||
impl traits::OnOff for KasaOutlet {
|
||||
fn is_on(&self) -> Result<bool, errors::ErrorCode> {
|
||||
let mut stream = TcpStream::connect(self.addr).or::<DeviceError>(Err(DeviceError::DeviceOffline.into()))?;
|
||||
let mut stream = TcpStream::connect(self.addr).or::<DeviceError>(Err(DeviceError::DeviceOffline))?;
|
||||
|
||||
let body = Request::get_sysinfo().encrypt();
|
||||
stream.write_all(&body).and(stream.flush()).or::<DeviceError>(Err(DeviceError::TransientError.into()))?;
|
||||
stream.write_all(&body).and(stream.flush()).or::<DeviceError>(Err(DeviceError::TransientError))?;
|
||||
|
||||
let mut received = Vec::new();
|
||||
let mut rx_bytes = [0; 1024];
|
||||
@@ -212,10 +212,10 @@ impl traits::OnOff for KasaOutlet {
|
||||
}
|
||||
|
||||
fn set_on(&mut self, on: bool) -> Result<(), errors::ErrorCode> {
|
||||
let mut stream = TcpStream::connect(self.addr).or::<DeviceError>(Err(DeviceError::DeviceOffline.into()))?;
|
||||
let mut stream = TcpStream::connect(self.addr).or::<DeviceError>(Err(DeviceError::DeviceOffline))?;
|
||||
|
||||
let body = Request::set_relay_state(on).encrypt();
|
||||
stream.write_all(&body).and(stream.flush()).or::<DeviceError>(Err(DeviceError::TransientError.into()))?;
|
||||
stream.write_all(&body).and(stream.flush()).or::<DeviceError>(Err(DeviceError::TransientError))?;
|
||||
|
||||
let mut received = Vec::new();
|
||||
let mut rx_bytes = [0; 1024];
|
||||
|
||||
@@ -62,7 +62,7 @@ impl GoogleHomeDevice for WakeOnLAN {
|
||||
let mut name = device::Name::new(&self.info.name);
|
||||
name.add_default_name("Computer");
|
||||
|
||||
return name;
|
||||
name
|
||||
}
|
||||
|
||||
fn get_id(&self) -> &str {
|
||||
|
||||
14
src/error.rs
14
src/error.rs
@@ -21,7 +21,7 @@ impl MissingEnv {
|
||||
}
|
||||
|
||||
pub fn has_missing(self) -> result::Result<(), Self> {
|
||||
if self.keys.len() > 0 {
|
||||
if !self.keys.is_empty() {
|
||||
Err(self)
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -29,19 +29,25 @@ impl MissingEnv {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MissingEnv {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for MissingEnv {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Missing environment variable")?;
|
||||
if self.keys.len() == 0 {
|
||||
if self.keys.is_empty() {
|
||||
unreachable!("This error should only be returned if there are actually missing environment variables");
|
||||
}
|
||||
if self.keys.len() == 1 {
|
||||
write!(f, " '{}'", self.keys[0])?;
|
||||
} else {
|
||||
write!(f, "s '{}'", self.keys[0])?;
|
||||
self.keys.iter().skip(1).map(|key| {
|
||||
self.keys.iter().skip(1).try_for_each(|key| {
|
||||
write!(f, ", '{key}'")
|
||||
}).collect::<fmt::Result>()?;
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -61,7 +61,7 @@ pub fn start(mut presence_rx: presence::Receiver, mut light_sensor_rx: light_sen
|
||||
loop {
|
||||
tokio::select! {
|
||||
res = presence_rx.changed() => {
|
||||
if !res.is_ok() {
|
||||
if res.is_err() {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ pub fn start(mut presence_rx: presence::Receiver, mut light_sensor_rx: light_sen
|
||||
hue_bridge.on_presence(presence).await;
|
||||
}
|
||||
res = light_sensor_rx.changed() => {
|
||||
if !res.is_ok() {
|
||||
if res.is_err() {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ struct LightSensor {
|
||||
impl LightSensor {
|
||||
fn new(mqtt: MqttDeviceConfig, min: isize, max: isize) -> Self {
|
||||
let (tx, is_dark) = watch::channel(false);
|
||||
Self { is_dark: is_dark.clone(), mqtt, min, max, tx }
|
||||
Self { is_dark, mqtt, min, max, tx }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
59
src/main.rs
59
src/main.rs
@@ -1,5 +1,5 @@
|
||||
#![feature(async_closure)]
|
||||
use std::{process, time::Duration, collections::HashMap};
|
||||
use std::{ process, time::Duration, collections::HashMap };
|
||||
|
||||
use axum::{extract::FromRef, http::StatusCode, routing::post, Json, Router, response::IntoResponse};
|
||||
|
||||
@@ -14,6 +14,7 @@ use automation::{
|
||||
};
|
||||
use dotenvy::dotenv;
|
||||
use rumqttc::{AsyncClient, MqttOptions, Transport, matches};
|
||||
use tokio::task::JoinHandle;
|
||||
use tracing::{debug, error, info, metadata::LevelFilter};
|
||||
use futures::future::join_all;
|
||||
|
||||
@@ -92,6 +93,60 @@ async fn app() -> anyhow::Result<()> {
|
||||
debug_bridge::start(presence.clone(), light_sensor.clone(), config, client.clone());
|
||||
}
|
||||
|
||||
// Super hacky implementation for the washing machine, just for testing
|
||||
{
|
||||
let mut handle = None::<JoinHandle<()>>;
|
||||
let mut mqtt = mqtt.subscribe();
|
||||
client.subscribe("zigbee2mqtt/bathroom/washing", rumqttc::QoS::AtLeastOnce).await.unwrap();
|
||||
tokio::spawn(async move {
|
||||
if let Some(ntfy) = ntfy {
|
||||
loop {
|
||||
let message = mqtt.recv().await.unwrap();
|
||||
|
||||
if !matches(&message.topic, "zigbee2mqtt/bathroom/washing") {
|
||||
continue;
|
||||
}
|
||||
|
||||
let map: HashMap<String, serde_json::Value> = serde_json::from_slice(&message.payload).unwrap();
|
||||
debug!("Test: {:?}", map);
|
||||
|
||||
let strength = match map.get("strength").map(|value| value.as_i64().unwrap()) {
|
||||
Some(s) => s,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
if strength > 15 {
|
||||
debug!("Strength over 15");
|
||||
|
||||
// Update of strength over 15 which means we are still running, cancel any
|
||||
// running timer
|
||||
if let Some(handle) = handle.take() {
|
||||
handle.abort();
|
||||
}
|
||||
|
||||
// Start a new timer, if the timer runs out we have not had an update of
|
||||
// more then 15 in the last timeout period, assume we are done, notify user
|
||||
let ntfy = ntfy.clone();
|
||||
handle = Some(
|
||||
tokio::spawn(async move {
|
||||
debug!("Starting timeout of 10 min for washing machine...");
|
||||
tokio::time::sleep(Duration::from_secs(10*60)).await;
|
||||
debug!("Notifying user!");
|
||||
|
||||
let notification = ntfy::Notification::new()
|
||||
.set_title("Laundy is done")
|
||||
.set_message("Do not forget to hang it!")
|
||||
.set_priority(ntfy::Priority::High);
|
||||
|
||||
ntfy.send(notification).await.ok();
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let devices = devices::start(mqtt.subscribe(), presence.clone(), light_sensor.clone());
|
||||
join_all(
|
||||
config
|
||||
@@ -125,7 +180,7 @@ async fn app() -> anyhow::Result<()> {
|
||||
|
||||
debug!(username = user.preferred_username, "{result:#?}");
|
||||
|
||||
return (StatusCode::OK, Json(result)).into_response();
|
||||
(StatusCode::OK, Json(result)).into_response()
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -102,6 +102,12 @@ impl Notification {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Notification {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Ntfy {
|
||||
fn new(base_url: &str, topic: &str, tx: Sender) -> Self {
|
||||
Self { base_url: base_url.to_owned(), topic: topic.to_owned(), tx }
|
||||
@@ -148,7 +154,7 @@ pub fn start(mut presence_rx: presence::Receiver, config: &NtfyConfig) -> Sender
|
||||
}
|
||||
});
|
||||
|
||||
return tx;
|
||||
tx
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
||||
@@ -25,11 +25,11 @@ struct Presence {
|
||||
impl Presence {
|
||||
fn build(mqtt: MqttDeviceConfig) -> Result<Self, MissingWildcard> {
|
||||
if !has_wildcards(&mqtt.topic) {
|
||||
return Err(MissingWildcard::new(&mqtt.topic).into());
|
||||
return Err(MissingWildcard::new(&mqtt.topic));
|
||||
}
|
||||
|
||||
let (tx, overall_presence) = watch::channel(false);
|
||||
Ok(Self { devices: HashMap::new(), overall_presence: overall_presence.clone(), mqtt, tx })
|
||||
Ok(Self { devices: HashMap::new(), overall_presence, mqtt, tx })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ impl OnMqtt for Presence {
|
||||
let offset = self.mqtt.topic.find('+').or(self.mqtt.topic.find('#')).expect("Presence::new fails if it does not contain wildcards");
|
||||
let device_name = &message.topic[offset..];
|
||||
|
||||
if message.payload.len() == 0 {
|
||||
if message.payload.is_empty() {
|
||||
// Remove the device from the map
|
||||
debug!("State of device [{device_name}] has been removed");
|
||||
self.devices.remove(device_name);
|
||||
|
||||
Reference in New Issue
Block a user