Различия
Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
| sw:openhab:examples:heating:3pa [2023/12/26 17:45] – lazygatto | sw:openhab:examples:heating:3pa [2023/12/26 18:07] (текущий) – lazygatto | ||
|---|---|---|---|
| Строка 5: | Строка 5: | ||
| Управлением открытия/ | Управлением открытия/ | ||
| - | 1. Установлен Add-on [[https:// | + | 1. Установлен Add-on [[https:// |
| Код правила для расчета PID: | Код правила для расчета PID: | ||
| Строка 45: | Строка 45: | ||
| </ | </ | ||
| + | |||
| + | Поскольку котел у меня 1-контурный, | ||
| 2. Следующее правило запускается по cron каждые 3 минуты, | 2. Следующее правило запускается по cron каждые 3 минуты, | ||
| + | |||
| + | Код правила управления 3-х ходовым клапаном: | ||
| + | <sxh> | ||
| + | configuration: | ||
| + | triggers: | ||
| + | - id: " | ||
| + | configuration: | ||
| + | cronExpression: | ||
| + | type: timer.GenericCronTrigger | ||
| + | conditions: [] | ||
| + | actions: | ||
| + | - inputs: {} | ||
| + | id: " | ||
| + | configuration: | ||
| + | type: application/ | ||
| + | script: >- | ||
| + | /* | ||
| + | |||
| + | |||
| + | Items to control 3p Actuator | ||
| + | |||
| + | three_way_close - close relay | ||
| + | |||
| + | three_way_open - open relay | ||
| + | |||
| + | |||
| + | */ | ||
| + | |||
| + | |||
| + | function rotateActuator (pidValue) { | ||
| + | | ||
| + | var actionTimerCorrection = 2 // Maybe 1 to any reasonable value, decreasing rotation time | ||
| + | var actionTimerMax = 15000 // milliseconds, | ||
| + | var actionTimerMin = 1000 // milliseconds, | ||
| + | | ||
| + | console.log(' | ||
| + | | ||
| + | var actionItem3pActuator = null | ||
| + | var action = null | ||
| + | var actionTimer = 0 | ||
| + | | ||
| + | action = (pidValue > 0) ? ' | ||
| + | | ||
| + | action3pActuator = items.getItem(' | ||
| + | actionTimer = Math.round( Math.abs( pidValue ) / actionTimerCorrection ) * 500 | ||
| + | |||
| + | // Limit to actionTimerMax if it more | ||
| + | actionTimer = (actionTimer > actionTimerMax) ? actionTimerMax : actionTimer; | ||
| + | | ||
| + | if (actionTimer >= actionTimerMin) | ||
| + | { | ||
| + | console.log (' | ||
| + | | ||
| + | console.info(action3pActuator.name + ' send command ON') | ||
| + | action3pActuator.sendCommand(' | ||
| + | | ||
| + | setTimeout(() => { | ||
| + | console.info(action3pActuator.name + ' send command OFF') | ||
| + | action3pActuator.sendCommand(' | ||
| + | }, actionTimer); | ||
| + | | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | console.info(' | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | rotateActuator(items.tp_pid.state) | ||
| + | type: script.ScriptAction | ||
| + | |||
| + | </ | ||
| + | |||
| + | Знать текущее положение клапана, | ||
| + | Но интересно же! :) | ||
| + | |||
| + | Поэтому попробовал реализовать и такую вещь, как отображение текущего уровня открытия 3-х ходового клапана. | ||
| + | |||
| + | Логика следующая. Есть отдельный Item ('' | ||
| + | И отдельное правило, | ||
| + | |||
| + | Экспериментальным путем было установлено, | ||
| + | |||
| + | Код правила для обновления статуса клапана: | ||
| + | <sxh> | ||
| + | configuration: | ||
| + | triggers: | ||
| + | - id: " | ||
| + | configuration: | ||
| + | itemName: three_way_close | ||
| + | type: core.ItemStateChangeTrigger | ||
| + | - id: " | ||
| + | configuration: | ||
| + | itemName: three_way_open | ||
| + | type: core.ItemStateChangeTrigger | ||
| + | conditions: [] | ||
| + | actions: | ||
| + | - inputs: {} | ||
| + | id: " | ||
| + | configuration: | ||
| + | type: application/ | ||
| + | script: >- | ||
| + | | ||
| + | var maxRotationTime = 127000 | ||
| + | |||
| + | |||
| + | var current3pAState = items.tp_3pA_status.state | ||
| + | |||
| + | var new3pAState = null | ||
| + | |||
| + | |||
| + | var cacheId = ' | ||
| + | |||
| + | var processDuration = 0 | ||
| + | |||
| + | |||
| + | var stor = cache.private.get(cacheId, | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | })); | ||
| + | |||
| + | |||
| + | function resetStorage(stor) { | ||
| + | stor.openStarts = null; | ||
| + | stor.closeStarts = null; | ||
| + | cache.private.put(stor.cacheId, | ||
| + | } | ||
| + | |||
| + | |||
| + | function startMoving(stor, | ||
| + | stor[direction + ' | ||
| + | cache.private.put(stor.cacheId, | ||
| + | console.log(' | ||
| + | } | ||
| + | |||
| + | |||
| + | function stopMoving(stor, | ||
| + | | ||
| + | processDuration = Date.now() - stor[direction + ' | ||
| + | | ||
| + | console.log(' | ||
| + | |||
| + | rotationPercent = processDuration / maxRotationTime; | ||
| + | console.log(' | ||
| + | |||
| + | new3pAState = Number.parseFloat(current3pAState) + ((direction == ' | ||
| + | | ||
| + | console.log(' | ||
| + | |||
| + | items.tp_3pA_status.postUpdate(new3pAState) | ||
| + | resetStorage(stor) | ||
| + | } | ||
| + | |||
| + | |||
| + | var direction = null | ||
| + | |||
| + | |||
| + | switch(event.itemName) { | ||
| + | case ' | ||
| + | direction = ' | ||
| + | if (event.itemState.toString() == ' | ||
| + | startMoving(stor, | ||
| + | } else { | ||
| + | stopMoving(stor, | ||
| + | } | ||
| + | break | ||
| + | |||
| + | case ' | ||
| + | direction = ' | ||
| + | if (event.itemState.toString() == ' | ||
| + | startMoving(stor, | ||
| + | } else { | ||
| + | stopMoving(stor, | ||
| + | } | ||
| + | break | ||
| + | |||
| + | default: | ||
| + | console.error(' | ||
| + | break | ||
| + | } | ||
| + | type: script.ScriptAction | ||
| + | |||
| + | </ | ||
| + | |||
| + | 4. Ну и в завершение есть еще небольшое правило, | ||
| <sxh> | <sxh> | ||