add pc switch automation
This commit is contained in:
		
							parent
							
								
									7106e9fbe2
								
							
						
					
					
						commit
						dc60244834
					
				
							
								
								
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -289,7 +289,7 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "mqttAutomation" | ||||
| version = "1.2.0" | ||||
| version = "1.3.0" | ||||
| dependencies = [ | ||||
|  "crossbeam", | ||||
|  "json", | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| [package] | ||||
| name = "mqttAutomation" | ||||
| version = "1.2.0" | ||||
| version = "1.3.0" | ||||
| edition = "2021" | ||||
| 
 | ||||
| [dependencies] | ||||
|  | ||||
| @ -11,15 +11,46 @@ use crate::automation::json::json_parser; | ||||
| #[derive(Deserialize)] | ||||
| pub struct SettingsConf { | ||||
|     base_topic: String, | ||||
| 
 | ||||
|     alarm_hour: u8, | ||||
|     alarm_minute: u8 | ||||
| } | ||||
| 
 | ||||
| struct PingStats { | ||||
|     total: u16, | ||||
|     fails: u16, | ||||
|     avg: f32 | ||||
| } | ||||
| 
 | ||||
| fn ping_stat_update(stats: &mut PingStats, payload: String) -> Option<f32> { | ||||
|     let mut new_value: Option<f32> = None; | ||||
|     if !payload.eq("false") { | ||||
|         match payload.parse::<f32>() { | ||||
|             Ok(value) => new_value = Some(value), | ||||
|             Err(_) => {} | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     stats.total += 1; | ||||
|     match new_value { | ||||
|         Some(value) => stats.avg += (value - stats.avg) / f32::from(stats.total - stats.fails), | ||||
|         None => stats.fails += 1 | ||||
|     } | ||||
|     new_value | ||||
| } | ||||
| 
 | ||||
| pub struct Automation { | ||||
|     tx: Sender<mqtt_client::MqttMessage>, | ||||
| 
 | ||||
|     clock_dow: u8, | ||||
|     clock_hour: u8, | ||||
|     clock_min: u8, | ||||
|     clock_sec: u8, | ||||
| 
 | ||||
|     elfdesktop_last_on: u32, | ||||
|     elfdesktop_state: bool, | ||||
| 
 | ||||
|     ping_elfdesktop: PingStats, | ||||
| 
 | ||||
|     config: SettingsConf | ||||
| } | ||||
| @ -33,7 +64,7 @@ impl Automation { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn lamp01_set(&self, state: bool) { | ||||
|     fn tx_set(&self, topic: String, state: bool) { | ||||
|         let payload: String; | ||||
|         if state { | ||||
|             payload = String::from("ON"); | ||||
| @ -41,12 +72,22 @@ impl Automation { | ||||
|             payload = String::from("OFF"); | ||||
|         } | ||||
|         self.tx({ mqtt_client::MqttMessage { | ||||
|             topic: String::from("/cool/devices/lamp-01/set"), | ||||
|             topic: topic, | ||||
|             payload: payload, | ||||
|             retain: false, | ||||
|             qos: mqtt_client::QoS::AtMostOnce, | ||||
|         }}); | ||||
|     } | ||||
|     fn lamp01_set(&self, state: bool) { | ||||
|         self.tx_set(String::from("/cool/devices/lamp-01/set"), state); | ||||
|     } | ||||
|     fn pc_sw_set(&self, state: bool) { | ||||
|         self.tx_set(String::from("/cool/devices/sw-01/set"), state); | ||||
|     } | ||||
| 
 | ||||
|     fn get_current_time(&self) -> u32 { | ||||
|         u32::from(self.clock_dow) * 24 + u32::from(self.clock_hour) * 60 + u32::from(self.clock_min) | ||||
|     } | ||||
| 
 | ||||
|     fn alarm(&self) { | ||||
|         self.lamp01_set(true); | ||||
| @ -74,16 +115,29 @@ impl Automation { | ||||
|     } | ||||
| 
 | ||||
|     fn clock_message_in(&mut self, message: mqtt_client::MqttMessage) { | ||||
|         if message.topic.eq("clock/time/hour") { | ||||
|         if message.topic.eq("clock/time/second") { | ||||
| 
 | ||||
|             match message.payload.parse::<u8>() { | ||||
|                 Err(e) => 
 | ||||
|                     println!("ERROR: clock_message_in: clock/time/hour has invalid payload ({:?})", e), | ||||
|                 Ok(n) => { | ||||
|                     self.clock_hour = n; | ||||
|                     
 | ||||
|                     if self.config.alarm_minute == 0 && n == self.config.alarm_hour && self.clock_dow < 5 { | ||||
|                         self.alarm(); | ||||
|                     println!("ERROR: clock_message_in: clock/time/second has invalid payload ({:?})", e), | ||||
|                 Ok(n) => {                    
 | ||||
|                     self.clock_sec = n; | ||||
| 
 | ||||
|                     if n % 20 == 0 { | ||||
|                         let json = format!( | ||||
|                             "{{ \"deviceID\": 0, \"ping\": {}, \"pong\": {} }}", | ||||
|                             self.ping_elfdesktop.avg, | ||||
|                             1.0 - (f32::from(self.ping_elfdesktop.fails) / f32::from(self.ping_elfdesktop.total)) | ||||
|                         ); | ||||
|                         self.tx({ mqtt_client::MqttMessage { | ||||
|                             topic: String::from("/kees/db/insert/ping"), | ||||
|                             payload: json, | ||||
|                             retain: false, | ||||
|                             qos: mqtt_client::QoS::AtMostOnce, | ||||
|                         }}); | ||||
|                         self.ping_elfdesktop.total = 0; | ||||
|                         self.ping_elfdesktop.fails = 0; | ||||
|                         self.ping_elfdesktop.avg = 0.0; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @ -97,7 +151,24 @@ impl Automation { | ||||
|                 Ok(n) => {                    
 | ||||
|                     self.clock_min = n; | ||||
| 
 | ||||
|                     if n == self.config.alarm_minute && self.clock_hour == self.config.alarm_hour && self.clock_dow < 5 { | ||||
|                     if n == self.config.alarm_minute 
 | ||||
|                       && self.clock_hour == self.config.alarm_hour 
 | ||||
|                       && self.clock_dow < 5 { | ||||
|                         self.alarm(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         else if message.topic.eq("clock/time/hour") { | ||||
| 
 | ||||
|             match message.payload.parse::<u8>() { | ||||
|                 Err(e) => 
 | ||||
|                     println!("ERROR: clock_message_in: clock/time/hour has invalid payload ({:?})", e), | ||||
|                 Ok(n) => { | ||||
|                     self.clock_hour = n; | ||||
|                     
 | ||||
|                     if self.config.alarm_minute == 0 && n == self.config.alarm_hour && self.clock_dow < 5 { | ||||
|                         self.alarm(); | ||||
|                     } | ||||
|                 } | ||||
| @ -113,7 +184,7 @@ impl Automation { | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         // println!("DEBUG: clock_message_in: current time: {}:{}", self.clock_hour, self.clock_min);
 | ||||
|         // println!("DEBUG: clock_message_in: current time: {}:{}:{}", self.clock_hour, self.clock_min, self.clock_sec);
 | ||||
|     } | ||||
| 
 | ||||
|     fn message_in(&mut self, message: mqtt_client::MqttMessage) { | ||||
| @ -140,6 +211,30 @@ impl Automation { | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         else if message.topic.eq("/kees/ping/elfdesktop") { | ||||
| 
 | ||||
|             let now: u32 = self.get_current_time(); | ||||
|             let ping = ping_stat_update(&mut self.ping_elfdesktop, message.payload); | ||||
| 
 | ||||
|             match ping { | ||||
|                 None => { | ||||
|                     if self.elfdesktop_last_on < now - 3 { | ||||
|                         if self.elfdesktop_state { | ||||
|                             self.pc_sw_set(false); | ||||
|                             self.elfdesktop_state = false; | ||||
|                         } | ||||
|                     } | ||||
|                 }, | ||||
|                 Some(_) => { | ||||
|                     self.elfdesktop_last_on = now; | ||||
|                     if !self.elfdesktop_state { | ||||
|                         self.pc_sw_set(true); | ||||
|                         self.elfdesktop_state = true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -147,16 +242,11 @@ impl Automation { | ||||
| impl mqtt_client::MqttTool<SettingsConf> for Automation { | ||||
|     fn new(client: rumqttc::Client, tx: Sender<mqtt_client::MqttMessage>, config: SettingsConf) -> Automation { | ||||
| 
 | ||||
|         match client.subscribe("clock/time/hour", QoS::AtMostOnce) { | ||||
|         match client.subscribe("clock/time/#", QoS::AtMostOnce) { | ||||
|             Err(e) => | ||||
|                 println!("ERROR: main: faild to subscribe to clock/time/hour ({})", e), | ||||
|             Ok(_) => {} | ||||
|         } | ||||
|         match client.subscribe("clock/time/minute", QoS::AtMostOnce) { | ||||
|             Err(e) => | ||||
|                 println!("ERROR: main: faild to subscribe to clock/time/minute ({})", e), | ||||
|             Ok(_) => {} | ||||
|         } | ||||
|         match client.subscribe("clock/date/dow", QoS::AtMostOnce) { | ||||
|             Err(e) => | ||||
|                 println!("ERROR: main: faild to subscribe to clock/date/dow ({})", e), | ||||
| @ -172,13 +262,26 @@ impl mqtt_client::MqttTool<SettingsConf> for Automation { | ||||
|                 println!("ERROR: main: faild to subscribe to KNMITemp/values ({})", e), | ||||
|             Ok(_) => {} | ||||
|         } | ||||
|         match client.subscribe("/kees/ping/#", QoS::AtMostOnce) { | ||||
|             Err(e) => | ||||
|                 println!("ERROR: main: faild to subscribe to KNMITemp/values ({})", e), | ||||
|             Ok(_) => {} | ||||
|         } | ||||
| 
 | ||||
|         Automation { | ||||
|             tx, | ||||
| 
 | ||||
|             clock_dow: u8::MAX, | ||||
|             clock_hour: u8::MAX, | ||||
|             clock_min: u8::MAX, | ||||
|             config: config | ||||
|             clock_sec: u8::MAX, | ||||
| 
 | ||||
|             elfdesktop_last_on: u32::MAX, | ||||
|             elfdesktop_state: false, | ||||
| 
 | ||||
|             ping_elfdesktop: { PingStats { total: 0, fails: 0, avg: 0.0 } }, | ||||
| 
 | ||||
|             config: config, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user