Compare commits
2 Commits
3fb6051e4a
...
84eb4b2365
| Author | SHA1 | Date | |
|---|---|---|---|
| 84eb4b2365 | |||
| 49bd17d52b |
@ -1,5 +1,6 @@
|
|||||||
default:
|
default:
|
||||||
loglevel: "DEBUG"
|
loglevel: "DEBUG"
|
||||||
|
darkmode: true
|
||||||
|
|
||||||
mqtt:
|
mqtt:
|
||||||
broker: "192.168.178.2"
|
broker: "192.168.178.2"
|
||||||
|
|||||||
@ -1,6 +1,21 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct DefaultConfig {
|
||||||
|
pub loglevel: Option<String>,
|
||||||
|
pub darkmode: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct ModbusConfig {
|
||||||
|
pub host: String,
|
||||||
|
pub port: u16,
|
||||||
|
pub max_coils_addr: Option<u16>,
|
||||||
|
pub max_input_addr: Option<u16>,
|
||||||
|
pub max_holding_addr: Option<u16>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct MqttConfig {
|
pub struct MqttConfig {
|
||||||
pub broker: String,
|
pub broker: String,
|
||||||
@ -30,20 +45,6 @@ pub struct ModbusRegisterConfig {
|
|||||||
pub comment: Option<String>,
|
pub comment: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
pub struct ModbusConfig {
|
|
||||||
pub host: String,
|
|
||||||
pub port: u16,
|
|
||||||
pub max_coils_addr: Option<u16>,
|
|
||||||
pub max_input_addr: Option<u16>,
|
|
||||||
pub max_holding_addr: Option<u16>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
pub struct DefaultConfig {
|
|
||||||
pub loglevel: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
pub default: DefaultConfig,
|
pub default: DefaultConfig,
|
||||||
|
|||||||
25
src/main.rs
25
src/main.rs
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer, Result};
|
use actix_web::{web, App, HttpResponse, HttpServer, Result};
|
||||||
use actix_files as actix_fs;
|
use actix_files as actix_fs;
|
||||||
use std::sync::{Mutex, Arc};
|
use std::sync::{Mutex, Arc};
|
||||||
@ -12,9 +11,6 @@ mod modbus;
|
|||||||
use crate::config::{AppConfig, ModbusRegisterConfig, ModbusValueMaps};
|
use crate::config::{AppConfig, ModbusRegisterConfig, ModbusValueMaps};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ...existing code...
|
|
||||||
|
|
||||||
struct AppState {
|
struct AppState {
|
||||||
config: Mutex<AppConfig>,
|
config: Mutex<AppConfig>,
|
||||||
value_maps: Arc<Mutex<ModbusValueMaps>>,
|
value_maps: Arc<Mutex<ModbusValueMaps>>,
|
||||||
@ -44,9 +40,6 @@ impl AppState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ...existing code...
|
|
||||||
|
|
||||||
async fn index(data: web::Data<AppState>) -> Result<HttpResponse> {
|
async fn index(data: web::Data<AppState>) -> Result<HttpResponse> {
|
||||||
let config = data.config.lock().unwrap();
|
let config = data.config.lock().unwrap();
|
||||||
let value_maps = data.value_maps.lock().unwrap();
|
let value_maps = data.value_maps.lock().unwrap();
|
||||||
@ -168,7 +161,17 @@ async fn save_settings(
|
|||||||
settings: web::Json<AppConfig>,
|
settings: web::Json<AppConfig>,
|
||||||
) -> Result<HttpResponse> {
|
) -> Result<HttpResponse> {
|
||||||
let mut config = data.config.lock().unwrap();
|
let mut config = data.config.lock().unwrap();
|
||||||
let new_config = settings.into_inner();
|
let mut new_config = settings.into_inner();
|
||||||
|
// Tabellenwerte erhalten, falls sie im Request null sind
|
||||||
|
if new_config.modbus_coils.is_none() {
|
||||||
|
new_config.modbus_coils = config.modbus_coils.clone();
|
||||||
|
}
|
||||||
|
if new_config.modbus_input_register.is_none() {
|
||||||
|
new_config.modbus_input_register = config.modbus_input_register.clone();
|
||||||
|
}
|
||||||
|
if new_config.modbus_holding_register.is_none() {
|
||||||
|
new_config.modbus_holding_register = config.modbus_holding_register.clone();
|
||||||
|
}
|
||||||
// Value-Maps neu initialisieren
|
// Value-Maps neu initialisieren
|
||||||
let mut value_maps = data.value_maps.lock().unwrap();
|
let mut value_maps = data.value_maps.lock().unwrap();
|
||||||
*value_maps = ModbusValueMaps::from_config(&new_config);
|
*value_maps = ModbusValueMaps::from_config(&new_config);
|
||||||
@ -184,6 +187,11 @@ async fn save_settings(
|
|||||||
Ok(HttpResponse::Ok().body("success"))
|
Ok(HttpResponse::Ok().body("success"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_config(data: web::Data<AppState>) -> HttpResponse {
|
||||||
|
let config = data.config.lock().unwrap();
|
||||||
|
HttpResponse::Ok().json(&*config)
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
@ -215,6 +223,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.route("/settings", web::get().to(settings_page))
|
.route("/settings", web::get().to(settings_page))
|
||||||
.route("/api/save", web::post().to(save_table))
|
.route("/api/save", web::post().to(save_table))
|
||||||
.route("/api/save-settings", web::post().to(save_settings))
|
.route("/api/save-settings", web::post().to(save_settings))
|
||||||
|
.route("/api/config", web::get().to(get_config))
|
||||||
.service(actix_fs::Files::new("/static", "./static"))
|
.service(actix_fs::Files::new("/static", "./static"))
|
||||||
})
|
})
|
||||||
.bind("0.0.0.0:8080")?
|
.bind("0.0.0.0:8080")?
|
||||||
|
|||||||
@ -1,11 +1,15 @@
|
|||||||
// Sortiere die Tabelle nach Adresse (addr) beim Laden der Seite
|
// Sortiere die Tabelle nach Adresse (addr) beim Laden der Seite
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Darkmode-Status aus localStorage übernehmen
|
// Darkmode-Status aus Konfiguration übernehmen
|
||||||
if (localStorage.getItem('darkmode') === 'true') {
|
fetch('/api/config')
|
||||||
document.body.classList.add('darkmode');
|
.then(response => response.json())
|
||||||
} else {
|
.then(config => {
|
||||||
document.body.classList.remove('darkmode');
|
if (config && config.default && config.default.darkmode === true) {
|
||||||
}
|
document.body.classList.add('darkmode');
|
||||||
|
} else {
|
||||||
|
document.body.classList.remove('darkmode');
|
||||||
|
}
|
||||||
|
});
|
||||||
const tableBody = document.getElementById('tableBody');
|
const tableBody = document.getElementById('tableBody');
|
||||||
if (tableBody) {
|
if (tableBody) {
|
||||||
// Extrahiere alle Zeilen und deren addr
|
// Extrahiere alle Zeilen und deren addr
|
||||||
|
|||||||
@ -1,4 +1,44 @@
|
|||||||
|
// Setze den Wert des Darkmode-Schalters beim Laden der Seite, sobald das Element existiert
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
fetch('/api/config')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(config => {
|
||||||
|
function setSwitch() {
|
||||||
|
const el = document.getElementById('darkmode_switch');
|
||||||
|
if (el) {
|
||||||
|
if (config && config.default && (config.default.darkmode === true || config.default.darkmode === 'true')) {
|
||||||
|
el.checked = true;
|
||||||
|
} else {
|
||||||
|
el.checked = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Falls das Element noch nicht existiert, erneut versuchen
|
||||||
|
setTimeout(setSwitch, 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setSwitch();
|
||||||
|
});
|
||||||
|
});
|
||||||
async function saveSettings() {
|
async function saveSettings() {
|
||||||
|
// Default (für [default])
|
||||||
|
const darkmode = document.getElementById('darkmode_switch')?.checked ?? null;
|
||||||
|
const defaultConfig = {
|
||||||
|
loglevel: document.getElementById('loglevel')?.value || null,
|
||||||
|
darkmode: darkmode
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modbus
|
||||||
|
const modbus = {
|
||||||
|
host: document.getElementById('modbus_host').value,
|
||||||
|
port: parseInt(document.getElementById('modbus_port').value, 10),
|
||||||
|
max_coils_addr: parseInt(document.getElementById('modbus_max_coils_addr').value, 10) || null,
|
||||||
|
max_input_addr: parseInt(document.getElementById('modbus_max_input_addr').value, 10) || null,
|
||||||
|
max_holding_addr: parseInt(document.getElementById('modbus_max_holding_addr').value, 10) || null,
|
||||||
|
modbus_coils: null,
|
||||||
|
modbus_input_register: null,
|
||||||
|
modbus_holding_register: null
|
||||||
|
};
|
||||||
|
|
||||||
// MQTT
|
// MQTT
|
||||||
const mqtt = {
|
const mqtt = {
|
||||||
broker: document.getElementById('mqtt_broker').value,
|
broker: document.getElementById('mqtt_broker').value,
|
||||||
@ -18,28 +58,11 @@ async function saveSettings() {
|
|||||||
measurement: document.getElementById('influxdb_measurement').value || null
|
measurement: document.getElementById('influxdb_measurement').value || null
|
||||||
};
|
};
|
||||||
|
|
||||||
// Modbus
|
|
||||||
const modbus = {
|
|
||||||
host: document.getElementById('modbus_host').value,
|
|
||||||
port: parseInt(document.getElementById('modbus_port').value, 10),
|
|
||||||
max_coils_addr: parseInt(document.getElementById('modbus_max_coils_addr').value, 10) || null,
|
|
||||||
max_input_addr: parseInt(document.getElementById('modbus_max_input_addr').value, 10) || null,
|
|
||||||
max_holding_addr: parseInt(document.getElementById('modbus_max_holding_addr').value, 10) || null,
|
|
||||||
modbus_coils: null,
|
|
||||||
modbus_input_register: null,
|
|
||||||
modbus_holding_register: null
|
|
||||||
};
|
|
||||||
|
|
||||||
// Default (für [default])
|
|
||||||
const defaultConfig = {
|
|
||||||
loglevel: document.getElementById('loglevel')?.value || null
|
|
||||||
};
|
|
||||||
|
|
||||||
const settings = {
|
const settings = {
|
||||||
default: defaultConfig,
|
default: defaultConfig,
|
||||||
|
modbus,
|
||||||
mqtt,
|
mqtt,
|
||||||
influxdb,
|
influxdb
|
||||||
modbus
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -70,16 +93,3 @@ async function saveSettings() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Darkmode Toggle
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const btn = document.getElementById('darkmode-toggle');
|
|
||||||
if (!btn) return;
|
|
||||||
// Initialer Zustand aus LocalStorage
|
|
||||||
if (localStorage.getItem('darkmode') === 'true') {
|
|
||||||
document.body.classList.add('darkmode');
|
|
||||||
}
|
|
||||||
btn.addEventListener('click', function() {
|
|
||||||
document.body.classList.toggle('darkmode');
|
|
||||||
localStorage.setItem('darkmode', document.body.classList.contains('darkmode'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@ -41,9 +41,37 @@
|
|||||||
<option value="WARN">WARN</option>
|
<option value="WARN">WARN</option>
|
||||||
<option value="ERROR">ERROR</option>
|
<option value="ERROR">ERROR</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" style="text-align:right;">
|
<div class="form-group" style="display: flex; align-items: center; gap: 12px;">
|
||||||
<button id="darkmode-toggle" class="add-btn" type="button">🌙 Darkmode umschalten</button>
|
<label for="darkmode_switch">Darkmode:</label>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" id="darkmode_switch">
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-section">
|
||||||
|
<h2>Modbus Konfiguration</h2>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="modbus_host">Host:</label>
|
||||||
|
<input type="text" id="modbus_host" class="text-input" value="{{ modbus.host }}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="modbus_port">Port:</label>
|
||||||
|
<input type="text" id="modbus_port" class="text-input" value="{{ modbus.port }}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="modbus_max_coils_addr">Max Coils Addr:</label>
|
||||||
|
<input type="text" id="modbus_max_coils_addr" class="text-input" value="{{ modbus.max_coils_addr | default(value="") }}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="modbus_max_input_addr">Max Input Addr:</label>
|
||||||
|
<input type="text" id="modbus_max_input_addr" class="text-input" value="{{ modbus.max_input_addr | default(value="") }}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="modbus_max_holding_addr">Max Holding Addr:</label>
|
||||||
|
<input type="text" id="modbus_max_holding_addr" class="text-input" value="{{ modbus.max_holding_addr | default(value="") }}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -99,30 +127,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings-section">
|
|
||||||
<h2>Modbus Konfiguration</h2>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="modbus_host">Host:</label>
|
|
||||||
<input type="text" id="modbus_host" class="text-input" value="{{ modbus.host }}" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="modbus_port">Port:</label>
|
|
||||||
<input type="text" id="modbus_port" class="text-input" value="{{ modbus.port }}" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="modbus_max_coils_addr">Max Coils Addr:</label>
|
|
||||||
<input type="text" id="modbus_max_coils_addr" class="text-input" value="{{ modbus.max_coils_addr | default(value="") }}" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="modbus_max_input_addr">Max Input Addr:</label>
|
|
||||||
<input type="text" id="modbus_max_input_addr" class="text-input" value="{{ modbus.max_input_addr | default(value="") }}" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="modbus_max_holding_addr">Max Holding Addr:</label>
|
|
||||||
<input type="text" id="modbus_max_holding_addr" class="text-input" value="{{ modbus.max_holding_addr | default(value="") }}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button class="save-btn" onclick="saveSettings()">💾 Einstellungen speichern</button>
|
<button class="save-btn" onclick="saveSettings()">💾 Einstellungen speichern</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user