add tank temp
Signed-off-by: Frank Villaro-Dixon <frank@villaro-dixon.eu>
This commit is contained in:
parent
f06c297ce7
commit
585547b920
5 changed files with 146 additions and 9 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -53,6 +53,7 @@ name = "daikin_altherma"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tungstenite",
|
||||
"url",
|
||||
"uuid",
|
||||
|
@ -160,6 +161,7 @@ name = "mytest"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"daikin_altherma",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -8,6 +8,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
serde_json = "1.0.114"
|
||||
thiserror = "1.0.57"
|
||||
tungstenite = "0.21.0"
|
||||
url = "2.5.0"
|
||||
|
||||
|
|
|
@ -6,4 +6,5 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
daikin_altherma = {path = "/home/frank/src/github.com/frankkkkk/daikin-altherma-rs/"}
|
||||
daikin_altherma = {path = "/home/frank/src/github.com/frankkkkk/daikin-altherma-rs/"}
|
||||
thiserror = "1.0.57"
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
use daikin_altherma::DaikinAlthermaClient;
|
||||
fn main() {
|
||||
let mut a = DaikinAlthermaClient::new("192.168.11.100".to_string());
|
||||
let am = a.get_adapter_model();
|
||||
println!("Adapter model: {am}");
|
||||
// let am = a.get_adapter_model();
|
||||
// println!("Adapter model: {am}");
|
||||
//
|
||||
|
||||
//a.set_holiday_mode(false);
|
||||
|
||||
let hm = a.is_holiday_mode();
|
||||
println!("Holiday mode: {hm}");
|
||||
|
||||
let tp = a.get_tank_parameters().unwrap();
|
||||
println!("Tank: {:?}", tp);
|
||||
}
|
||||
|
|
139
src/lib.rs
139
src/lib.rs
|
@ -1,15 +1,84 @@
|
|||
use std::{fmt::Debug, net::TcpStream};
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
use serde_json::{json, Value};
|
||||
use tungstenite::{connect, stream, Error, Message, WebSocket};
|
||||
use tungstenite::{connect, stream, Message, WebSocket};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DAError {
|
||||
#[error("Communication error")]
|
||||
CommunicationError,
|
||||
#[error("Conversion error")]
|
||||
ConversionError,
|
||||
}
|
||||
|
||||
pub struct DaikinAlthermaClient {
|
||||
//todo WS con
|
||||
ws_client: WebSocket<stream::MaybeTlsStream<TcpStream>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TankParameters {
|
||||
// The current temperature of the water tank
|
||||
temperature: f64,
|
||||
// The setpoint (wanted) temperature of the water tank
|
||||
setpoint_temperature: f64,
|
||||
// Is the tank heating enabled
|
||||
enabled: bool,
|
||||
// Is it on powerful (quick heating) mode
|
||||
powerful: bool,
|
||||
}
|
||||
|
||||
trait FromJsonValue<T>: Sized {
|
||||
fn from_json_value(value: &Value) -> Result<T, DAError>;
|
||||
}
|
||||
|
||||
// Implement the trait for i64
|
||||
impl FromJsonValue<i64> for i64 {
|
||||
fn from_json_value(value: &Value) -> Result<Self, DAError> {
|
||||
let v: Option<i64> = value.as_i64();
|
||||
match v {
|
||||
Some(x) => Ok(x),
|
||||
_ => Err(DAError::ConversionError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the trait for f64
|
||||
impl FromJsonValue<f64> for f64 {
|
||||
fn from_json_value(value: &Value) -> Result<Self, DAError> {
|
||||
let v: Option<f64> = value.as_f64();
|
||||
match v {
|
||||
Some(x) => Ok(x),
|
||||
_ => Err(DAError::ConversionError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the trait for String
|
||||
impl FromJsonValue<String> for String {
|
||||
fn from_json_value(value: &Value) -> Result<Self, DAError> {
|
||||
let v: Option<&str> = value.as_str();
|
||||
match v {
|
||||
Some(x) => Ok(x.to_string()),
|
||||
_ => Err(DAError::ConversionError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the trait for bool
|
||||
impl FromJsonValue<bool> for bool {
|
||||
fn from_json_value(value: &Value) -> Result<Self, DAError> {
|
||||
let v: Option<bool> = value.as_bool();
|
||||
match v {
|
||||
Some(x) => Ok(x),
|
||||
_ => Err(DAError::ConversionError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DaikinAlthermaClient {
|
||||
pub fn new(adapter_hostname: String) -> Self {
|
||||
let url_str = format!("ws://{adapter_hostname}/mca");
|
||||
|
@ -29,11 +98,69 @@ impl DaikinAlthermaClient {
|
|||
}
|
||||
|
||||
pub fn is_holiday_mode(&mut self) -> bool {
|
||||
let v = self
|
||||
.request_value("1/Holiday/HolidayState/la", None, "/m2m:rsp/pc/m2m:cin/con")
|
||||
let v: i64 = self
|
||||
.request_value_hp_dft("1/Holiday/HolidayState/la")
|
||||
.unwrap();
|
||||
|
||||
return v.as_i64().unwrap() == 1;
|
||||
return v == 1;
|
||||
}
|
||||
|
||||
pub fn set_holiday_mode(&mut self, holiday_mode: bool) -> Result<(), DAError> {
|
||||
let value = match holiday_mode {
|
||||
true => 1,
|
||||
false => 0,
|
||||
};
|
||||
|
||||
let payload = serde_json::json!({
|
||||
"con": value,
|
||||
"cnf": "text/plain:0"
|
||||
});
|
||||
|
||||
self.set_value_hp("1/Holiday/HolidayState", Some(payload), "/")
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_tank_parameters(&mut self) -> Result<TankParameters, DAError> {
|
||||
let temperature: f64 = self
|
||||
.request_value_hp_dft("2/Sensor/TankTemperature/la")
|
||||
.unwrap();
|
||||
|
||||
let setpoint_temperature: f64 = self
|
||||
.request_value_hp_dft("2/Operation/TargetTemperature/la")
|
||||
.unwrap();
|
||||
|
||||
let enabled_str: String = self.request_value_hp_dft("2/Operation/Power/la").unwrap();
|
||||
let powerful_i: i64 = self
|
||||
.request_value_hp_dft("2/Operation/Powerful/la")
|
||||
.unwrap();
|
||||
|
||||
Ok(TankParameters {
|
||||
temperature,
|
||||
setpoint_temperature,
|
||||
enabled: enabled_str == "on",
|
||||
powerful: powerful_i == 1,
|
||||
})
|
||||
}
|
||||
|
||||
fn request_value_hp_dft<T: FromJsonValue<T>>(&mut self, item: &str) -> Result<T, DAError> {
|
||||
let hp_item = format!("MNAE/{item}");
|
||||
let json_val = self
|
||||
.request_value(hp_item.as_str(), None, "/m2m:rsp/pc/m2m:cin/con")
|
||||
.unwrap();
|
||||
T::from_json_value(&json_val)
|
||||
}
|
||||
|
||||
fn set_value_hp(
|
||||
&mut self,
|
||||
item: &str,
|
||||
payload: Option<Value>,
|
||||
output_path: &str,
|
||||
) -> Result<(), DAError> {
|
||||
let hp_item = format!("MNAE/{item}");
|
||||
self.request_value(hp_item.as_str(), payload, output_path)
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn request_value(
|
||||
|
@ -79,11 +206,11 @@ impl DaikinAlthermaClient {
|
|||
|
||||
let result: Value = serde_json::from_str(&msg).expect("Can't parse JSON");
|
||||
|
||||
//println!(">>> {result}");
|
||||
|
||||
assert_eq!(result["m2m:rsp"]["rqi"], reqid);
|
||||
assert_eq!(result["m2m:rsp"]["to"], "hello"); //XXX
|
||||
//
|
||||
println!("Rslt is {result}. Opath is {output_path}");
|
||||
|
||||
match result.pointer(output_path) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => Err("Todo".to_string()),
|
||||
|
|
Loading…
Reference in a new issue