danfoss-ally cloud

Подключает ioBroker к облаку Danfoss Ally.

Текущий релиз
0.2.20
Разработчик
Stefan Koch
Лицензия
MIT

Облачный адаптер для Danfoss Ally™ — с использованием OAuth2 (учетные данные клиента). Считывает данные о температуре, влажности, положении клапана и состоянии батареи для всех устройств в вашей учетной записи Ally и позволяет выполнять целевые разовые записи без принудительного изменения режима или цепочек операций.


Функции

  • Прямое подключение к API Danfoss Ally Cloud
  • Автоматическое обновление токена OAuth2**
  • Обнаруживает все зарегистрированные устройства
  • Считывает все доступные данные с датчиков и элементов управления (температура, влажность, заряд батареи, положение клапана и т. д.).
  • Преобразует исходные значения Danfoss (×0,1) в реальные единицы (°C, %)
  • Полностью автоматический опрос с настраиваемым интервалом.
  • Поддерживает отдельные изолированные команды записи из ioBroker в облако.

Основные моменты

  • Одиночная запись — каждое состояние передается независимо (автоматическое переключение режимов отсутствует)
  • Smooth Sync Logic
  • Антирасовая позиция (5 с): пропустить один опрос сразу после локального внесения предложений.
  • Удержание окна (1 мин): защита последних локальных значений от перезаписи.
  • Подавление задержек (15 с): игнорировать временно устаревшие данные облака
  • Мягкое обновление (~1,5 с): повторная выборка только затронутых состояний после каждой записи.
  • Тихое логирование — информационный уровень для корректной работы, отладочный уровень для диагностики.
  • Автоматическое масштабирование — температура/влажность автоматически преобразуются в °C / %

Примечание: Обновления облачных сервисов из приложения Danfoss Ally могут отображаться в ioBroker с небольшой задержкой (1–2 минуты).


Поддерживаемые устройства

  • Термостаты радиатора Danfoss Ally™ TRV
  • Danfoss Icon2 RT (комнатные термостаты)
  • Контроллер Danfoss Icon2 Реле котла Danfoss Ally™
  • Danfoss Ally™ Gateway

(Другие устройства Danfoss обнаружены автоматически)


Конфигурация

Перейдите в Экземпляры → danfoss-ally → Настройки

