Desde que vivo sozinho que tenho um problema com as lavagens de roupa, acontece-me muitas vezes colocar a roupa a lavar e esquecer-me dela no final, ficando dentro da maquina, quase sempre isso dá direito a ter de repetir a lavagem.
Assim sendo o meu objetivo era acabar com este desperdício de recursos, então neste pequeno tutorial vou explicar como fiz e o que fiz para obter isso.
1 - Eu já tinha instalado no meu quadro elétrico um Shelly EM a medir o consumo total de energia, então no meu caso aproveitei o segundo canal e coloquei uma pinça a medir apenas o circuito da maquina roupa (aqui em casa é separado), no entanto podem optar por outras soluções, por ex uma plug wifi ou zigbee desde que tenha monitorização de consumo elétrico, pois isso é a base desta solução. Em relação ao shelly em vamos usar a entidade de potencia e de energia, pois mais a frente vão perceber que aproveitei a energia para tornar a coisa mais bonita.
2 - Criar uma entidade input text para a maquina da roupa, eu faço isso usando a opção Helpers nas configurações do HA.
3 - Automação com o NodeRed
[{"id":"82c4ed04.94f0e","type":"tab","label":"Maquina Roupa","disabled":false,"info":""},{"id":"6455ddb.0d82124","type":"comment","z":"82c4ed04.94f0e","name":"Automação para definir estado da Maquina Roupa","info":"","x":210,"y":40,"wires":[]},{"id":"178b2fe0.b4219","type":"api-call-service","z":"82c4ed04.94f0e","name":"Set Parada - Off","server":"48c6a047.be8eb","version":1,"debugenabled":false,"service_domain":"input_text","service":"set_value","entityId":"input_text.maquina_roupa","data":"{\t \"value\": \"off\"\t}","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":460,"y":100,"wires":[[]]},{"id":"68a336fe.856108","type":"api-call-service","z":"82c4ed04.94f0e","name":"Set A lavar - On","server":"48c6a047.be8eb","version":1,"debugenabled":false,"service_domain":"input_text","service":"set_value","entityId":"input_text.maquina_roupa","data":"{\t \"value\": \"on\"\t}","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":460,"y":160,"wires":[[]]},{"id":"7ab0c377.ac137c","type":"api-current-state","z":"82c4ed04.94f0e","name":"off","server":"48c6a047.be8eb","version":1,"outputs":2,"halt_if":"off","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_text.maquina_roupa","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":270,"y":160,"wires":[["68a336fe.856108"],[]]},{"id":"283b1e4c.2778c2","type":"api-current-state","z":"82c4ed04.94f0e","name":"on","server":"48c6a047.be8eb","version":1,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_text.maquina_roupa","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":270,"y":100,"wires":[["178b2fe0.b4219"],[]]},{"id":"aa87fdc2.edbe7","type":"function","z":"82c4ed04.94f0e","name":"","func":"const haStates = global.get('homeassistant').homeAssistant.states;\nconst entity = haStates['sensor.energy_maquina_roupa'];\n\nif(msg.payload) {\n const data = {\n state: entity.state,\n startTime: Date.now(),\n };\n context.set('savedState', data);\n} else {\n const data = context.get('savedState');\n\n if (data === undefined) {\n return;\n }\n\n const energy = parseFloat(Math.abs(entity.state - data.state)).toFixed(2);\n\n const duration = millisToMinutesAndSeconds(Date.now() - data.startTime);\n\n const payload = {\n energy: energy,\n duration: duration,\n }\n\n msg.payload = payload;\n\n return msg;\n}\n\nfunction millisToMinutesAndSeconds(millis) {\n let minutes = Math.floor(millis / 60000);\n let seconds = ((millis % 60000) / 1000).toFixed(0);\n return minutes + \":\" + (seconds < 10 ? '0' : '') + seconds;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":280,"y":220,"wires":[["5441bfa3.16bfd"]]},{"id":"5441bfa3.16bfd","type":"link out","z":"82c4ed04.94f0e","name":"Not Maq Roupa OFF","links":["1d117b66.6e9cb5"],"x":395,"y":220,"wires":[]},{"id":"5df4b74f.953e88","type":"server-state-changed","z":"82c4ed04.94f0e","name":"Maquina Roupa","server":"48c6a047.be8eb","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_text.maquina_roupa","entityidfiltertype":"exact","outputinitially":false,"state_type":"habool","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,"x":100,"y":220,"wires":[["aa87fdc2.edbe7"]]},{"id":"bec9f91b.672ae8","type":"server-state-changed","z":"82c4ed04.94f0e","name":"Power Maquina","server":"48c6a047.be8eb","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.power_maquina_lavar_roupa","entityidfiltertype":"exact","outputinitially":false,"state_type":"num","haltifstate":"10","halt_if_type":"num","halt_if_compare":"lt","outputs":2,"output_only_on_state_change":true,"for":"120","forType":"num","forUnits":"seconds","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":100,"y":100,"wires":[["283b1e4c.2778c2"],[]]},{"id":"e12dff48.96ee7","type":"server-state-changed","z":"82c4ed04.94f0e","name":"Power Maquina","server":"48c6a047.be8eb","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.power_maquina_lavar_roupa","entityidfiltertype":"exact","outputinitially":false,"state_type":"num","haltifstate":"5","halt_if_type":"num","halt_if_compare":"gt","outputs":2,"output_only_on_state_change":true,"for":"10","forType":"num","forUnits":"seconds","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":100,"y":160,"wires":[["7ab0c377.ac137c"],[]]},{"id":"48c6a047.be8eb","type":"server","name":"Home Assistant","addon":true}]
Esta automação faz o seguinte, assim que a maquina consome mais de 10W durante 5s seguidos e a maquina da roupa esta OFF, o nodered escreve ON na entidade input text criada para a maquina da roupa, e sempre que a potencia da maquina é inferior a 5W durante 120s e a maquina está ON, o nodered escreve na entidade da maquina OFF. Esses 120s existem para evitar falsos OFF durante o ciclo, isto porque por vezes a maquina esta parada, com consumo residual.
Além disto com o NodeRed uso um outro flow que me permite calcular o consumo de energia kw/h durante o ciclo de lavagem e o tempo total de lavagem da maquina. e esse flow cria uma notificação que me é enviada para o telegram
[{"id":"aa87fdc2.edbe7","type":"function","z":"82c4ed04.94f0e","name":"","func":"const haStates = global.get('homeassistant').homeAssistant.states;\nconst entity = haStates['sensor.energy_maquina_roupa'];\n\nif(msg.payload) {\n const data = {\n state: entity.state,\n startTime: Date.now(),\n };\n context.set('savedState', data);\n} else {\n const data = context.get('savedState');\n\n if (data === undefined) {\n return;\n }\n\n const energy = parseFloat(Math.abs(entity.state - data.state)).toFixed(2);\n\n const duration = millisToMinutesAndSeconds(Date.now() - data.startTime);\n\n const payload = {\n energy: energy,\n duration: duration,\n }\n\n msg.payload = payload;\n\n return msg;\n}\n\nfunction millisToMinutesAndSeconds(millis) {\n let minutes = Math.floor(millis / 60000);\n let seconds = ((millis % 60000) / 1000).toFixed(0);\n return minutes + \":\" + (seconds < 10 ? '0' : '') + seconds;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":280,"y":220,"wires":[["5441bfa3.16bfd"]]},{"id":"5441bfa3.16bfd","type":"link out","z":"82c4ed04.94f0e","name":"Not Maq Roupa OFF","links":["1d117b66.6e9cb5"],"x":395,"y":220,"wires":[]},{"id":"5df4b74f.953e88","type":"server-state-changed","z":"82c4ed04.94f0e","name":"Maquina Roupa","server":"48c6a047.be8eb","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_text.maquina_roupa","entityidfiltertype":"exact","outputinitially":false,"state_type":"habool","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,"x":100,"y":220,"wires":[["aa87fdc2.edbe7"]]},{"id":"48c6a047.be8eb","type":"server","name":"Home Assistant","addon":true}]
[{"id":"4ccf887.a246978","type":"template","z":"a2477c22.c6cb1","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"A lavagem da maquina da roupa terminou,\na energia consumida durante o ciclo foi de {{payload.energy}}kWh,\ne o tempo total foi de {{payload.duration}}.","output":"str","x":220,"y":240,"wires":[["188e4a34.825236"]]},{"id":"188e4a34.825236","type":"telegrambot-notify","z":"a2477c22.c6cb1","name":"Máquina Roupa","bot":"75de7d79.3586a4","chatId":"","message":"","parseMode":"","x":400,"y":240,"wires":[]},{"id":"75de7d79.3586a4","type":"telegrambot-config","botname":"Hassio","usernames":"JMTHassio_BoT","chatIds":"942164466","pollInterval":"300"}]
Vão acabar com uma mensagem no telegram desde genero.
INFO Importante - tudo isto foi retirado das mentes brilhantes do utilizadores deste forum, do discord e da internet em geral.
Qualquer duvida ou sugestão, é só colocar aí…