Werte in den MQTT Broker übermitteln
This commit is contained in:
1 parent
483d27750b
commit
58bacd2f6d
6 files changed
+310
-8
No files matched your search
+5
-4
@@ -3,7 +3,7 @@ use tera::Tera;
|
||||
use crate::config::{AppConfig, ModbusValueMaps};
|
||||
|
||||
pub struct AppState {
|
||||
pub config: Mutex<AppConfig>,
|
||||
pub config: Arc<Mutex<AppConfig>>,
|
||||
pub value_maps: Arc<Mutex<ModbusValueMaps>>,
|
||||
pub templates: Tera,
|
||||
}
|
||||
@@ -11,9 +11,10 @@ pub struct AppState {
|
||||
impl AppState {
|
||||
pub fn load_from_conf(conf_path: &str) -> Self {
|
||||
let conf_str = std::fs::read_to_string(conf_path).expect("Config-Datei konnte nicht gelesen werden");
|
||||
let config: AppConfig = serde_yaml::from_str(&conf_str).expect("Config-Deserialisierung fehlgeschlagen");
|
||||
|
||||
let value_maps = Arc::new(Mutex::new(ModbusValueMaps::from_config(&config)));
|
||||
let config: AppConfig = serde_yaml::from_str(&conf_str).expect("Config-Deserialisierung fehlgeschlagen");
|
||||
let config = Arc::new(Mutex::new(config));
|
||||
let value_maps = Arc::new(Mutex::new(ModbusValueMaps::from_config(&config.lock().unwrap())));
|
||||
|
||||
let tera = match Tera::new("templates/**/*") {
|
||||
Ok(t) => t,
|
||||
@@ -24,7 +25,7 @@ impl AppState {
|
||||
};
|
||||
|
||||
AppState {
|
||||
config: Mutex::new(config),
|
||||
config,
|
||||
value_maps,
|
||||
templates: tera,
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use serde::{Serialize, Deserialize};
|
||||
mod config;
|
||||
mod modbus;
|
||||
mod app_state;
|
||||
mod mqtt;
|
||||
pub mod modbus_types;
|
||||
use crate::config::{AppConfig, ModbusValueMaps};
|
||||
use crate::modbus_types::{ModbusInputRegisterConfig, ModbusHoldingRegisterConfig, ModbusCoilsConfig};
|
||||
@@ -247,6 +248,12 @@ async fn main() -> std::io::Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
// Starte MQTT-Thread
|
||||
{
|
||||
let value_maps = Arc::clone(&app_state.value_maps);
|
||||
mqtt::start_mqtt_thread(Arc::clone(&app_state.config), value_maps);
|
||||
}
|
||||
|
||||
println!("Server läuft auf http://0.0.0.0:8080");
|
||||
|
||||
HttpServer::new(move || {
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use crate::config::{AppConfig, ModbusValueMaps};
|
||||
use rumqttc::{MqttOptions, Client, QoS};
|
||||
|
||||
pub fn start_mqtt_thread(config: Arc<Mutex<AppConfig>>, values: Arc<Mutex<ModbusValueMaps>>) {
|
||||
let mqtt_config = {
|
||||
let cfg = config.lock().unwrap();
|
||||
cfg.mqtt.clone()
|
||||
};
|
||||
let broker = if mqtt_config.broker.is_empty() { "localhost".to_string() } else { mqtt_config.broker.clone() };
|
||||
let port = if mqtt_config.port == 0 { 1883 } else { mqtt_config.port };
|
||||
let path = if let Some(ref p) = mqtt_config.path { p.clone() } else { "paramod/values".to_string() };
|
||||
let user = mqtt_config.user.clone().unwrap_or_default();
|
||||
let password = mqtt_config.password.clone().unwrap_or_default();
|
||||
let user_is_empty = user.is_empty();
|
||||
|
||||
thread::spawn(move || {
|
||||
let mut mqttoptions = MqttOptions::new("paramod-client", broker, port);
|
||||
if !user_is_empty {
|
||||
mqttoptions.set_credentials(user, password);
|
||||
}
|
||||
let (mut client, mut connection) = Client::new(mqttoptions, 10);
|
||||
loop {
|
||||
{
|
||||
let values = values.lock().unwrap();
|
||||
// Input Register
|
||||
for (name, val) in &values.modbus_input_register_values {
|
||||
if let Some(v) = val {
|
||||
if should_publish(&config, name, "input_register") {
|
||||
let topic = format!("{}/{}", path, name);
|
||||
let payload = format!("{}", v);
|
||||
let _ = client.publish(topic, QoS::AtLeastOnce, false, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Holding Register
|
||||
for (name, val) in &values.modbus_holding_register_values {
|
||||
if let Some(v) = val {
|
||||
if should_publish(&config, name, "holding_register") {
|
||||
let topic = format!("{}/{}", path, name);
|
||||
let payload = format!("{}", v);
|
||||
let _ = client.publish(topic, QoS::AtLeastOnce, false, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Coils
|
||||
for (name, val) in &values.modbus_coils_values {
|
||||
if let Some(v) = val {
|
||||
if should_publish(&config, name, "coils") {
|
||||
let topic = format!("{}/{}", path, name);
|
||||
let payload = format!("{}", v);
|
||||
let _ = client.publish(topic, QoS::AtLeastOnce, false, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle MQTT connection events
|
||||
for _event in connection.iter().take(1) {
|
||||
// Optionally log or handle events
|
||||
}
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn should_publish(config: &Arc<Mutex<AppConfig>>, name: &str, reg_type: &str) -> bool {
|
||||
let cfg = config.lock().unwrap();
|
||||
match reg_type {
|
||||
"input_register" => {
|
||||
if let Some(regs) = &cfg.modbus_input_register {
|
||||
for map in regs {
|
||||
if let Some(reg) = map.get(name) {
|
||||
return reg.mqtt.unwrap_or(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"holding_register" => {
|
||||
if let Some(regs) = &cfg.modbus_holding_register {
|
||||
for map in regs {
|
||||
if let Some(reg) = map.get(name) {
|
||||
return reg.mqtt.unwrap_or(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"coils" => {
|
||||
if let Some(coils) = &cfg.modbus_coils {
|
||||
for map in coils {
|
||||
if let Some(coil) = map.get(name) {
|
||||
return coil.mqtt.unwrap_or(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
false
|
||||
}
|
||||
Reference in new issue
Block a user