Este dispositivo, que desempenha a dupla função de controlar (ligar e desligar) o circuito ao qual está ligado, bem como de medir 8 grandezas relacionadas com a energia electrica, está à venda na Internet em diversos sitios, nomeadamente a Aliexpress, ou na Amazon, por valores que rondam os 28 Euros. Existe um segundo dispositivo, com a marca e modelo SINOTIMER WDS688, que se trata aparentemente de um clone. Já houve confirmação de utilizadores, de este ter sido convertido com sucesso para Tasmota pelo mesmo processo. Alguns links para os dois artigos, no retalho online:
SMTONOFF ZMAi-90 - https://pt.aliexpress.com/item/32962808336.html
SINOTIMER WDS688 - WDS688 90 250VAC WIFI Smart Switch Energy Meter Remote Control by APP Energy Saving Wattmeter Multi functional Countdown Timer - AliExpress
As 8 grandezas que o dispositivo mede são nomeadamente:
- energia total consumida em kWh;
- tensão da rede electrica, em Volts;
- corrente instantânea consumida pelo circuito electrico, em Amperes;
- potência aparente em Watts;
- potência activa em Watts;
- potência reactiva em Watts;
- factor de potência em %;
- frequência em Hz;
Em termos de corrente, segundo é anunciado pelo fabricante, o relé suporta o máximo de 60 Amperes.
Apesar de ter vindo a identificar que este dispositivo teria potencial para poder ser convertido em Tasmota e assim deixar de (pelos menos) depender da cloud Tuya, deparei-me com o facto que na comunidade ainda não se tinha ido para além da conversão (através do projecto tuya-convert) para Tasmota, habilitando aquilo que este firmware permitia na altura, nomeadamente o controlo do relé e não mais do que isso.
Assim, pus mãos à obra e decidi investigar melhor o dispositivo, e fazer o necessario a fim de chegar a um procedimento que esteja tão ao alcançe de todos quanto possivel.
- Preparação do dispositivo
A primeira coisa que é necessario fazer, como não podia deixar de ser, é a conversão do dispositivo em si. Existem duas abordagens possíveis: 1) uma que tem por vantagem não implicar abrir fisicamente o dispositivo e dominar a arte do ferro de soldar, mas que por outro lado pode não funcionar com todos os firmwares colocados pelo fabricante, e também tem um pouco de complexidade no setup de software necessario; e 2) outra, que apesar de exigir o acesso fisico ao dispositivo de modo a poder ligar a porta série para programação, tem a garantia de funcionar independentemente do firmware que esteja originalmente no dispositivo, e é relativamente simples do ponto de vista do setup de software necessario.
Assim temos respectivamente:
1.1 - Converter usando o utilitario tuya-convert:
- configurar um computador com uma instalação de linux (pode ser uma imagem em VMWare, ou até mesmo um Raspberry Pi (ver detalhes em https://github.com/ct-Open-Source/tuya-convert). Este computador terá de dispor de uma interface WiFi;
- obter o binario do firmware Tasmota, versão 7.2 ou superior (já inclui o comando SerialConfig, necessario para esta integração) - pode ser obtido a partir daqui - https://github.com/arendst/Tasmota/releases;
- seguir os passos de setup do tuya-convert (clone do repo git, execução do script install_prereq.sh);
- colocar o binario do firmware Tasmota obtido anteriormente, por debaixo da pasta files/ do projecto tuya-convert;
- colocar o dispositivo em modo de emparelhamento (deixar o botão “Pair” pressionado durante alguns segundos até o LED azul piscar);
- na maquina linux, correr o script ./start_flash.sh e seguir as instruções apresentadas. O bootloader do tuya-convert será instalado no dispositivo e posto em execução. Serão apresentados os comandos curl para ser possivel fazer o backup do firmware original, e o update para o firmware Tasmota (ou outro) que esteja na pasta files/;
- assim que o Tasmota estiver flashado no dispositivo, como em qualquer dispositivo “tasmotizado”, há de estar visivel um novo AP WiFi, com um nome semelhante a “tasmota-xxxx”. Ligar a este AP e preencher os detalhes da sua rede WiFi no formulário (captive portal) que é apresentado. Após carregar em “Save”, o dispositivo irá reinciar e ficar associado à rede que foi especificada.
1.2 - converter usando adaptador série:
- para começar é necessario dispor de um adaptador que forneça os niveis da porta série a 3.3 Volts (5 Volts ou mais irão danificar permanentemente o hardware). Pode ser usado por exemplo o adaptador USB “FTDI FT232RL”. Assegurar que o jumper deste está na posição 3.3V:
- será necessario soldar temporariamente um fio entre o pino RSTn do microcontrolador V9821 (responsavel pelas medições de energia) e GND. O objectivo é colocar este microcontrolar desactivado enquanto se procede à programação do microcontrolador principal. O respectivo contacto pode ser localizado com base na imagem:
- soldar também um fio entre o pino GPIO0 do microncontrador principal (o ESP8266 localizado na breakout board TYWE3S). Isto irá colocar este microntrolador em modo de programação.
- por fim soldar também fios para os pinos TX, RX e GND deste mesmo microcontrolador. Estes fios irão ligar ao adaptador de porta série indicado acima;
- Fornecer 5 Volts e GND aos pinos indicados na imagem mostrada acima;
- de seguida, usando o script python “esptool” (que pode ser obtido deste projecto - https://github.com/espressif/esptool), proceder ao flash do firmware. Como indicado acima, para o procedimento com o tuya-convert, o binário trata-se do mesmo ficheiro e pode ser obtido da mesma localização. É necessario no comando de programação, forçar o tamanho da flash a 1MB devido ao facto que para este dispositivo a tool não consegue reconhecer correctamente o tamanho da flash:
$ esptool.py --port COM3 --baud 74880 --after no_reset write_flash --flash_size 1MB --flash_mode dio 0x00000 tasmota.bin --erase-all
(substituir COM3 pelo valor apropriado no vosso caso - ver por exemplo no “Gestor de Dispositivos” do Windows)
- após o dispositivo ter sido programado com sucesso, desligá-lo e remover os shunts e ligações efectuadas excepto a alimentação. Ligar novamente a alimentação de +5 Volts e GND de modo a testar o dispositivo. Há de estar visivel um novo AP WiFi, com um nome semelhante a “tasmota-xxxx”. Ligar a este AP e preencher os detalhes da sua rede WiFi no formulário (captive portal) que é apresentado. Após carregar em “Save”, o dispositivo irá reinciar e ficar associado à rede que foi especificada.
- desligar a alimentação, montar a placa novamente no dispositivo, e ligar este com uma ficha de electricidade de modo a poder ser testado directamente com uma carga.
2 - Configurar o Tasmota
2.1 - para começar será necessario configurar o Tasmota relativamente aos seus aspectos básicos: MQTT enable e configuração dos detalhes do broker:
- entrando na web UI do dispositivo, ir a Configuration > Configure Other > carregar em “MQTT enable” e atribuir o “friendly name”. Clicar em Save no final:
- ir também a Configuration > Configure MQTT e definir os detalhes do broker MQTT ao qual o dispositivo se irá ligar. Clicar em Save no final:
- de modo a preparar os pinos GPIO e definir o tipo de módulo, ir a Configuration > Configure Module. Começar por definir o módulo como “Generic (0)”. Clicar em “Save”. Voltar ao mesmo menu depois de o dispositivo reiniciar, e definir as portas GPIO conforme a imagem:
2.2. Configurar a porta série do dispositivo (esta é usada para a comunicação com o microncontrolador escravo - o V9821 usado para as medições)
- no menu principal ir a “Console”;
- introduzir o comando abaixo, de modo a definir a velocidade:
Baudrate 9600
- configurar os parâmetros da porta correctos, usando o comando:
`SerialConfig 8E1``
2.3. Definir uma regra para que o dispositivo envie o comando de medição para o microcontrolador escravo periodicamente
- novamente na consola, escrever:
Rule1 on System#Boot do RuleTimer1 10 endon on Rules#Timer=1 do backlog SerialSend5 fe010f080000001c; RuleTimer1 10 endon
- habilitar a regra, escrevendo:
Rule1 1
- com esta regra o Tasmota passará a enviar a cada 10 segundo o pedido de medição. A resposta será publicada no tópico MQTT de telemetria (e.g. tele/general-meter-switch/RESULT):
02:59:15 MQT: tele/general-meter-switch/RESULT = {"SerialReceived":"FE01083002000076230000808404000050000028431100000000007253110000100000A6"}
- de modo a evitar comportamentos adversos, tais como o chamado “ghost switching”, executar também os seguintes comandos:
PowerOnState 3
SwitchRetain OFF
ButtonRetain OFF
PowerRetain ON
3 - Configurar o Hass.io
Aqui será necessario definir dois tipos de entidades: 1) sensor - um por cada medição (são 8 no total); 2) switch - para controlar o estado do relé;
3.1. Editar o ficheiro que está em /config/configuration.yaml.
- Adicionar as seguintes entradas na secção “sensor”:
- platform: mqtt
name: "Mains Consumed Energy"
state_topic: "tele/general-meter-switch/RESULT"
value_template: >-
{% set message = value_json.SerialReceived %}
{% set payload = message[6:14] %}
{% set payload_len = (payload | length) %}
{% set result = namespace(value='') %}
{% for i in range(0, payload_len + 1) | reverse -%}
{%- if i is divisibleby 2 -%}
{%- set result.value = result.value + payload[i:i+2] -%}
{%- endif -%}
{%- endfor -%}
{{ (result.value|float) / 100 }}
unit_of_measurement: 'kWh'
- platform: mqtt
name: "Mains Voltage"
state_topic: "tele/general-meter-switch/RESULT"
value_template: >-
{% set message = value_json.SerialReceived %}
{% set payload = message[14:22] %}
{% set payload_len = (payload | length) %}
{% set result = namespace(value='') %}
{% for i in range(0, payload_len + 1) | reverse -%}
{%- if i is divisibleby 2 -%}
{%- set result.value = result.value + payload[i:i+2] -%}
{%- endif -%}
{%- endfor -%}
{{ (result.value|float) / 10 }}
unit_of_measurement: 'Volts'
- platform: mqtt
name: "Mains Current"
state_topic: "tele/general-meter-switch/RESULT"
value_template: >-
{% set message = value_json.SerialReceived %}
{% set payload = message[22:30] %}
{% set payload_len = (payload | length) %}
{% set result = namespace(value='') %}
{% for i in range(0, payload_len + 1) | reverse -%}
{%- if i is divisibleby 2 -%}
{%- set result.value = result.value + payload[i:i+2] -%}
{%- endif -%}
{%- endfor -%}
{{ (result.value|float) / 10000 }}
unit_of_measurement: 'Amps'
- platform: mqtt
name: "Mains Frequency"
state_topic: "tele/general-meter-switch/RESULT"
value_template: >-
{% set message = value_json.SerialReceived %}
{% set payload = message[30:38] %}
{% set payload_len = (payload | length) %}
{% set result = namespace(value='') %}
{% for i in range(0, payload_len + 1) | reverse -%}
{%- if i is divisibleby 2 -%}
{%- set result.value = result.value + payload[i:i+2] -%}
{%- endif -%}
{%- endfor -%}
{{ (result.value|float) / 100 }}
unit_of_measurement: 'Hz'
- platform: mqtt
name: "Mains Active Power"
state_topic: "tele/general-meter-switch/RESULT"
value_template: >-
{% set message = value_json.SerialReceived %}
{% set payload = message[38:46] %}
{% set payload_len = (payload | length) %}
{% set result = namespace(value='') %}
{% for i in range(0, payload_len + 1) | reverse -%}
{%- if i is divisibleby 2 -%}
{%- set result.value = result.value + payload[i:i+2] -%}
{%- endif -%}
{%- endfor -%}
{{ (result.value|float) / 100 }}
unit_of_measurement: 'Watts'
- platform: mqtt
name: "Mains Reactive Power"
state_topic: "tele/general-meter-switch/RESULT"
value_template: >-
{% set message = value_json.SerialReceived %}
{% set payload = message[46:54] %}
{% set payload_len = (payload | length) %}
{% set result = namespace(value='') %}
{% for i in range(0, payload_len + 1) | reverse -%}
{%- if i is divisibleby 2 -%}
{%- set result.value = result.value + payload[i:i+2] -%}
{%- endif -%}
{%- endfor -%}
{{ (result.value|float) / 100 }}
unit_of_measurement: 'Watts'
- platform: mqtt
name: "Mains Apparent Power"
state_topic: "tele/general-meter-switch/RESULT"
value_template: >-
{% set message = value_json.SerialReceived %}
{% set payload = message[54:62] %}
{% set payload_len = (payload | length) %}
{% set result = namespace(value='') %}
{% for i in range(0, payload_len + 1) | reverse -%}
{%- if i is divisibleby 2 -%}
{%- set result.value = result.value + payload[i:i+2] -%}
{%- endif -%}
{%- endfor -%}
{{ (result.value|float) / 100 }}
unit_of_measurement: 'Watts'
- platform: mqtt
name: "Mains Power Factor"
state_topic: "tele/general-meter-switch/RESULT"
value_template: >-
{% set message = value_json.SerialReceived %}
{% set payload = message[62:70] %}
{% set payload_len = (payload | length) %}
{% set result = namespace(value='') %}
{% for i in range(0, payload_len + 1) | reverse -%}
{%- if i is divisibleby 2 -%}
{%- set result.value = result.value + payload[i:i+2] -%}
{%- endif -%}
{%- endfor -%}
{{ (result.value|float) / 10 }}
unit_of_measurement: '%'
- editar a secção “switch”, acrescentando:
- platform: mqtt
name: general-meter-switch
state_topic: 'stat/general-meter-switch/RESULT'
value_template: '{{ value_json["POWER"] }}'
command_topic: 'cmnd/general-meter-switch/POWER'
availability_topic: 'tele/general-meter-switch/LWT'
qos: 1
payload_on: 'ON'
payload_off: 'OFF'
payload_available: 'Online'
payload_not_available: 'Offline'
retain: false
- reiniciar o Hass.io. Caso a UI lovelace esteja em modo automático, os badges dos novos sensores deverão passar a estar visíveis:
- bem como o cartão para controlar o relé:
Espero que este procedimento seja útil na integração com este tipo de dispositivo.
As instruções que compus originalmente (em inglês) bem como o relato do processo ao longo do “reverse engineering” do dispositivo, podem ser encontrados no meu blog
Cumprimentos