ПолеОписание
Ключ/секрет APIВаши учетные данные для приложения разработчика Danfoss
URL токенаКонечная точка токена OAuth2 (например, https://api.danfoss.com/oauth2/token)
Область действияДополнительная область действия OAuth2 (например, read write)
Интервал опросаПо умолчанию 300s
Интервал опросаПо умолчанию 300 с

Более короткие интервалы обновления происходят быстрее, но создают больший трафик к API. Оптимальный баланс — 30–60 секунд.

API Key:      your-client-id
API Secret:   your-client-secret
Token URL:    https://api.danfoss.com/oauth2/token
API Base URL: https://api.danfoss.com/ally
Polling:      300

Штаты

Каждое обнаруженное устройство создает дерево устройств: danfoss-ally.0.<device_id>.*

Состояние статуса против состояния контроля

Адаптер разделяет значения состояния, доступные только для чтения, от значений управления, доступных для записи.

Канал статуса

danfoss-ally.0.<deviceId>.status.*

Эти состояния отражают значения, полученные из API Danfoss Cloud.

Характеристики:

  • читать: правда
  • write: false

Не следует записывать данные в эти состояния из скриптов.

Примеры:

  • status.temp_current
  • status.temp_set
  • status.mode
  • status.humidity_value
  • status.battery_percentage

Канал управления

danfoss-ally.0.<deviceId>.control.*

Эти состояния предназначены для взаимодействия с пользователем и могут быть созданы с помощью скриптов или Blockly.

Характеристики:

  • читать: правда
  • write: true

Примеры:

  • control.temp_set
  • control.manual_mode_fast
  • control.mode
  • control.child_lock

Адаптер автоматически отправляет команды в облако Danfoss и обновляет соответствующие значения состояния.

Примеры чтения

ШтатОписаниеЕдиница измерения
status.temp_currentТекущая температура°C
status.battery_percentageУровень заряда батареи%
status.modeТекущий режим (auto, manual, at_home, …)
status.work_state, status.output_status, status.faultСтатус или ошибка
status.upper_temp / status.lower_tempТемпературные пределы°C
status.upper_temp / status.lower_tempТемпературные пределы°C

Все числовые значения масштабируются автоматически в диапазоне от ×0,1 до °C/% .


Письмо

Адаптер поддерживает целевую запись в каждое управляемое состояние без автоматического переключения режимов. Это дает вам полный контроль в Blockly, JavaScript или в пользовательских логических скриптах.

Доступное для записи состояниеОжидаемое значение / поведение
control.temp_setЦелевая температура (°C, шаг 0,5; отправлено ×10)
control.at_home_setting, control.leaving_home_setting, control.pause_setting, control.holiday_settingЗаданные температуры
control.modemanual, at_home, leaving_home, pause, holiday, auto
control.child_locktrue / false
control.SetpointChangeSourceExternally или schedule
control.SetpointChangeSourceExternally или schedule

Адаптер не переключает режимы автоматически при записи заданных значений — вы сами определяете это в соответствии со своей логикой.


Пример (Blockly / Script)

// Manual mode
setState("danfoss-ally.0.<id>.control.mode", "manual");
setState("danfoss-ally.0.<id>.control.temp_set", 21.5);

// At home
setState("danfoss-ally.0.<id>.control.mode", "at_home");
setState("danfoss-ally.0.<id>.control.at_home_setting", 21.0);

// Leaving home
setState("danfoss-ally.0.<id>.control.mode", "leaving_home");
setState("danfoss-ally.0.<id>.control.leaving_home_setting", 19.0);

// Pause
setState("danfoss-ally.0.<id>.control.mode", "pause");
setState("danfoss-ally.0.<id>.control.pause_setting", 5.0);

// Holiday
setState("danfoss-ally.0.<id>.control.mode", "holiday");
setState("danfoss-ally.0.<id>.control.holiday_setting", 10.0);

// Child lock
setState("danfoss-ally.0.<id>.control.child_lock", true);

// Explicit source (usually not needed)
setState("danfoss-ally.0.<id>.control.SetpointChangeSource", "Externally"); // or 'schedule'

Команды записи должны быть нацелены на состояния control.*.

Состояния status.* представляют собой зеркала только для чтения из облака Danfoss.


Логика синхронизации

МеханизмПродолжительностьЦель
АнтирасистскийПропустить один опрос после написания местного текста
Удерживайте1 минПредотвратить перезапись локальных данных в облаке
Подавление задержек15 сИгнорировать устаревшие облачные данные
Мягкое обновление~1,5 сПовторная загрузка только затронутых состояний

Эти механизмы обеспечивают плавную синхронизацию между ioBroker и облаком Danfoss без мерцания или зацикливания значений.


Ведение журнала

Адаптер предоставляет подробную информацию на уровне отладки для диагностики, но при нормальной работе остается бесшумным.

  • Обновления с параметром ack=true игнорируются без уведомления.
  • HOLD, MATCH, SUPPRESS → отладочная, безвредная диагностика — После первоначального запуска инвентаризации в журналах отладки отображаются только изменения реальных значений.
  • Ошибки API (HTTP 400/401) автоматически повторяются (регистрируются в режиме отладки)
  • После каждого опроса очищается сводка уровня отладки:

Пример сводки результатов опроса

CHANGES bf0a...: temp_set: 25 -> 30, manual_mode_fast: 25 -> 30
Updated 13 devices. Mode=poll, Changed=2, Skipped=253, Held=0, AckFixed=0
Skipping poll (anti-race pause 5000ms)

Пример вывода в лог

🔄 Starting Danfoss Ally adapter...
🔑 Refreshing OAuth2 token...
✅ Token acquired. Expires in ~3599 s
📡 Found 13 devices, updating states...
✅ Updated 13 devices from Danfoss Ally Cloud.
⏱ Polling interval set to 300 s

Обработка токенов

  • Использует поток передачи учетных данных клиента OAuth2
  • Автоматический запрос токена при запуске, обновление перед истечением срока действия.
  • При ошибке 401 Unauthorized: обновите страницу и повторите попытку.
  • Токены хранятся в памяти, никогда не сохраняются.
  • Поддерживается необязательная область действия (scope) / аудитория (audience). — Все события, связанные с токенами, отображаются в журнале отладки.

Конечные точки API

Адаптер взаимодействует с API Danfoss Ally Cloud (базовый URL-адрес настраивается).

МетодКонечная точкаЦель
POST/oauth2/tokenЗапрос токена доступа
GET/devices/{id}/statusЧтение телеметрии устройства
GET/devices/{id}Резервный вариант для отсутствующего статуса
POST/devices/{id}/commandsОтправить команду на однократную запись
POST/devices/{id}/commandsОтправить одну команду записи

Заголовки: Authorization: Bearer <token> Content-Type: application/json Необязательно: X-App-Key, X-Tenant-Id и т. д.

Обработка ошибок:

  • 400: недопустимый заголовок/значение → записано в лог
  • 401: обновление токена + повторная попытка
  • 5xx: повторная попытка следующего опроса
  • Температура записывается с автоматическим масштабированием в 10 раз (например, 21,5 → 215).

Опрос

  • По умолчанию: 300 с (можно настроить)
  • Обновления затрагивали только измененные значения.
  • Включает в себя всю описанную выше логику предотвращения гонок/удержаний/задержек/мягкого обновления. — Сводная информация после каждого опроса показывает измененные, пропущенные и сохраненные штаты.

Пишет

  • temp_set сначала пытается выполнить комбинированную команду SetpointChangeSource + temp_set.
  • Термостаты Ally TRV также получают значение manual_mode_fast, если такая точка данных существует, поскольку некоторые устройства сообщают о заданном вручную значении.
  • Опрос обновляет только status.*; control.* остается каналом чистой записи, чтобы избежать циклов обратной связи.
  • Режим + температура должны быть указаны отдельно.
  • Значения ограничены допустимыми пределами и масштабированы в 10 раз.
  • child_lock: пытается 0/1, повторяет попытку true/false при ошибке 400
  • SetpointChangeSource: необязательный параметр; temp_set пытается использовать "Externally" для TRV союзников. — Если облако впоследствии снова сообщит о старой заданной точке, адаптер запишет предупреждение вместо того, чтобы молча принять её.

Все записи об отправке, повторной попытке и подтверждении отображаются в режиме отладки.


Разработка

npm i
node main.js

или установить с помощью инструментов разработки ioBroker.


Changelog

0.2.20

  • Reduced debug log noise after startup: repeated polls now log only real value changes
  • Removed repeated per-device debug inventory lines after the first poll
  • Avoided object-valued status writes from fallback responses
  • Added Boiler Relay fallback objects when the Danfoss API lists the relay but returns no status entries
  • Resolved ioBroker repository checker warnings for Prettier config, ESLint devDependency, translated news entries, workflow concurrency, and tracked ignored tool files
  • Updated GitHub Actions workflow dependencies from the open Dependabot PRs

0.2.19

  • Stopped polling from writing cloud values back into control.* states to avoid feedback loops with Loxone/scripts
  • Added state.from to debug write logs so external write sources can be identified
  • Added direct status fallback for devices that are listed without status values, improving Boiler Relay datapoints
  • Reduced poll debug noise: the initial run still logs all SET lines, later polls summarize changed values per device

0.2.18

  • Improved Ally TRV setpoint writes by additionally sending manual_mode_fast when available
  • Added explicit warnings when the Danfoss Cloud does not confirm the requested setpoint
  • Improved device naming/detection for relay-like devices so the Boiler Relay is easier to identify

0.2.17

  • Improved Ally TRV temp_set writes by trying SetpointChangeSource=Externally and temp_set as one combined command first
  • Falls back to temp_set only if Danfoss rejects the combined command
  • Fixed control.switch subscriptions for Icon2 / Boiler Relay writes
  • Added alias handling for Occupied_Setpoint
  • Fixed jsonConfig header validation warning

0.2.16

  • Fixed temp_set for Ally TRVs (SetpointChangeSource=Externally auto-sent)
  • Fixed wrong path for lower_temp/upper_temp clamp
  • Fixed OccupiedSetpoint scaling (÷100 instead of ÷10)
  • Added type hints for 16 new data points (MeasuredValue, pi_heating_demand, window_state, etc.)
  • Icon2 switch state is now writable
  • Fixed jsonConfig admin validation warning (missing size property)
  • Added Boiler Relay to supported devices

License

MIT License

Copyright (c) 2025-2026 Author Stefan8485@me.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.