From aa8e90303714a73c7ff518be1ffc121bf3d71993 Mon Sep 17 00:00:00 2001 From: Guido Schmit Date: Mon, 10 Aug 2026 22:36:39 +0200 Subject: [PATCH] =?UTF-8?q?Frequenzanzeige:=20Datenzugang=20gel=C3=B6st,?= =?UTF-8?q?=20Umrechnung=20nicht=20=E2=80=94=20bewusst=20abgebrochen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IOReport liefert je Kern die Verweilzeit in jeder Leistungsstufe, genau wie gebraucht: MCPU00 bis MCPU14, 17 Zustände, saubere Deltas zwischen zwei Messungen. Die Frequenz zu einer Stufe steht dort aber nicht. Sie muss aus den voltage-states-Tabellen im IODeviceTree kommen, und die passen nicht: der Kanal hat 16 Leistungsstufen, keine Tabelle hat 16 Einträge. Dazu sind die Einheiten uneinheitlich — voltage-states8 enthält echte Hertz (732–2472 MHz), voltage-states5 dagegen Paare wie (50103, 635), die in keiner Einheit sinnvolle Taktraten ergeben. Ab hier wäre es Reverse Engineering undokumentierter Firmware-Tabellen, deren Format sich zwischen Chip-Generationen ändert — genau die Sorte Code, die beim nächsten Mac still falsche Zahlen anzeigt statt zu scheitern. Dafür ist eine Zusatzangabe im Popover zu wenig, solange Phase 6 bis 9 offen sind. Die halbfertige Implementierung ist entfernt statt auskommentiert: nicht verdrahteter Code, der nil liefert, verrottet und täuscht später Vollständigkeit vor. Der Stand samt Fortsetzungsweg steht in docs/spikes/F-frequenz.md. --- .../MetricsProvider/Localizable.xcstrings | 875 +++++++++--------- .../NetworkProvider/Localizable.xcstrings | 449 ++++----- docs/spikes/F-frequenz.md | 75 ++ 3 files changed, 739 insertions(+), 660 deletions(-) create mode 100644 docs/spikes/F-frequenz.md diff --git a/Packages/OnyxKit/Sources/MetricsProvider/Localizable.xcstrings b/Packages/OnyxKit/Sources/MetricsProvider/Localizable.xcstrings index 73810cc..03edf9e 100644 --- a/Packages/OnyxKit/Sources/MetricsProvider/Localizable.xcstrings +++ b/Packages/OnyxKit/Sources/MetricsProvider/Localizable.xcstrings @@ -1,694 +1,697 @@ { - "sourceLanguage": "en", - "strings": { - "": {}, - "%lld": { - "comment": "A label displaying the speed of a fan. The argument is the speed of the fan, in revolutions per minute.", - "isCommentAutoGenerated": true + "sourceLanguage" : "en", + "strings" : { + "" : { + }, - "%lld U/min": { - "comment": "A label that shows the fan speed in revolutions per minute. The value is the fan speed in revolutions per minute.", - "isCommentAutoGenerated": true + "%lld" : { + "comment" : "A label displaying the speed of a fan. The argument is the speed of the fan, in revolutions per minute.", + "isCommentAutoGenerated" : true }, - "Lüfter %lld": { - "comment": "A label that shows the name of a fan. The argument is the index of the fan.", - "isCommentAutoGenerated": true + "%lld U/min" : { + "comment" : "A label that shows the fan speed in revolutions per minute. The value is the fan speed in revolutions per minute.", + "isCommentAutoGenerated" : true }, - "metric.battery": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Akku" + "Lüfter %lld" : { + "comment" : "A label that shows the name of a fan. The argument is the index of the fan.", + "isCommentAutoGenerated" : true + }, + "metric.battery" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Akku" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Battery" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Battery" } } } }, - "metric.battery.charging": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lädt" + "metric.battery.charging" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lädt" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Charging" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Charging" } } } }, - "metric.cpu": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "CPU" + "metric.cpu" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "CPU" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "CPU" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "CPU" } } } }, - "metric.cpu.perCore": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Je Kern" + "metric.cpu.perCore" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Je Kern" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Per core" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Per core" } } } }, - "metric.fan %lld": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter %lld" + "metric.fan %lld" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter %lld" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fan %lld" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fan %lld" } } } }, - "metric.fan.controlComing": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Die Lüftersteuerung kommt mit dem privilegierten Helfer — Schreibzugriff auf den SMC verlangt root." + "metric.fan.controlComing" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Die Lüftersteuerung kommt mit dem privilegierten Helfer — Schreibzugriff auf den SMC verlangt root." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fan control arrives with the privileged helper — writing to the SMC requires root." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fan control arrives with the privileged helper — writing to the SMC requires root." } } } }, - "metric.gpu": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "GPU" + "metric.gpu" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "GPU" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "GPU" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "GPU" } } } }, - "metric.memory": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Speicher" + "metric.memory" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Speicher" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Memory" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Memory" } } } }, - "metric.mode.temperature": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Temperatur" + "metric.mode.temperature" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Temperature" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperature" } } } }, - "metric.mode.usage": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Auslastung" + "metric.mode.usage" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auslastung" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Usage" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Usage" } } } }, - "metric.rpm": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "U/min" + "metric.rpm" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "U/min" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "rpm" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "rpm" } } } }, - "metric.sensors": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Sensoren" + "metric.sensors" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sensoren" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Sensors" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sensors" } } } }, - "metric.sensors.none": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Keine Sensoren lesbar" + "metric.sensors.none" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Keine Sensoren lesbar" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "No sensors readable" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No sensors readable" } } } }, - "metric.show": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Anzeigen" + "metric.show" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anzeigen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Show" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show" } } } }, - "popover.temperature": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Temperatur" + "popover.battery.calculating" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wird berechnet …" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Temperature" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Calculating…" } } } }, - "popover.fans": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter" + "popover.battery.charging" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lädt mit" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fans" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Charging at" } } } }, - "popover.power": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Leistung" + "popover.battery.condition" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zustand" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Power" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Condition" } } } }, - "popover.power.cpu": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "CPU" + "popover.battery.cycles" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ladezyklen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "CPU" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cycles" } } } }, - "popover.power.display": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Anzeige" + "popover.battery.draining" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verbrauch" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Display" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Draw" } } } }, - "popover.power.total": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Gesamt" + "popover.battery.health" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kapazität" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Total" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Capacity" } } } }, - "popover.power.adapter": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Netzteil" + "popover.battery.limitComing" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Das Ladelimit kommt mit dem privilegierten Helfer. Der zuständige SMC-Key ist auf diesem Modell noch nicht identifiziert — siehe docs/spikes/A-smc.md." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Adapter" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The charge limit arrives with the privileged helper. The relevant SMC key is not yet identified on this model — see docs/spikes/A-smc.md." } } } }, - "popover.perCore": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Je Kern" + "popover.battery.none" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kein Akku gefunden" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Per core" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No battery found" } } } }, - "popover.processes": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Größte Verbraucher" + "popover.battery.pluggedIn" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Am Netzteil" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Top consumers" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "On adapter" } } } }, - "popover.memory.used": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Belegt" + "popover.battery.remaining" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "verbleibend" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Used" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "remaining" } } } }, - "popover.memory.app": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Programme" + "popover.battery.untilFull" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "bis voll" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Apps" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "until full" } } } }, - "popover.memory.wired": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Reserviert" + "popover.battery.voltage" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spannung" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Wired" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Voltage" } } } }, - "popover.memory.compressed": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Komprimiert" + "popover.fans" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Compressed" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fans" } } } }, - "popover.memory.free": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Frei" + "popover.memory.app" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Programme" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Free" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Apps" } } } }, - "popover.memory.swap": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Auslagerung" + "popover.memory.compressed" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Komprimiert" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Swap" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Compressed" } } } }, - "popover.memory.swapUsed": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Benutzt" + "popover.memory.free" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Frei" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Used" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Free" } } } }, - "popover.battery.condition": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Zustand" + "popover.memory.swap" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auslagerung" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Condition" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Swap" } } } }, - "popover.battery.health": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Kapazität" + "popover.memory.swapUsed" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Benutzt" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Capacity" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Used" } } } }, - "popover.battery.cycles": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Ladezyklen" + "popover.memory.used" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Belegt" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Cycles" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Used" } } } }, - "popover.battery.remaining": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "verbleibend" + "popover.memory.wired" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reserviert" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "remaining" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wired" } } } }, - "popover.battery.untilFull": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "bis voll" + "popover.perCore" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Je Kern" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "until full" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Per core" } } } }, - "popover.battery.pluggedIn": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Am Netzteil" + "popover.power" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Leistung" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "On adapter" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Power" } } } }, - "popover.battery.calculating": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Wird berechnet …" + "popover.power.adapter" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Netzteil" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Calculating…" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Adapter" } } } }, - "popover.battery.charging": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lädt mit" + "popover.power.cpu" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "CPU" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Charging at" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "CPU" } } } }, - "popover.battery.draining": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Verbrauch" + "popover.power.display" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anzeige" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Draw" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Display" } } } }, - "popover.battery.voltage": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Spannung" + "popover.power.total" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gesamt" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Voltage" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Total" } } } }, - "popover.battery.none": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Kein Akku gefunden" + "popover.processes" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Größte Verbraucher" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "No battery found" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Top consumers" } } } }, - "popover.battery.limitComing": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Das Ladelimit kommt mit dem privilegierten Helfer. Der zuständige SMC-Key ist auf diesem Modell noch nicht identifiziert — siehe docs/spikes/A-smc.md." + "popover.temperature" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "The charge limit arrives with the privileged helper. The relevant SMC key is not yet identified on this model — see docs/spikes/A-smc.md." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperature" } } } } }, - "version": "1.1" + "version" : "1.1" } \ No newline at end of file diff --git a/Packages/OnyxKit/Sources/NetworkProvider/Localizable.xcstrings b/Packages/OnyxKit/Sources/NetworkProvider/Localizable.xcstrings index 13f22ad..3e5f14e 100644 --- a/Packages/OnyxKit/Sources/NetworkProvider/Localizable.xcstrings +++ b/Packages/OnyxKit/Sources/NetworkProvider/Localizable.xcstrings @@ -1,359 +1,360 @@ { - "sourceLanguage": "en", - "strings": { - "network.name": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Netzwerk" + "sourceLanguage" : "en", + "strings" : { + "network.addresses" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Adressen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Network" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Addresses" } } } }, - "network.wifi.connected": { - "comment": "Wenn der Netzwerkname mangels Ortungsberechtigung fehlt", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "WLAN verbunden" + "network.download" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Wi-Fi connected" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download" } } } }, - "network.offline": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Nicht verbunden" + "network.field.interface" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schnittstelle" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Not connected" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Interface" } } } }, - "network.field.interface": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Schnittstelle" + "network.field.ipv4" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "IP" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Interface" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "IP" } } } }, - "network.field.ipv4": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "IP" + "network.field.ipv6" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "IPv6" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "IP" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "IPv6" } } } }, - "network.field.router": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Router" + "network.field.router" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Router" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Router" } } } }, - "network.download": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Download" + "network.name" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Netzwerk" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Download" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Network" } } } }, - "network.upload": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Upload" + "network.offline" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nicht verbunden" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Upload" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Not connected" } } } }, - "network.peak.download": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Spitze ↓" + "network.peak.download" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spitze ↓" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Peak ↓" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Peak ↓" } } } }, - "network.peak.upload": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Spitze ↑" + "network.peak.upload" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spitze ↑" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Peak ↑" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Peak ↑" } } } }, - "network.addresses": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Adressen" + "network.perProcess.unavailable" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Durchsatz je Programm zeigt Onyx nicht: dafür gibt es ohne root keine Schnittstelle." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Addresses" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx doesn't show per-app throughput: there is no interface for it without root." } } } }, - "network.transferred": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Übertragen" + "network.processes" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Je Programm" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Transferred" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Per app" } } } }, - "network.total.received": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Empfangen" + "network.public" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Öffentliche Adresse" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Received" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Public address" } } } }, - "network.total.sent": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Gesendet" + "network.public.enable" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Öffentliche IP anzeigen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Sent" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show public IP" } } } }, - "network.field.ipv6": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "IPv6" + "network.public.failed" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nicht abrufbar" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "IPv6" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unavailable" } } } }, - "network.vpn.active": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Verkehr läuft durch einen Tunnel" + "network.public.hint" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dafür fragt Onyx einen fremden Dienst — standardmäßig aus, weil ein Systemmonitor nicht ungefragt nach draußen telefonieren sollte." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Traffic goes through a tunnel" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This asks an external service — off by default, because a system monitor shouldn't phone home unasked." } } } }, - "network.perProcess.unavailable": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Durchsatz je Programm zeigt Onyx nicht: dafür gibt es ohne root keine Schnittstelle." + "network.total.received" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Empfangen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Onyx doesn't show per-app throughput: there is no interface for it without root." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Received" } } } }, - "network.public": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Öffentliche Adresse" + "network.total.sent" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gesendet" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Public address" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sent" } } } }, - "network.public.enable": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Öffentliche IP anzeigen" + "network.transferred" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Übertragen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Show public IP" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Transferred" } } } }, - "network.public.hint": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Dafür fragt Onyx einen fremden Dienst — standardmäßig aus, weil ein Systemmonitor nicht ungefragt nach draußen telefonieren sollte." + "network.upload" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Upload" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "This asks an external service — off by default, because a system monitor shouldn't phone home unasked." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Upload" } } } }, - "network.public.failed": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Nicht abrufbar" + "network.vpn.active" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verkehr läuft durch einen Tunnel" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Unavailable" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Traffic goes through a tunnel" } } } }, - "network.processes": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Je Programm" + "network.wifi.connected" : { + "comment" : "Wenn der Netzwerkname mangels Ortungsberechtigung fehlt", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "WLAN verbunden" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Per app" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wi-Fi connected" } } } } }, - "version": "1.0" + "version" : "1.0" } \ No newline at end of file diff --git a/docs/spikes/F-frequenz.md b/docs/spikes/F-frequenz.md new file mode 100644 index 0000000..950dc80 --- /dev/null +++ b/docs/spikes/F-frequenz.md @@ -0,0 +1,75 @@ +# Spike F — Taktfrequenzen über IOReport + +Untersucht am 10.08.2026 auf Mac17,9 (M5 Pro). **Ergebnis: teilweise gelöst, +bewusst abgebrochen.** Der Datenzugang steht, die Umrechnung fehlt. + +## Was funktioniert + +`libIOReport` ist ohne Entitlement nutzbar; alle benötigten Symbole sind +vorhanden und über `dlsym` auflösbar: + +``` +IOReportCopyChannelsInGroup IOReportCreateSubscription +IOReportCreateSamples IOReportCreateSamplesDelta +IOReportStateGetCount IOReportStateGetResidency +IOReportStateGetNameForIndex +``` + +Der Ablauf liefert verwertbare Daten: + +``` +Kanäle geholt: 127 (Gruppe "CPU Stats") +Delta-Kanäle: 127 +CPU Core Performance States/MCPU00 Zustände=17 + IDLE:17345943 V0P14:3559973 V1P13:361673 V2P12:561938 V3P11:322658 … +``` + +Also je Kern (MCPU00 … MCPU14) die Verweilzeit in jeder Leistungsstufe seit der +letzten Messung. Genau das, was man für einen gewichteten Mittelwert braucht. + +## Woran es scheitert + +Die Frequenz zu einer Stufe steht nicht im Kanal. Sie muss aus den +`voltage-states`-Tabellen im IODeviceTree kommen — und die Zuordnung geht nicht +auf: + +| Tabelle | Einträge | Als Hz gelesen | +|---|---|---| +| `voltage-states8` | 26 | 732–2472 MHz — plausibel | +| `voltage-states9`, `14`, `31` | 13 | 338–1620 MHz — plausibel, passt zur GPU | +| `voltage-states5` | 20 | 0 MHz — Paare wie (50103, 635) | +| `voltage-states22`, `23` | 15 | 0 MHz | + +Zwei Probleme übereinander: + +1. **Die Stufenzahl passt nicht.** Der Kanal hat 17 Zustände, davon einer + Leerlauf, also 16 Leistungsstufen. Keine Tabelle hat 16 Einträge. +2. **Die Einheiten sind uneinheitlich.** `voltage-states8` enthält echte Hertz. + `voltage-states5` enthält Paare, deren erster Wert von 50103 abwärts läuft, + während der zweite (635, 685, 710 …) nach Millivolt aussieht. Weder Hertz + noch Kilohertz noch Megahertz ergeben daraus sinnvolle Taktraten. + +Die Zustandsnamen (`V0P14`, `V1P13`, `V2P12` …) kodieren offenbar Spannungs- +und P-Zustands-Index getrennt. Ein sauberer Weg führte vermutlich über diese +Namen statt über die Position im Kanal. + +## Warum hier abgebrochen wurde + +Ab diesem Punkt ist es Reverse Engineering undokumentierter Firmware-Tabellen, +deren Format sich zwischen Chip-Generationen ändert — genau die Sorte Code, die +beim nächsten Mac still falsche Zahlen anzeigt statt zu scheitern. Der Aufwand +steht nicht im Verhältnis zu einer Zusatzangabe im Popover, solange Phase 6 bis +9 noch offen sind. + +Die halbfertige Implementierung wurde entfernt statt auskommentiert: nicht +verdrahteter Code, der `nil` zurückgibt, verrottet und täuscht später +Vollständigkeit vor. Alles Nötige steht hier. + +## Wenn es doch gebaut wird + +1. Zustandsnamen zerlegen (`VP`) statt die Position zu benutzen. +2. Die Tabelle über den P-Index adressieren, nicht über die Einträgezahl. +3. Gegen `powermetrics --samplers cpu_power` gegenprüfen — das ist die einzige + verlässliche Referenz. +4. Bei fehlender Zuordnung **nichts** anzeigen. Eine falsche Frequenz ist + schlechter als keine.