Feature: Eastron SDM-630 Support + Float32 Decode (v1.1.5)

- inverters.py: data_type Feld in Sensor (uint16/uint32/float32)
  + SDM-630 Definition (16 Sensoren: U/I/P L1-L3, PF, Freq, kWh)
  + read_ranges: [(0, 76)] — alle Sensoren in einem Batch
- modbus_client.py: Float32 IEEE 754 Decode via struct.unpack
  (SDM-630 liefert Floats, Growatt liefert skalierte Integer)
- index.html: "Wechselrichter" → "Gerät" — Add-on unterstützt
  jetzt beliebige Modbus-Geräte, nicht nur Wechselrichter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
retr0
2026-04-26 17:07:14 +02:00
parent fd5625b99a
commit 33c6a15644
4 changed files with 54 additions and 17 deletions
+10 -10
View File
@@ -161,7 +161,7 @@
<main>
<div class="tabs">
<div class="tab active" onclick="switchTab('live')">Live-Daten</div>
<div class="tab" onclick="switchTab('inverters')">Wechselrichter</div>
<div class="tab" onclick="switchTab('inverters')">Geräte</div>
<div class="tab" onclick="switchTab('settings')">Einstellungen</div>
</div>
@@ -195,11 +195,11 @@
<!-- Inverter Edit Modal -->
<div class="modal-backdrop" id="modal-backdrop" onclick="closeModal(event)">
<div class="modal" onclick="event.stopPropagation()">
<h2 id="modal-title">Wechselrichter hinzufügen</h2>
<h2 id="modal-title">Gerät hinzufügen</h2>
<input type="hidden" id="modal-id">
<div class="field"><label>Name</label>
<input type="text" id="modal-name" placeholder="z.B. Dach Süd"></div>
<div class="field"><label>Modell</label>
<div class="field"><label>Gerätetyp</label>
<select id="modal-model"></select></div>
<div class="field"><label>IP-Adresse</label>
<input type="text" id="modal-ip" placeholder="10.10.20.190"></div>
@@ -296,7 +296,7 @@ async function refreshData() {
document.getElementById("pill-mqtt").className = `pill ${d.mqtt_ok ? "ok" : "err"}`;
const keys = Object.keys(d.inverters || {});
document.getElementById("subtitle").textContent =
keys.length ? `${keys.length} Wechselrichter` : "Keine Wechselrichter";
keys.length ? `${keys.length} Gerät${keys.length !== 1 ? "e" : ""}` : "Keine Geräte";
renderLive(d.inverters || {});
} catch(e) {
document.getElementById("pill-mqtt").className = "pill err";
@@ -306,7 +306,7 @@ async function refreshData() {
function renderLive(inverters) {
const el = document.getElementById("live-content");
if (!Object.keys(inverters).length) {
el.innerHTML = '<div class="no-data">Keine Wechselrichter konfiguriert.<br>Bitte im Tab „Wechselrichter" hinzufügen.</div>';
el.innerHTML = '<div class="no-data">Keine Geräte konfiguriert.<br>Bitte im Tab „Geräte" hinzufügen.</div>';
return;
}
el.innerHTML = Object.values(inverters).map(inv => {
@@ -366,7 +366,7 @@ function renderInverterList() {
<div class="inv-card-header">
<div class="inv-card-icon">☀️</div>
<div class="inv-card-info">
<div class="inv-card-name">${esc(inv.name || "Wechselrichter")}</div>
<div class="inv-card-name">${esc(inv.name || "Gerät")}</div>
<div class="inv-card-model">${esc(model.name || inv.inverter_model)}</div>
</div>
</div>
@@ -381,7 +381,7 @@ function renderInverterList() {
</div>
</div>`;
}).join("");
el.innerHTML = cards + `<div class="add-btn" onclick="openModal()"> Wechselrichter hinzufügen</div>`;
el.innerHTML = cards + `<div class="add-btn" onclick="openModal()"> Gerät hinzufügen</div>`;
}
async function openModal(invId) {
@@ -389,7 +389,7 @@ async function openModal(invId) {
const modal = document.getElementById("modal-backdrop");
if (invId) {
const inv = invertersList.find(i => i.id === invId) || {};
document.getElementById("modal-title").textContent = "Wechselrichter bearbeiten";
document.getElementById("modal-title").textContent = "Gerät bearbeiten";
document.getElementById("modal-id").value = inv.id || "";
document.getElementById("modal-name").value = inv.name || "";
document.getElementById("modal-model").value = inv.inverter_model || "MIC_1500_TL_X";
@@ -399,7 +399,7 @@ async function openModal(invId) {
document.getElementById("modal-prefix").value = inv.mqtt_topic_prefix || "";
document.getElementById("modal-interval").value = inv.update_interval || 30;
} else {
document.getElementById("modal-title").textContent = "Wechselrichter hinzufügen";
document.getElementById("modal-title").textContent = "Gerät hinzufügen";
document.getElementById("modal-id").value = "";
document.getElementById("modal-name").value = "";
document.getElementById("modal-ip").value = "";
@@ -450,7 +450,7 @@ async function saveInverter() {
}
async function deleteInverter(id) {
if (!confirm("Wechselrichter wirklich löschen?")) return;
if (!confirm("Gerät wirklich löschen?")) return;
invertersList = invertersList.filter(i => i.id !== id);
try {
await fetchJSON(api("api/inverters-config"), {