iobroker.jetframe 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +357 -0
- package/admin/SF-Pro.ttf +0 -0
- package/admin/admin.d.ts +65 -0
- package/admin/frame.html +982 -0
- package/admin/frame.html.bak-aircraft-card-real-row-20260518-1608 +1236 -0
- package/admin/frame.html.bak-aircraft-card-structure-20260518-1517 +1236 -0
- package/admin/frame.html.bak-aircraft-logo-id-fix-20260518-1639 +1239 -0
- package/admin/frame.html.bak-shortcut-test +1236 -0
- package/admin/frame.html.bak-tablet-class-20260518-1729 +1239 -0
- package/admin/heatmap.html +216 -0
- package/admin/index.html +268 -0
- package/admin/index_m.html +1749 -0
- package/admin/jetframe.css +1260 -0
- package/admin/jetframe.css.bak-airbus-landscape-fix +4630 -0
- package/admin/jetframe.css.bak-aircraft-card-clean-equal-20260518-1438 +4899 -0
- package/admin/jetframe.css.bak-aircraft-card-real-row-20260518-1608 +4814 -0
- package/admin/jetframe.css.bak-aircraft-card-row-left-20260518-1525 +4604 -0
- package/admin/jetframe.css.bak-aircraft-card-slim-equal-20260518-1446 +4647 -0
- package/admin/jetframe.css.bak-aircraft-card-structure-20260518-1517 +4646 -0
- package/admin/jetframe.css.bak-aircraft-inline-final-20260518-1527 +4654 -0
- package/admin/jetframe.css.bak-aircraft-row-compact-fix-20260518-1639 +4763 -0
- package/admin/jetframe.css.bak-before-aircrafttype-purge +4818 -0
- package/admin/jetframe.css.bak-before-cleanup +4670 -0
- package/admin/jetframe.css.bak-before-remove-tablet-only-20260518-1711 +4896 -0
- package/admin/jetframe.css.bak-before-tablet-layout-rework-20260518-1650 +4914 -0
- package/admin/jetframe.css.bak-clean-duplicate-fonts-20260518-1340 +4975 -0
- package/admin/jetframe.css.bak-clean-old-index-fix-20260518-1937 +5167 -0
- package/admin/jetframe.css.bak-hardleft-airbus +4751 -0
- package/admin/jetframe.css.bak-index-iphone-landscape-20260518-1931 +5030 -0
- package/admin/jetframe.css.bak-index-landscape-final-20260518-1941 +5167 -0
- package/admin/jetframe.css.bak-index-landscape-real-20260518-1936 +5186 -0
- package/admin/jetframe.css.bak-landscape-compact-jumbo-bold-20260518-1343 +4802 -0
- package/admin/jetframe.css.bak-logo-align-final +4551 -0
- package/admin/jetframe.css.bak-logo-final2 +4551 -0
- package/admin/jetframe.css.bak-narrowbody-font-fix +4992 -0
- package/admin/jetframe.css.bak-nuke-airbus-align +4790 -0
- package/admin/jetframe.css.bak-pill-balance-20260518-1603 +4773 -0
- package/admin/jetframe.css.bak-pill-balance-fix +4910 -0
- package/admin/jetframe.css.bak-radar-fix-fonts +4710 -0
- package/admin/jetframe.css.bak-shortcut-test +4899 -0
- package/admin/jetframe.css.bak-smaller-aircraft-card-fonts-20260518-1345 +4897 -0
- package/admin/jetframe.css.bak-tablet-fix-real-20260518-1748 +4945 -0
- package/admin/jetframe.css.bak-tablet-fullscreen-fix-20260518-1804 +4972 -0
- package/admin/jetframe.css.bak-tablet-landscape-layout-20260518-1645 +4802 -0
- package/admin/jetframe.css.bak-tablet-layout-final-20260518-1839 +4802 -0
- package/admin/jetframe.css.bak-tablet-layout-v3-20260518-1729 +4802 -0
- package/admin/jetframe.css.bak-tablet-layout-v4-20260518-1801 +4957 -0
- package/admin/jetframe.css.bak-tablet-layout-v5-20260518-1843 +4970 -0
- package/admin/jetframe.css.bak-tablet-layout-v6-20260518-1848 +4958 -0
- package/admin/jetframe.css.bak-tablet-layout-v7-20260518-1909 +4985 -0
- package/admin/jetframe.css.bak-tablet-only-landscape-v2-20260518-1707 +4802 -0
- package/admin/jetframe.css.bak-tablet-pages-final-20260519-1857 +5188 -0
- package/admin/jetframe.css.bak-tablet-pages-final-20260519-1859 +5347 -0
- package/admin/jetframe.css.bak-tablet-pages-v2-20260519-190807 +5349 -0
- package/admin/jetframe.css.bak-typography-align-final +4818 -0
- package/admin/jetframe.png +0 -0
- package/admin/manifest.webmanifest +15 -0
- package/admin/src/app.tsx +58 -0
- package/admin/src/components/settings.tsx +97 -0
- package/admin/src/i18n/de.json +11 -0
- package/admin/src/i18n/en.json +11 -0
- package/admin/src/i18n/es.json +11 -0
- package/admin/src/i18n/fr.json +11 -0
- package/admin/src/i18n/i18n.d.ts +28 -0
- package/admin/src/i18n/it.json +11 -0
- package/admin/src/i18n/nl.json +11 -0
- package/admin/src/i18n/pl.json +11 -0
- package/admin/src/i18n/pt.json +11 -0
- package/admin/src/i18n/ru.json +11 -0
- package/admin/src/i18n/uk.json +11 -0
- package/admin/src/i18n/zh-cn.json +11 -0
- package/admin/src/index.tsx +25 -0
- package/admin/stats.html +228 -0
- package/admin/style.css +32 -0
- package/admin/tsconfig.json +11 -0
- package/admin/words.js +46 -0
- package/build/lib/adsb.js +218 -0
- package/build/lib/adsb.js.map +7 -0
- package/build/lib/airportNamesDe.js +131 -0
- package/build/lib/airportNamesDe.js.map +7 -0
- package/build/lib/airports.js +281 -0
- package/build/lib/airports.js.map +7 -0
- package/build/lib/classify.js +339 -0
- package/build/lib/classify.js.map +7 -0
- package/build/lib/config.js +103 -0
- package/build/lib/config.js.map +7 -0
- package/build/lib/flightInfo.js +1409 -0
- package/build/lib/flightInfo.js.map +7 -0
- package/build/lib/geo.js +84 -0
- package/build/lib/geo.js.map +7 -0
- package/build/lib/images.js +422 -0
- package/build/lib/images.js.map +7 -0
- package/build/lib/specialLiveries.js +342 -0
- package/build/lib/specialLiveries.js.map +7 -0
- package/build/lib/states.js +971 -0
- package/build/lib/states.js.map +7 -0
- package/build/lib/staticFiles.js +73 -0
- package/build/lib/staticFiles.js.map +7 -0
- package/build/lib/types.js +17 -0
- package/build/lib/types.js.map +7 -0
- package/build/lib/visConfig.js +52 -0
- package/build/lib/visConfig.js.map +7 -0
- package/build/main.js +1454 -0
- package/build/main.js.map +7 -0
- package/io-package.json +169 -0
- package/package.json +82 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/main.ts"],
|
|
4
|
+
"sourcesContent": ["import * as utils from '@iobroker/adapter-core';\nimport * as https from 'https';\nimport * as http from 'http';\n\nimport type { Aircraft } from './lib/types';\nimport { copyStaticFiles } from './lib/staticFiles';\nimport { updateAirportJson } from './lib/airports';\nimport { updateSpecialLiveries } from './lib/specialLiveries';\nimport { readConfig } from './lib/config';\nimport { fetchAdsb, parseAircraft } from './lib/adsb';\nimport { getMatches } from './lib/classify';\nimport { ensureStates, writeFlight, clearFlight } from './lib/states';\n\nimport { clearImageCache, ensureImageDirs, saveImages } from './lib/images';\nimport { writeVisConfig } from './lib/visConfig';\n\nimport { enrichFlightInfo } from './lib/flightInfo';\n\nclass Jetframe extends utils.Adapter {\n\tprivate timer: NodeJS.Timeout | null = null;\n\tprivate statisticsTimer: NodeJS.Timeout | null = null;\n\tprivate liveTarget: Partial<Aircraft> | null = null;\n\tprivate liveInfo: Partial<Aircraft> | null = null;\n\tprivate liveStarted = 0;\n\tprivate lastStartKey = '';\n\tprivate lastStartTs = 0;\n\tprivate lastImageSaveKey = '';\n\tprivate lastIdleRunwayText = '';\n\n\tpublic constructor(options: Partial<utils.AdapterOptions> = {}) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\tname: 'jetframe',\n\t\t});\n\n\t\tthis.on('ready', this.onReady.bind(this));\n\t\tthis.on('unload', this.onUnload.bind(this));\n\t\tthis.on('stateChange', this.onStateChange.bind(this));\n\t}\n\n\tprivate async onReady(): Promise<void> {\n\t\tthis.log.info('JetFrame Adapter gestartet');\n\t\tawait copyStaticFiles(this);\n\n\t\ttry {\n\t\t\tconst config = readConfig(this);\n\n\t\t\tawait ensureStates(this, config);\n\t\t\tawait this.ensureStatisticsStates(config.dpRoot);\n\t\t\tawait this.resetTodayStatisticsIfNeeded(`${config.dpRoot}.statistics`);\n\t\t\tthis.scheduleStatisticsRotation(config.dpRoot);\n\t\t\tawait this.ensureProbableRunwayStates(config.dpRoot);\n\t\t\tawait this.ensureIdleRunwayState(config.dpRoot);\n\t\t\tthis.subscribeStates('clearImageCache');\n\t\t\tthis.log.debug('[JetFrame] States OK');\n\n\t\t\tawait ensureImageDirs(this, this.logDebug.bind(this), this.logWarn.bind(this));\n\n\t\t\tawait writeVisConfig(this, this.config, this.logDebug.bind(this), this.logWarn.bind(this));\n\t\t\tthis.log.debug('[JetFrame] Images OK');\n\n\t\t\tupdateAirportJson(this, this.logDebug.bind(this), this.logWarn.bind(this)).catch(e => {\n\t\t\t\tthis.logWarn(`Airport DB Update Fehler: ${this.errorText(e)}`);\n\t\t\t});\n\t\t\tupdateSpecialLiveries(this, this.logDebug.bind(this), this.logWarn.bind(this)).catch(e => {\n\t\t\t\tthis.logWarn(`Special-Liveries DB Update Fehler: ${this.errorText(e)}`);\n\t\t\t});\n\n\t\t\tthis.log.debug('[JetFrame] Starte Loop');\n\n\t\t\tthis.loop().catch(e => {\n\t\t\t\tthis.logError(`Loop Start Fehler: ${this.errorText(e)}`);\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthis.logError(`onReady Fehler: ${this.errorText(e)}`);\n\t\t}\n\t}\n\n\tprivate async onStateChange(id: string, state: ioBroker.State | null | undefined): Promise<void> {\n\t\tif (!state || state.ack || state.val !== true) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst config = readConfig(this);\n\n\t\tif (id !== `${config.dpRoot}.clearImageCache`) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait clearImageCache(this, this.logDebug.bind(this), this.logWarn.bind(this));\n\t\t\tawait this.setForeignStateAsync(`${config.dpRoot}.clearImageCache`, false, true);\n\t\t\tthis.log.info('JetFrame Bild-/Logo-Cache wurde geleert');\n\t\t} catch (e) {\n\t\t\tthis.logWarn(`Cache leeren fehlgeschlagen: ${this.errorText(e)}`);\n\t\t\tawait this.setForeignStateAsync(`${config.dpRoot}.clearImageCache`, false, true);\n\t\t}\n\t}\n\n\tprivate async ensureIdleRunwayState(dpRoot: string): Promise<void> {\n\t\ttry {\n\t\t\tawait (this as any).setForeignObjectNotExistsAsync(`${dpRoot}.idleRunwayText`, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: {\n\t\t\t\t\tname: 'Idle active runway text',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\trole: 'text',\n\t\t\t\t\tread: true,\n\t\t\t\t\twrite: false,\n\t\t\t\t},\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthis.logWarn(`idleRunwayText State konnte nicht erstellt werden: ${this.errorText(e)}`);\n\t\t}\n\t}\n\n\tprivate async updateIdleRunway(a: Aircraft, config: any): Promise<void> {\n\t\tconst track = Number((a as any).trackDeg || (a as any).track || 0);\n\n\t\tif (!Number.isFinite(track) || !track) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet runways: any[] = [];\n\n\t\ttry {\n\t\t\tconst st = await this.getForeignStateAsync(`${config.dpRoot}.airportjson`);\n\t\t\tconst airports = JSON.parse(String(st?.val || '[]'));\n\n\t\t\tconst airportIata = String(config.airport?.iata || '')\n\t\t\t\t.trim()\n\t\t\t\t.toUpperCase();\n\n\t\t\tconst airport = Array.isArray(airports)\n\t\t\t\t? airports.find(\n\t\t\t\t\t\t(x: any) =>\n\t\t\t\t\t\t\tString(x.iata || x.IATA || '')\n\t\t\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t\t\t.toUpperCase() === airportIata,\n\t\t\t\t\t)\n\t\t\t\t: null;\n\n\t\t\trunways = Array.isArray(airport?.runways) ? airport.runways : [];\n\t\t} catch {\n\t\t\trunways = [];\n\t\t}\n\n\t\tlet bestName = '';\n\t\tlet bestGroup = '';\n\t\tlet bestDiff = 999;\n\n\t\tfor (const rw of runways) {\n\t\t\tconst sides = [\n\t\t\t\t{ name: rw.leIdent, heading: rw.leHeadingDeg },\n\t\t\t\t{ name: rw.heIdent, heading: rw.heHeadingDeg },\n\t\t\t];\n\n\t\t\tfor (const side of sides) {\n\t\t\t\tconst name = String(side.name || '')\n\t\t\t\t\t.trim()\n\t\t\t\t\t.toUpperCase();\n\t\t\t\tconst heading = Number(side.heading);\n\n\t\t\t\tif (!name || !Number.isFinite(heading)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tlet diff = Math.abs(track - heading);\n\n\t\t\t\tif (diff > 180) {\n\t\t\t\t\tdiff = 360 - diff;\n\t\t\t\t}\n\n\t\t\t\tif (diff < bestDiff) {\n\t\t\t\t\tbestDiff = diff;\n\t\t\t\t\tbestName = name;\n\t\t\t\t\tbestGroup = name.replace(/[LCR]$/i, '');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet runway = '';\n\n\t\tif (bestName && bestDiff <= 35) {\n\t\t\trunway = `RWY ${bestGroup || bestName} aktiv`;\n\t\t} else {\n\t\t\trunway = `Aktive Richtung ${Math.round(track)}\u00B0`;\n\t\t}\n\n\t\tconst mode = a.mode === 'LANDING' ? 'Landungen' : a.mode === 'TAKEOFF' ? 'Starts' : 'Traffic';\n\n\t\tconst text = `${runway} \u00B7 ${mode}`;\n\n\t\tif (text === this.lastIdleRunwayText) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.lastIdleRunwayText = text;\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.idleRunwayText`, text, true);\n\t}\n\n\tprivate async ensureProbableRunwayStates(dpRoot: string): Promise<void> {\n\t\tconst bases = [`${dpRoot}.current`, `${dpRoot}.airport`, `${dpRoot}.overflight`];\n\n\t\tfor (const base of bases) {\n\t\t\tawait this.ensureSimpleState(`${base}.probableRunway`, 'Probable runway', 'string', 'text');\n\t\t\tawait this.ensureSimpleState(`${base}.probableRunwayText`, 'Probable runway text', 'string', 'text');\n\t\t\tawait this.ensureSimpleState(`${base}.probableRunwayHeading`, 'Probable runway heading', 'number', 'value');\n\t\t\tawait this.ensureSimpleState(\n\t\t\t\t`${base}.probableRunwayDiffDeg`,\n\t\t\t\t'Probable runway difference degrees',\n\t\t\t\t'number',\n\t\t\t\t'value',\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async ensureSimpleState(id: string, name: string, type: ioBroker.CommonType, role: string): Promise<void> {\n\t\ttry {\n\t\t\tawait (this as any).setForeignObjectNotExistsAsync(id, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: {\n\t\t\t\t\tname,\n\t\t\t\t\ttype,\n\t\t\t\t\trole,\n\t\t\t\t\tread: true,\n\t\t\t\t\twrite: false,\n\t\t\t\t},\n\t\t\t\tnative: {},\n\t\t\t});\n\n\t\t\tconst st = await this.getForeignStateAsync(id);\n\n\t\t\tif (!st) {\n\t\t\t\tawait this.setForeignStateAsync(id, type === 'number' ? 0 : type === 'boolean' ? false : '', true);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tthis.logWarn(`State konnte nicht erstellt/initialisiert werden: ${id} | ${this.errorText(e)}`);\n\t\t}\n\t}\n\n\tprivate async applyProbableRunway(a: Aircraft, config: any): Promise<void> {\n\t\tconst track = Number((a as any).trackDeg || (a as any).track || 0);\n\n\t\tif (!Number.isFinite(track) || !track) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet runways: any[] = [];\n\n\t\ttry {\n\t\t\tconst st = await this.getForeignStateAsync(`${config.dpRoot}.airportjson`);\n\t\t\tconst airports = JSON.parse(String(st?.val || '[]'));\n\n\t\t\tconst airportIata = String(config.airport?.iata || '')\n\t\t\t\t.trim()\n\t\t\t\t.toUpperCase();\n\n\t\t\tconst airport = Array.isArray(airports)\n\t\t\t\t? airports.find(\n\t\t\t\t\t\t(x: any) =>\n\t\t\t\t\t\t\tString(x.iata || x.IATA || '')\n\t\t\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t\t\t.toUpperCase() === airportIata,\n\t\t\t\t\t)\n\t\t\t\t: null;\n\n\t\t\trunways = Array.isArray(airport?.runways) ? airport.runways : [];\n\t\t} catch {\n\t\t\trunways = [];\n\t\t}\n\n\t\tlet bestName = '';\n\t\tlet bestGroup = '';\n\t\tlet bestHeading = 0;\n\t\tlet bestDiff = 999;\n\n\t\tfor (const rw of runways) {\n\t\t\tconst sides = [\n\t\t\t\t{ name: rw.leIdent, heading: rw.leHeadingDeg },\n\t\t\t\t{ name: rw.heIdent, heading: rw.heHeadingDeg },\n\t\t\t];\n\n\t\t\tfor (const side of sides) {\n\t\t\t\tconst name = String(side.name || '')\n\t\t\t\t\t.trim()\n\t\t\t\t\t.toUpperCase();\n\t\t\t\tconst heading = Number(side.heading);\n\n\t\t\t\tif (!name || !Number.isFinite(heading)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tlet diff = Math.abs(track - heading);\n\n\t\t\t\tif (diff > 180) {\n\t\t\t\t\tdiff = 360 - diff;\n\t\t\t\t}\n\n\t\t\t\tif (diff < bestDiff) {\n\t\t\t\t\tbestDiff = diff;\n\t\t\t\t\tbestName = name;\n\t\t\t\t\tbestGroup = name.replace(/[LCR]$/i, '');\n\t\t\t\t\tbestHeading = heading;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!bestName || bestDiff > 35) {\n\t\t\t(a as any).probableRunway = '';\n\t\t\t(a as any).probableRunwayText = '';\n\t\t\t(a as any).probableRunwayHeading = 0;\n\t\t\t(a as any).probableRunwayDiffDeg = 0;\n\t\t\t(a as any).runwayConfidence = 0;\n\t\t\treturn;\n\t\t}\n\n\t\tconst modeIcon = a.mode === 'LANDING' ? '\uD83D\uDEEC' : a.mode === 'TAKEOFF' ? '\uD83D\uDEEB' : '\uD83D\uDCE1';\n\t\tconst modeText = a.mode === 'LANDING' ? 'Landung' : a.mode === 'TAKEOFF' ? 'Start' : 'Traffic';\n\n\t\tconst confidence = Math.max(0, Math.min(100, Math.round(100 - (bestDiff / 35) * 100)));\n\n\t\t(a as any).probableRunway = bestGroup || bestName;\n\t\t(a as any).probableRunwayHeading = Math.round(bestHeading);\n\t\t(a as any).probableRunwayDiffDeg = Math.round(bestDiff);\n\t\t(a as any).runwayConfidence = confidence;\n\t\t(a as any).probableRunwayText = `${modeIcon} vermutlich RWY ${bestGroup || bestName} \u00B7 ${modeText}`;\n\t}\n\n\tprivate async ensureStatisticsStates(dpRoot: string): Promise<void> {\n\t\tconst base = `${dpRoot}.statistics`;\n\n\t\tawait this.ensureSimpleState(`${base}.totalFlightsSeen`, 'Total flights seen', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.landings`, 'Landings', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.departures`, 'Departures', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.overflights`, 'Overflights', 'number', 'value');\n\n\t\tawait this.ensureSimpleState(`${base}.lastFlight`, 'Last flight', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.lastAirline`, 'Last airline', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.lastRoute`, 'Last route', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.lastRegistration`, 'Last registration', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.lastSeen`, 'Last seen', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.airlineRanking`, 'Airline ranking JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(`${base}.airlineRankingText`, 'Airline ranking text', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.aircraftTypeRanking`, 'Aircraft type ranking JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(`${base}.aircraftTypeRankingText`, 'Aircraft type ranking text', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.registrationRanking`, 'Registration ranking JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(`${base}.registrationRankingText`, 'Registration ranking text', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.runwayUsageRanking`, 'Runway usage ranking JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(`${base}.runwayUsageRankingText`, 'Runway usage ranking text', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.airlineRunwayRanking`, 'Airline runway ranking JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.airlineRunwayRankingText`,\n\t\t\t'Airline runway ranking text',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\n\t\tawait this.ensureSimpleState(`${base}.flightLogHistory`, 'Flight log history JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(`${base}.flightLogHistoryText`, 'Flight log history text', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.today.date`, 'Today date', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.today.totalFlights`, 'Today total flights', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.today.landings`, 'Today landings', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.today.departures`, 'Today departures', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.today.overflights`, 'Today overflights', 'number', 'value');\n\n\t\tawait this.ensureSimpleState(`${base}.today.firstSeen`, 'Today first seen', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.today.lastSeen`, 'Today last seen', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.today.lastFlight`, 'Today last flight', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.today.lastAirline`, 'Today last airline', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.today.lastRoute`, 'Today last route', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.today.lastRegistration`, 'Today last registration', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.today.topAirline`, 'Today top airline', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.today.topRoute`, 'Today top route', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.today.airlineRanking`, 'Today airline ranking JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.today.airlineRankingText`,\n\t\t\t'Today airline ranking text',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\t\tawait this.ensureSimpleState(`${base}.today.routeRanking`, 'Today route ranking JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(`${base}.today.routeRankingText`, 'Today route ranking text', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.today.hourly`, 'Today hourly flights JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(`${base}.today.hourlyText`, 'Today hourly flights text', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.today.bestSpotterHour`, 'Today best spotter hour', 'string', 'text');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.today.currentHourFlights`,\n\t\t\t'Today current hour flights',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\t\tawait this.ensureSimpleState(`${base}.today.rushHourNow`, 'Rush hour now', 'boolean', 'indicator');\n\t\tawait this.ensureSimpleState(`${base}.today.rushHourText`, 'Rush hour text', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.today.a380Count`, 'Today A380 count', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.today.b747Count`, 'Today B747 count', 'number', 'value');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.today.heavyAircraftCount`,\n\t\t\t'Today heavy aircraft count',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.today.specialLiveryCount`,\n\t\t\t'Today special livery count',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\n\t\tawait this.ensureSimpleState(`${base}.yesterday.date`, 'Yesterday date', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.yesterday.totalFlights`, 'Yesterday total flights', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.yesterday.landings`, 'Yesterday landings', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.yesterday.departures`, 'Yesterday departures', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.yesterday.overflights`, 'Yesterday overflights', 'number', 'value');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.yesterday.bestSpotterHour`,\n\t\t\t'Yesterday best spotter hour',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.yesterday.bestHourFlights`,\n\t\t\t'Yesterday best hour flights',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\t\tawait this.ensureSimpleState(`${base}.yesterday.topAirline`, 'Yesterday top airline', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.yesterday.topRoute`, 'Yesterday top route', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.yesterday.a380Count`, 'Yesterday A380 count', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.yesterday.b747Count`, 'Yesterday B747 count', 'number', 'value');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.yesterday.heavyAircraftCount`,\n\t\t\t'Yesterday heavy aircraft count',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.yesterday.specialLiveryCount`,\n\t\t\t'Yesterday special livery count',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\t\tawait this.ensureSimpleState(`${base}.yesterday.hourly`, 'Yesterday hourly JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.yesterday.airlineRankingText`,\n\t\t\t'Yesterday airline ranking text',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.yesterday.routeRankingText`,\n\t\t\t'Yesterday route ranking text',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\n\t\tawait this.ensureSimpleState(`${base}.history.daily`, 'Daily statistics history JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(`${base}.history.dailyText`, 'Daily statistics history text', 'string', 'text');\n\n\t\tawait this.ensureSimpleState(`${base}.alltime.bestDayDate`, 'Alltime best day date', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.alltime.bestDayFlights`, 'Alltime best day flights', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.alltime.bestHour`, 'Alltime best hour', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.alltime.bestHourFlights`, 'Alltime best hour flights', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.alltime.bestAirline`, 'Alltime best airline', 'string', 'text');\n\t\tawait this.ensureSimpleState(`${base}.alltime.bestRoute`, 'Alltime best route', 'string', 'text');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.alltime.bestAircraftType`,\n\t\t\t'Alltime best aircraft type',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\t\tawait this.ensureSimpleState(`${base}.alltime.a380Count`, 'Alltime A380 count', 'number', 'value');\n\t\tawait this.ensureSimpleState(`${base}.alltime.b747Count`, 'Alltime B747 count', 'number', 'value');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.alltime.heavyAircraftCount`,\n\t\t\t'Alltime heavy aircraft count',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.alltime.specialLiveryCount`,\n\t\t\t'Alltime special livery count',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.alltime.bestSpecialDayDate`,\n\t\t\t'Alltime best special day date',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.alltime.bestSpecialDayCount`,\n\t\t\t'Alltime best special day count',\n\t\t\t'number',\n\t\t\t'value',\n\t\t);\n\t\tawait this.ensureSimpleState(`${base}.alltime.hourly`, 'Alltime hourly JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.alltime.airlineRanking`,\n\t\t\t'Alltime airline ranking JSON',\n\t\t\t'string',\n\t\t\t'json',\n\t\t);\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.alltime.airlineRankingText`,\n\t\t\t'Alltime airline ranking text',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\t\tawait this.ensureSimpleState(`${base}.alltime.routeRanking`, 'Alltime route ranking JSON', 'string', 'json');\n\t\tawait this.ensureSimpleState(\n\t\t\t`${base}.alltime.routeRankingText`,\n\t\t\t'Alltime route ranking text',\n\t\t\t'string',\n\t\t\t'text',\n\t\t);\n\t}\n\n\tprivate async readNumberState(id: string): Promise<number> {\n\t\ttry {\n\t\t\tconst st = await this.getForeignStateAsync(id);\n\t\t\tconst n = Number(st?.val || 0);\n\t\t\treturn Number.isFinite(n) ? n : 0;\n\t\t} catch {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tprivate async readJsonState<T>(id: string, fallback: T): Promise<T> {\n\t\ttry {\n\t\t\tconst st = await this.getForeignStateAsync(id);\n\t\t\tconst raw = String(st?.val || '').trim();\n\n\t\t\tif (!raw) {\n\t\t\t\treturn fallback;\n\t\t\t}\n\n\t\t\treturn JSON.parse(raw) as T;\n\t\t} catch {\n\t\t\treturn fallback;\n\t\t}\n\t}\n\n\tprivate topRankingText(entries: Array<[string, number]>, limit = 5): string {\n\t\treturn entries\n\t\t\t.slice(0, limit)\n\t\t\t.map(([name, count], index) => `${index + 1}. ${name} \u00B7 ${count}`)\n\t\t\t.join('\\n');\n\t}\n\n\tprivate sortedRanking(data: Record<string, number>, limit = 30): Array<[string, number]> {\n\t\treturn Object.entries(data)\n\t\t\t.filter(([name]) => !!this.clean(name))\n\t\t\t.sort((aEntry, bEntry) => bEntry[1] - aEntry[1] || aEntry[0].localeCompare(bEntry[0]))\n\t\t\t.slice(0, limit);\n\t}\n\n\tprivate async incrementRankingState(\n\t\tid: string,\n\t\ttextId: string,\n\t\tkey: string,\n\t\tlimit = 30,\n\t\ttextLimit = 5,\n\t): Promise<Array<[string, number]>> {\n\t\tconst cleanKey = this.clean(key);\n\n\t\tif (!cleanKey) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst ranking = await this.readJsonState<Record<string, number>>(id, {});\n\t\tranking[cleanKey] = (ranking[cleanKey] || 0) + 1;\n\n\t\tconst sorted = this.sortedRanking(ranking, limit);\n\n\t\tawait this.setForeignStateAsync(id, JSON.stringify(Object.fromEntries(sorted)), true);\n\t\tawait this.setForeignStateAsync(textId, this.topRankingText(sorted, textLimit), true);\n\n\t\treturn sorted;\n\t}\n\n\tprivate async updateGlobalDetailedStatistics(\n\t\tbase: string,\n\t\ta: Aircraft,\n\t\tinfo: {\n\t\t\tmode: string;\n\t\t\tcallsign: string;\n\t\t\tairline: string;\n\t\t\tregistration: string;\n\t\t\troute: string;\n\t\t},\n\t): Promise<void> {\n\t\tconst type =\n\t\t\tthis.clean((a as any).aircraftTypeText) ||\n\t\t\tthis.clean(a.aircraftModel) ||\n\t\t\tthis.clean(a.aircraftType) ||\n\t\t\tthis.clean((a as any).type) ||\n\t\t\t'Unbekannt';\n\n\t\tawait this.incrementRankingState(`${base}.aircraftTypeRanking`, `${base}.aircraftTypeRankingText`, type, 40, 8);\n\n\t\tif (info.registration) {\n\t\t\tawait this.incrementRankingState(\n\t\t\t\t`${base}.registrationRanking`,\n\t\t\t\t`${base}.registrationRankingText`,\n\t\t\t\tinfo.registration,\n\t\t\t\t50,\n\t\t\t\t8,\n\t\t\t);\n\t\t}\n\n\t\tconst runway = this.clean((a as any).probableRunway || '');\n\t\tconst runwayConfidence = Number((a as any).runwayConfidence || 0);\n\n\t\tif (runway && runwayConfidence >= 40) {\n\t\t\tawait this.incrementRankingState(\n\t\t\t\t`${base}.runwayUsageRanking`,\n\t\t\t\t`${base}.runwayUsageRankingText`,\n\t\t\t\trunway,\n\t\t\t\t30,\n\t\t\t\t8,\n\t\t\t);\n\n\t\t\tconst airlineRunwayKey = `${info.airline} \u2192 RWY ${runway}`;\n\n\t\t\tawait this.incrementRankingState(\n\t\t\t\t`${base}.airlineRunwayRanking`,\n\t\t\t\t`${base}.airlineRunwayRankingText`,\n\t\t\t\tairlineRunwayKey,\n\t\t\t\t50,\n\t\t\t\t8,\n\t\t\t);\n\t\t}\n\n\t\tconst historyId = `${base}.flightLogHistory`;\n\t\tconst historyTextId = `${base}.flightLogHistoryText`;\n\n\t\tconst history = await this.readJsonState<any[]>(historyId, []);\n\n\t\tconst entry = {\n\t\t\tts: new Date().toISOString(),\n\t\t\tmode: info.mode,\n\t\t\tphase: this.clean((a as any).flightPhase || ''),\n\t\t\tcallsign: info.callsign,\n\t\t\tairline: info.airline,\n\t\t\troute: info.route,\n\t\t\toriginIata: this.clean(a.originIata || ''),\n\t\t\tdestIata: this.clean(a.destIata || ''),\n\t\t\tregistration: info.registration,\n\t\t\taircraftType: type,\n\t\t\trunway,\n\t\t\trunwayConfidence: Number.isFinite(runwayConfidence) ? runwayConfidence : 0,\n\t\t};\n\n\t\thistory.unshift(entry);\n\n\t\tconst limitedHistory = history.slice(0, 200);\n\n\t\tconst historyText = limitedHistory\n\t\t\t.slice(0, 10)\n\t\t\t.map(item => {\n\t\t\t\tconst d = new Date(item.ts);\n\t\t\t\tconst hh = String(d.getHours()).padStart(2, '0');\n\t\t\t\tconst mm = String(d.getMinutes()).padStart(2, '0');\n\t\t\t\tconst icon = item.mode === 'LANDING' ? '\uD83D\uDEEC' : item.mode === 'TAKEOFF' ? '\uD83D\uDEEB' : '\uD83D\uDEE9\uFE0F';\n\t\t\t\tconst rw = item.runway ? ` \u00B7 RWY ${item.runway}` : '';\n\t\t\t\tconst routeText = item.route ? ` \u00B7 ${item.route}` : '';\n\n\t\t\t\treturn `${hh}:${mm} ${icon} ${item.callsign || '?'} \u00B7 ${item.airline || '?'}${routeText}${rw}`;\n\t\t\t})\n\t\t\t.join('\\n');\n\n\t\tawait this.setForeignStateAsync(historyId, JSON.stringify(limitedHistory), true);\n\t\tawait this.setForeignStateAsync(historyTextId, historyText, true);\n\t}\n\n\tprivate isA380(a: Aircraft): boolean {\n\t\tconst all = [(a as any).aircraftTypeText, a.aircraftModel, a.aircraftType, (a as any).type]\n\t\t\t.map(v => this.clean(v).toUpperCase())\n\t\t\t.join(' ')\n\t\t\t.replace(/[\\s_-]/g, '');\n\n\t\treturn /A380|A388|A38/.test(all);\n\t}\n\n\tprivate isB747(a: Aircraft): boolean {\n\t\tconst all = [(a as any).aircraftTypeText, a.aircraftModel, a.aircraftType, (a as any).type]\n\t\t\t.map(v => this.clean(v).toUpperCase())\n\t\t\t.join(' ')\n\t\t\t.replace(/[\\s_-]/g, '');\n\n\t\treturn /B747|B741|B742|B743|B744|B748|747/.test(all);\n\t}\n\n\tprivate isHeavyAircraft(a: Aircraft): boolean {\n\t\tconst all = [\n\t\t\t(a as any).aircraftTypeText,\n\t\t\ta.aircraftModel,\n\t\t\ta.aircraftType,\n\t\t\t(a as any).type,\n\t\t\t(a as any).aircraftSize,\n\t\t]\n\t\t\t.map(v => this.clean(v).toUpperCase())\n\t\t\t.join(' ')\n\t\t\t.replace(/[\\s_-]/g, '');\n\n\t\treturn (\n\t\t\t/WIDEBODY|HEAVY|SUPERJUMBO|JUMBO|HEAVYCARGO/.test(all) ||\n\t\t\t/A300|A310|A330|A332|A333|A338|A339|A340|A342|A343|A345|A346/.test(all) ||\n\t\t\t/A350|A359|A35K|A351|A380|A388/.test(all) ||\n\t\t\t/B747|B741|B742|B743|B744|B748/.test(all) ||\n\t\t\t/B757|B752|B753/.test(all) ||\n\t\t\t/B767|B762|B763|B764/.test(all) ||\n\t\t\t/B777|B772|B773|B77W|B778|B779|B77L|B77F/.test(all) ||\n\t\t\t/B787|B788|B789|B78X/.test(all) ||\n\t\t\t/MD11|DC10|L1011|IL86|IL96/.test(all) ||\n\t\t\t/AN124|AN225|C5M|GALAXY|C17|C17A|GLOBEMASTER|A400|A400M/.test(all)\n\t\t);\n\t}\n\n\tprivate isSpecialFlight(a: Aircraft): boolean {\n\t\treturn !!(\n\t\t\t(a as any).isSpecial ||\n\t\t\tthis.clean((a as any).specialText) ||\n\t\t\tthis.clean((a as any).specialLiveryTitle) ||\n\t\t\tthis.clean((a as any).specialLiveryDescription) ||\n\t\t\tthis.clean((a as any).specialLiveryFull) ||\n\t\t\tthis.clean((a as any).specialLiveryVisText)\n\t\t);\n\t}\n\n\tprivate mergeRanking(target: Record<string, number>, source: Record<string, number>): Record<string, number> {\n\t\tfor (const [key, value] of Object.entries(source || {})) {\n\t\t\tconst cleanKey = this.clean(key);\n\n\t\t\tif (!cleanKey) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst count = Number(value || 0);\n\n\t\t\tif (!Number.isFinite(count) || count <= 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\ttarget[cleanKey] = (target[cleanKey] || 0) + count;\n\t\t}\n\n\t\treturn target;\n\t}\n\n\tprivate bestHourFromHourly(\n\t\thourly: Record<string, { total: number; landings: number; departures: number; overflights: number }>,\n\t): {\n\t\thour: string;\n\t\ttotal: number;\n\t} {\n\t\tconst best = Object.entries(hourly || {})\n\t\t\t.filter(([, value]) => Number(value?.total || 0) > 0)\n\t\t\t.sort((a, b) => Number(b[1].total || 0) - Number(a[1].total || 0) || Number(a[0]) - Number(b[0]))[0];\n\n\t\treturn best ? { hour: `${best[0]}:00`, total: Number(best[1].total || 0) } : { hour: '', total: 0 };\n\t}\n\n\tprivate async archiveTodayStatistics(base: string, storedDate: string): Promise<void> {\n\t\tconst todayBase = `${base}.today`;\n\t\tconst yesterdayBase = `${base}.yesterday`;\n\n\t\tconst totalFlights = await this.readNumberState(`${todayBase}.totalFlights`);\n\n\t\tif (!storedDate || totalFlights <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst landings = await this.readNumberState(`${todayBase}.landings`);\n\t\tconst departures = await this.readNumberState(`${todayBase}.departures`);\n\t\tconst overflights = await this.readNumberState(`${todayBase}.overflights`);\n\t\tconst a380Count = await this.readNumberState(`${todayBase}.a380Count`);\n\t\tconst b747Count = await this.readNumberState(`${todayBase}.b747Count`);\n\t\tconst heavyAircraftCount = await this.readNumberState(`${todayBase}.heavyAircraftCount`);\n\t\tconst specialLiveryCount = await this.readNumberState(`${todayBase}.specialLiveryCount`);\n\n\t\tconst hourly = await this.readJsonState<\n\t\t\tRecord<string, { total: number; landings: number; departures: number; overflights: number }>\n\t\t>(`${todayBase}.hourly`, this.emptyHourlyStats());\n\n\t\tconst airlineRanking = await this.readJsonState<Record<string, number>>(`${todayBase}.airlineRanking`, {});\n\t\tconst routeRanking = await this.readJsonState<Record<string, number>>(`${todayBase}.routeRanking`, {});\n\n\t\tconst airlineSorted = this.sortedRanking(airlineRanking, 20);\n\t\tconst routeSorted = this.sortedRanking(routeRanking, 20);\n\t\tconst bestHour = this.bestHourFromHourly(hourly);\n\n\t\tconst topAirline = airlineSorted.length ? `${airlineSorted[0][0]} \u00B7 ${airlineSorted[0][1]}` : '';\n\t\tconst topRoute = routeSorted.length ? `${routeSorted[0][0]} \u00B7 ${routeSorted[0][1]}` : '';\n\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.date`, storedDate, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.totalFlights`, totalFlights, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.landings`, landings, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.departures`, departures, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.overflights`, overflights, true);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${yesterdayBase}.bestSpotterHour`,\n\t\t\tbestHour.hour ? `${bestHour.hour} \u00B7 ${bestHour.total} Fl\u00FCge` : '',\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.bestHourFlights`, bestHour.total, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.topAirline`, topAirline, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.topRoute`, topRoute, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.a380Count`, a380Count, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.b747Count`, b747Count, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.heavyAircraftCount`, heavyAircraftCount, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.specialLiveryCount`, specialLiveryCount, true);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.hourly`, JSON.stringify(hourly), true);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${yesterdayBase}.airlineRankingText`,\n\t\t\tthis.topRankingText(airlineSorted, 5),\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(`${yesterdayBase}.routeRankingText`, this.topRankingText(routeSorted, 5), true);\n\n\t\tconst historyId = `${base}.history.daily`;\n\t\tconst history = await this.readJsonState<any[]>(historyId, []);\n\n\t\tconst entry = {\n\t\t\tdate: storedDate,\n\t\t\ttotalFlights,\n\t\t\tlandings,\n\t\t\tdepartures,\n\t\t\toverflights,\n\t\t\tbestHour: bestHour.hour,\n\t\t\tbestHourFlights: bestHour.total,\n\t\t\ttopAirline,\n\t\t\ttopRoute,\n\t\t\ta380Count,\n\t\t\tspecialLiveryCount,\n\t\t};\n\n\t\tconst limitedHistory = [entry, ...history.filter(item => this.clean(item?.date) !== storedDate)].slice(0, 365);\n\n\t\tconst historyText = limitedHistory\n\t\t\t.slice(0, 14)\n\t\t\t.map(item => {\n\t\t\t\tconst best = item.bestHour ? ` \u00B7 beste Zeit ${item.bestHour}` : '';\n\t\t\t\tconst special = Number(item.specialLiveryCount || 0) > 0 ? ` \u00B7 \u2B50 ${item.specialLiveryCount}` : '';\n\t\t\t\tconst heavy = Number(item.heavyAircraftCount || 0) > 0 ? ` \u00B7 Heavy ${item.heavyAircraftCount}` : '';\n\t\t\t\tconst a380 = Number(item.a380Count || 0) > 0 ? ` \u00B7 A380 ${item.a380Count}` : '';\n\t\t\t\tconst b747 = Number(item.b747Count || 0) > 0 ? ` \u00B7 B747 ${item.b747Count}` : '';\n\n\t\t\t\treturn `${item.date}: ${item.totalFlights} Fl\u00FCge${best}${heavy}${a380}${b747}${special}`;\n\t\t\t})\n\t\t\t.join('\\n');\n\n\t\tawait this.setForeignStateAsync(historyId, JSON.stringify(limitedHistory), true);\n\t\tawait this.setForeignStateAsync(`${base}.history.dailyText`, historyText, true);\n\n\t\tconst currentBestDayFlights = await this.readNumberState(`${base}.alltime.bestDayFlights`);\n\n\t\tif (totalFlights > currentBestDayFlights) {\n\t\t\tawait this.setForeignStateAsync(`${base}.alltime.bestDayDate`, storedDate, true);\n\t\t\tawait this.setForeignStateAsync(`${base}.alltime.bestDayFlights`, totalFlights, true);\n\t\t}\n\n\t\tconst currentBestSpecial = await this.readNumberState(`${base}.alltime.bestSpecialDayCount`);\n\n\t\tif (specialLiveryCount > currentBestSpecial) {\n\t\t\tawait this.setForeignStateAsync(`${base}.alltime.bestSpecialDayDate`, storedDate, true);\n\t\t\tawait this.setForeignStateAsync(`${base}.alltime.bestSpecialDayCount`, specialLiveryCount, true);\n\t\t}\n\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.a380Count`,\n\t\t\t(await this.readNumberState(`${base}.alltime.a380Count`)) + a380Count,\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.specialLiveryCount`,\n\t\t\t(await this.readNumberState(`${base}.alltime.specialLiveryCount`)) + specialLiveryCount,\n\t\t\ttrue,\n\t\t);\n\n\t\tconst alltimeHourly = await this.readJsonState<Record<string, number>>(`${base}.alltime.hourly`, {});\n\n\t\tfor (const [hour, value] of Object.entries(hourly || {})) {\n\t\t\talltimeHourly[hour] = (alltimeHourly[hour] || 0) + Number(value?.total || 0);\n\t\t}\n\n\t\tconst bestAlltimeHour = Object.entries(alltimeHourly)\n\t\t\t.filter(([, count]) => Number(count || 0) > 0)\n\t\t\t.sort((a, b) => Number(b[1] || 0) - Number(a[1] || 0) || Number(a[0]) - Number(b[0]))[0];\n\n\t\tawait this.setForeignStateAsync(`${base}.alltime.hourly`, JSON.stringify(alltimeHourly), true);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.bestHour`,\n\t\t\tbestAlltimeHour ? `${bestAlltimeHour[0]}:00` : '',\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.bestHourFlights`,\n\t\t\tbestAlltimeHour ? Number(bestAlltimeHour[1] || 0) : 0,\n\t\t\ttrue,\n\t\t);\n\n\t\tconst alltimeAirlines = this.mergeRanking(\n\t\t\tawait this.readJsonState<Record<string, number>>(`${base}.alltime.airlineRanking`, {}),\n\t\t\tairlineRanking,\n\t\t);\n\n\t\tconst alltimeRoutes = this.mergeRanking(\n\t\t\tawait this.readJsonState<Record<string, number>>(`${base}.alltime.routeRanking`, {}),\n\t\t\trouteRanking,\n\t\t);\n\n\t\tconst alltimeAirlineSorted = this.sortedRanking(alltimeAirlines, 50);\n\t\tconst alltimeRouteSorted = this.sortedRanking(alltimeRoutes, 50);\n\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.airlineRanking`,\n\t\t\tJSON.stringify(Object.fromEntries(alltimeAirlineSorted)),\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.airlineRankingText`,\n\t\t\tthis.topRankingText(alltimeAirlineSorted, 8),\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.routeRanking`,\n\t\t\tJSON.stringify(Object.fromEntries(alltimeRouteSorted)),\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.routeRankingText`,\n\t\t\tthis.topRankingText(alltimeRouteSorted, 8),\n\t\t\ttrue,\n\t\t);\n\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.bestAirline`,\n\t\t\talltimeAirlineSorted.length ? `${alltimeAirlineSorted[0][0]} \u00B7 ${alltimeAirlineSorted[0][1]}` : '',\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.bestRoute`,\n\t\t\talltimeRouteSorted.length ? `${alltimeRouteSorted[0][0]} \u00B7 ${alltimeRouteSorted[0][1]}` : '',\n\t\t\ttrue,\n\t\t);\n\n\t\tconst aircraftTypeRanking = await this.readJsonState<Record<string, number>>(`${base}.aircraftTypeRanking`, {});\n\t\tconst aircraftTypeSorted = this.sortedRanking(aircraftTypeRanking, 50);\n\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.alltime.bestAircraftType`,\n\t\t\taircraftTypeSorted.length ? `${aircraftTypeSorted[0][0]} \u00B7 ${aircraftTypeSorted[0][1]}` : '',\n\t\t\ttrue,\n\t\t);\n\n\t\tthis.log.info(`[JetFrame] Tagesstatistik archiviert: ${storedDate} \u00B7 ${totalFlights} Fl\u00FCge`);\n\t}\n\n\tprivate todayDateKey(): string {\n\t\tconst d = new Date();\n\t\tconst yyyy = d.getFullYear();\n\t\tconst mm = String(d.getMonth() + 1).padStart(2, '0');\n\t\tconst dd = String(d.getDate()).padStart(2, '0');\n\n\t\treturn `${yyyy}-${mm}-${dd}`;\n\t}\n\n\tprivate async resetTodayStatisticsIfNeeded(base: string): Promise<void> {\n\t\tconst todayBase = `${base}.today`;\n\t\tconst today = this.todayDateKey();\n\n\t\tlet storedDate = '';\n\n\t\ttry {\n\t\t\tconst st = await this.getForeignStateAsync(`${todayBase}.date`);\n\t\t\tstoredDate = this.clean(st?.val);\n\t\t} catch {\n\t\t\tstoredDate = '';\n\t\t}\n\n\t\tif (storedDate === today) {\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.archiveTodayStatistics(base, storedDate);\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.date`, today, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.totalFlights`, 0, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.landings`, 0, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.departures`, 0, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.overflights`, 0, true);\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.firstSeen`, '', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastSeen`, '', true);\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastFlight`, '', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastAirline`, '', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastRoute`, '', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastRegistration`, '', true);\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.topAirline`, '', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.topRoute`, '', true);\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.airlineRanking`, '{}', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.airlineRankingText`, '', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.routeRanking`, '{}', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.routeRankingText`, '', true);\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.hourly`, JSON.stringify(this.emptyHourlyStats()), true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.hourlyText`, '', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.bestSpotterHour`, '', true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.currentHourFlights`, 0, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.rushHourNow`, false, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.rushHourText`, '', true);\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.a380Count`, 0, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.b747Count`, 0, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.heavyAircraftCount`, 0, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.specialLiveryCount`, 0, true);\n\t}\n\n\tprivate emptyHourlyStats(): Record<\n\t\tstring,\n\t\t{ total: number; landings: number; departures: number; overflights: number }\n\t> {\n\t\tconst result: Record<string, { total: number; landings: number; departures: number; overflights: number }> = {};\n\n\t\tfor (let h = 0; h < 24; h++) {\n\t\t\tconst key = String(h).padStart(2, '0');\n\t\t\tresult[key] = {\n\t\t\t\ttotal: 0,\n\t\t\t\tlandings: 0,\n\t\t\t\tdepartures: 0,\n\t\t\t\toverflights: 0,\n\t\t\t};\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate async updateTodayHourlyStatistics(todayBase: string, mode: string): Promise<void> {\n\t\tconst now = new Date();\n\t\tconst hour = String(now.getHours()).padStart(2, '0');\n\n\t\tconst hourly = await this.readJsonState<\n\t\t\tRecord<string, { total: number; landings: number; departures: number; overflights: number }>\n\t\t>(`${todayBase}.hourly`, this.emptyHourlyStats());\n\n\t\tif (!hourly[hour]) {\n\t\t\thourly[hour] = {\n\t\t\t\ttotal: 0,\n\t\t\t\tlandings: 0,\n\t\t\t\tdepartures: 0,\n\t\t\t\toverflights: 0,\n\t\t\t};\n\t\t}\n\n\t\thourly[hour].total += 1;\n\n\t\tif (mode === 'LANDING') {\n\t\t\thourly[hour].landings += 1;\n\t\t} else if (mode === 'TAKEOFF') {\n\t\t\thourly[hour].departures += 1;\n\t\t} else if (mode === 'OVERFLIGHT') {\n\t\t\thourly[hour].overflights += 1;\n\t\t}\n\n\t\tconst entries = Object.entries(hourly).sort((a, b) => Number(a[0]) - Number(b[0]));\n\n\t\tconst activeEntries = entries.filter(([, v]) => v.total > 0);\n\n\t\tconst hourlyText = activeEntries\n\t\t\t.map(([h, v]) => `${h}:00 \u00B7 ${v.total} (${v.landings}\uD83D\uDEEC ${v.departures}\uD83D\uDEEB ${v.overflights}\uD83D\uDEE9\uFE0F)`)\n\t\t\t.join('\\n');\n\n\t\tconst best = activeEntries.slice().sort((a, b) => b[1].total - a[1].total || Number(a[0]) - Number(b[0]))[0];\n\n\t\tconst currentHourTotal = hourly[hour]?.total || 0;\n\t\tconst avgActive =\n\t\t\tactiveEntries.length > 0\n\t\t\t\t? activeEntries.reduce((sum, [, v]) => sum + v.total, 0) / activeEntries.length\n\t\t\t\t: 0;\n\n\t\tconst rushHourNow = currentHourTotal >= 5 && currentHourTotal >= Math.max(3, Math.ceil(avgActive * 1.35));\n\n\t\tconst rushHourText = rushHourNow\n\t\t\t? `\uD83D\uDD25 Rushhour: ${currentHourTotal} Fl\u00FCge seit ${hour}:00`\n\t\t\t: currentHourTotal > 0\n\t\t\t\t? `Aktuelle Stunde: ${currentHourTotal} Fl\u00FCge`\n\t\t\t\t: '';\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.hourly`, JSON.stringify(hourly), true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.hourlyText`, hourlyText, true);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${todayBase}.bestSpotterHour`,\n\t\t\tbest ? `${best[0]}:00 \u00B7 ${best[1].total} Fl\u00FCge` : '',\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(`${todayBase}.currentHourFlights`, currentHourTotal, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.rushHourNow`, rushHourNow, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.rushHourText`, rushHourText, true);\n\t}\n\n\tprivate async updateTodayStatistics(\n\t\tbase: string,\n\t\ta: Aircraft,\n\t\tinfo: {\n\t\t\tmode: string;\n\t\t\tcallsign: string;\n\t\t\tairline: string;\n\t\t\tregistration: string;\n\t\t\troute: string;\n\t\t},\n\t): Promise<void> {\n\t\tawait this.resetTodayStatisticsIfNeeded(base);\n\n\t\tconst todayBase = `${base}.today`;\n\t\tconst nowIso = new Date().toISOString();\n\n\t\tconst total = (await this.readNumberState(`${todayBase}.totalFlights`)) + 1;\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.totalFlights`, total, true);\n\n\t\tif (info.mode === 'LANDING') {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.landings`,\n\t\t\t\t(await this.readNumberState(`${todayBase}.landings`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t} else if (info.mode === 'TAKEOFF') {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.departures`,\n\t\t\t\t(await this.readNumberState(`${todayBase}.departures`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t} else if (info.mode === 'OVERFLIGHT') {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.overflights`,\n\t\t\t\t(await this.readNumberState(`${todayBase}.overflights`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst firstSeen = this.clean((await this.getForeignStateAsync(`${todayBase}.firstSeen`))?.val);\n\n\t\t\tif (!firstSeen) {\n\t\t\t\tawait this.setForeignStateAsync(`${todayBase}.firstSeen`, nowIso, true);\n\t\t\t}\n\t\t} catch {\n\t\t\tawait this.setForeignStateAsync(`${todayBase}.firstSeen`, nowIso, true);\n\t\t}\n\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastSeen`, nowIso, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastFlight`, info.callsign, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastAirline`, info.airline, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastRoute`, info.route, true);\n\t\tawait this.setForeignStateAsync(`${todayBase}.lastRegistration`, info.registration, true);\n\n\t\tconst airlineRanking = await this.readJsonState<Record<string, number>>(`${todayBase}.airlineRanking`, {});\n\t\tairlineRanking[info.airline] = (airlineRanking[info.airline] || 0) + 1;\n\n\t\tconst airlineSorted = Object.entries(airlineRanking)\n\t\t\t.sort((aEntry, bEntry) => bEntry[1] - aEntry[1] || aEntry[0].localeCompare(bEntry[0]))\n\t\t\t.slice(0, 20);\n\n\t\tconst airlineText = airlineSorted\n\t\t\t.slice(0, 5)\n\t\t\t.map(([name, count], index) => `${index + 1}. ${name} \u00B7 ${count}`)\n\t\t\t.join('\\n');\n\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${todayBase}.airlineRanking`,\n\t\t\tJSON.stringify(Object.fromEntries(airlineSorted)),\n\t\t\ttrue,\n\t\t);\n\t\tawait this.setForeignStateAsync(`${todayBase}.airlineRankingText`, airlineText, true);\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${todayBase}.topAirline`,\n\t\t\tairlineSorted.length ? `${airlineSorted[0][0]} \u00B7 ${airlineSorted[0][1]}` : '',\n\t\t\ttrue,\n\t\t);\n\n\t\tif (info.route) {\n\t\t\tconst routeRanking = await this.readJsonState<Record<string, number>>(`${todayBase}.routeRanking`, {});\n\t\t\trouteRanking[info.route] = (routeRanking[info.route] || 0) + 1;\n\n\t\t\tconst routeSorted = Object.entries(routeRanking)\n\t\t\t\t.filter(([routeName]) => {\n\t\t\t\t\tconst r = this.clean(routeName);\n\t\t\t\t\treturn r && !r.includes('?') && r.includes('\u2192');\n\t\t\t\t})\n\t\t\t\t.sort((aEntry, bEntry) => bEntry[1] - aEntry[1] || aEntry[0].localeCompare(bEntry[0]))\n\t\t\t\t.slice(0, 20);\n\n\t\t\tconst routeText = routeSorted\n\t\t\t\t.slice(0, 5)\n\t\t\t\t.map(([name, count], index) => `${index + 1}. ${name} \u00B7 ${count}`)\n\t\t\t\t.join('\\n');\n\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.routeRanking`,\n\t\t\t\tJSON.stringify(Object.fromEntries(routeSorted)),\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\tawait this.setForeignStateAsync(`${todayBase}.routeRankingText`, routeText, true);\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.topRoute`,\n\t\t\t\trouteSorted.length ? `${routeSorted[0][0]} \u00B7 ${routeSorted[0][1]}` : '',\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\tif (this.isA380(a)) {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.a380Count`,\n\t\t\t\t(await this.readNumberState(`${todayBase}.a380Count`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\tif (this.isB747(a)) {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.b747Count`,\n\t\t\t\t(await this.readNumberState(`${todayBase}.b747Count`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\tif (this.isHeavyAircraft(a)) {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.heavyAircraftCount`,\n\t\t\t\t(await this.readNumberState(`${todayBase}.heavyAircraftCount`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\tif (this.isSpecialFlight(a)) {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${todayBase}.specialLiveryCount`,\n\t\t\t\t(await this.readNumberState(`${todayBase}.specialLiveryCount`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\tawait this.updateTodayHourlyStatistics(todayBase, info.mode);\n\t}\n\n\tprivate async updateStatistics(dpRoot: string, a: Aircraft): Promise<void> {\n\t\tconst base = `${dpRoot}.statistics`;\n\t\tconst mode = String(a.mode || '').toUpperCase();\n\n\t\tconst callsign = this.clean(a.routeCallsign || a.callsign || a.hex || '');\n\t\tconst airline = this.clean(a.airlineName || 'Unbekannte Airline');\n\t\tconst registration = this.clean(a.registration || '');\n\n\t\tconst origin = this.clean(a.originIata || '');\n\t\tconst dest = this.clean(a.destIata || '');\n\n\t\t// Route nur verwenden, wenn Start UND Ziel bekannt sind.\n\t\t// Unvollst\u00E4ndige Routen wie \"? \u2192 FRA\" oder \"FCO \u2192 ?\" werden ignoriert.\n\t\tconst route = origin && dest ? `${origin} \u2192 ${dest}` : '';\n\n\t\tawait this.setForeignStateAsync(\n\t\t\t`${base}.totalFlightsSeen`,\n\t\t\t(await this.readNumberState(`${base}.totalFlightsSeen`)) + 1,\n\t\t\ttrue,\n\t\t);\n\n\t\tif (mode === 'LANDING') {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${base}.landings`,\n\t\t\t\t(await this.readNumberState(`${base}.landings`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t} else if (mode === 'TAKEOFF') {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${base}.departures`,\n\t\t\t\t(await this.readNumberState(`${base}.departures`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t} else if (mode === 'OVERFLIGHT') {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${base}.overflights`,\n\t\t\t\t(await this.readNumberState(`${base}.overflights`)) + 1,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\tawait this.setForeignStateAsync(`${base}.lastFlight`, callsign, true);\n\t\tawait this.setForeignStateAsync(`${base}.lastAirline`, airline, true);\n\t\tawait this.setForeignStateAsync(`${base}.lastRoute`, route, true);\n\t\tawait this.setForeignStateAsync(`${base}.lastRegistration`, registration, true);\n\t\tawait this.setForeignStateAsync(`${base}.lastSeen`, new Date().toISOString(), true);\n\n\t\tconst ranking = await this.readJsonState<Record<string, number>>(`${base}.airlineRanking`, {});\n\n\t\tranking[airline] = (ranking[airline] || 0) + 1;\n\n\t\tconst sorted = Object.entries(ranking)\n\t\t\t.sort((aEntry, bEntry) => bEntry[1] - aEntry[1] || aEntry[0].localeCompare(bEntry[0]))\n\t\t\t.slice(0, 20);\n\n\t\tconst rankingJson = Object.fromEntries(sorted);\n\n\t\tconst rankingText = sorted\n\t\t\t.slice(0, 5)\n\t\t\t.map(([name, count], index) => `${index + 1}. ${name} \u00B7 ${count}`)\n\t\t\t.join('\\n');\n\n\t\tawait this.setForeignStateAsync(`${base}.airlineRanking`, JSON.stringify(rankingJson), true);\n\t\tawait this.setForeignStateAsync(`${base}.airlineRankingText`, rankingText, true);\n\n\t\tawait this.updateGlobalDetailedStatistics(base, a, {\n\t\t\tmode,\n\t\t\tcallsign,\n\t\t\tairline,\n\t\t\tregistration,\n\t\t\troute,\n\t\t});\n\n\t\tawait this.updateTodayStatistics(base, a, {\n\t\t\tmode,\n\t\t\tcallsign,\n\t\t\tairline,\n\t\t\tregistration,\n\t\t\troute,\n\t\t});\n\t}\n\n\tprivate async loop(): Promise<void> {\n\t\ttry {\n\t\t\tthis.clearTimer();\n\n\t\t\tconst config = readConfig(this);\n\n\t\t\tif (!config.enabled) {\n\t\t\t\tawait this.setForeignStateAsync(`${config.dpRoot}.status`, 'disabled', true);\n\n\t\t\t\tthis.scheduleNext(config.searchPollSeconds);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.liveTarget) {\n\t\t\t\tawait this.liveLoop();\n\t\t\t} else {\n\t\t\t\tawait this.searchLoop();\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tthis.logError(`JetFrame Fehler: ${this.errorText(e)}`);\n\n\t\t\tconst config = readConfig(this);\n\t\t\tthis.scheduleNext(config.searchPollSeconds);\n\t\t}\n\t}\n\n\tprivate async searchLoop(): Promise<void> {\n\t\tconst config = readConfig(this);\n\n\t\tthis.log.debug('Search Loop gestartet');\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.status`, 'searching', true);\n\n\t\tconst data = await fetchAdsb(\n\t\t\tconfig,\n\t\t\tthis.httpJsonRaw.bind(this),\n\t\t\tthis.logWarn.bind(this),\n\t\t\tthis.logDebug.bind(this),\n\t\t);\n\n\t\tthis.log.debug('[JetFrame] ADSB Fetch OK');\n\n\t\tconst aircraft = parseAircraft(data);\n\t\tthis.log.debug(`[JetFrame] ADSB parsed: ${aircraft.length}`);\n\t\tthis.log.debug(`Aircraft parsed: ${aircraft.length}`);\n\n\t\tconst matches = getMatches(config, aircraft);\n\n\t\tif (matches.length) {\n\t\t\tawait this.updateIdleRunway(matches[0], config);\n\t\t}\n\n\t\tthis.log.debug(`Matches gefunden: ${matches.length}`);\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.lastUpdate`, new Date().toISOString(), true);\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.allCount`, aircraft.length, true);\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.matchCount`, matches.length, true);\n\n\t\tif (!matches.length) {\n\t\t\tawait this.setForeignStateAsync(\n\t\t\t\t`${config.dpRoot}.current.text`,\n\t\t\t\t`Kein Start/Landung/\u00DCberflug bei ${config.airport.iata}`,\n\t\t\t\ttrue,\n\t\t\t);\n\n\t\t\tthis.scheduleNext(config.searchPollSeconds);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.log.debug(\n\t\t\t`Best Match: ${matches[0].callsign || matches[0].hex || '?'} | alt=${matches[0].altFt}ft | mode=${matches[0].mode}`,\n\t\t);\n\n\t\tawait this.startNewFlight(matches[0]);\n\t}\n\n\tprivate async liveLoop(): Promise<void> {\n\t\tconst config = readConfig(this);\n\n\t\tconst elapsed = (Date.now() - this.liveStarted) / 1000;\n\n\t\tconst data = await fetchAdsb(\n\t\t\tconfig,\n\t\t\tthis.httpJsonRaw.bind(this),\n\t\t\tthis.logWarn.bind(this),\n\t\t\tthis.logDebug.bind(this),\n\t\t);\n\n\t\tconst aircraft = parseAircraft(data);\n\n\t\tconst matches = getMatches(config, aircraft);\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.lastUpdate`, new Date().toISOString(), true);\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.allCount`, aircraft.length, true);\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.matchCount`, matches.length, true);\n\n\t\tconst live = this.findCurrentLive(matches, this.liveTarget);\n\n\t\tconst bestNow = matches[0];\n\n\t\tif (bestNow && !live && this.isDifferentAircraft(bestNow, this.liveTarget)) {\n\t\t\tthis.log.info(`Neues Flugzeug erkannt, schalte um: ${bestNow.callsign || bestNow.hex}`);\n\n\t\t\tawait this.startNewFlight(bestNow);\n\t\t\treturn;\n\t\t}\n\n\t\tif (elapsed >= config.liveMaxSeconds) {\n\t\t\tthis.liveTarget = null;\n\t\t\tthis.liveStarted = 0;\n\t\t\tthis.liveInfo = null;\n\n\t\t\tawait clearFlight(this, `${config.dpRoot}.current`);\n\n\t\t\tawait this.setForeignStateAsync(`${config.dpRoot}.status`, 'cleared', true);\n\n\t\t\tthis.scheduleNext(config.searchPollSeconds);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!live) {\n\t\t\tthis.liveTarget = null;\n\t\t\tthis.liveStarted = 0;\n\n\t\t\tthis.log.info('Live Flug verloren');\n\n\t\t\tawait clearFlight(this, `${config.dpRoot}.current`);\n\n\t\t\tawait this.setForeignStateAsync(`${config.dpRoot}.status`, 'lost', true);\n\n\t\t\tthis.scheduleNext(config.searchPollSeconds);\n\t\t\treturn;\n\t\t}\n\n\t\tconst bases = [`${config.dpRoot}.current`];\n\n\t\tif (this.liveTarget?.mode === 'OVERFLIGHT') {\n\t\t\tbases.push(`${config.dpRoot}.overflight`);\n\t\t} else {\n\t\t\tbases.push(`${config.dpRoot}.airport`);\n\t\t}\n\n\t\tconst enrichedLive: Aircraft = {\n\t\t\t...(this.liveInfo || {}),\n\t\t\t...live,\n\n\t\t\t// Diese Werte kommen nur aus saveImages()/enrichFlightInfo\n\t\t\t// und d\u00FCrfen vom Live-ADS-B-Update nicht wieder leer \u00FCberschrieben werden.\n\t\t\tlocalLogoUrl: this.liveInfo?.localLogoUrl || live.localLogoUrl || '',\n\t\t\tlocalImageUrl: this.liveInfo?.localImageUrl || live.localImageUrl || '',\n\t\t\tfinalImageUrl: this.liveInfo?.finalImageUrl || live.finalImageUrl || '',\n\t\t\tlogoUrl: this.liveInfo?.logoUrl || live.logoUrl || '',\n\t\t\trouteCallsign: this.liveInfo?.routeCallsign || live.routeCallsign || live.callsign || '',\n\t\t\taircraftModel: this.liveInfo?.aircraftModel || live.aircraftModel || live.aircraftType || live.type || '',\n\n\t\t\tisSpecial: this.liveInfo?.isSpecial || live.isSpecial || false,\n\t\t\tspecialText: this.liveInfo?.specialText || live.specialText || '',\n\t\t\tspecialLiveryTitle: this.liveInfo?.specialLiveryTitle || live.specialLiveryTitle || '',\n\t\t\tspecialLiveryDescription: this.liveInfo?.specialLiveryDescription || live.specialLiveryDescription || '',\n\t\t\tspecialLiveryFull: this.liveInfo?.specialLiveryFull || live.specialLiveryFull || '',\n\t\t\tspecialLiveryVisText: this.liveInfo?.specialLiveryVisText || live.specialLiveryVisText || '',\n\t\t};\n\n\t\tawait this.applyProbableRunway(enrichedLive, config);\n\n\t\tthis.liveInfo = {\n\t\t\t...enrichedLive,\n\t\t};\n\n\t\tfor (const base of bases) {\n\t\t\tawait writeFlight(this, base, enrichedLive);\n\t\t}\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.status`, 'live', true);\n\n\t\tthis.scheduleNext(config.livePollSeconds);\n\t}\n\n\tprivate async applySpecialLivery(a: Aircraft, dpRoot: string): Promise<void> {\n\t\tconst reg = this.clean(a.registration).toUpperCase();\n\n\t\tif (!reg) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst st = await this.getForeignStateAsync(`${dpRoot}.specialLiveries`);\n\t\t\tconst raw = String(st?.val || '').trim();\n\n\t\t\tif (!raw || raw === '[]') {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst list = JSON.parse(raw);\n\n\t\t\tif (!Array.isArray(list)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst hit = list.find(item => {\n\t\t\t\tconst itemReg = this.clean(item?.registration).toUpperCase();\n\t\t\t\treturn itemReg && itemReg === reg;\n\t\t\t});\n\n\t\t\tif (!hit) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst emoji = this.clean(hit.emoji) || '\uD83C\uDFA8';\n\t\t\tconst title = this.clean(hit.title) || this.clean(hit.type) || 'Special Livery';\n\t\t\tconst description = this.clean(hit.description);\n\t\t\tconst airline = this.clean(hit.airline);\n\n\t\t\t(a as any).isSpecial = true;\n\t\t\t(a as any).specialLiveryTitle = title;\n\t\t\t(a as any).specialLiveryDescription = description;\n\t\t\t(a as any).specialLiveryFull = description || title;\n\t\t\t(a as any).specialLiveryVisText = `${emoji} ${title}`;\n\t\t\t(a as any).specialText = `${emoji} ${title}${airline ? ` \u00B7 ${airline}` : ''}`;\n\n\t\t\tthis.log.info(`Special Livery erkannt: ${reg} \u00B7 ${title}`);\n\t\t} catch (e) {\n\t\t\tthis.logWarn(`Special-Livery Match Fehler: ${this.errorText(e)}`);\n\t\t}\n\t}\n\n\tprivate async startNewFlight(rawMatch: Aircraft): Promise<void> {\n\t\tconst config = readConfig(this);\n\n\t\tconst startKey = this.flightKey(rawMatch);\n\t\tconst now = Date.now();\n\n\t\tif (startKey && startKey === this.lastStartKey && now - this.lastStartTs < 15000) {\n\t\t\tthis.log.debug(`Gleicher Flug wurde gerade erst gestartet \u2192 ignoriere: ${startKey}`);\n\n\t\t\tthis.scheduleNext(config.livePollSeconds);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.lastStartKey = startKey;\n\t\tthis.lastStartTs = now;\n\n\t\tthis.log.debug(`Starte neuen Flug: ${rawMatch.callsign || rawMatch.hex}`);\n\n\t\tconst best = await enrichFlightInfo(\n\t\t\tthis,\n\t\t\tconfig,\n\t\t\trawMatch,\n\t\t\tthis.httpJson.bind(this),\n\t\t\tthis.httpText.bind(this),\n\t\t\tthis.logDebug.bind(this),\n\t\t\tthis.logWarn.bind(this),\n\t\t);\n\n\t\tawait this.applySpecialLivery(best, config.dpRoot);\n\t\tawait this.applyProbableRunway(best, config);\n\n\t\tthis.log.info(\n\t\t\t`Neuer Flug: callsign=${best.callsign || ''} route=${best.originIata || '?'} \u2192 ${best.destIata || '?'} | ${best.originName || '?'} \u2192 ${best.destName || '?'}${best.probableRunwayText ? ` | ${best.probableRunwayText}` : ''}`,\n\t\t);\n\n\t\tawait this.updateStatistics(config.dpRoot, best);\n\n\t\tthis.liveTarget = {\n\t\t\thex: best.hex,\n\t\t\tcallsign: best.callsign,\n\t\t\tmode: best.mode,\n\t\t};\n\n\t\t// Bilder/Logos nur EINMAL pro Flug behandeln.\n\t\tconst imageSaveKey = this.flightKey(best);\n\n\t\tif (imageSaveKey && imageSaveKey !== this.lastImageSaveKey) {\n\t\t\tawait saveImages(this, config, best, this.logDebug.bind(this), this.logWarn.bind(this));\n\t\t\tthis.lastImageSaveKey = imageSaveKey;\n\t\t}\n\n\t\tthis.liveInfo = {\n\t\t\t...best,\n\t\t};\n\n\t\tthis.liveStarted = Date.now();\n\n\t\tawait writeFlight(this, `${config.dpRoot}.current`, best);\n\n\t\tif (best.mode === 'OVERFLIGHT') {\n\t\t\tawait writeFlight(this, `${config.dpRoot}.overflight`, best);\n\t\t} else {\n\t\t\tawait writeFlight(this, `${config.dpRoot}.airport`, best);\n\t\t}\n\n\t\tawait this.setForeignStateAsync(`${config.dpRoot}.status`, 'live', true);\n\n\t\tthis.scheduleNext(config.livePollSeconds);\n\t}\n\n\tprivate findCurrentLive(matches: Aircraft[], target: Partial<Aircraft> | null): Aircraft | null {\n\t\tif (!matches.length || !target) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\tmatches.find(a => {\n\t\t\t\tconst aHex = this.clean(a.hex).toLowerCase();\n\t\t\t\tconst tHex = this.clean(target.hex).toLowerCase();\n\n\t\t\t\tconst aCall = this.clean(a.callsign).toUpperCase();\n\t\t\t\tconst tCall = this.clean(target.callsign).toUpperCase();\n\n\t\t\t\tif (aHex && tHex && aHex === tHex) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (aCall && tCall && aCall === tCall) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}) || null\n\t\t);\n\t}\n\n\tprivate isDifferentAircraft(a: Aircraft | null | undefined, target: Partial<Aircraft> | null): boolean {\n\t\tif (!a || !target) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst aHex = this.clean(a.hex).toLowerCase();\n\t\tconst tHex = this.clean(target.hex).toLowerCase();\n\n\t\tconst aCall = this.clean(a.callsign).toUpperCase();\n\t\tconst tCall = this.clean(target.callsign).toUpperCase();\n\n\t\tif (aCall && tCall && aCall === tCall) {\n\t\t\treturn false;\n\t\t}\n\t\tif (aHex && tHex && aHex === tHex) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (aCall && tCall) {\n\t\t\treturn aCall !== tCall;\n\t\t}\n\t\tif (aHex && tHex) {\n\t\t\treturn aHex !== tHex;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate flightKey(a: Aircraft): string {\n\t\tconst hex = this.clean(a.hex).toLowerCase();\n\t\tconst cs = this.clean(a.callsign).toUpperCase();\n\n\t\tif (cs) {\n\t\t\treturn `CS:${cs}`;\n\t\t}\n\t\tif (hex) {\n\t\t\treturn `HEX:${hex}`;\n\t\t}\n\n\t\treturn '';\n\t}\n\n\tprivate scheduleStatisticsRotation(dpRoot: string): void {\n\t\tif (this.statisticsTimer) {\n\t\t\tclearInterval(this.statisticsTimer);\n\t\t\tthis.statisticsTimer = null;\n\t\t}\n\n\t\tthis.statisticsTimer = setInterval(() => {\n\t\t\tthis.resetTodayStatisticsIfNeeded(`${dpRoot}.statistics`).catch(e => {\n\t\t\t\tthis.logWarn(`Tagesstatistik-Rotation fehlgeschlagen: ${this.errorText(e)}`);\n\t\t\t});\n\t\t}, 60000);\n\t}\n\n\tprivate clearStatisticsTimer(): void {\n\t\tif (this.statisticsTimer) {\n\t\t\tclearInterval(this.statisticsTimer);\n\t\t\tthis.statisticsTimer = null;\n\t\t}\n\t}\n\n\tprivate scheduleNext(seconds: number): void {\n\t\tthis.timer = setTimeout(() => this.loop(), seconds * 1000);\n\t}\n\n\tprivate clearTimer(): void {\n\t\tif (this.timer) {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = null;\n\t\t}\n\t}\n\n\tprivate async httpJson(url: string): Promise<any> {\n\t\tconst res = await this.httpRequest(url, {\n\t\t\ttimeout: 12000,\n\t\t\theaders: {\n\t\t\t\t'User-Agent':\n\t\t\t\t\t'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36',\n\t\t\t\tAccept: 'application/json,text/plain,*/*',\n\t\t\t\t'Accept-Language': 'de-DE,de;q=0.9,en;q=0.8',\n\t\t\t\t'Cache-Control': 'no-cache',\n\t\t\t\tPragma: 'no-cache',\n\t\t\t},\n\t\t});\n\n\t\tif (typeof res === 'string') {\n\t\t\treturn JSON.parse(res);\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tprivate async httpJsonRaw(url: string): Promise<any> {\n\t\tconst res = await this.httpRequest(url, {\n\t\t\ttimeout: 20000,\n\t\t\theaders: {\n\t\t\t\t'User-Agent': 'Mozilla/5.0',\n\t\t\t\tAccept: 'application/json,text/plain,*/*',\n\t\t\t},\n\t\t});\n\n\t\tif (typeof res === 'string') {\n\t\t\tconst text = res.trim();\n\n\t\t\tif (text.startsWith('<')) {\n\t\t\t\tthrow new Error('HTML statt JSON erhalten');\n\t\t\t}\n\n\t\t\treturn JSON.parse(text);\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tprivate async httpText(url: string): Promise<string> {\n\t\tconst res = await this.httpRequest(url, {\n\t\t\ttimeout: 15000,\n\t\t\theaders: {\n\t\t\t\t'User-Agent': 'Mozilla/5.0 AppleWebKit/605.1.15 Safari/604.1',\n\n\t\t\t\tAccept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\n\n\t\t\t\t'Accept-Language': 'de-DE,de;q=0.9,en;q=0.8',\n\n\t\t\t\tReferer: 'https://www.google.com/',\n\t\t\t},\n\t\t});\n\n\t\treturn String(res || '');\n\t}\n\n\tprivate httpRequest(\n\t\turl: string,\n\t\toptions: {\n\t\t\ttimeout?: number;\n\t\t\theaders?: Record<string, string>;\n\t\t} = {},\n\t): Promise<string> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst client = url.startsWith('https') ? https : http;\n\n\t\t\tconst req = client.get(\n\t\t\t\turl,\n\t\t\t\t{\n\t\t\t\t\theaders: options.headers || {},\n\t\t\t\t\ttimeout: options.timeout || 15000,\n\t\t\t\t},\n\t\t\t\tres => {\n\t\t\t\t\tlet body = '';\n\n\t\t\t\t\tres.on('data', chunk => {\n\t\t\t\t\t\tbody += chunk;\n\t\t\t\t\t});\n\n\t\t\t\t\tres.on('end', () => {\n\t\t\t\t\t\tif (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {\n\t\t\t\t\t\t\tthis.httpRequest(res.headers.location, options).then(resolve).catch(reject);\n\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (res.statusCode && res.statusCode >= 400) {\n\t\t\t\t\t\t\treject(new Error(`HTTP ${res.statusCode} bei ${url}`));\n\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresolve(body);\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treq.on('error', reject);\n\n\t\t\treq.setTimeout(options.timeout || 15000, () => {\n\t\t\t\treq.destroy(new Error(`timeout of ${options.timeout || 15000}ms exceeded`));\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async ensureMetaObject(): Promise<void> {\n\t\tconst id = `${this.namespace}.meta`;\n\n\t\ttry {\n\t\t\tconst obj = await this.getObjectAsync(id);\n\n\t\t\tif (!obj) {\n\t\t\t\tawait this.setObjectAsync(id, {\n\t\t\t\t\ttype: 'meta',\n\t\t\t\t\tcommon: {\n\t\t\t\t\t\tname: 'JetFrame Files',\n\t\t\t\t\t\ttype: 'meta.user',\n\t\t\t\t\t},\n\t\t\t\t\tnative: {},\n\t\t\t\t});\n\n\t\t\t\tthis.log.info('Meta-Objekt f\u00FCr Dateien erstellt');\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tthis.log.error(`Meta-Objekt Fehler: ${this.errorText(e)}`);\n\t\t}\n\t}\n\n\tprivate logDebug(msg: string): void {\n\t\tconst config = readConfig(this);\n\t\tthis.log.debug(`[JetFrame] ${msg}`);\n\t}\n\n\tprivate logWarn(msg: string): void {\n\t\tthis.log.warn(`[JetFrame] \u26A0\uFE0F ${msg}`);\n\t}\n\n\tprivate logError(msg: string): void {\n\t\tthis.log.error(`[JetFrame] \u274C ${msg}`);\n\t}\n\n\tprivate clean(v: unknown): string {\n\t\treturn String(v || '').trim();\n\t}\n\n\tprivate errorText(e: unknown): string {\n\t\tif (!e) {\n\t\t\treturn 'unbekannter Fehler';\n\t\t}\n\t\tif (typeof e === 'string') {\n\t\t\treturn e;\n\t\t}\n\t\tif (e instanceof Error) {\n\t\t\treturn e.message;\n\t\t}\n\n\t\ttry {\n\t\t\treturn JSON.stringify(e);\n\t\t} catch {\n\t\t\treturn String(e);\n\t\t}\n\t}\n\n\tprivate onUnload(callback: () => void): void {\n\t\ttry {\n\t\t\tthis.clearTimer();\n\t\t\tthis.clearStatisticsTimer();\n\t\t\tcallback();\n\t\t} catch {\n\t\t\tcallback();\n\t\t}\n\t}\n}\n\nif (require.main !== module) {\n\tmodule.exports = (options: Partial<utils.AdapterOptions> | undefined) => new Jetframe(options);\n} else {\n\t(() => new Jetframe())();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/io-package.json
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
{
|
|
2
|
+
"common": {
|
|
3
|
+
"webExtension": true,
|
|
4
|
+
"name": "jetframe",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"news": {
|
|
7
|
+
"1.0.0": {
|
|
8
|
+
"en": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
9
|
+
"de": "Version 1.0.0 – Komplett neues Web-UI (Glassmorphism, vollständig responsiv für iPhone, iPad und Desktop), verbessertes ADS-B Fallback-System, neue Flugstatistiken mit Heatmap, Heavy-Aircraft- und Special-Livery-Tracking, sauberere TypeScript-Codebasis.",
|
|
10
|
+
"ru": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
11
|
+
"pt": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
12
|
+
"nl": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
13
|
+
"fr": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
14
|
+
"it": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
15
|
+
"es": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
16
|
+
"pl": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
17
|
+
"uk": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase.",
|
|
18
|
+
"zh-cn": "Version 1.0.0 – Complete redesign of the web UI (glassmorphism, fully responsive for iPhone, iPad and desktop), improved ADS-B fallback system, new flight statistics with heatmap, heavy aircraft and special livery tracking, cleaner TypeScript codebase."
|
|
19
|
+
},
|
|
20
|
+
"0.5.0": {
|
|
21
|
+
"en": "Added configurable visualization settings, visual source selection, aircraft prioritization, squawk/emergency detection, improved admin map behavior and mobile layout fixes.",
|
|
22
|
+
"de": "Konfigurierbare Visualisierung, auswählbare Anzeigequelle, Flugzeug-Priorisierung, Squawk-/Notfall-Erkennung sowie Verbesserungen an Admin-Karte und mobilem Layout hinzugefügt.",
|
|
23
|
+
"ru": "Добавлены настраиваемая визуализация, выбор источника отображения, приоритизация воздушных судов, обнаружение squawk/аварийных кодов, улучшения карты администратора и мобильной раскладки.",
|
|
24
|
+
"pt": "Adicionadas configurações de visualização, seleção da fonte exibida, priorização de aeronaves, detecção de squawk/emergência e melhorias no mapa/admin mobile.",
|
|
25
|
+
"nl": "Configureerbare visualisatie, selecteerbare weergavebron, vliegtuigprioritering, squawk/nooddetectie en verbeteringen aan admin-kaart en mobiele layout toegevoegd.",
|
|
26
|
+
"fr": "Ajout de paramètres de visualisation configurables, sélection de la source affichée, priorisation des avions, détection squawk/urgence et améliorations de la carte admin/mobile.",
|
|
27
|
+
"it": "Aggiunte impostazioni di visualizzazione configurabili, selezione della sorgente visualizzata, priorità degli aeromobili, rilevamento squawk/emergenza e miglioramenti alla mappa admin/mobile.",
|
|
28
|
+
"es": "Añadida visualización configurable, selección de fuente visual, priorización de aeronaves, detección de squawk/emergencia y mejoras del mapa admin/móvil.",
|
|
29
|
+
"pl": "Dodano konfigurowalną wizualizację, wybór źródła widoku, priorytetyzację samolotów, wykrywanie squawk/awarii oraz poprawki mapy admina i widoku mobilnego.",
|
|
30
|
+
"uk": "Додано налаштовувану візуалізацію, вибір джерела відображення, пріоритизацію літаків, виявлення squawk/аварійних кодів та покращення карти адміністратора і мобільного вигляду.",
|
|
31
|
+
"zh-cn": "新增可配置的可视化设置、显示来源选择、飞机优先级、Squawk/紧急状态检测,并改进了管理界面地图和移动端布局。"
|
|
32
|
+
},
|
|
33
|
+
"0.1.0": {
|
|
34
|
+
"en": "initial release",
|
|
35
|
+
"de": "Erstveröffentlichung",
|
|
36
|
+
"ru": "Начальная версия",
|
|
37
|
+
"pt": "lançamento inicial",
|
|
38
|
+
"nl": "Eerste uitgave",
|
|
39
|
+
"fr": "Première version",
|
|
40
|
+
"it": "Versione iniziale",
|
|
41
|
+
"es": "Versión inicial",
|
|
42
|
+
"pl": "Pierwsze wydanie",
|
|
43
|
+
"uk": "Початкова версія",
|
|
44
|
+
"zh-cn": "首次出版"
|
|
45
|
+
},
|
|
46
|
+
"0.2.0": {
|
|
47
|
+
"en": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
48
|
+
"de": "Beta-Release mit HexDB-Routen/Bildern, deutschen Flughafen-Ortsnamen, verbesserter Sprachausgabe-Triggerlogik, Nur-Überflug-Modus und Admin-UI-Fixes.",
|
|
49
|
+
"ru": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
50
|
+
"pt": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
51
|
+
"nl": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
52
|
+
"fr": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
53
|
+
"it": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
54
|
+
"es": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
55
|
+
"pl": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
56
|
+
"uk": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes.",
|
|
57
|
+
"zh-cn": "Beta release with HexDB route/image support, German airport city names, improved speech trigger handling, overflight-only mode and admin UI fixes."
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"titleLang": {
|
|
61
|
+
"en": "JetFrame",
|
|
62
|
+
"de": "JetFrame",
|
|
63
|
+
"ru": "ПолетСтена",
|
|
64
|
+
"pt": "Parede de voo",
|
|
65
|
+
"nl": "VluchtWall",
|
|
66
|
+
"fr": "Mur de Vol",
|
|
67
|
+
"it": "JetFrame",
|
|
68
|
+
"es": "Muro de vuelo",
|
|
69
|
+
"pl": "Ściana lotu",
|
|
70
|
+
"uk": "JetFrame",
|
|
71
|
+
"zh-cn": "飞行墙"
|
|
72
|
+
},
|
|
73
|
+
"desc": {
|
|
74
|
+
"en": "Flight tracking and visualization for window-based aircraft detection",
|
|
75
|
+
"de": "Flugverfolgung und -visualisierung zur fensterbasierten Flugzeugerkennung",
|
|
76
|
+
"ru": "Отслеживание полета и визуализация для обнаружения самолетов через окно",
|
|
77
|
+
"pt": "Rastreamento e visualização de voo para detecção de aeronaves baseada em janela",
|
|
78
|
+
"nl": "Vluchttracking en -visualisatie voor raamgebaseerde vliegtuigdetectie",
|
|
79
|
+
"fr": "Suivi et visualisation des vols pour la détection des avions par fenêtre",
|
|
80
|
+
"it": "Tracciamento e visualizzazione del volo per il rilevamento degli aerei basato su finestre",
|
|
81
|
+
"es": "Seguimiento y visualización de vuelos para la detección de aeronaves mediante ventanas",
|
|
82
|
+
"pl": "Śledzenie lotu i wizualizacja do wykrywania samolotów za pomocą okien",
|
|
83
|
+
"uk": "Відстеження польоту та візуалізація для виявлення літака через вікно",
|
|
84
|
+
"zh-cn": "基于窗口的飞机检测的飞行跟踪和可视化"
|
|
85
|
+
},
|
|
86
|
+
"authors": [
|
|
87
|
+
"backfisch88 <h@h.de>"
|
|
88
|
+
],
|
|
89
|
+
"keywords": [
|
|
90
|
+
"flight",
|
|
91
|
+
"adsb",
|
|
92
|
+
"aircraft",
|
|
93
|
+
"tracking",
|
|
94
|
+
"fr24"
|
|
95
|
+
],
|
|
96
|
+
"licenseInformation": {
|
|
97
|
+
"type": "free",
|
|
98
|
+
"license": "MIT"
|
|
99
|
+
},
|
|
100
|
+
"platform": "Javascript/Node.js",
|
|
101
|
+
"icon": "jetframe.png",
|
|
102
|
+
"enabled": true,
|
|
103
|
+
"extIcon": "https://raw.githubusercontent.com/backfisch88/ioBroker.jetframe/main/admin/jetframe.png",
|
|
104
|
+
"readme": "https://github.com/backfisch88/ioBroker.jetframe/blob/main/README.md",
|
|
105
|
+
"loglevel": "info",
|
|
106
|
+
"tier": 3,
|
|
107
|
+
"mode": "daemon",
|
|
108
|
+
"type": "visualization",
|
|
109
|
+
"compact": true,
|
|
110
|
+
"connectionType": "cloud",
|
|
111
|
+
"dataSource": "poll",
|
|
112
|
+
"adminUI": {
|
|
113
|
+
"config": "materialize"
|
|
114
|
+
},
|
|
115
|
+
"dependencies": [
|
|
116
|
+
{
|
|
117
|
+
"js-controller": ">=6.0.11"
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"globalDependencies": [
|
|
121
|
+
{
|
|
122
|
+
"admin": ">=7.0.23"
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
"native": {
|
|
126
|
+
"speechEnabled": true
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"native": {
|
|
130
|
+
"enabled": true,
|
|
131
|
+
"airportIata": "FRA",
|
|
132
|
+
"airportName": "Frankfurt",
|
|
133
|
+
"airportLat": 50.035686,
|
|
134
|
+
"airportLon": 8.562813,
|
|
135
|
+
"homeLat": 50.08637,
|
|
136
|
+
"homeLon": 8.69163,
|
|
137
|
+
"windowBearingDeg": 184,
|
|
138
|
+
"windowFovDeg": 120,
|
|
139
|
+
"maxHomeDistanceNm": 3.5,
|
|
140
|
+
"radiusNm": 15,
|
|
141
|
+
"minAltitudeFt": 1000,
|
|
142
|
+
"maxAltitudeFt": 5000,
|
|
143
|
+
"autoRunwayTrackToleranceDeg": 65,
|
|
144
|
+
"minClimbRate": 60,
|
|
145
|
+
"minSinkRate": -60,
|
|
146
|
+
"searchPollSeconds": 20,
|
|
147
|
+
"livePollSeconds": 5,
|
|
148
|
+
"liveMaxSeconds": 120,
|
|
149
|
+
"overflightEnabled": false,
|
|
150
|
+
"overflightMaxDistanceNm": 1.2,
|
|
151
|
+
"overflightMinAltitudeFt": 4000,
|
|
152
|
+
"overflightMaxAltitudeFt": 45000,
|
|
153
|
+
"speechMode": "browser",
|
|
154
|
+
"speechTemplate": "{modeSpeechText}: {airlineName} {bestCallsign} {routeDirectionText} {routeOtherAirport} in {altitudeFt} Fuß. {windowPositionSpeechText}.",
|
|
155
|
+
"overflightRequiresWindow": false,
|
|
156
|
+
"overflightOnly": false,
|
|
157
|
+
"simpleApiHost": "",
|
|
158
|
+
"simpleApiPort": 8087,
|
|
159
|
+
"visualSource": "current",
|
|
160
|
+
"externalManufacturerLogos": false,
|
|
161
|
+
"manufacturerLogoUrls": "",
|
|
162
|
+
"externalAirlineLogos": false,
|
|
163
|
+
"airlineLogoBaseUrl": "",
|
|
164
|
+
"cacheExternalImages": false
|
|
165
|
+
},
|
|
166
|
+
"objects": [],
|
|
167
|
+
"instanceObjects": [],
|
|
168
|
+
"version": "0.6.0"
|
|
169
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iobroker.jetframe",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Live flight tracking and visualization for window-based aircraft detection",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "backfisch88",
|
|
7
|
+
"email": "h@h.de"
|
|
8
|
+
},
|
|
9
|
+
"contributors": [
|
|
10
|
+
{
|
|
11
|
+
"name": "backfisch"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/backfisch88/ioBroker.jetframe",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"flight",
|
|
18
|
+
"adsb",
|
|
19
|
+
"aircraft",
|
|
20
|
+
"tracking",
|
|
21
|
+
"fr24",
|
|
22
|
+
"ioBroker",
|
|
23
|
+
"jetframe",
|
|
24
|
+
"aviation"
|
|
25
|
+
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/backfisch88/ioBroker.jetframe.git"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">= 22"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@iobroker/adapter-core": "^3.3.2"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@alcalzone/release-script": "^5.1.1",
|
|
38
|
+
"@alcalzone/release-script-plugin-iobroker": "^5.1.2",
|
|
39
|
+
"@alcalzone/release-script-plugin-license": "^5.1.1",
|
|
40
|
+
"@alcalzone/release-script-plugin-manual-review": "^5.1.1",
|
|
41
|
+
"@iobroker/adapter-dev": "^1.5.0",
|
|
42
|
+
"@iobroker/dev-server": "^0.8.0",
|
|
43
|
+
"@iobroker/eslint-config": "^2.2.0",
|
|
44
|
+
"@iobroker/testing": "^5.2.2",
|
|
45
|
+
"@tsconfig/node22": "^22.0.5",
|
|
46
|
+
"@types/iobroker": "^7.1.1",
|
|
47
|
+
"@types/node": "^22.19.17",
|
|
48
|
+
"prettier": "^3.8.3",
|
|
49
|
+
"rimraf": "^6.1.3",
|
|
50
|
+
"source-map-support": "^0.5.21",
|
|
51
|
+
"ts-node": "^10.9.2",
|
|
52
|
+
"typescript": "~5.9.3"
|
|
53
|
+
},
|
|
54
|
+
"main": "build/main.js",
|
|
55
|
+
"files": [
|
|
56
|
+
"admin/",
|
|
57
|
+
"build/",
|
|
58
|
+
"www/",
|
|
59
|
+
"io-package.json",
|
|
60
|
+
"package.json",
|
|
61
|
+
"README.md",
|
|
62
|
+
"LICENSE"
|
|
63
|
+
],
|
|
64
|
+
"scripts": {
|
|
65
|
+
"prebuild": "rimraf build",
|
|
66
|
+
"build": "build-adapter ts",
|
|
67
|
+
"watch": "build-adapter ts --watch",
|
|
68
|
+
"test:ts": "mocha --config test/mocharc.custom.json src/**/*.test.ts",
|
|
69
|
+
"test:package": "mocha test/package --exit",
|
|
70
|
+
"test:integration": "mocha test/integration --exit",
|
|
71
|
+
"test": "npm run test:ts && npm run test:package",
|
|
72
|
+
"check": "tsc --noEmit",
|
|
73
|
+
"lint": "eslint -c eslint.config.mjs .",
|
|
74
|
+
"translate": "translate-adapter",
|
|
75
|
+
"release": "release-script",
|
|
76
|
+
"dev-server": "dev-server"
|
|
77
|
+
},
|
|
78
|
+
"bugs": {
|
|
79
|
+
"url": "https://github.com/backfisch88/ioBroker.jetframe/issues"
|
|
80
|
+
},
|
|
81
|
+
"readmeFilename": "README.md"
|
|
82
|
+
}
|