Modbus Werte werden nun ausgelesen
This commit is contained in:
parent
c499f1b97c
commit
459b97d95c
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -355,6 +355,12 @@ version = "3.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.11.0"
|
||||
@ -688,6 +694,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
@ -1732,6 +1739,7 @@ dependencies = [
|
||||
"serde_yaml",
|
||||
"tera",
|
||||
"tokio",
|
||||
"tokio-modbus",
|
||||
"toml",
|
||||
]
|
||||
|
||||
@ -1835,6 +1843,22 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-modbus"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e82dfb1a3265ca939b7a76103c89ad770f8cc0ea8de76c83d352e7c1fc5b2c8b"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"log",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.17"
|
||||
|
||||
@ -16,3 +16,4 @@ tera = "1.19"
|
||||
config = "0.14"
|
||||
toml = "0.8"
|
||||
serde_derive = "1.0"
|
||||
tokio-modbus = "0.7"
|
||||
|
||||
14
paramod.yaml
14
paramod.yaml
@ -1,14 +1,12 @@
|
||||
default:
|
||||
loglevel: DEBUG
|
||||
darkmode: false
|
||||
|
||||
darkmode: true
|
||||
mqtt:
|
||||
broker: 192.168.178.2
|
||||
button_circulation: zigbee2mqtt/WirelessButton
|
||||
password: 97sm3pHNSMZ4M5qUj0x8
|
||||
port: 1883
|
||||
user: admin
|
||||
|
||||
password: 97sm3pHNSMZ4M5qUj0x8
|
||||
button_circulation: zigbee2mqtt/WirelessButton
|
||||
influxdb:
|
||||
bucket: Paradigma
|
||||
location: Radebeul
|
||||
@ -16,14 +14,12 @@ influxdb:
|
||||
org: skaville
|
||||
token: i-sXFQbEkSC1XVzqFEaFwXwzasbsEIciVlK4SaAUOEvk0VjQPkD3fr8d7_3SPeyseTZkqj7ZMZU78b3n2F6_SQ==
|
||||
url: 192.168.178.2:8086
|
||||
|
||||
modbus:
|
||||
host: 192.168.178.10
|
||||
port: 502
|
||||
max_coils_addr: 8
|
||||
max_holding_addr: 61
|
||||
max_input_addr: 45
|
||||
port: 502
|
||||
|
||||
modbus_coils:
|
||||
- MgtSystem: {addr: 0, write: false, mqtt: false, influxdb: false, comment: Leitsystem aktiv}
|
||||
- HK1pres: {addr: 1, write: false, mqtt: false, influxdb: false, comment: HK1 vorhanden}
|
||||
@ -34,7 +30,6 @@ modbus_coils:
|
||||
- Zrelease: {addr: 6, write: true, mqtt: false, influxdb: false, comment: Zirkulation freigegeben}
|
||||
- Zlock: {addr: 7, write: true, mqtt: false, influxdb: false, comment: Zirkulation gesperrt}
|
||||
- SHKpres: {addr: 8, write: false, mqtt: false, influxdb: false, comment: Schwimmbadheizkrei vorhanden}
|
||||
|
||||
modbus_input_register:
|
||||
- TA: {addr: 0, type: INT16, factor: 0.1, mqtt: true, influxdb: true}
|
||||
- TV: {addr: 1, type: INT16, factor: 0.1, mqtt: false, influxdb: true}
|
||||
@ -81,7 +76,6 @@ modbus_input_register:
|
||||
- TKW: {addr: 42, type: INT16, factor: 0.1, mqtt: false, influxdb: true}
|
||||
- VKW: {addr: 43, type: INT16, factor: 0.1, mqtt: false, influxdb: true}
|
||||
- VSPm: {addr: 44, type: INT16, factor: 0.1, mqtt: false, influxdb: true}
|
||||
|
||||
modbus_holding_register:
|
||||
- nothing: {addr: 0, type: UINT16, factor: 1, mqtt: false, influxdb: false}
|
||||
- ErrLS: {addr: 1, type: UINT16, factor: 1, mqtt: false, influxdb: true}
|
||||
|
||||
108
src/modbus.rs
108
src/modbus.rs
@ -5,63 +5,95 @@ use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio_modbus::prelude::*;
|
||||
use tokio_modbus::client::tcp;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
/// Startet einen Thread, der zyklisch Modbus-Register abfragt und ModbusValueMaps aktualisiert
|
||||
pub fn start_modbus_polling_thread(
|
||||
_modbus_config: &ModbusConfig,
|
||||
modbus_config: &ModbusConfig,
|
||||
input_registers: &Option<Vec<HashMap<String, ModbusRegisterConfig>>>,
|
||||
holding_registers: &Option<Vec<HashMap<String, ModbusRegisterConfig>>>,
|
||||
coils: &Option<Vec<HashMap<String, ModbusCoilsConfig>>>,
|
||||
value_maps: Arc<Mutex<ModbusValueMaps>>,
|
||||
poll_interval: Duration,
|
||||
) {
|
||||
let host = modbus_config.host.clone();
|
||||
let port = modbus_config.port;
|
||||
|
||||
let input_registers = input_registers.clone();
|
||||
let holding_registers = holding_registers.clone();
|
||||
let coils = coils.clone();
|
||||
thread::spawn(move || {
|
||||
let addr: SocketAddr = format!("{}:{}", host, port).parse().unwrap();
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
loop {
|
||||
// Input Register
|
||||
if let Some(ref vec) = input_registers {
|
||||
for map in vec {
|
||||
for (key, reg) in map {
|
||||
let typ = reg.r#type.as_deref().unwrap_or("");
|
||||
let value = match typ {
|
||||
"INT16" => { let raw: i16 = 0; raw as f64 },
|
||||
"UINT16" => { let raw: u16 = 0; raw as f64 },
|
||||
"UINT32" => { let raw1: u16 = 0; let raw2: u16 = 0; let raw32: u32 = ((raw1 as u32) << 16) | (raw2 as u32); raw32 as f64 },
|
||||
_ => 0.0,
|
||||
};
|
||||
if let Ok(mut maps) = value_maps.lock() {
|
||||
maps.modbus_input_register_values.insert(key.clone(), value);
|
||||
// Verbindungsaufbau
|
||||
let connect_result = rt.block_on(async {
|
||||
tcp::connect_slave(addr, 1u8.into()).await
|
||||
});
|
||||
match connect_result {
|
||||
Ok(mut client) => {
|
||||
// Werte abfragen
|
||||
// Input Register
|
||||
if let Some(ref vec) = input_registers {
|
||||
for map in vec {
|
||||
for (key, reg) in map {
|
||||
let addr = reg.addr;
|
||||
let typ = reg.r#type.as_deref().unwrap_or("");
|
||||
let factor = reg.factor.unwrap_or(1.0);
|
||||
let value = rt.block_on(async {
|
||||
match typ {
|
||||
"INT16" | "UINT16" => client.read_input_registers(addr, 1).await.ok().map(|v| v[0] as f64 * factor),
|
||||
"UINT32" => client.read_input_registers(addr, 2).await.ok().map(|v| ((v[0] as u32) << 16 | (v[1] as u32)) as f64 * factor),
|
||||
_ => Some(0.0),
|
||||
}
|
||||
}).unwrap_or(0.0);
|
||||
if let Ok(mut maps) = value_maps.lock() {
|
||||
maps.modbus_input_register_values.insert(key.clone(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Holding Register
|
||||
if let Some(ref vec) = holding_registers {
|
||||
for map in vec {
|
||||
for (key, reg) in map {
|
||||
let typ = reg.r#type.as_deref().unwrap_or("");
|
||||
let value = match typ {
|
||||
"INT16" => { let raw: i16 = 0; raw as f64 },
|
||||
"UINT16" => { let raw: u16 = 0; raw as f64 },
|
||||
"UINT32" => { let raw1: u16 = 0; let raw2: u16 = 0; let raw32: u32 = ((raw1 as u32) << 16) | (raw2 as u32); raw32 as f64 },
|
||||
_ => 0.0,
|
||||
};
|
||||
if let Ok(mut maps) = value_maps.lock() {
|
||||
maps.modbus_holding_register_values.insert(key.clone(), value);
|
||||
// Holding Register
|
||||
if let Some(ref vec) = holding_registers {
|
||||
for map in vec {
|
||||
for (key, reg) in map {
|
||||
let addr = reg.addr;
|
||||
let typ = reg.r#type.as_deref().unwrap_or("");
|
||||
let factor = reg.factor.unwrap_or(1.0);
|
||||
let value = rt.block_on(async {
|
||||
match typ {
|
||||
"INT16" | "UINT16" => client.read_holding_registers(addr, 1).await.ok().map(|v| v[0] as f64 * factor),
|
||||
"UINT32" => client.read_holding_registers(addr, 2).await.ok().map(|v| ((v[0] as u32) << 16 | (v[1] as u32)) as f64 * factor),
|
||||
_ => Some(0.0),
|
||||
}
|
||||
}).unwrap_or(0.0);
|
||||
if let Ok(mut maps) = value_maps.lock() {
|
||||
maps.modbus_holding_register_values.insert(key.clone(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Coils
|
||||
if let Some(ref vec) = coils {
|
||||
for map in vec {
|
||||
for (key, _reg) in map {
|
||||
let value = 0.0; // Hier Coil-Wert abfragen
|
||||
if let Ok(mut maps) = value_maps.lock() {
|
||||
maps.modbus_coils_values.insert(key.clone(), value);
|
||||
// Coils
|
||||
if let Some(ref vec) = coils {
|
||||
for map in vec {
|
||||
for (key, reg) in map {
|
||||
let addr = reg.addr;
|
||||
let value = rt.block_on(async {
|
||||
client.read_coils(addr, 1).await.ok().map(|v| if v[0] { 1.0 } else { 0.0 })
|
||||
}).unwrap_or(0.0);
|
||||
if let Ok(mut maps) = value_maps.lock() {
|
||||
maps.modbus_coils_values.insert(key.clone(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
eprintln!("Modbus: Verbindung fehlgeschlagen, retry in {:?}", poll_interval);
|
||||
thread::sleep(poll_interval);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
thread::sleep(poll_interval);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user