diff --git a/java-scripts/java-scripts/Traccar Logging: EQA 300.js b/java-scripts/java-scripts/Traccar Logging: EQA 300.js new file mode 100644 index 0000000..64d84a6 --- /dev/null +++ b/java-scripts/java-scripts/Traccar Logging: EQA 300.js @@ -0,0 +1,121 @@ +/*********************************************** + * EQA 300 ioBroker → Traccar (OwnTracks über HTTP, Port 5144) + * sendet NUR bei Positionsänderung + mit Speed + Battery + * jetzt mit setInterval() statt schedule() + ***********************************************/ +const http = require("http"); + +// === Grundkonfiguration === +const TRACCAR_HOST = "192.168.2.125"; // IP oder Hostname deines Traccar +const TRACCAR_PORT = 5144; // OwnTracks-Port +const DEVICE_TID = "EQA"; // in Traccar muss das Gerät so heißen! + +// === ioBroker-Datenpunkte === +const LAT_STATE = "mercedesme.0.W1N9N0KB9TJ192372.state.positionLat.doubleValue"; +const LON_STATE = "mercedesme.0.W1N9N0KB9TJ192372.state.positionLong.doubleValue"; +const SPD_STATE = "mercedesme.0.W1N9N0KB9TJ192372.state.speedUnitFromIC.doubleValue"; +const BAT_STATE = "mercedesme.0.W1N9N0KB9TJ192372.state.soc.displayValue"; + +// === Sende- und Bewegungsparameter === +const SEND_INTERVAL_SECONDS = 180; // wie oft prüfen (hier: alle 3 Minuten) +const MIN_DISTANCE_METERS = 15; // minimale Bewegung für neue Übertragung + +// interne Speicherung der letzten Position +let lastLat = null; +let lastLon = null; + +// === Hilfsfunktion: Haversine-Distanz (Meter) === +function distanceMeters(lat1, lon1, lat2, lon2) { + const R = 6371000; // Erdradius in Metern + const toRad = (v) => v * Math.PI / 180; + const dLat = toRad(lat2 - lat1); + const dLon = toRad(lon2 - lon1); + const a = + Math.sin(dLat / 2) ** 2 + + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * + Math.sin(dLon / 2) ** 2; + return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); +} + +// === Hauptfunktion === +function sendOwntracks(force = false) { + const lat = getState(LAT_STATE)?.val; + const lon = getState(LON_STATE)?.val; + + const rawSpeed = getState(SPD_STATE)?.val; + const rawBatt = getState(BAT_STATE)?.val; + + const speed = rawSpeed !== undefined && rawSpeed !== null ? Number(rawSpeed) : NaN; + const batt = rawBatt !== undefined && rawBatt !== null ? Number(rawBatt) : NaN; + + if (lat == null || lon == null) { + log("OwnTracks→Traccar: keine gültigen Koordinaten – sende nicht", "warn"); + return; + } + + // Bewegung prüfen + if (!force && lastLat !== null && lastLon !== null) { + const dist = distanceMeters(lastLat, lastLon, lat, lon); + if (dist < MIN_DISTANCE_METERS) { + log(`OwnTracks→Traccar: keine relevante Bewegung (${dist.toFixed(1)} m) – nichts gesendet.`); + return; + } + } + + const tst = Math.floor(Date.now() / 1000); + + // === OwnTracks-kompatibles JSON === + const data = { + "_type": "location", + "lat": lat, + "lon": lon, + "tid": DEVICE_TID, + "tst": tst, + "acc": 5 + }; + + if (!Number.isNaN(speed)) data.vel = speed; + if (!Number.isNaN(batt)) data.batt = batt; + + const payload = JSON.stringify(data); + + const options = { + host: TRACCAR_HOST, + port: TRACCAR_PORT, + path: "/", + method: "POST", + headers: { + "Content-Type": "application/json", + "Content-Length": Buffer.byteLength(payload), + "Connection": "close" + } + }; + + const req = http.request(options, (res) => { + let body = ""; + res.on("data", (chunk) => body += chunk); + res.on("end", () => { + log(`OwnTracks→Traccar: gesendet lat=${lat}, lon=${lon}, status=${res.statusCode}, speed=${!Number.isNaN(speed)?speed:"-"}, batt=${!Number.isNaN(batt)?batt:"-"}`); + if (body && body.trim()) log("OwnTracks→Traccar: Antwort: " + body); + lastLat = lat; + lastLon = lon; + }); + }); + + req.on("error", (err) => log("OwnTracks→Traccar: HTTP-Fehler: " + err, "error")); + req.write(payload); + req.end(); +} + +// === Intervall + Trigger === +// → läuft alle SEND_INTERVAL_SECONDS Sekunden +setInterval(() => sendOwntracks(false), SEND_INTERVAL_SECONDS * 1000); + +// → sofortige Übertragung bei Koordinatenänderung +on({ id: LAT_STATE, change: "ne" }, () => sendOwntracks(false)); +on({ id: LON_STATE, change: "ne" }, () => sendOwntracks(false)); + +// → erstes Mal sofort senden +sendOwntracks(true); + +log(`OwnTracks→Traccar-Sender gestartet (alle ${SEND_INTERVAL_SECONDS}s, nur bei Bewegung, mit Speed & Battery).`);