Adicionando um contador SDM-220 ao OpenHab

Quase um ano se passou desde a minha primeira publicação sobre um medidor elétrico com a interface RS485 / ModBus SDM-220 , e havia um segundo artigo sobre como coletar dados e processar estatísticas. Este é o terceiro, espero que seja o último. Ela é sobre como integrar o contador ao OpenHab . O resultado está finalmente completamente bem comigo.



Portanto, a primeira tentativa de coletar estatísticas do contador foi feita usando um serviço de nuvem externo ThingSpeak . Como servidor local que pesquisa o contador, usamos um thin client (mini computador) com o Ubuntu Server instalado no pendrive. Este foi o primeiro erro - o pen drive "morreu" depois de 3 meses (um acidente, pensei). Sem tirar conclusões, matei o segundo pen drive em 2 meses (regularidade). Na terceira versão, um bolso usb com um parafuso de 2,5 "já era usado como armazenamento.

O próprio serviço ThingSpeak permite algum processamento, mas não fornece flexibilidade suficiente com a manipulação de dados. Os dados por dia, por exemplo, foram coletados como a soma dos dados por hora. Se algum pacote de dados não chegou ao servidor ou eu enviei alguns dados durante o teste, ocorreu um erro. Pensamentos de que seria necessário manter uma contabilidade de duas taxas com referência à hora do dia não foram adicionados otimismo.

Em geral, eu decidi aprender o OpenHab .

A primeira tarefa: obter dados brutos do contador.


A instalação do OpenHab em si é detalhada nas instruções . Após a instalação, é necessário instalar a ligação ModBus - binding-modbus1 - 1.9.0 através do painel Paper UI → Bindings

O barramento ModÂus é pesquisado através do adaptador USB-RS485, portanto, é necessário garantir que o adaptador esteja no sistema e adicionar os direitos de acesso do usuário openhab à porta:

lsusb Bus 002 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC ls /dev/ttyUSB* /dev/ttyUSB0 sudo adduser openhab dialout sudo adduser openhab tty 

Em seguida, é recomendável configurar permissões para Java (isso também é descrito em detalhes nas instruções de instalação do OpenHab):

 sudo vi /etc/default/openhab2 EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0" 

Após essas manipulações, você precisa configurar o arquivo de configuração services / modbus.cfg :

  sudo vi /etc/openhab2/services/modbus.cfg #   poll=30000 #        ,        .  start -  .   connection      (9600,8,n,1),        . # - 0x00 serial.slave1.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none serial.slave1.type=input serial.slave1.start=0 serial.slave1.length=2 serial.slave1.valuetype=float32 # - 0x06 serial.slave2.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none serial.slave2.type=input serial.slave2.start=6 serial.slave2.length=2 serial.slave2.valuetype=float32 #  - 0x0C serial.slave3.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none serial.slave3.type=input serial.slave3.start=12 serial.slave3.length=2 serial.slave3.valuetype=float32 #  ( ) - 0x156 serial.slave4.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none serial.slave4.type=input serial.slave4.start=342 serial.slave4.length=2 serial.slave4.valuetype=float32 

Então você precisa criar os itens de dados no arquivo items / sdm220.items :

 sudo vi /etc/openhab2/items/sdm220.items #    Group gSDM220 # ,      , energy -       Number sdm220_voltage " [%.1f ]" <energy> (gSDM220) {modbus="slave1:0"} Number sdm220_current " [%.2f ]" <energy> (gSDM220) {modbus="slave2:0"} Number sdm220_actpower " [%.1f ]" <energy> (gSDM220) {modbus="slave3:0"} Number sdm220_actcounter "  [%.1f *]" <energy> (gSDM220) {modbus="slave4:0"} 

Resta adicionar as leituras atuais no painel. Para fazer isso, edite o arquivo sitemaps / default.sitemap :

 sudo vi /etc/openhab2/sitemaps/default.sitemap sitemap default label="alk0v SmartHome (default sitemap)" { Frame label="" { Text item=sdm220_voltage Text item=sdm220_current Text item=sdm220_actpower Text item=sdm220_actcounter } } 

Em princípio, isso é suficiente para ver a leitura atual do medidor:



Tarefa 2: Configurar o HabPanel e visualizar leituras


