This commit is contained in:
Paul Zinselmeyer 2024-02-17 19:15:42 +01:00
parent 42f5458235
commit 77391a057b
Signed by: pfzetto
GPG Key ID: B471A1AF06C895FD
4 changed files with 319 additions and 410 deletions

570
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2,23 +2,16 @@
"nodes": {
"crane": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": [
"rust-overlay"
]
},
"locked": {
"lastModified": 1691803597,
"narHash": "sha256-khWW1Owzselq5o816Lb7x624d6QGnv+kpronK3ndkr4=",
"lastModified": 1707685877,
"narHash": "sha256-XoXRS+5whotelr1rHiZle5t5hDg9kpguS5yk8c8qzOc=",
"owner": "ipetkov",
"repo": "crane",
"rev": "7809d369710abb17767b624f9e72b500373580bc",
"rev": "2c653e4478476a52c6aa3ac0495e4dea7449ea0e",
"type": "github"
},
"original": {
@ -27,32 +20,16 @@
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
@ -63,11 +40,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1692447944,
"narHash": "sha256-fkJGNjEmTPvqBs215EQU4r9ivecV5Qge5cF/QDLVn3U=",
"lastModified": 1708118438,
"narHash": "sha256-kk9/0nuVgA220FcqH/D2xaN6uGyHp/zoxPNUmPCMmEE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d680ded26da5cf104dd2735a51e88d2d8f487b4d",
"rev": "5863c27340ba4de8f83e7e3c023b9599c3cb3c80",
"type": "github"
},
"original": {
@ -95,11 +72,11 @@
]
},
"locked": {
"lastModified": 1692670201,
"narHash": "sha256-WbCKJRfh1Zb7N7g8Fzq7/Hg6i6yCbvaa0OAi4cSHk1w=",
"lastModified": 1708135817,
"narHash": "sha256-EUMO/K3+Wgh0THOLoRXhxrh6G/pQ7BlJ8No+ciy1nKA=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "bf5196c27545735374376d96d41f209bae3643e1",
"rev": "c77e68d33a84ce3f9e86905c0f2ef78d5defad28",
"type": "github"
},
"original": {

View File

@ -15,8 +15,6 @@
url = "github:ipetkov/crane";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils";
rust-overlay.follows = "rust-overlay";
};
};
};

View File

@ -4,8 +4,6 @@ use std::{
};
use log::{debug, info, warn};
use rumqttc::{AsyncClient, ClientError, MqttOptions, QoS};
use serde_json::json;
use serial::{CharSize, Parity, SerialPort, StopBits};
const PATTERN_COUNT: usize = 1;
@ -19,39 +17,14 @@ async fn main() {
dotenvy::dotenv().ok();
env_logger::init();
loop {
info!("Connecting to MQTT");
let mut mqtt_options = MqttOptions::new(
"stromsensor",
env::var("MQTT_HOST").expect("MQTT_HOST env var"),
env::var("MQTT_PORT")
.expect("MQTT_PORT env var")
.parse()
.expect("valid MQTT_PORT"),
);
mqtt_options.set_credentials(
env::var("MQTT_USER").expect("MQTT_USER env var"),
env::var("MQTT_PASS").expect("MQTT_PASS env var"),
);
mqtt_options.set_keep_alive(Duration::from_secs(5));
let (mut mqtt, mut eventloop) = AsyncClient::new(mqtt_options, 10);
tokio::spawn(async move {
loop {
eventloop.poll().await.unwrap();
}
});
advertise(&mut mqtt).await.unwrap();
let mut port =
serial::open(&env::var("USB_PORT").expect("USB_PORT environment variable")).unwrap();
interact(&mut port, &mut mqtt).await.unwrap();
interact(&mut port).await.unwrap();
}
}
async fn interact<T: SerialPort>(port: &mut T, mqtt: &mut AsyncClient) -> anyhow::Result<()> {
async fn interact<T: SerialPort>(port: &mut T) -> anyhow::Result<()> {
port.reconfigure(&|settings| {
settings.set_baud_rate(serial::Baud9600).unwrap();
settings.set_parity(Parity::ParityNone);
@ -70,10 +43,7 @@ async fn interact<T: SerialPort>(port: &mut T, mqtt: &mut AsyncClient) -> anyhow
let mut prev_time = Instant::now();
let mut brake = 0_u32;
let brake_target: u32 = env::var("INSERT_EVERY_NTH")
.expect("INSERT_EVERY_NTH environment variable")
.parse()
.expect("Number in INSERT_EVERY_NTH");
let brake_target: u32 = 1;
let mut empty_messages = 0;
loop {
@ -103,8 +73,6 @@ async fn interact<T: SerialPort>(port: &mut T, mqtt: &mut AsyncClient) -> anyhow
result[0] / 10,
val / 10.0
);
publish(result[0] / 10, val / 10.0, mqtt).await?;
}
prev_value = result[0];
@ -144,75 +112,3 @@ fn extract_values(queue: &mut Vec<u8>) -> [i32; PATTERN_COUNT] {
queue.clear();
value
}
async fn publish(energy: i32, power: f64, client: &mut AsyncClient) -> Result<(), ClientError> {
debug!("publishing sensor state to mqtt");
client
.publish(
"pfz4/stromsensor",
QoS::AtLeastOnce,
false,
json!({
"power": power,
"energy": energy
})
.to_string(),
)
.await?;
Ok(())
}
async fn advertise(client: &mut AsyncClient) -> Result<(), ClientError> {
debug!("advertising device on mqtt");
let device = json!({
"name":"Stromsensor",
"manufacturer": "pfz4",
"model": "stromsensor",
"identifiers": [
"stromsensor"
]
});
client
.publish(
"homeassistant/sensor/stromsensor/power/config",
QoS::AtLeastOnce,
true,
json! ({
"device": device,
"name": "Aktuell",
"unit_of_measurement": "W",
"state_class": "measurement",
"device_class": "power",
"state_topic": "pfz4/stromsensor",
"suggested_display_precision":2,
"unique_id": "stromsensor_power",
"object_id": "stromsensor_power",
"value_template": "{{ value_json.power }}"
})
.to_string(),
)
.await?;
client
.publish(
"homeassistant/sensor/stromsensor/energy/config",
QoS::AtLeastOnce,
true,
json! ({
"device": device,
"name": "Zaehlerstand",
"unit_of_measurement": "Wh",
"state_class": "total_increasing",
"device_class": "energy",
"state_topic": "pfz4/stromsensor",
"unique_id": "stromsensor_energy",
"object_id": "stromsensor_energy",
"value_template": "{{ value_json.energy }}"
})
.to_string(),
)
.await?;
Ok(())
}