Начал я плавно переводить громоздкие автоматизации из Home Assistant в NodeRED, и хочу поделиться своим вариантом решения управления увлажнителем. Задача на первый взгляд простая (включи да выключи), но со временем к ней добавилось довольно много дополнительных условий, поэтому статья ¯\_(ツ)_/¯
Примечание
Я занимаюсь автоматизацией умного дома для других людей не первый год, и данный сценарий работы является сборником моих собственных пожеланий, а так же пожеланий и запросов наших клиентов.
Задача
У меня трудится Smartmi Evaporative Humidifier 2, он выбран как один из лучших на основе анализа чужих обзоров и личного тестирования разных моделей разных производителей, но флоу подходит к любому многоскоростному увлажнителю с управлением из УД. Даже с односкоростным увлажнителем, при некотором изменении флоу, будет полезно. Итак, список требований, которые есть конкретно к работе увлажнителя:
- Он не должен часто включаться и выключаться. Это раздражает слух
- Он не должен запускаться, если недавно кондиционер работал в режиме осушения. Все таки в умном доме не должно идти соревнований между отоплением и охлаждением и т.д.
- Он должен работать только если кто-то есть дома. Если дома никого нет, он включается лишь в экстренных случаях (влажность ниже 30%)
- Надо не забыть про экран- мне ни к чему еще один ночник
- Экономия ресурсов (опишу позже)
Далее, я хочу иметь дополнительные флаги, которые у меня управляют всеми климатическими автоматизациями
- Климат-контроль (если выключен, климатическая техника самостоятельно не думает)
- Гостевой режим (если включен, то даже при уходе из дома всех известных ему жильцов, все автоматизации работают так, будто дома кто-то есть)
- Желаемая влажность (параметр, отвечающий за работу и вытяжек, и осушения, и увлажнения. При его изменении, реакция должна быть моментальной. Я не хочу ждать смены режима, включения или выключения устройства по 5 минут при изменении желаемой влажности)
- Понижать скорость на ночь (не всегда ночью хочется слушать шум от приточки или увлажнителя на полную. При активации этого переключателя, максимальная скорость работы устройств становится ниже независимо от показателей текущей температуры/ влажности)
- Задержка выключения. Вся климатическая техника выключается, если дома нет хозяев, но можно задать и задержку. Допустим, только если дома никого нет 1-2-3 часа, она выключается. Ибо если ты ушел из дома ненадолго, а вернулся в остывшую и сухую квартиру- не круто
Решение
Из этих условий и родился данный флоу, который запускается каждые 5 минут, либо без ограничений по времени при изменении любого из параметров, требующих моментальной реакции.
Проверяем влажность (в моем случае это усредненная по всем датчикам влажности в квартире кроме ванной, но если увлажнителей у вас несколько, то усредненная по той зоне, для которой увлажнитель предназначен), гостевой режим, есть-ли кто-то дома (и прошло ли указанное для отключения время если нет) и давно ли работало осушение.
Спасибо Home Assistant за то, что до сих пор не способен сохранять время последнего состояния при перезагрузке (оно выставляется на время запуска HA), поэтому дальше мы проверяем, что Home Assistant был запущен больше чем 2 часа назад, и только если это правда, можем проверять, что осушение не работало 2 часа. В противном случае в течение первых 2х часов после запуска HA увлажнитель бы не включался. В данном случае получается, что в случае ошибок в логике, увлажнитель и осушитель могут посоревноваться, но только первые 2 часа после запуска.
Дальше просто несколько разных уровней влажности, ведущих к разным режимам работы увлажнителя, в зависимости от того, надо нам понижать скорость на ночь или нет.
Так же, днем посылается команда на включение экрана, а ночью на выключение. Можно было бы посылать ее и один раз, а не каждые 5 минут, но я не доверяю wi-fi устройствам, поэтому лишний раз никому не помешает.
При решении такой же задачи с увлажнителем, имеющим всего одну скорость, я бы просто сильнее уменьшил значения влажности для ночного режима, которые ведут к его включению.
Усредненная влажность
Я так же использую переключатель для вариативности усредненной температуры и влажности. Она может как быть 24 часа в сутки средним между всеми комнатами (кроме ванной, естественно), так и быть средней только по датчикам спален. Таким образом, по желанию, можно на ночь автоматически переходить на поддержание нужного климата только в спальнях. Зачем остальное, если ночью вы спите?
Ниже код этого датчика
#Средняя температура для термостата
#Днем равна средней температуре, ночью равна ей же, если helper "Ночью только спальни" выключен, и средней только по спальням, если включен
- platform: template
sensors:
average_temperature_for_thermostat:
friendly_name: Средняя температура для термостата
unique_id: average_temperature_for_thermostat
unit_of_measurement: '°C'
value_template: >-
{% if now().hour > 6 and now().hour < 23 %}
{{ states.sensor.average_temperature.state }}
{% elif is_state('input_boolean.night_only_bedrooms', 'on') %}
{{ states.sensor.average_temperature_bedrooms.state }}
{% else %}
{{ states.sensor.average_temperature.state }}
{% endif %}
Код для импорта (не забываем изменить сервер на свой)
[{"id":"68ec22673149800e","type":"tab","label":"Увлажнитель Xiaomi","disabled":false,"info":"","env":[]},{"id":"91824bf3c61443c3","type":"server-state-changed","z":"68ec22673149800e","name":"Влажность","server":"5e62137c.2011cc","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":"Увлажнитель NodeRED"},{"property":"icon","value":"mdi:air-humidifier"}],"entityidfilter":"sensor.average_humidity_for_thermostat","entityidfiltertype":"exact","outputinitially":false,"state_type":"num","haltifstate":"","halt_if_type":"num","halt_if_compare":"gt","outputs":1,"output_only_on_state_change":false,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload.average","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":410,"y":720,"wires":[["1eb433c439920317"]]},{"id":"1eb433c439920317","type":"delay","z":"68ec22673149800e","name":"1 msg/5min","pauseType":"rate","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"5","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":570,"y":720,"wires":[["3074a1a94ba7258b"]]},{"id":"db06adad25c72aa2","type":"api-current-state","z":"68ec22673149800e","name":"Кто-то есть дома","server":"5e62137c.2011cc","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.somebody_home_manual_tracker","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"flow","value":"","valueType":"entityState"},{"property":"data","propertyType":"flow","value":"entity","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":490,"y":860,"wires":[["8c2e8a7637abdf05"],["0fa985f35e2abb5e"]]},{"id":"3074a1a94ba7258b","type":"api-current-state","z":"68ec22673149800e","name":"Климат- контроль","server":"5e62137c.2011cc","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.klimat_kontrol","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"flow","value":"","valueType":"entityState"},{"property":"data","propertyType":"flow","value":"entity","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":910,"y":720,"wires":[["e81039862f45535e"],[]]},{"id":"e81039862f45535e","type":"api-current-state","z":"68ec22673149800e","name":"Гости (Климат)","server":"5e62137c.2011cc","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.ignore_home_left_climate","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"flow","value":"","valueType":"entityState"},{"property":"data","propertyType":"flow","value":"entity","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":480,"y":800,"wires":[["8c2e8a7637abdf05"],["db06adad25c72aa2"]]},{"id":"6c0a330b33d6ddb2","type":"api-call-service","z":"68ec22673149800e","name":"Выключить","server":"5e62137c.2011cc","version":5,"debugenabled":false,"domain":"humidifier","service":"turn_off","areaId":[],"deviceId":[],"entityId":["humidifier.humidifier"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":2610,"y":780,"wires":[[]]},{"id":"8c2e8a7637abdf05","type":"api-current-state","z":"68ec22673149800e","name":"Желаемая влажность","server":"5e62137c.2011cc","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"gt","entity_id":"input_number.my_humidity","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload.wanted","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":760,"y":800,"wires":[["738f2571791f69bc"]]},{"id":"401c8fd0f09637be","type":"comment","z":"68ec22673149800e","name":"Увлажнитель","info":"","x":970,"y":520,"wires":[]},{"id":"173f11867041d21c","type":"time-range-switch","z":"68ec22673149800e","name":"День/ Ночь ","lat":"41.6841132","lon":"44.8342294","startTime":"07:00","endTime":"23:00","startOffset":0,"endOffset":0,"x":1930,"y":780,"wires":[["5ae731bddaa065bb","c7773961c53227ce"],["398e732586a3c79d","8a3d49761fb92218"]]},{"id":"50efc825b7c78319","type":"api-call-service","z":"68ec22673149800e","name":"Включить","server":"5e62137c.2011cc","version":5,"debugenabled":false,"domain":"humidifier","service":"turn_on","areaId":[],"deviceId":[],"entityId":["humidifier.humidifier"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1760,"y":780,"wires":[["173f11867041d21c"]]},{"id":"ce31ff684bfb26f2","type":"api-call-service","z":"68ec22673149800e","name":"Скорость 3","server":"5e62137c.2011cc","version":5,"debugenabled":false,"domain":"humidifier","service":"set_mode","areaId":[],"deviceId":[],"entityId":["humidifier.humidifier"],"data":"{\"mode\":\"High\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":2610,"y":900,"wires":[[]]},{"id":"9d1e7707437f0b67","type":"api-call-service","z":"68ec22673149800e","name":"Скорость 1","server":"5e62137c.2011cc","version":5,"debugenabled":false,"domain":"humidifier","service":"set_mode","areaId":[],"deviceId":[],"entityId":["humidifier.humidifier"],"data":"{\"mode\":\"Low\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":2610,"y":820,"wires":[[]]},{"id":"c7773961c53227ce","type":"switch","z":"68ec22673149800e","name":"Влажность в доме","property":"payload.average","propertyType":"msg","rules":[{"t":"gt","v":"(payload.wanted + 0.5)","vt":"jsonata"},{"t":"btwn","v":"(payload.wanted + 0.5)","vt":"jsonata","v2":"payload.wanted","v2t":"jsonata"},{"t":"btwn","v":"payload.wanted","vt":"jsonata","v2":"(payload.wanted - 2)","v2t":"jsonata"},{"t":"lt","v":"(payload.wanted - 2)","vt":"jsonata"}],"checkall":"false","repair":false,"outputs":4,"x":2370,"y":820,"wires":[["6c0a330b33d6ddb2"],["9d1e7707437f0b67"],["da9e25a9b001eb7a"],["ce31ff684bfb26f2"]]},{"id":"da9e25a9b001eb7a","type":"api-call-service","z":"68ec22673149800e","name":"Скорость 2","server":"5e62137c.2011cc","version":5,"debugenabled":false,"domain":"humidifier","service":"set_mode","areaId":[],"deviceId":[],"entityId":["humidifier.humidifier"],"data":"{\"mode\":\"Mid\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":2610,"y":860,"wires":[[]]},{"id":"2f7dee7ccbc58e15","type":"switch","z":"68ec22673149800e","name":"Влажность в доме","property":"payload.average","propertyType":"msg","rules":[{"t":"gt","v":"(payload.wanted + 0.5)","vt":"jsonata"},{"t":"btwn","v":"(payload.wanted + 0.5)","vt":"jsonata","v2":"payload.wanted","v2t":"jsonata"},{"t":"lt","v":"payload.wanted","vt":"jsonata"}],"checkall":"false","repair":false,"outputs":3,"x":2370,"y":900,"wires":[["6c0a330b33d6ddb2"],["9d1e7707437f0b67"],["da9e25a9b001eb7a"]]},{"id":"d71a62e5056e4ac0","type":"api-current-state","z":"68ec22673149800e","name":"Средняя >= 30","server":"5e62137c.2011cc","version":3,"outputs":2,"halt_if":"30","halt_if_type":"num","halt_if_compare":"gte","entity_id":"sensor.average_humidity","state_type":"num","blockInputOverrides":false,"outputProperties":[],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":920,"y":960,"wires":[["6c0a330b33d6ddb2"],["d9a7fd566be1ac42"]]},{"id":"d9a7fd566be1ac42","type":"api-call-service","z":"68ec22673149800e","name":"Включить","server":"5e62137c.2011cc","version":5,"debugenabled":false,"domain":"humidifier","service":"turn_on","areaId":[],"deviceId":[],"entityId":["humidifier.humidifier"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1100,"y":980,"wires":[["ce31ff684bfb26f2"]]},{"id":"d846d7a4aa2ea459","type":"server-state-changed","z":"68ec22673149800e","name":"Возврат/ уход из дома","server":"5e62137c.2011cc","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.somebody_home_manual_tracker","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[],"x":440,"y":680,"wires":[["90dd4e8d36a56458"]]},{"id":"8a3d49761fb92218","type":"api-current-state","z":"68ec22673149800e","name":"Понижать скорость","server":"5e62137c.2011cc","version":3,"outputs":2,"halt_if":"off","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.ponizhat_skorost_uvlazhnitelia_osushitelia_na_noch","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"flow","value":"","valueType":"entityState"},{"property":"data","propertyType":"flow","value":"entity","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":2140,"y":860,"wires":[["c7773961c53227ce"],["2f7dee7ccbc58e15"]]},{"id":"29297f63ccfac237","type":"server-state-changed","z":"68ec22673149800e","name":"Понижать скорость","server":"5e62137c.2011cc","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.ponizhat_skorost_uvlazhnitelia_osushitelia_na_noch","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[],"x":440,"y":640,"wires":[["90dd4e8d36a56458"]]},{"id":"24811c2862ed04c6","type":"server-state-changed","z":"68ec22673149800e","name":"Желаемая влажность","server":"5e62137c.2011cc","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":"Увлажнитель NodeRED"},{"property":"icon","value":"mdi:air-humidifier"}],"entityidfilter":"input_number.my_humidity","entityidfiltertype":"exact","outputinitially":false,"state_type":"num","haltifstate":"","halt_if_type":"num","halt_if_compare":"gt","outputs":1,"output_only_on_state_change":false,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[],"x":440,"y":600,"wires":[["90dd4e8d36a56458"]]},{"id":"b1408b7b8046e186","type":"server-state-changed","z":"68ec22673149800e","name":"Климат- контроль","server":"5e62137c.2011cc","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":"Увлажнитель NodeRED"},{"property":"icon","value":"mdi:air-humidifier"}],"entityidfilter":"input_boolean.klimat_kontrol","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":false,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[],"x":430,"y":560,"wires":[["90dd4e8d36a56458"]]},{"id":"16ebb9958033bcd2","type":"api-current-state","z":"68ec22673149800e","name":"Не работает осушение","server":"5e62137c.2011cc","version":3,"outputs":2,"halt_if":"dry","halt_if_type":"str","halt_if_compare":"is_not","entity_id":"climate.konditsioner","state_type":"str","blockInputOverrides":false,"outputProperties":[],"for":"","forType":"num","forUnits":"hours","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1570,"y":820,"wires":[["50efc825b7c78319"],["6c0a330b33d6ddb2"]]},{"id":"90dd4e8d36a56458","type":"api-current-state","z":"68ec22673149800e","name":"Влажность","server":"5e62137c.2011cc","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.average_humidity_for_thermostat","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload.average","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":690,"y":600,"wires":[["3074a1a94ba7258b"]]},{"id":"738f2571791f69bc","type":"switch","z":"68ec22673149800e","name":"Средняя < желаемой + 0.5","property":"payload.average","propertyType":"msg","rules":[{"t":"lt","v":"(payload.wanted + 0.5)","vt":"jsonata"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":880,"y":880,"wires":[["aec602bfba453410"],["6c0a330b33d6ddb2"]]},{"id":"5ae731bddaa065bb","type":"api-call-service","z":"68ec22673149800e","name":"Экран ВКЛ","server":"5e62137c.2011cc","version":5,"debugenabled":false,"domain":"select","service":"select_option","areaId":[],"deviceId":[],"entityId":["select.humidifier_led_brightness"],"data":"{\"option\":\"bright\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":2610,"y":740,"wires":[[]]},{"id":"398e732586a3c79d","type":"api-call-service","z":"68ec22673149800e","name":"Экран ВЫКЛ","server":"5e62137c.2011cc","version":5,"debugenabled":false,"domain":"select","service":"select_option","areaId":[],"deviceId":[],"entityId":["select.humidifier_led_brightness"],"data":"{\"option\":\"off\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":2610,"y":940,"wires":[[]]},{"id":"aec602bfba453410","type":"api-render-template","z":"68ec22673149800e","name":"HA запущен меньше 2х часов назад","server":"5e62137c.2011cc","version":0,"template":"{{(as_timestamp(now())-as_timestamp(states.sensor.last_boot_ha_beautiful.last_updated)) < 7200 }}","resultsLocation":"payload.time_since_start","resultsLocationType":"msg","templateLocation":"template","templateLocationType":"msg","x":1170,"y":820,"wires":[["57e1059031cfaee7"]]},{"id":"57e1059031cfaee7","type":"switch","z":"68ec22673149800e","name":"Switch","property":"payload.time_since_start","propertyType":"msg","rules":[{"t":"eq","v":"True","vt":"str"},{"t":"eq","v":"False","vt":"str"}],"checkall":"false","repair":false,"outputs":2,"x":1390,"y":800,"wires":[["50efc825b7c78319"],["16ebb9958033bcd2"]]},{"id":"0fa985f35e2abb5e","type":"api-current-state","z":"68ec22673149800e","name":"Задержка","server":"5e62137c.2011cc","version":3,"outputs":2,"halt_if":"False","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.time_has_come","state_type":"str","blockInputOverrides":false,"outputProperties":[],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":670,"y":940,"wires":[["8c2e8a7637abdf05"],["d71a62e5056e4ac0"]]},{"id":"5e62137c.2011cc","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false}]
У увлажнителя есть еще и экран, которым тоже хочется управлять. В моем случае он включается в 6 утра и выключается в 11 вечера. Во flow этого нет, потому что за утреннюю и вечернюю автоматику (это просто списки того что нужно включить/выключить или сбросить, срабатывающие каждый день). В связи с этим, не вижу смысла переносить управление этим в NodeRED.
Если кому-то придет идея с еще какими-то дополнительными ограничевающими параметрами, с удовольствием прочту в комментах, обсужу и добавлю себе :)