iobroker.govee-smart 2.6.6 → 2.6.7
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/README.md
CHANGED
|
@@ -128,6 +128,10 @@ This adapter's MQTT authentication and BLE-over-LAN (ptReal) protocol implementa
|
|
|
128
128
|
Placeholder for the next version (at the beginning of the line):
|
|
129
129
|
### **WORK IN PROGRESS**
|
|
130
130
|
-->
|
|
131
|
+
### 2.6.7 (2026-05-10)
|
|
132
|
+
|
|
133
|
+
- Cleaner ready-log: removed the device/sensor/group online-summary because it ran before the LAN scan had settled and could falsely show all lights as offline.
|
|
134
|
+
|
|
131
135
|
### 2.6.6 (2026-05-10)
|
|
132
136
|
|
|
133
137
|
- Internal refactoring. No changes for users.
|
|
@@ -150,10 +154,6 @@ This adapter's MQTT authentication and BLE-over-LAN (ptReal) protocol implementa
|
|
|
150
154
|
- A rejected Govee API key now surfaces an actionable hint in the log so you know where to look.
|
|
151
155
|
- Various behind-the-scenes hardening of all four communication channels (LAN, MQTT, Cloud-events, Cloud REST) — invisible if everything was already running fine, robustness if something is unstable.
|
|
152
156
|
|
|
153
|
-
### 2.6.2 (2026-05-09)
|
|
154
|
-
|
|
155
|
-
- Adapter log messages are now English only, in line with the ioBroker community standard. Localized state names, descriptions and dropdown labels (11 languages) are unchanged. The user-visible segment-detection wizard text in the admin UI also remains localized.
|
|
156
|
-
|
|
157
157
|
Older entries are in [CHANGELOG_OLD.md](CHANGELOG_OLD.md).
|
|
158
158
|
|
|
159
159
|
## Support
|
|
@@ -120,12 +120,6 @@ function checkAllReady(adapter) {
|
|
|
120
120
|
}
|
|
121
121
|
function logDeviceSummary(adapter) {
|
|
122
122
|
var _a, _b;
|
|
123
|
-
if (!adapter.deviceManager) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const all = adapter.deviceManager.getDevices();
|
|
127
|
-
const devices = all.filter((d) => d.sku !== "BaseGroup");
|
|
128
|
-
const groups = all.filter((d) => d.sku === "BaseGroup");
|
|
129
123
|
const channels = ["LAN"];
|
|
130
124
|
if (adapter.cloudWasConnected) {
|
|
131
125
|
channels.push("Cloud");
|
|
@@ -136,28 +130,7 @@ function logDeviceSummary(adapter) {
|
|
|
136
130
|
if ((_b = adapter.openapiMqttClient) == null ? void 0 : _b.connected) {
|
|
137
131
|
channels.push("Cloud-events");
|
|
138
132
|
}
|
|
139
|
-
|
|
140
|
-
const onlineDevices = devices.filter((d) => d.state.online === true);
|
|
141
|
-
const parts = [];
|
|
142
|
-
if (devices.length > 0) {
|
|
143
|
-
const onlineLights = lightDevices.filter((d) => d.state.online === true).length;
|
|
144
|
-
const totalLights = lightDevices.length;
|
|
145
|
-
if (totalLights > 0) {
|
|
146
|
-
parts.push(
|
|
147
|
-
totalLights === onlineLights ? `${totalLights} light${totalLights > 1 ? "s" : ""} online` : `${totalLights} light${totalLights > 1 ? "s" : ""} (${onlineLights} online, ${totalLights - onlineLights} offline)`
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
const sensors = devices.length - lightDevices.length;
|
|
151
|
-
if (sensors > 0) {
|
|
152
|
-
const onlineSensors = onlineDevices.filter((d) => d.type !== "devices.types.light").length;
|
|
153
|
-
parts.push(`${sensors} sensor${sensors > 1 ? "s" : ""} (${onlineSensors} with data)`);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (groups.length > 0) {
|
|
157
|
-
parts.push(`${groups.length} group${groups.length > 1 ? "s" : ""}`);
|
|
158
|
-
}
|
|
159
|
-
const summary = parts.length > 0 ? parts.join(", ") : "no devices found";
|
|
160
|
-
adapter.log.info(`Govee adapter ready \u2014 ${summary} \u2014 channels: ${channels.join("+")}`);
|
|
133
|
+
adapter.log.info(`Govee adapter ready \u2014 channels: ${channels.join("+")}`);
|
|
161
134
|
if (adapter.cloudClient && !adapter.cloudWasConnected) {
|
|
162
135
|
const reason = adapter.cloudClient.getFailureReason();
|
|
163
136
|
adapter.log.warn(reason ? `Cloud not connected \u2014 ${reason}` : `Cloud not connected \u2014 see earlier errors`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/handlers/connection-state.ts"],
|
|
4
|
-
"sourcesContent": ["import type { DeviceManager } from \"../device-manager\";\nimport type { GoveeCloudClient } from \"../govee-cloud-client\";\nimport type { GoveeMqttClient } from \"../govee-mqtt-client\";\nimport type { GoveeOpenapiMqttClient } from \"../govee-openapi-mqtt-client\";\nimport { httpsRequest } from \"../http-client\";\nimport { errMessage } from \"../types\";\nimport { GOVEE_APP_VERSION } from \"../govee-constants\";\n\n/**\n * Adapter surface required by the connection-state helpers \u2014 covers the\n * info.connection bookkeeping plus ready-summary + app-version drift\n * monitoring + stale-device reaping.\n */\nexport interface ConnectionStateAdapter {\n readonly log: ioBroker.Logger;\n readonly deviceManager: DeviceManager | null;\n readonly cloudClient: GoveeCloudClient | null;\n readonly cloudWasConnected: boolean;\n readonly diagnosticsLastRun: Map<string, number>;\n readonly mqttClient: GoveeMqttClient | null;\n readonly openapiMqttClient: GoveeOpenapiMqttClient | null;\n readonly lanClient: unknown;\n readonly stateManager: { cleanupDevices(devices: unknown[]): Promise<unknown> } | null;\n readonly lanScanDone: boolean;\n readonly statesReady: boolean;\n readonly cloudInitDone: boolean;\n readonly appApiInitialPollDone: boolean;\n readyLogged: boolean;\n lastConnectionState: boolean | null;\n setStateAsync(id: string, state: ioBroker.SettableState | ioBroker.StateValue): Promise<unknown>;\n}\n\n/**\n * Update global `info.connection` \u2014 the ioBroker-IDC indicator.\n *\n * Semantik:\n * - Mit Devices: `connected = true` wenn MIND. ein Device online ist.\n * Wenn alle offline \u2192 false (User sieht: kein Device antwortet).\n * - Ohne Devices: `connected = true` wenn der LAN-Stack l\u00E4uft. Sonst\n * false (z.B. EADDRINUSE oder bind-Fehler).\n *\n * Write-only-on-change cache (lastConnectionState) so we don't spam\n * setStateAsync on every device-state-update.\n *\n */\nexport function updateConnectionState(adapter: ConnectionStateAdapter): void {\n const devices = adapter.deviceManager?.getDevices() ?? [];\n const hasDevices = devices.length > 0;\n const anyOnline = devices.some(d => d.state.online);\n const lanRunning = adapter.lanClient !== null;\n const connected = hasDevices ? anyOnline : lanRunning;\n if (connected !== adapter.lastConnectionState) {\n adapter.lastConnectionState = connected;\n adapter.setStateAsync(\"info.connection\", { val: connected, ack: true }).catch(() => {});\n }\n}\n\n/**\n * Daily app-version-drift check vs. the iTunes app-store lookup.\n *\n * Govee's app2.govee.com endpoints reject very stale User-Agent strings.\n * Compares live iOS app version with local `GOVEE_APP_VERSION`. On drift\n * > 2 minor: warn-Log + state `info.appVersionDrift`. Failures (5xx,\n * network) are silent debug-logged \u2014 no user impact.\n *\n */\nexport async function checkAppVersionDrift(adapter: ConnectionStateAdapter): Promise<void> {\n try {\n const resp = await httpsRequest<{ resultCount?: number; results?: Array<{ version?: string }> }>({\n method: \"GET\",\n url: \"https://itunes.apple.com/lookup?bundleId=com.ihoment.GoVeeSensor\",\n headers: { \"User-Agent\": \"ioBroker.govee-smart\" },\n timeout: 10_000,\n });\n const liveVersion = resp.results?.[0]?.version;\n if (typeof liveVersion !== \"string\" || liveVersion.length === 0) {\n return;\n }\n const localParts = GOVEE_APP_VERSION.split(\".\").map(Number);\n const liveParts = liveVersion.split(\".\").map(Number);\n const localMajor = localParts[0] ?? 0;\n const localMinor = localParts[1] ?? 0;\n const liveMajor = liveParts[0] ?? 0;\n const liveMinor = liveParts[1] ?? 0;\n const liveTotal = liveMajor * 100 + liveMinor;\n const localTotal = localMajor * 100 + localMinor;\n const driftMinor = liveTotal - localTotal;\n const driftMessage =\n driftMinor === 0\n ? `current (live=${liveVersion}, local=${GOVEE_APP_VERSION})`\n : driftMinor <= 2\n ? `minor drift (live=${liveVersion}, local=${GOVEE_APP_VERSION})`\n : `STALE (live=${liveVersion}, local=${GOVEE_APP_VERSION}) \u2014 bump GOVEE_APP_VERSION`;\n await adapter.setStateAsync(\"info.appVersionDrift\", { val: driftMessage, ack: true }).catch(() => undefined);\n if (driftMinor > 2) {\n adapter.log.warn(\n `Govee app version drift: live ${liveVersion} vs local ${GOVEE_APP_VERSION} \u2014 undocumented endpoints may start failing. Run sync-govee-app-version.py + release a new adapter version.`,\n );\n } else {\n adapter.log.debug(`App version: ${driftMessage}`);\n }\n } catch (e) {\n adapter.log.debug(`App version check failed: ${errMessage(e)}`);\n }\n}\n\n/**\n * Delete ioBroker objects for devices no longer present and drop the same\n * devices from adapter-level maps. Diagnostics-buffer + diagnosticsLastRun\n * are reaped so removed-device data doesn't leak into the next adapter\n * lifetime.\n *\n */\nexport async function reapStaleDevices(adapter: ConnectionStateAdapter): Promise<void> {\n if (!adapter.stateManager || !adapter.deviceManager) {\n return;\n }\n const currentDevices = adapter.deviceManager.getDevices();\n await adapter.stateManager.cleanupDevices(currentDevices);\n\n const liveDeviceIds = new Set(currentDevices.map(d => d.deviceId));\n adapter.deviceManager.getDiagnostics().pruneOrphans(liveDeviceIds);\n\n const liveKeys = new Set(currentDevices.map(d => `${d.sku}:${d.deviceId}`));\n for (const key of adapter.diagnosticsLastRun.keys()) {\n if (!liveKeys.has(key)) {\n adapter.diagnosticsLastRun.delete(key);\n }\n }\n}\n\n/**\n * Check if all configured channels are initialized and log ready message.\n * Called from MQTT onConnection callback and end of onReady.\n *\n */\nexport function checkAllReady(adapter: ConnectionStateAdapter): void {\n if (adapter.readyLogged) {\n return;\n }\n if (!adapter.lanScanDone) {\n return;\n }\n if (!adapter.statesReady) {\n return;\n }\n if (adapter.cloudClient && !adapter.cloudInitDone) {\n return;\n }\n if (adapter.mqttClient && !adapter.mqttClient.connected) {\n return;\n }\n if (adapter.openapiMqttClient && !adapter.openapiMqttClient.connected) {\n return;\n }\n if (adapter.deviceManager?.hasDeviceNeedingAppApi() && !adapter.appApiInitialPollDone) {\n return;\n }\n adapter.readyLogged = true;\n logDeviceSummary(adapter);\n // Persist any learned changes from the initial load (e.g. resolveSegmentCount\n // collapsing Cloud's 15 to the real 10 on H70D1). One-shot on first ready;\n // subsequent mutations persist themselves (MQTT bumps, wizard, manual-mode).\n adapter.deviceManager?.saveDevicesToCache();\n}\n\n/**\n * Log final ready message with device/group/channel summary.\n *\n */\nexport function logDeviceSummary(adapter: ConnectionStateAdapter): void {\n
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { DeviceManager } from \"../device-manager\";\nimport type { GoveeCloudClient } from \"../govee-cloud-client\";\nimport type { GoveeMqttClient } from \"../govee-mqtt-client\";\nimport type { GoveeOpenapiMqttClient } from \"../govee-openapi-mqtt-client\";\nimport { httpsRequest } from \"../http-client\";\nimport { errMessage } from \"../types\";\nimport { GOVEE_APP_VERSION } from \"../govee-constants\";\n\n/**\n * Adapter surface required by the connection-state helpers \u2014 covers the\n * info.connection bookkeeping plus ready-summary + app-version drift\n * monitoring + stale-device reaping.\n */\nexport interface ConnectionStateAdapter {\n readonly log: ioBroker.Logger;\n readonly deviceManager: DeviceManager | null;\n readonly cloudClient: GoveeCloudClient | null;\n readonly cloudWasConnected: boolean;\n readonly diagnosticsLastRun: Map<string, number>;\n readonly mqttClient: GoveeMqttClient | null;\n readonly openapiMqttClient: GoveeOpenapiMqttClient | null;\n readonly lanClient: unknown;\n readonly stateManager: { cleanupDevices(devices: unknown[]): Promise<unknown> } | null;\n readonly lanScanDone: boolean;\n readonly statesReady: boolean;\n readonly cloudInitDone: boolean;\n readonly appApiInitialPollDone: boolean;\n readyLogged: boolean;\n lastConnectionState: boolean | null;\n setStateAsync(id: string, state: ioBroker.SettableState | ioBroker.StateValue): Promise<unknown>;\n}\n\n/**\n * Update global `info.connection` \u2014 the ioBroker-IDC indicator.\n *\n * Semantik:\n * - Mit Devices: `connected = true` wenn MIND. ein Device online ist.\n * Wenn alle offline \u2192 false (User sieht: kein Device antwortet).\n * - Ohne Devices: `connected = true` wenn der LAN-Stack l\u00E4uft. Sonst\n * false (z.B. EADDRINUSE oder bind-Fehler).\n *\n * Write-only-on-change cache (lastConnectionState) so we don't spam\n * setStateAsync on every device-state-update.\n *\n */\nexport function updateConnectionState(adapter: ConnectionStateAdapter): void {\n const devices = adapter.deviceManager?.getDevices() ?? [];\n const hasDevices = devices.length > 0;\n const anyOnline = devices.some(d => d.state.online);\n const lanRunning = adapter.lanClient !== null;\n const connected = hasDevices ? anyOnline : lanRunning;\n if (connected !== adapter.lastConnectionState) {\n adapter.lastConnectionState = connected;\n adapter.setStateAsync(\"info.connection\", { val: connected, ack: true }).catch(() => {});\n }\n}\n\n/**\n * Daily app-version-drift check vs. the iTunes app-store lookup.\n *\n * Govee's app2.govee.com endpoints reject very stale User-Agent strings.\n * Compares live iOS app version with local `GOVEE_APP_VERSION`. On drift\n * > 2 minor: warn-Log + state `info.appVersionDrift`. Failures (5xx,\n * network) are silent debug-logged \u2014 no user impact.\n *\n */\nexport async function checkAppVersionDrift(adapter: ConnectionStateAdapter): Promise<void> {\n try {\n const resp = await httpsRequest<{ resultCount?: number; results?: Array<{ version?: string }> }>({\n method: \"GET\",\n url: \"https://itunes.apple.com/lookup?bundleId=com.ihoment.GoVeeSensor\",\n headers: { \"User-Agent\": \"ioBroker.govee-smart\" },\n timeout: 10_000,\n });\n const liveVersion = resp.results?.[0]?.version;\n if (typeof liveVersion !== \"string\" || liveVersion.length === 0) {\n return;\n }\n const localParts = GOVEE_APP_VERSION.split(\".\").map(Number);\n const liveParts = liveVersion.split(\".\").map(Number);\n const localMajor = localParts[0] ?? 0;\n const localMinor = localParts[1] ?? 0;\n const liveMajor = liveParts[0] ?? 0;\n const liveMinor = liveParts[1] ?? 0;\n const liveTotal = liveMajor * 100 + liveMinor;\n const localTotal = localMajor * 100 + localMinor;\n const driftMinor = liveTotal - localTotal;\n const driftMessage =\n driftMinor === 0\n ? `current (live=${liveVersion}, local=${GOVEE_APP_VERSION})`\n : driftMinor <= 2\n ? `minor drift (live=${liveVersion}, local=${GOVEE_APP_VERSION})`\n : `STALE (live=${liveVersion}, local=${GOVEE_APP_VERSION}) \u2014 bump GOVEE_APP_VERSION`;\n await adapter.setStateAsync(\"info.appVersionDrift\", { val: driftMessage, ack: true }).catch(() => undefined);\n if (driftMinor > 2) {\n adapter.log.warn(\n `Govee app version drift: live ${liveVersion} vs local ${GOVEE_APP_VERSION} \u2014 undocumented endpoints may start failing. Run sync-govee-app-version.py + release a new adapter version.`,\n );\n } else {\n adapter.log.debug(`App version: ${driftMessage}`);\n }\n } catch (e) {\n adapter.log.debug(`App version check failed: ${errMessage(e)}`);\n }\n}\n\n/**\n * Delete ioBroker objects for devices no longer present and drop the same\n * devices from adapter-level maps. Diagnostics-buffer + diagnosticsLastRun\n * are reaped so removed-device data doesn't leak into the next adapter\n * lifetime.\n *\n */\nexport async function reapStaleDevices(adapter: ConnectionStateAdapter): Promise<void> {\n if (!adapter.stateManager || !adapter.deviceManager) {\n return;\n }\n const currentDevices = adapter.deviceManager.getDevices();\n await adapter.stateManager.cleanupDevices(currentDevices);\n\n const liveDeviceIds = new Set(currentDevices.map(d => d.deviceId));\n adapter.deviceManager.getDiagnostics().pruneOrphans(liveDeviceIds);\n\n const liveKeys = new Set(currentDevices.map(d => `${d.sku}:${d.deviceId}`));\n for (const key of adapter.diagnosticsLastRun.keys()) {\n if (!liveKeys.has(key)) {\n adapter.diagnosticsLastRun.delete(key);\n }\n }\n}\n\n/**\n * Check if all configured channels are initialized and log ready message.\n * Called from MQTT onConnection callback and end of onReady.\n *\n */\nexport function checkAllReady(adapter: ConnectionStateAdapter): void {\n if (adapter.readyLogged) {\n return;\n }\n if (!adapter.lanScanDone) {\n return;\n }\n if (!adapter.statesReady) {\n return;\n }\n if (adapter.cloudClient && !adapter.cloudInitDone) {\n return;\n }\n if (adapter.mqttClient && !adapter.mqttClient.connected) {\n return;\n }\n if (adapter.openapiMqttClient && !adapter.openapiMqttClient.connected) {\n return;\n }\n if (adapter.deviceManager?.hasDeviceNeedingAppApi() && !adapter.appApiInitialPollDone) {\n return;\n }\n adapter.readyLogged = true;\n logDeviceSummary(adapter);\n // Persist any learned changes from the initial load (e.g. resolveSegmentCount\n // collapsing Cloud's 15 to the real 10 on H70D1). One-shot on first ready;\n // subsequent mutations persist themselves (MQTT bumps, wizard, manual-mode).\n adapter.deviceManager?.saveDevicesToCache();\n}\n\n/**\n * Log final ready message with device/group/channel summary.\n *\n */\nexport function logDeviceSummary(adapter: ConnectionStateAdapter): void {\n // Device/sensor/group counts are intentionally not logged here: at\n // ready-time the LAN scan and MQTT push are still settling, so an\n // \"X online, Y offline\" summary often shows lights as offline that\n // come up moments later. The user-visible online state lives in the\n // state tree where it stays accurate.\n const channels: string[] = [\"LAN\"];\n if (adapter.cloudWasConnected) {\n channels.push(\"Cloud\");\n }\n if (adapter.mqttClient?.connected) {\n channels.push(\"MQTT\");\n }\n if (adapter.openapiMqttClient?.connected) {\n channels.push(\"Cloud-events\");\n }\n adapter.log.info(`Govee adapter ready \u2014 channels: ${channels.join(\"+\")}`);\n\n if (adapter.cloudClient && !adapter.cloudWasConnected) {\n const reason = adapter.cloudClient.getFailureReason();\n adapter.log.warn(reason ? `Cloud not connected \u2014 ${reason}` : `Cloud not connected \u2014 see earlier errors`);\n }\n if (adapter.mqttClient && !adapter.mqttClient.connected) {\n const reason = adapter.mqttClient.getFailureReason();\n adapter.log.warn(reason ? `MQTT not connected \u2014 ${reason}` : `MQTT not connected \u2014 see earlier errors`);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "govee-smart",
|
|
4
|
-
"version": "2.6.
|
|
4
|
+
"version": "2.6.7",
|
|
5
5
|
"news": {
|
|
6
|
+
"2.6.7": {
|
|
7
|
+
"en": "Cleaner ready-log: removed the device/sensor/group online-summary because it ran before the LAN scan had settled and could falsely show all lights as offline.",
|
|
8
|
+
"de": "Aufgeräumter Ready-Log: Die Geräte-/Sensor-/Gruppen-Online-Zusammenfassung ist raus — sie lief bevor der LAN-Scan fertig war und konnte fälschlich alle Lichter als offline anzeigen.",
|
|
9
|
+
"ru": "Чище лог готовности: убрана сводка устройств/сенсоров/групп онлайн — она запускалась до завершения LAN-сканирования и могла ошибочно показывать все лампы как offline.",
|
|
10
|
+
"pt": "Log de pronto mais limpo: removido o resumo de dispositivos/sensores/grupos online — corria antes do scan LAN terminar e podia mostrar incorretamente todas as lâmpadas como offline.",
|
|
11
|
+
"nl": "Schonere ready-log: de samenvatting van apparaten/sensoren/groepen-online is weg — ze liep voordat de LAN-scan klaar was en kon ten onrechte alle lampen als offline tonen.",
|
|
12
|
+
"fr": "Log de prêt plus propre : le récapitulatif appareils/capteurs/groupes en ligne est retiré — il s'exécutait avant la fin du scan LAN et pouvait afficher à tort toutes les lampes comme hors ligne.",
|
|
13
|
+
"it": "Ready-log più pulito: rimosso il riepilogo dispositivi/sensori/gruppi online — partiva prima della fine dello scan LAN e poteva indicare erroneamente tutte le luci offline.",
|
|
14
|
+
"es": "Log de listo más limpio: eliminado el resumen de dispositivos/sensores/grupos en línea — se ejecutaba antes de que terminara el escaneo LAN y podía mostrar erróneamente todas las luces como offline.",
|
|
15
|
+
"pl": "Czystszy log gotowości: usunięto podsumowanie urządzeń/czujników/grup online — działało przed zakończeniem skanu LAN i mogło błędnie pokazywać wszystkie lampy jako offline.",
|
|
16
|
+
"uk": "Чистіший ready-лог: прибрано зведення пристрої/сенсори/групи онлайн — воно виконувалося до завершення LAN-сканування і могло помилково показувати всі лампи як offline.",
|
|
17
|
+
"zh-cn": "更干净的就绪日志:移除了设备/传感器/分组在线摘要——它在 LAN 扫描完成前就运行,可能错误地把所有灯显示为离线。"
|
|
18
|
+
},
|
|
6
19
|
"2.6.6": {
|
|
7
20
|
"en": "Internal refactoring (main.ts on plan target ~800 LOC, 11 handler modules in lib/handlers/). No changes for users.",
|
|
8
21
|
"de": "Internes Refactoring (main.ts auf Plan-Ziel ~800 LOC, 11 Handler-Module in lib/handlers/). Keine Änderungen für Benutzer.",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "Dokumentacja: wpisy changelog (v2.5.x–v2.6.0) przywrócone na angielski — kilka punktów pozostało po niemiecku. Bez zmian w kodzie.",
|
|
81
94
|
"uk": "Документація: записи changelog (v2.5.x–v2.6.0) відновлено англійською — деякі пункти лишалися німецькою. Без змін у коді.",
|
|
82
95
|
"zh-cn": "文档:将 v2.5.x–v2.6.0 的 changelog 条目恢复为英文 — 之前部分条目残留为德文。无代码更改。"
|
|
83
|
-
},
|
|
84
|
-
"2.6.0": {
|
|
85
|
-
"en": "Multi-language: info/warn/error logs and state names/descriptions are now in your ioBroker system language (11 languages). Debug logs and stack traces stay English.",
|
|
86
|
-
"de": "Mehrsprachig: info/warn/error-Logs sowie Datenpunkt-Namen und -Beschreibungen sind jetzt in der ioBroker-Systemsprache (11 Sprachen). Debug-Logs und Stack-Traces bleiben englisch.",
|
|
87
|
-
"ru": "Многоязычность: info/warn/error-логи и имена/описания состояний теперь на языке системы ioBroker (11 языков). Debug и stack-trace остаются английскими.",
|
|
88
|
-
"pt": "Multilíngua: logs info/warn/error e nomes/descrições de estados agora no idioma do sistema ioBroker (11 idiomas). Debug e stack-traces ficam em inglês.",
|
|
89
|
-
"nl": "Meertalig: info/warn/error-logs en statusnamen/-beschrijvingen nu in de ioBroker-systeemtaal (11 talen). Debug en stacktraces blijven Engels.",
|
|
90
|
-
"fr": "Multilingue : logs info/warn/error et noms/descriptions d'états désormais dans la langue système ioBroker (11 langues). Debug et stack-traces restent en anglais.",
|
|
91
|
-
"it": "Multilingua: log info/warn/error e nomi/descrizioni degli stati ora nella lingua di sistema ioBroker (11 lingue). Debug e stack-trace restano in inglese.",
|
|
92
|
-
"es": "Multilenguaje: logs info/warn/error y nombres/descripciones de estados ahora en el idioma del sistema ioBroker (11 idiomas). Debug y stack-traces permanecen en inglés.",
|
|
93
|
-
"pl": "Wielojęzyczność: logi info/warn/error oraz nazwy/opisy stanów teraz w języku systemu ioBroker (11 języków). Debug i stack-trace pozostają po angielsku.",
|
|
94
|
-
"uk": "Багатомовність: info/warn/error-логи та імена/описи станів тепер мовою системи ioBroker (11 мов). Debug та stack-traces лишаються англійськими.",
|
|
95
|
-
"zh-cn": "多语言:info/warn/error 日志以及状态名称/描述现在使用 ioBroker 系统语言(11 种)。Debug 日志与堆栈跟踪保持英文。"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|