O OpenHab suporta vários painéis de controle. Externamente, gostei mais do HabPanel . Através da interface do usuário do Paper → User Interfaces, instale o HabPanel - ui-habpanel - 2.0.0 .

Para desenhar gráficos, você também precisa armazenar dados em algum lugar. O OpenHab usa o termo Persistência para bancos de dados. Eu queria usar o banco de dados MySQL, a comunidade discutiu muitos problemas com esse banco de dados; no final, encontrei uma instrução que funcionou para mim também.

Portanto, instale o MySQL Persistence (persistence-mysql - 1.9.0).

Instale o MySQL:

 sudo apt-get install mysql-server sudo mysql -u root -p 

Configure a base:

 CREATE DATABASE OpenHAB; CREATE USER 'openhab'@'localhost' IDENTIFIED BY 'YOURPASSWORD'; GRANT ALL PRIVILEGES ON OpenHAB.* TO 'openhab'@'localhost'; quit 

Reinicie o openhab:

 sudo service openhab2 stop sudo service openhab2 start 

Edite services / mysql.cfg :

 # the database url like 'jdbc:mysql://<host>:<port>/<database>' (without quotes) url=jdbc:mysql://localhost:3306/openhab # the database user user=openhab # the database password password=YOURPASSWORD 

Edite persistence / mysql.persist . Por padrão, os valores de todos os itens serão inseridos no banco de dados a cada alteração:

 Strategies { // if no strategy is specified for an item entry below, the default list will be used everyMinute : "0 * * * * ?" every5Minutes : "0 */5 * * * ?" everyHour : "0 0 * * * ?" everyDay : "0 0 0 * * ?" default = everyChange } Items { // persist all items once a day and on every change and restore them from the db at startup * : strategy = default, restoreOnStartup } 

Se tudo estiver configurado corretamente, a tabela Itens e as tabelas ItemXX de cada Item devem aparecer no banco de dados.

 mysql> use openhab; Database changed mysql> show tables; +-------------------+ | Tables_in_openhab | +-------------------+ | Item1 | | Item2 | | Item3 | | Item4 | | Items | +-------------------+ 5 rows in set (0.00 sec) mysql> select * from Items; +--------+--------------------------+ | ItemId | ItemName | +--------+--------------------------+ | 1 | sdm220_voltage | | 2 | sdm220_actpower | | 3 | sdm220_actcounter | | 4 | sdm220_current | +--------+--------------------------+ 4 rows in set (0.00 sec) 

Agora você pode trazer beleza ao HabPanel.

Adicione um painel, adicione novos widgets a ele. Para exibir valores, use o widget Manequim para exibir gráficos - Gráfico . Tudo é intuitivo aqui. Deduzi os parâmetros de potência e tensão em um gráfico usando duas escalas Y diferentes.

Especifique o mysql como uma fonte de dados:



Defina limites para o eixo de tensão:



Adicione itens, indique a cor e o tipo da linha para eles, pois a tensão indica o eixo secundário:



Nós obtemos o resultado :)



A terceira tarefa: medição horária e diária da eletricidade consumida


É bom exibir uma mudança de estado ao longo do tempo, mas eu também queria obter estatísticas sobre o consumo por uma hora, dia, mês. Ou seja, a tarefa é executar periodicamente alguns cálculos. É aqui que o mecanismo de regras do OpenHab entra.

Então, configuramos as regras .

Primeiro, você precisa adicionar novos itens a items / sdm220.items :

 Number sdm220_hourcounter (gSDM220) Number sdm220_daycounter (gSDM220) 

Em seguida, crie o arquivo rules / energy.rules , no qual você precisa especificar 2 regras: uma será executada uma vez por hora, a segunda - uma vez por dia.

 rule "Energy by hour" when Time cron "0 0 * * * ?" then // .            var hour = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1), "mysql":).state as DecimalType //      logInfo("TEST","sdm220_hourcounter = "+hour) //  Item postUpdate(sdm220_hourcounter, hour) end rule "Energy by day" when Time cron "0 0 0 * * ?" then var day = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType postUpdate(sdm220_daycounter, day) 

