java-scripts/java-scripts/Traccar Logging: EQA 300.js hinzugefügt
This commit is contained in:
121
java-scripts/java-scripts/Traccar Logging: EQA 300.js
Normal file
121
java-scripts/java-scripts/Traccar Logging: EQA 300.js
Normal file
@@ -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).`);
|
||||||
Reference in New Issue
Block a user