Applied clippy rules

This commit is contained in:
Dreaded_X 2023-04-10 01:29:48 +02:00
parent 7d5ce71e5b
commit 839c0a1c57
Signed by: Dreaded_X
GPG Key ID: FA5F485356B0D2D4
17 changed files with 139 additions and 53 deletions

2
.cargo/config.toml Normal file
View File

@ -0,0 +1,2 @@
[build]
target = "x86_64-unknown-linux-gnu"

View File

@ -23,7 +23,7 @@ pub trait GoogleHomeDevice: AsOnOff + AsScene {
fn sync(&self) -> response::sync::Device {
let name = self.get_device_name();
let mut device = response::sync::Device::new(&self.get_id(), &name.name, self.get_device_type());
let mut device = response::sync::Device::new(self.get_id(), &name.name, self.get_device_type());
device.name = name;
device.will_report_state = self.will_report_state();
@ -49,7 +49,7 @@ pub trait GoogleHomeDevice: AsOnOff + AsScene {
device.traits = traits;
return device;
device
}
fn query(&self) -> response::query::Device {
@ -65,7 +65,7 @@ pub trait GoogleHomeDevice: AsOnOff + AsScene {
.ok();
}
return device;
device
}
fn execute(&mut self, command: &CommandType) -> Result<(), ErrorCode> {
@ -84,7 +84,7 @@ pub trait GoogleHomeDevice: AsOnOff + AsScene {
},
}
return Ok(());
Ok(())
}
}

View File

@ -21,16 +21,16 @@ impl GoogleHome {
Self { user_id: user_id.into() }
}
pub fn handle_request(&self, request: Request, mut devices: &mut HashMap<&str, &mut dyn GoogleHomeDevice>) -> Result<Response, FullfillmentError> {
pub fn handle_request(&self, request: Request, devices: &mut HashMap<&str, &mut dyn GoogleHomeDevice>) -> Result<Response, FullfillmentError> {
// TODO: What do we do if we actually get more then one thing in the input array, right now
// we only respond to the first thing
let payload = request
.inputs
.into_iter()
.map(|input| match input {
Intent::Sync => ResponsePayload::Sync(self.sync(&devices)),
Intent::Query(payload) => ResponsePayload::Query(self.query(payload, &devices)),
Intent::Execute(payload) => ResponsePayload::Execute(self.execute(payload, &mut devices)),
Intent::Sync => ResponsePayload::Sync(self.sync(devices)),
Intent::Query(payload) => ResponsePayload::Query(self.query(payload, devices)),
Intent::Execute(payload) => ResponsePayload::Execute(self.execute(payload, devices)),
}).next();
payload
@ -45,7 +45,7 @@ impl GoogleHome {
.map(|(_, device)| device.sync())
.collect::<Vec<_>>();
return resp_payload;
resp_payload
}
fn query(&self, payload: request::query::Payload, devices: &HashMap<&str, &mut dyn GoogleHomeDevice>) -> query::Payload {
@ -63,10 +63,10 @@ impl GoogleHome {
device
}, |device| device.query());
return (id, device);
(id, device)
}).collect();
return resp_payload;
resp_payload
}
@ -100,9 +100,9 @@ impl GoogleHome {
// TODO: We only get one error not all errors
if let Err(err) = results {
return (id, Err(err));
(id, Err(err))
} else {
return (id, Ok(true));
(id, Ok(true))
}
})
}).for_each(|(id, state)| {
@ -126,7 +126,7 @@ impl GoogleHome {
}
});
return resp_payload;
resp_payload
}
}
@ -157,11 +157,11 @@ mod tests {
name.add_default_name("Outlet");
name.add_nickname("Nightlight");
return name;
name
}
fn get_id(&self) -> &str {
return &self.name;
&self.name
}
fn is_online(&self) -> bool {
@ -212,7 +212,7 @@ mod tests {
}
fn get_id(&self) -> &str {
return "living/party_mode";
"living/party_mode"
}
fn is_online(&self) -> bool {

View File

@ -96,7 +96,7 @@ mod tests {
assert_eq!(payload.commands[0].devices[1].id, "456");
assert_eq!(payload.commands[0].execution.len(), 1);
match payload.commands[0].execution[0] {
CommandType::OnOff{on} => assert_eq!(on, true),
CommandType::OnOff{on} => assert!(on),
_ => panic!("Expected OnOff")
}
},

View File

@ -24,6 +24,12 @@ impl Payload {
}
}
impl Default for Payload {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Command {
@ -78,8 +84,7 @@ mod tests {
fn serialize() {
let mut execute_resp = Payload::new();
let mut state = State::default();
state.on = Some(true);
let state = State { on: Some(true) };
let mut command = Command::new(Status::Success);
command.states = Some(States {
online: true,

View File

@ -24,6 +24,12 @@ impl Payload {
}
}
impl Default for Payload {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Status {
@ -64,6 +70,12 @@ impl Device {
}
}
impl Default for Device {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -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)?
},
};

View File

@ -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;
}

View File

@ -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 {

View File

@ -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];

View File

@ -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 {

View File

@ -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(())

View File

@ -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;
}

View File

@ -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 }
}
}

View File

@ -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()
}),
);

View File

@ -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]

View File

@ -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);