Você pode usar o console do OpenHab para depuração. Nome de usuário e senha padrão: openhab / habopen. Você pode se conectar a ele com o comando:

 ssh -p 8101 openhab@localhost openhab> log:tail 19:22:00.012 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.526123046875 19:22:00.014 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.861083984375 19:22:09.462 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_current changed from 16.0433025360107421875 to 5.69449329376220703125 19:22:11.500 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_actcounter changed from 2387.51904296875 to 2387.5458984375 19:22:13.532 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_voltage changed from 192.7679595947265625 to 200.4195098876953125 19:22:15.568 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_actpower changed from 2271.8486328125 to 1132.8717041015625 19:23:00.014 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.515869140625 19:23:00.015 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.8769531250 

Ou você pode visualizar o arquivo de log:

 tail -f /var/log/openhab2/openhab.log 2017-04-18 19:17:45.587 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'energy.rules' 2017-04-18 19:18:00.259 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.571044921875 2017-04-18 19:18:00.272 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.8330078125 2017-04-18 19:19:00.015 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.83789062500 2017-04-18 19:19:00.025 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.557861328125 2017-04-18 19:20:00.013 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.55517578125 2017-04-18 19:20:00.024 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.859130859375 

Pretendo mudar o medidor de eletricidade principal para um de duas tarifas, de acordo com o qual a eletricidade consumida no intervalo das 23:00 às 07:00 é paga com um coeficiente de 0,5, então eu gostaria de ver o efeito esperado e manter uma medição de duas tarifas. No começo, simplesmente adicionei condições adicionais de tempo aos Itens e Regras e adicionei as leituras do dia e da noite em duas tabelas diferentes. Tudo estava bonito no banco de dados, mas parecia desajeitado no gráfico, pois o gráfico conectava os dois últimos valores com uma linha reta:



Para divertir meu senso de beleza, tive que me preocupar um pouco.

Portanto, o script final de regras para a contabilidade de duas tarifas se parece com isso:

 rule "Energy by hour" when Time cron "0 0 * * * ?" then var hour = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1), "mysql":).state as DecimalType //   if(now.getHourOfDay > 7 && now.getHourOfDay < 23) { logInfo("TEST","sdm220_hourcounter_day = "+hour) postUpdate(sdm220_hourcounter_day, hour) } else { //        //      primary key  timestamp,               if(now.getHourOfDay==7) { postUpdate(sdm220_hourcounter_night, hour) Thread::sleep(1000) postUpdate(sdm220_hourcounter_night, 0) Thread::sleep(1000) postUpdate(sdm220_hourcounter_day, 0) Thread::sleep(1000) postUpdate(sdm220_hourcounter_day, hour) } else if(now.getHourOfDay==23) { postUpdate(sdm220_hourcounter_day, hour) Thread::sleep(1000) postUpdate(sdm220_hourcounter_day,0) Thread::sleep(1000) postUpdate(sdm220_hourcounter_night, 0) Thread::sleep(1000) postUpdate(sdm220_hourcounter_night, hour) } else { postUpdate(sdm220_hourcounter_night, hour) } } postUpdate(sdm220_hourcounter, hour) end rule "Energy by day" when Time cron "0 0 0 * * ?" then var day = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType //night counter, 00:00..07:00 + 23:00..00:00 var day2 = sdm220_actcounter.historicState(now.minusHours(17),"mysql":).state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType + sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1),"mysql":).state as DecimalType //day counter, 07:00..23:00 var day1 = sdm220_actcounter.historicState(now.minusHours(1),"mysql":).state as DecimalType - sdm220_actcounter.historicState(now.minusHours(17),"mysql":).state as DecimalType logInfo("TEST","sdm220_daycounter_day = "+day1) logInfo("TEST","sdm220_daycounter_night = "+day2) logInfo("TEST","sdm220_daycounter = "+day) postUpdate(sdm220_daycounter, day) postUpdate(sdm220_daycounter_day, day1) postUpdate(sdm220_daycounter_night, day2) end 

Antes de editar o script, adicione os itens necessários:

 Number sdm220_hourcounter_day (gSDM220) Number sdm220_hourcounter_night (gSDM220) Number sdm220_daycounter_day (gSDM220) Number sdm220_daycounter_night (gSDM220) 

Agora, o fluxograma horário e diário é assim:



Provavelmente é tudo. Também está planejado adicionar um cálculo de eletricidade e consumo de dinheiro por mês para uma tarifa diária e noturna e uma geração de relatórios com envio por correio.

Source: https://habr.com/ru/post/pt403237/


All Articles