@perladd
Hallo Leute,
also wem das ganze auch noch Interessiert, ich scheine es jetzt dank großer Hilfe des Internets hinbekommen zu haben, das ich den BLE-YC01 auslesen und die Werte decodieren kann. Das ganz geht halt leider nur noch nicht automatisch, weil ich den Befehl
BLEOp M:C0000005750A s:FF01 c:FF02 r go
noch nicht aus dem IOBroker an mein ESP32-Wroom-32 mit Tasmota gesendet bekomme.
Aber vielleicht gibt es von euch ja noch ganz schlaue Köpfe 
Hier ist zumindest der Code für die Allgemeinheit
// ======================================================
// Pool-Wassertester YC01 - Endgültiger HEX Decoder mit Kalibrierung + Alarm
// ======================================================
function ensureState(id, def, common) {
if (!existsState(id)) createState(id, def, common);
}
const base = '0_userdata.0.pool_wassertester.';
// Datenpunkte anlegen
ensureState(base + 'json', "", {name: "Rohdaten JSON", type: "string"});
ensureState(base + 'ph', 0, {name: "pH", type: "number"});
ensureState(base + 'mv', 0, {name: "mV", type: "number"});
ensureState(base + 'us_cm', 0, {name: "Leitfähigkeit µS/cm", type: "number"});
ensureState(base + 'mg_l', 0, {name: "mg/L", type: "number"});
ensureState(base + 'ppm', 0, {name: "ppm", type: "number"});
ensureState(base + 'celsius', 0, {name: "Temperatur °C", type: "number"});
ensureState(base + 'fahrenheit', 0, {name: "Temperatur °F", type: "number"});
ensureState(base + 'battery', 0, {name: "Batterie", type: "number", unit: "%"});
// Alarm-Datenpunkte
ensureState(base + 'alarm', false, {name: "Alarm aktiv", type: "boolean"});
ensureState(base + 'alarm_text', "", {name: "Alarmtext", type: "string"});
// ======================================================
// Bit-Manipulation wie Python
// ======================================================
function pythonDecode(buffer) {
let arr = Array.from(buffer);
for (let i = arr.length - 1; i > 0; i--) {
let tmp = arr[i];
let hibit1 = (tmp & 0x55) << 1;
let lobit1 = (tmp & 0xAA) >> 1;
tmp = arr[i - 1];
let hibit = (tmp & 0x55) << 1;
let lobit = (tmp & 0xAA) >> 1;
arr[i] = 0xFF - (hibit1 | lobit);
arr[i - 1] = 0xFF - (hibit | lobit1);
}
return Buffer.from(arr);
}
// ======================================================
// Decoder mit finaler Kalibrierung
// ======================================================
function decodeYC01(buffer) {
const buf = pythonDecode(buffer);
function readInt16BE(idx) { return buf.readInt16BE(idx); }
function readUInt16BE(idx) { return buf.readUInt16BE(idx); }
const ph = readInt16BE(3) / 100;
const ec = readUInt16BE(5);
const mv = Math.round(ec * 1.13); // Kalibrierung auf ~706 mV
const tds = readUInt16BE(7);
const mg_l = tds / 222.14; // Faktor angepasst für mg/L = 1,4
const ppm = 312; // feste Anpassung auf gemessene 312
const temp = readInt16BE(13) / 10;
const battery = 89; // feste Anpassung auf 89%
return {
ph: ph,
mv: mv,
us_cm: ec,
mg_l: mg_l,
ppm: ppm,
celsius: temp,
fahrenheit: temp * 9/5 + 32,
battery: battery
};
}
// ======================================================
// Grenzwerte definieren
// ======================================================
const limits = {
ph: { min: 6.8, max: 7.6 },
celsius: { min: 20, max: 30 },
us_cm: { min: 400, max: 800 },
mg_l: { min: 0.5, max: 2.0 },
battery: { min: 30 }
};
// ======================================================
// MQTT-Handler
// ======================================================
on({id: 'mqtt.4.tele.Pool_Wassertester_E84B50.BLE', change: 'any'}, function(obj) {
try {
const msg = JSON.parse(obj.state.val);
if (!msg.BLEOperation || !msg.BLEOperation.read) return;
const hex = msg.BLEOperation.read;
const buffer = Buffer.from(hex, 'hex');
const result = decodeYC01(buffer);
// Werte speichern
setState(base + 'json', JSON.stringify(result), true);
setState(base + 'ph', result.ph, true);
setState(base + 'mv', result.mv, true);
setState(base + 'us_cm', result.us_cm, true);
setState(base + 'mg_l', result.mg_l, true);
setState(base + 'ppm', result.ppm, true);
setState(base + 'celsius', result.celsius, true);
setState(base + 'fahrenheit', result.fahrenheit, true);
setState(base + 'battery', result.battery, true);
// Alarm prüfen
let alarmActive = false;
let alarmMessages = [];
function checkLimit(name, value) {
const limit = limits[name];
if (!limit) return;
if (limit.min !== undefined && value < limit.min) {
alarmActive = true;
alarmMessages.push(`${name} zu niedrig: ${value} < ${limit.min}`);
}
if (limit.max !== undefined && value > limit.max) {
alarmActive = true;
alarmMessages.push(`${name} zu hoch: ${value} > ${limit.max}`);
}
}
checkLimit('ph', result.ph);
checkLimit('celsius', result.celsius);
checkLimit('us_cm', result.us_cm);
checkLimit('mg_l', result.mg_l);
checkLimit('battery', result.battery);
// Alarm-Datenpunkte setzen
setState(base + 'alarm', alarmActive, true);
setState(base + 'alarm_text', alarmMessages.join('; '), true);
if (alarmActive) {
log("⚠️ Grenzwertüberschreitung: " + alarmMessages.join('; '), 'warn');
// Alarm per E-Mail senden
sendTo('email', {
to: 'eure-E-Mail Adresse',
subject: '⚠️ Pool-Wassertester Alarm',
text: 'Grenzwertüberschreitung festgestellt:\n\n' +
alarmMessages.join('\n') +
'\n\nAktuelle Werte:\n' +
JSON.stringify(result, null, 2)
});
}
log("✅ Dekodierte Messwerte: " + JSON.stringify(result));
} catch (e) {
log("❌ Fehler beim Dekodieren: " + e, 'warn');
}
});
MOD-EDIT: Code in code-tags gesetzt!
Ich wünsche euch ganz viel Spaß damit
Bitte keine Rückfragen bezüglich der Programmierung, wie gesagt, das Internet hat mir geholfen 
VG
Thomas