const DEBUG = true
let filePath = '/opt/iobroker/iobroker-data/ElsterTable.inc';
let elsterJsObject = convertToJsObject(filePath);
const CanScnifferId = "mqtt.0.TTF"
//const CanScnifferId = "mqtt.0.TTF.303"
let scanAllElsterIdsTimerVar, scanAllStatestimerVar, scanShortStatestimerVar
let GlobscanAllElsterIds = {
   lastPosition: 0,
   lastkey: "0",
 //  geraet: 0x0180
}
// Das muss einmal pro Zieladresse ausgeführt werden um zu scannen welche Datenpunke abfragbar sind
// Jeweils einmal pro Adresse 
scanAllElsterIds(0x0180,0)
let GlobscanAllStates = {
   lastPosition: 0,
   lastkey: "0",
   intervall: 10 * 60 * 1000,
}
scanAllStates()
// Die Hier angegebenen Datenpunkte werden in einem unter Intervall angegebenen Intervall in Millisekunden regelmäßig aktiv abgefragt
let GlobshortScan = {
   lastPosition: 0,
   lastkey: "0",
   intervall: 30000,
   iDs: [
    //   { geraet: 0x0180, elsterName: "WPVORLAUFIST" },
    //   { geraet: 0x0180, elsterName: "RUECKLAUFISTTEMP" },
   //    { geraet: 0x0180, elsterName: "MASCHINENDRUCK" },
   //    { geraet: 0x0301, elsterName: "VORLAUFSOLLTEMP" },
   //    { geraet: 0x0180, elsterName: "PUFFERSOLL" },
   ]
}
scanShortStates()
on({ id: CanScnifferId + '.pload', change: "ne" }, function (obj) {
   if (DEBUG || false) log(obj.state.val)
   const telegramObj = parseCanTelegram(JSON.parse(obj.state.val))
   if (Number(telegramObj.elsterIndex) == Number(GlobscanAllElsterIds.lastkey)) {
       //log("gleich")
       //log(Number(telegramObj.elsterIndex) + " - " + Number(GlobscanAllElsterIds.lastkey))
       clearTimeout(scanAllElsterIdsTimerVar)
       scanAllElsterIds(GlobscanAllElsterIds.geraet, GlobscanAllElsterIds.lastPosition + 1)
   }
   if (Number(telegramObj.elsterIndex) == Number(GlobscanAllStates.lastkey)) {
       //log("gleich")
       //log(Number(telegramObj.elsterIndex) + " - " + Number(GlobscanAllElsterIds.lastkey))
       clearTimeout(scanAllStatestimerVar)
       scanAllStates(GlobscanAllStates.lastPosition + 1)
   }
   if (Number(telegramObj.elsterIndex) == Number(GlobshortScan.lastkey)) {
       //log("gleich")
       //log(Number(telegramObj.elsterIndex) + " - " + Number(GlobscanAllElsterIds.lastkey))
       clearTimeout(scanShortStatestimerVar)
       scanShortStates(GlobshortScan.lastPosition + 1)
   }
   //evaluateMessages(JSON.parse(obj.state.val))
   //log(JSON.stringify(telegramObj));
   //writeLog(JSON.stringify(telegramObj)), 'CanLog.csv').catch(error => console.error(JSON.stringify(error)));
});
function convertToJsObject(filePath) {
   // In einer echten JavaScript-Umgebung müsste hier die fs-Bibliothek verwendet werden,
   // um die Datei zu lesen. Der folgende Code ist eine vereinfachte Darstellung.
   const fs = require('fs');
   let elsterTable = {};
   // Lies die Datei synchron, dies ist in einem realen Szenario zu vermeiden
   let fileContent = fs.readFileSync(filePath, 'utf-8');
   let lines = fileContent.split('\n');
   lines.forEach((line) => {
       // Ignorieren von Kommentaren und leeren Zeilen
       if (line.startsWith('//') || line.trim() === '' || line.startsWith('{') || line.startsWith('}')) {
           return;
       }
       // Entfernen von Anführungszeichen und geschweiften Klammern, dann Aufspaltung der Zeile in Teile
       let parts = line.replace('{', '').replace('}', '').replace(/"/g, '').trim().split(',');
       parts = parts.map(part => part.trim()).filter(part => part);
       // Überprüfen, ob die Zeile drei Teile enthält: Name, Index und Typ
       if (parts.length === 3) {
           let [name, index, type_] = parts;
           try {
               // Versuche, den Index von Hex zu Dezimal zu konvertieren
               let indexKey = parseInt(index, 16);
               // Hinzufügen zum JavaScript-Objekt
               elsterTable[indexKey] = { "name": name, "type": type_ };
           } catch (error) {
               // Wenn der Index nicht in einen Integer umgewandelt werden kann, ignorieren wir diese Zeile
               console.error('Konvertierungsfehler:', error);
           }
       }
   });
   return elsterTable;
}
// Das ElsterTable-Objekt, das zuvor erstellt wurde
let elsterTable = elsterJsObject
// Funktion zum Konvertieren der Hex-Daten in lesbare Werte
function convertData(hexString) {
   let bytes = [];
   for (let i = 0; i < hexString.length; i += 2) {
       bytes.push(parseInt(hexString.substr(i, 2), 16));
   }
   let rawValue = (bytes[1] << 8) | bytes[2]; // Korrigierte Byte-Position
   return rawValue / 10; // Annahme: Der Wert ist durch 10 zu teilen
}
// Funktion zum Auswerten der Nachrichten
function evaluateMessages(message) {
   //messages.forEach((message) => {
   let id = message.ID;
   let data = message.Data.replace(/\s/g, "");
   // Der Index ist das dritte Byte in der Nachricht, hier als Hex-String
   let indexHex = data.substr(4, 2);
   log(indexHex)
   let index = parseInt(indexHex, 16);
   let valueHEX = data.substr(6, 4);
   let value = parseInt(valueHEX, 16)
   log("Index:" + index)
   log("Data:" + data)
   log("Value Hex:" + valueHEX)
   log("Value Dezi:" + value)
   // Hole den Eintrag aus dem ElsterTable
   let entry = elsterTable[index];
   if (entry) {
       log(`Gerät: ${id}, Parameter: ${entry.name}, Wert: ${value / 10}`);
   } else {
       log(`Unbekannter Index: ${indexHex}. Message: ${message}`);
   }
}
function parseMessage(str) {
   // Zerlege den String in Teile und extrahiere relevante Teile
   const parts = str.trim().split(/\s+/);
   const idPart = parts[1].substring(2); // Entferne '0x'
   const dataPart = parts.slice(4).join('').replace("Data:", ""); // Entferne 'Data:'
   // Erstelle das messages-Objekt
   return {
       id: idPart, // Entfernt '0x'
       data: dataPart // Entfernt 'Data:'
   };
}
// Beispiel für die Verwendung der Funktion
//const messageStr = {"ID": "0x301", "Len": "7", "Data": "C0 01 11 00 DF 00 00"};
//evaluateMessages(messageStr)
// ****************************************************************
// :
function parseCanTelegram(telegram) {
   // Entferne alle Leerzeichen und prüfe das Format
   let dataString = telegram.Data.replace(/\s/g, '');
   if (dataString.length % 2 !== 0) {
       throw new Error('Ungültige Datenlänge');
   }
   // Zerlege die Daten in ihre Teile
   let parts = dataString.match(/.{1,2}/g).map(byte => parseInt(byte, 16));
   // Berechne die CAN-ID
   let calculatedId = (8 * (parts[0] & 0xF0)) + (parts[1] & 0x0F);
   let calculatedIdHex = calculatedId.toString(16).toUpperCase();
   calculatedIdHex = "0x" + ("000" + calculatedIdHex).slice(-4);
   // Überprüfe den Typ des Telegramms
   let typID = (parts[0] & 0x0F)
   let type
   switch (typID) {
       case 0:
           type = "write"
           break;
       case 1:
           type = "read"
           break;
       case 2:
           type = "response"
           break;
       case 3:
           type = "ack"
           break;
       case 4:
           type = "write ack"
           break;
       case 5:
           type = "write respond"
           break;
       case 6:
           type = "system"
           break;
       case 7:
           type = "system respond"
           break;
       default:
           type = "Unbekannt"
   }
   // Bestimme den Elster-Index und erhöhe ihn um 1
   let elsterIndex = parts[2] === 0xFA ? (((parts[3] << 8) + parts[4])) : (parts[2]);
   // Konvertiere den Elster-Index in vierstellige Hexadezimalzahl und entferne das zuvor hinzugefügte +1
   let elsterIndexHex = elsterIndex.toString(16).toUpperCase();
   let elsterFunktion = elsterTable[elsterIndex];
   elsterIndexHex = "0x" + ("000" + elsterIndexHex).slice(-4);
   let data = parts.slice(3).map(byte => byte.toString(16).padStart(2, '0')).join(' ').toUpperCase();
   // Nutzdaten, beginnend nach dem Elster-Index
   let dataIndexStart = parts[2] === 0xFA ? 5 : 3;
   let dataBytes = parts.slice(dataIndexStart, dataIndexStart + 2);
   let dataHex = dataBytes.map(byte => byte.toString(16).padStart(2, '0')).join('').toUpperCase();
   let dataDecimal = (dataBytes[0] << 8) + dataBytes[1];
   let dataDecimalCon = AllValuesConverter(dataDecimal, elsterFunktion.type, true)
   let StateToSet = "0_userdata.0.WP13." + telegram.ID.replace("0x", "") + "." + elsterFunktion.name
   log(StateToSet)
   log("state:" + StateToSet + " dataDecimalCon: " + dataDecimalCon)
   if (dataDecimal != 32768) {
       createState(StateToSet, dataDecimalCon, false)
       setState(StateToSet, dataDecimalCon, true)
   }
   return {
       raw: dataString,
       calculatedId: calculatedIdHex,
       type,
       elsterIndex: elsterIndexHex,
       elsterFunktion,
       dataHex,
       dataDecimal,
       FromID: telegram.ID,
       Len: telegram.Len
   };
}
function AllValuesConverter(value, TypeString, read = true) {
   //log("value to String: " +  value.toString().toLowerCase() )
   switch (TypeString) {
       case "et_datum":
           if (read) {
               return convertBytesToDatum(Number(value))
           } else {
               return convertDatumToBytes(value)
           }
           break;
       case "et_dec_val":
           if (read) {
               return Number((interpretAsSigned16(value) / 10).toFixed(1))
           } else {
               return Number((interpretAsSigned16(value) * 10).toFixed(0))
           }
           break;
       case "et_time_domain":
           if (read) {
               if (value == 0xFFFF) return "NA"
               if (value == 0x8080) return "-----"
               return convertBytesToTime(Number(value))
           } else {
               if (value.toString() == "NA") return 0xFFFF
               if (value.toString() == "-----") return 0x8080
               log("Zeitrückgabe: " + value + " zu: " + Number(convertTimeRangeToBytes(value.toString())))
               return Number(convertTimeRangeToBytes(value.toString()))
           }
           break;
       case "et_betriebsart":
           if (read) {
               if (value == 0x0000) return "Notbetrieb"
               if (value == 0x0100) return "Bereitschaft"
               if (value == 0x0200) return "Automatik"
               if (value == 0x0300) return "Tagbetrieb"
               if (value == 0x0400) return "Absenkbetrieb"
               if (value == 0x0500) return "Warmwasser"
               if (value == 0x0B00) return "FEKAuto"
               return value
           } else {
               //log("value to String: " +  value.toString().toLowerCase() )
               if (value.toString().toLowerCase() == "notbetrieb") return 0x0000
               if (value.toString().toLowerCase() == "bereitschaft") return 0x0100
               if (value.toString().toLowerCase() == "automatik") return 0x0200
               if (value.toString().toLowerCase() == "tagbetrieb") return 0x0300
               if (value.toString().toLowerCase() == "absenkbetrieb") return 0x0400
               if (value.toString().toLowerCase() == "warmwasser") return 0x0500
               if (value.toString().toLowerCase() == "fekauto") return 0x0B00
               return Number(value)
           }
           break;
       case "et_little_endian":
       case "et_little_bool":
           return littleEndianHexConvert(value)
           break;
       default:
           return value
   }
}
function interpretAsSigned16(uint16) {
   // Prüfen, ob die Zahl größer als der maximal positive Wert für einen vorzeichenbehafteten 16-Bit-Integer ist
   if (uint16 > 32767) {
       return uint16 - 65536;
   } else {
       return uint16;
   }
}
// Von Little Endian Hex zu Dezimal
function littleEndianHexConvert(value) {
   // Verschieben Sie die Bytes und kombinieren Sie sie
   let lowByte = value & 0xFF; // Extrahieren Sie das niedrigwertige Byte
   let highByte = (value & 0xFF00) >> 8; // Extrahieren und verschieben Sie das hochwertige Byte
   return (highByte | (lowByte << 8));
}
function convertBytesToTime(value) {
   let startByte = value >> 8;
   let endByte = value & 0xFF;
   return convertToTime(startByte) + ' - ' + convertToTime(endByte);
}
function convertBytesToDatum(value) {
   let startByte = value >> 8;
   let endByte = value & 0xFF;
   return (startByte) + '.' + (endByte);
}
function convertToTime(value) {
   let hours = Math.floor(value / 4);
   let minutes = (value % 4) * 15;
   return hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0');
}
function convertTimeToBytes(startTime, endTime) {
   let startUnits = convertToUnits(startTime);
   let endUnits = convertToUnits(endTime);
   return (startUnits << 8) + endUnits;
}
function convertToUnits(time) {
   let [hours, minutes] = time.split(':').map(Number);
   return hours * 4 + Math.floor(minutes / 15);
}
function convertTimeRangeToBytes(timeRange) {
   // Entfernen Sie alle Leerzeichen aus dem String
   let cleanedTimeRange = timeRange.replace(/\s/g, '');
   // Teilen Sie den bereinigten String in Start- und Endzeit
   let [startTime, endTime] = cleanedTimeRange.split('-');
   if (!endTime) return timeRange
   return convertTimeToBytes(startTime, endTime);
}
function convertDatumToBytes(datum) {
   let cleaneddatum = datum.replace(/\s/g, '');
   let [tag, monat] = cleaneddatum.split('.').map(Number);
   //log(tag + " " + monat + " " + typeof(monat))
   if (!monat) return datum
   return ((tag << 8) + (monat));
}
//console.log(convertBytesToTime(0x8080)); // Gibt "00:00 - 01:15" aus
//console.log(convertTimeToBytes("15:30", "01:15").toString(16)); // Gibt "105" aus
//console.log(convertTimeRangeToBytes("32:00 - 32:00").toString(16)); // Gibt "105" aus
//log(convertBytesToDatum(3851)) // Gibt "15.11" aus
//log(convertDatumToBytes("15.11"))
// Beispiel-Telegramm
let telegram = {
   "ID": "0x680",
   "Len": "6",
   "Data": "61010112340000"
}
//console.log(parseCanTelegram(telegram));
function buildCanIdWithTypeId(canId, typeId, elsterIndexHex, HexDaten) {
   let hexbuffer = Buffer.from("0000000000", "hex")
   hexbuffer[0] = Math.floor(parseInt(canId, 16) / 8) + parseInt(typeId, 16)
   hexbuffer[1] = (parseInt(canId, 16) % 8)
   let elsterBytes = Buffer.from(elsterIndexHex, "hex");
   hexbuffer[2] = elsterBytes[1];
   //hexbuffer[3] = elsterBytes[1];
   let DatenBytes = Buffer.from(HexDaten, "hex");
   hexbuffer[3] = DatenBytes[0];
   hexbuffer[4] = DatenBytes[1];
   return hexbuffer.toString('hex')
}
/***************************************
**********  LOG FILE ERSTELLEN  ************ 
****************************************/
const logpath = '/opt/iobroker/log/';
const fs = require('fs').promises;
async function writeLog(logEntry, filename = "ECOTest2.csv") {
   // Get the current date and time
   const now = new Date();
   const dateTime = now.toLocaleString();
{1}
   // Format the log entry
   const formattedEntry = `${dateTime}\t${logEntry}\n`;
{1}
   try {
       // Check if the file already exists
       await fs.stat(logpath + filename);
   } catch (error) {
       if (error.code === 'ENOENT') {
           // If the file does not exist, we need to add the header
           const header = 'DateTime\tLog Entry\n';
           await fs.writeFile(logpath + filename, header);
           log("neue datei erstellt");
       } else {
           // Some other error occurred
           throw error;
       }
   }
   // Append the log entry to the file
   try {
       await fs.appendFile(logpath + filename, formattedEntry);
       //console.log('Log entry saved!');
   } catch (error) {
       throw error;
   }
}
// Anwendung:
//writeLog('This is a test entry.', 'Filename.csv').catch(error => console.error(error));
//***************************************
//***************************************
function initElsterFrame(senderId, receiverId, elsterIdx, pdaten, typ = 1) {
   senderId = Number(senderId)
   const address = (Number(receiverId) & 0x780) >> 3;
   let data = new Array(7); // Erstellt ein Array mit 5 Elementen für die Datenbytes
   // Die Id und die Länge des Frames werden nicht direkt gesetzt, da in JavaScript
   // üblicherweise Objekte anstelle von direkt manipulierten Byte-Arrays verwendet werden.
   data[0] = (Number(address) & 0xF0) + Number(typ);
   data[1] = Number(receiverId) & 0x07;
   data[2] = 0xFA;
   data[3] = (Number(elsterIdx) >> 8) & 0xFF; // Höherwertiges Byte von ElsterIdx
   data[4] = Number(elsterIdx) & 0xFF; // Niederwertiges Byte von ElsterIdx
   data[5] = (Number(pdaten) >> 8) & 0xFF; // Niederwertiges Byte von ElsterIdx
   data[6] = Number(pdaten) & 0xFF; // Niederwertiges Byte von ElsterIdx
   return {
       ID: "0x" + senderId.toString(16),
       Len: "7",
       Data: data.map(byte => byte.toString(16).padStart(2, '0')).join('').toUpperCase()
   };
}
// Änderungen senden:
on({ id: new RegExp("0_userdata.0.WP13\..*"), change: "any", ack: false }, function (obj) {
   log("was geändert:" + obj.id + " ack:" + obj.state.ack)
   readDataFromObject(obj, 'write')
});
function readDataFromObject(obj, art = 'readonly') {
   let ID, elstername, mtelegram
   if (obj.id) {
       ID = "0x" + ((obj.id).split('.').slice(-2, -1)[0])
       elstername = ((obj.id).split('.').slice(-1)[0])
   } else {
       ID = "0x" + ((obj._id).split('.').slice(-2, -1)[0])
       elstername = ((obj._id).split('.').slice(-1)[0])
   }
   let elsterObjekt = Object.entries(elsterJsObject).find(([key, value]) => value.name === elstername);
{1}
   let elsterID = elsterObjekt[0]; // Der Schlüssel
   let gesuchtesObjekt = elsterObjekt[1]; // Das gesuchte Objekt
   // Verwenden Sie hier elsterID und gesuchtesObjekt wie benötigt
   // log (JSON.stringify(gesuchtesObjekt) + " : " + obj.state.val + " Konvertiert: " + AllValuesConverter(obj.state.val, gesuchtesObjekt.type ,true))
{1}
   //let elsterID = Object.keys(elsterJsObject).find(key => elsterJsObject[key].name === elstername);
   /*
       log("Gerät: " + ID)
       log("elstername: " + elstername)
       log("elsterIDHex: " + Number(elsterID).toString(16))
       log("value: " + obj.state.val)
       log("art: " + art)
   */
   if (art == 'write') {
       let dataDecimalCon = AllValuesConverter((obj.state.val), gesuchtesObjekt.type, false)
       mtelegram = JSON.stringify(initElsterFrame("0x680", ID, elsterID, dataDecimalCon, 2))
       log(" Wert Setzten: " + mtelegram)
       setState(CanScnifferId + '.canSend', mtelegram)
       setTimeout(function () {
           mtelegram = JSON.stringify(initElsterFrame("0x680", ID, elsterID, 0, 1))
           //log(" Wert abrufen: " + mtelegram)
           setState(CanScnifferId + '.canSend', mtelegram)
       }, 2 * 1000);
   } else if (art == 'readonly') {
       mtelegram = JSON.stringify(initElsterFrame("0x680", ID, elsterID, 0, 1))
       //log(" Wert abrufen: " + mtelegram)
       setState(CanScnifferId + '.canSend', mtelegram)
   }
}
//Zum Scannen aller verfügbaren Parameter eines gerätes
function scanAllElsterIds(geraet = 0x180, lastPosition = 0) {
   GlobscanAllElsterIds.geraet = geraet
   let canId, mtelegram
   let maxScan
   let keys = Object.keys(elsterJsObject);
   maxScan = keys.length
   if (lastPosition >= maxScan) {
       let Zeitkompl = Math.floor((Date.now() - GlobscanAllStates.Starttime) / 1000)
       if (DEBUG) log("Scan all ElsterIds beendet. Scandauer: " + Zeitkompl + " Sekunden für " + lastPosition + " Scans")
       GlobscanAllElsterIds.lastPosition = 0
       GlobscanAllElsterIds.lastkey = "0"
       GlobscanAllElsterIds.Starttime = 0
       return
   } else if (lastPosition == 0) {
       if (DEBUG) log("Scan all States gestartet")
       GlobscanAllElsterIds.Starttime = Date.now()
   }
   let key = keys[lastPosition]
   if (DEBUG) if (lastPosition % 20 == 0) log("(" + ((100 / maxScan) * lastPosition).toFixed(0) + "%) Scanposition: " + lastPosition + " von " + maxScan + " elsterID:" + key + " elstername:" + elsterJsObject[key].name)
   //log(key)
   mtelegram = JSON.stringify(initElsterFrame("0x680", geraet, key, 0, 1))
   //log(lastPosition + " von " + maxScan + " Wert abrufen: " + mtelegram)
   setState(CanScnifferId + '.canSend', mtelegram)
   GlobscanAllElsterIds.lastPosition = lastPosition
   GlobscanAllElsterIds.lastkey = key
   scanAllElsterIdsTimerVar = setTimeout(function () {
       scanAllElsterIds(geraet, lastPosition + 1); // Setzt den nächsten Aufruf auf 1000 ms später
   }, 5000)
}
//Zum Scannen aller Angelegten States
function scanAllStates(lastPosition = 0) {
   let mSelector = $("0_userdata.0.WP13.*");
   let maxScan = mSelector.length
   if (lastPosition >= maxScan - 1) {
       let Zeitkompl = Math.floor((Date.now() - GlobscanAllStates.Starttime) / 1000)
       if (DEBUG) log("Scan all States beendet. Scandauer: " + Zeitkompl + " Sekunden für " + lastPosition + " Scans")
       GlobscanAllStates.lastPosition = 0
       GlobscanAllStates.lastkey = "0"
       GlobscanAllStates.Starttime = 0
       setTimeout(function () {
           scanAllStates(0); // Setzt den nächsten Aufruf auf 1000 ms später
       }, GlobscanAllStates.intervall)
       return
   } else if (lastPosition == 0) {
       if (DEBUG) log("Scan all States gestartet")
       GlobscanAllStates.Starttime = Date.now()
   }
   //log("mSelector " + mSelector[lastPosition])
   let elstername = ((mSelector[lastPosition]).split('.').slice(-1)[0])
   let geraeteId = (mSelector[lastPosition]).split('.').slice(-2)[0]
   //log("GeraeteID:" + geraeteId )
   let elsterID = Object.keys(elsterJsObject).find(key => elsterJsObject[key].name === elstername);
   GlobscanAllStates.lastPosition = lastPosition
   GlobscanAllStates.lastkey = elsterID
   if (DEBUG) if (lastPosition % 20 == 0) log("ScanAllStates (" + ((100 / maxScan) * lastPosition).toFixed(0) + "%) Positiom:" + lastPosition + " von " + maxScan + " geraeteId:" + geraeteId + " elsterID:" + elsterID + " elstername:" + elstername)
   let myObj = getObject(mSelector[lastPosition])
   myObj.state = getState(mSelector[lastPosition])
   myObj.id = mSelector[lastPosition]
   //log(JSON.stringify(myObj))
   readDataFromObject(myObj)
   scanAllStatestimerVar = setTimeout(function () {
       if (elstername != "DATUM") log("Timeout position:" + lastPosition + " geraeteId:" + geraeteId + " elsterID:" + elsterID + " elstername:" + elstername)
       scanAllStates(lastPosition + 1); // Setzt den nächsten Aufruf auf 1000 ms später
   }, 5000)
}
function scanShortStates(lastPosition = 0) {
   let maxScan = GlobshortScan.iDs.length
   //log("Anzahl IDs Short:" + maxScan)
   if (lastPosition >= maxScan) {
       let Zeitkompl = Math.floor((Date.now() - GlobshortScan.Starttime) / 1000)
       if (DEBUG) log("Scan Short States beendet. Scandauer: " + Zeitkompl + " Sekunden für " + lastPosition + " Scans")
       GlobshortScan.lastPosition = 0
       GlobshortScan.lastkey = "0"
       GlobshortScan.Starttime = 0
       setTimeout(function () {
           scanShortStates(0); // Setzt den nächsten Aufruf auf 1000 ms später
       }, GlobshortScan.intervall)
       return
   } else if (lastPosition == 0) {
       if (DEBUG) log("Scan Short States gestartet")
       GlobshortScan.Starttime = Date.now()
   }
   //log("mSelector " + mSelector[lastPosition])
   let elstername = GlobshortScan.iDs[lastPosition].elsterName
   let elsterID = Object.keys(elsterJsObject).find(key => elsterJsObject[key].name === elstername);
   GlobshortScan.lastPosition = lastPosition
   GlobshortScan.lastkey = elsterID
   let esterState = "0_userdata.0.WP13." + GlobshortScan.iDs[lastPosition].geraet.toString(16).replace("tzt0x", "") + "." + elstername
   //log(esterState)
   if (DEBUG) if (lastPosition % 20 == 0) log("ScanShortStates (" + ((100 / maxScan) * lastPosition).toFixed(0) + "%) Positiom:" + lastPosition + " von " + maxScan + " elsterID:" + elsterID + " elstername:" + elstername)
   let myObj = getObject(esterState)
   myObj.state = getState(esterState)
   myObj.id = esterState
   //log(JSON.stringify(myObj))
   readDataFromObject(myObj)
   scanShortStatestimerVar = setTimeout(function () {
       log("Timeout Shortscan position:" + lastPosition + " elsterID:" + elsterID + " elstername:" + elstername)
       scanShortStates(lastPosition + 1); // Setzt den nächsten Aufruf auf 1000 ms später
   }, 5000)
}
/*
//Objekte löschen:
$('0_userdata.0.WP13.180.EL_*').each(function (id, i) {
           log(i + " - " + id + " existsObject: " + existsObject(id))
           //deleteObject(id,true);
});
*/
// Beispielaufruf
let canId, mtelegram
let Senderid = "0x680"
canId = "0x180"; // 384 in dezimal
//canId = "0x601"; // 384 in dezimal
let typeId = 1; // 1 in dezimal
let elsterIndexHex = "0x17a0"
let pHexDaten = 0x0000
mtelegram = JSON.stringify(initElsterFrame(Senderid, canId, elsterIndexHex, pHexDaten, typeId))
//console.log("Generiertes Telegramm:" + mtelegram);
//setState( CanScnifferId +'.canSend', mtelegram)
/*
setState( CanScnifferId +'.canSend', mtelegram, function () {
   setTimeout(function () {
       elsterIndexHex = "0x1700"
       pHexDaten = 0x8080
       mtelegram = JSON.stringify(initElsterFrame(Senderid, canId, elsterIndexHex, pHexDaten, typeId))
       console.log("Generiertes Telegramm:" + mtelegram);
       setState( CanScnifferId +'.canSend', mtelegram, function () {
           setTimeout(function () {
               elsterIndexHex = "0x1722"
               pHexDaten = 0x8080
               mtelegram = JSON.stringify(initElsterFrame(Senderid, canId, elsterIndexHex, pHexDaten, typeId))
               console.log("Generiertes Telegramm:" + mtelegram);
               setState( CanScnifferId +'.canSend', mtelegram)
           }, 200);
       })
   }, 200);
})
*/
//console.log(mtelegram); 
setTimeout(function () {
   typeId = 1;
   //elsterIndexHex = "0x1720"
   //HexDaten = "0000"
   mtelegram = JSON.stringify(initElsterFrame(Senderid, canId, elsterIndexHex, pHexDaten, typeId))
   //console.log("Generiertes Telegramm:" + mtelegram);
   //setState( CanScnifferId +'.canSend', mtelegram)
}, 2 * 1000);
//