Gå til innhold
  • Bli medlem

HAN til Home Assistant over ESPHome


Anbefalte innlegg

Hei,

 

Har mekka litt for å få HAN-data fra Kamstrup-måleren min (1-fas) inn i Home Assistant.

 

Bruker ESPHome med en ESP32 for å få inn data, forsøkte med en ESP8266, men den var ikke helt glad i software serieport, derfor måtte jeg ty til 32'en.

 

Koden er ganske stygg foreløpig, men kanskje det kan hjelpe noen andre på vei:)

 

Parser dataen ved å lese ut OBIS-koder og så hente tilknyttede data. Ingen CRC-sjekk e.l. da dingsen min ikke ser ut til å lese korrupte data i det hele tatt så langt.

 

Har lånt en del inspirasjon fra RoarFreds HAN-leser, selv om jeg endte opp med noe ganske annerledes etterhvert:)

 

ESPHome-konfigurasjonsfil:

esphome:
  name: ams
  platform: ESP32
  board: nodemcu-32s
  includes:
    mbus.h

wifi:
  power_save_mode: light
  networks:
  - ssid: "LulzNettOppe"
    password: ##PASSORD##
  - ssid: "LulzNettEkstra"
    password: ##PASSORD##
  - ssid: "LulzNett"
    password: ##PASSORD##

# Enable logging
logger:
  level: DEBUG

# Enable Home Assistant API
api:

ota:

uart:
  id: uart_bus
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 2400

# Example configuration entry
dallas:
  - pin: GPIO25
  
sensor:
  - platform: dallas
    address: 0xEA0214808622FF28
    name: "Temperature Sikringsskap"

  - platform: custom
    lambda: |-
      auto mbus_reader = new MbusReader(id(uart_bus));
      App.register_component(mbus_reader);
      return {mbus_reader->wattage_sensor, mbus_reader->reactive_power_sensor, mbus_reader->amperage_sensor, mbus_reader->voltage_sensor, mbus_reader->energy_sensor, mbus_reader->reactive_energy_sensor};
    
    sensors:
    - name: "AMS Wattage"
      unit_of_measurement: kW
      accuracy_decimals: 3
      filters:
        - multiply: 0.001
    - name: "AMS Reactive Power"
      unit_of_measurement: VAr
      accuracy_decimals: 0
      internal: true
    - name: "AMS Amperage"
      unit_of_measurement: A
      accuracy_decimals: 2
      filters:
        - multiply: 0.01
    - name: "AMS Voltage"
      unit_of_measurement: V
      accuracy_decimals: 0
    - name: "AMS Hourly Energy"
      unit_of_measurement: kWh
      accuracy_decimals: 3
      filters:
        - multiply: 0.01
    - name: "AMS Hourly Reactive Energy"
      unit_of_measurement: kVArh
      accuracy_decimals: 3
      internal: true
      filters:
        - multiply: 0.01

mbus.h:

#include "esphome.h"

class MbusReader : public Component, public uart::UARTDevice, public Sensor {
 public:
  MbusReader(uart::UARTComponent *parent) : uart::UARTDevice(parent) {}  
  uint8_t temp_byte = 0;
  uint8_t *temp_byte_pointer = &temp_byte;
  uint8_t uart_buffer_[512]{0};
  uint16_t uart_counter = 0;
  char uart_message[550];
  char temp_string[10];
  char obis_code[32];
  char temp_obis[10];
  uint32_t obis_value = 0;
  float wattage = 0;
  float amperage = 0;
  float voltage = 0;
  float energy = 0;

  Sensor *wattage_sensor = new Sensor();
  Sensor *amperage_sensor = new Sensor();
  Sensor *voltage_sensor = new Sensor();
  Sensor *energy_sensor = new Sensor();
  Sensor *reactive_power_sensor = new Sensor();
  Sensor *reactive_energy_sensor = new Sensor();

  void setup() override {

  }

  void loop() override {
    bool have_message = read_message();
  }

  bool read_message() {
    while(available() >= 1) {
      read_byte(this->temp_byte_pointer);
      if(temp_byte == 126) {
        if(uart_counter > 2) {
          uart_buffer_[uart_counter] = temp_byte;
          uart_counter++;
          uart_message[0] = '\0';
          strcpy(uart_message, "");
          for (uint16_t i = 0; i < uart_counter && i < 256; i++) {
            //sprintf(temp_string, "%02X", uart_buffer_[i]);
            //strncat(uart_message, temp_string, 2);
            if(uart_buffer_[i-1] == 9 && uart_buffer_[i] == 6) {
              obis_code[0] = '\0';
              strcpy(obis_code, "");
              for (uint16_t y = 1; y < 6; y++) {
                sprintf(temp_obis, "%d.", uart_buffer_[i + y]);
                strcat(obis_code, temp_obis);
              }
              sprintf(temp_obis, "%d", uart_buffer_[i + 6]);
              strcat(obis_code, temp_obis);
              ESP_LOGV("uart", "OBIS code found: %s message length: %d", obis_code, uart_buffer_[i + 7]);
              obis_value = 0;
              if(uart_buffer_[i + 7] == 6) {
                for(uint8_t y = 0; y < 4; y++) {
                  obis_value += (long)uart_buffer_[i + 8 + y] << ((3-y) * 8);
                }
              } else if(uart_buffer_[i + 7] == 18) {
                for(uint8_t y = 0; y < 2; y++) {
                  obis_value += (long)uart_buffer_[i + 8 + y] << ((1-y) * 8);
                }
              }
              
              if(strcmp(obis_code, "1.1.1.7.0.255") == 0) {
                  ESP_LOGV("uart", "Wattage: %d", obis_value);
                  wattage_sensor->publish_state(obis_value);
              } else if (strcmp(obis_code, "1.1.31.7.0.255") == 0) {
                  ESP_LOGV("uart", "Amperage: %d", obis_value);
                  amperage_sensor->publish_state(obis_value);
              } else if (strcmp(obis_code, "1.1.32.7.0.255") == 0) {
                  ESP_LOGV("uart", "Voltage: %d", obis_value);
                  voltage_sensor->publish_state(obis_value);
              } else if (strcmp(obis_code, "1.1.1.8.0.255") == 0) {
                  ESP_LOGV("uart", "Energy Usage Last Hour: %d", obis_value);
                  energy_sensor->publish_state(obis_value);
              } else if (strcmp(obis_code, "1.1.4.7.0.255") == 0) {
                  ESP_LOGV("uart", "Reactive Power: %d", obis_value);
                  reactive_power_sensor->publish_state(obis_value);
              } else if (strcmp(obis_code, "1.1.4.8.0.255") == 0) {
                  ESP_LOGV("uart", "Reactive Power Last Hour: %d", obis_value);
                  reactive_energy_sensor->publish_state(obis_value);
              } else {
                ESP_LOGV("uart", "Unknown OBIS %s, value: %d", obis_code, obis_value);
              }
            }
            //strncat(uart_message, " ", 1);
            }
          ESP_LOGV("uart", "%d length received", uart_counter);
          //ESP_LOGI("uart", "%d length received: %s", uart_counter, uart_message);
          ESP_LOGV("uart", "Message length: %d", uart_message[3]);
          uart_counter = 0;
          uart_message[0] = '\0';
          strcpy(uart_message, "");
        } else {
          uart_counter = 0;
        }
      }
      uart_buffer_[uart_counter] = temp_byte;
      uart_counter++;
    }

    return false;
  }  
};

 

  • Like 1
  • Thanks 1
Lenke til kommentar
Del på andre sider

  • 2 uker senere...

mkay, bare stussa på at det skulle være nødvendig med software serial, men om problemet låg andre plasser er det en annen sak.

 

logger:
  hardware_uart: UART1
uart:
  id: uart_bus
  tx_pin: GPIO15
  rx_pin: GPIO13
  baud_rate: 2400

Burde fjerne behovet for software serial, med log output på GPIO02, bootloader og flashing på vanlig tx/rx og når esp har bootet bytte til å kjøre uart på GPIO15/GPIO13 mot mbus. har ikkje mottatt mbus-ttl adapter enda, men tenker skal teste ved anledning. esphome godtar hvertfall config
 

Endret av bearer
Lenke til kommentar
Del på andre sider

Jeg bytta til ESP32'en før koden for å lese seriedataen var på stell, så det er mulig at kræsjproblematikken er løst i etterkant av det uten at jeg har testa.

 

Det var det oppsettet jeg kjørte på 8266'en, og det funka sånn periodevis, bare hyppige reboots. Verd et forsøk vil jeg anslå:)

Endret av Preben
Lenke til kommentar
Del på andre sider

  • 4 måneder senere...
  • 4 uker senere...
  • 1 måned senere...

På tide å komme med en tilbakemelding her. Om ikke annet for å vise takknemlighet til @Preben som har delt denne.

 

Jeg hadde et ESP32 (esp32doit-devkit-v1) liggende og fikk tak i en MBUS-ttl.

 

ESP32: https://www.aliexpress.com/item/32834331647.html?spm=a2g0s.9042311.0.0.27424c4dUJ3YpK)

MBUS-TTL: https://www.aliexpress.com/item/32834331647.html?spm=a2g0s.9042311.0.0.27424c4dUJ3YpK

 

Relativt kjapt å lodde pinner på MBUS og koble sammen med Dupont-kabler. RJ lagde jeg selv med en sånn tang som man bruker til det.

 

ESPhome-oppsettet er jo ferdig fra @Preben og man kan i praksis kopiere inn alt nedenfor OTA og det vil fungere. Jeg la til TIME-komponenten for å få inn en sensor som måler daglig forbruk (total_daily_energy) og tok bort Temperatursensoren som  jeg ikke har. Siden jeg også bruker en sensor utenfor HA så la jeg til MQTT-komponenten.

 

Jeg hadde en liten USB nødlader liggende som jeg koblet mellom ESP32'en og strømuttak slik at ESP'en forblir online ved strømbrudd. Tenkte at jeg skulle sette opp en automasjon som sjekker datastrømmen og varsler hvis det er strømbrudd på måleren.

 

Nå tikker dataen inn fortløpende :)

 

Jeg har egentlig ikke nyttgjort meg av dataen særlig ennå med tanke på smartere oppvarming og slikt, men det kommer på sikt. Jeg har satt opp et dashboard i Grafana som begynner å gi innsikt i mitt forbruk og prisnivå. Jeg bruker Tibber til å få strømpriser,

 

Grafana:

image.thumb.png.b921966996508bf6c56b083f75811624.png

 

Min ESPhome-config:

esphome:
  name: mbus_kamstrup
  platform: ESP32
  board: esp32doit-devkit-v1
  includes:
    mbus.h

wifi:
  ssid: "xxx"
  password: "xxx"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "xxx"
    password: "xxx"

captive_portal:

mqtt:
  broker: 192.168.x.xxx
  port: 1883
  username: xxx
  password: xxx

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

time:
  - platform: sntp
    id: my_time

uart:
  id: uart_bus
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 2400
  
sensor:
  - platform: total_daily_energy
    name: "AMS Daily Energy"
    unit_of_measurement: kWh
    accuracy_decimals: 2
    power_id: ams_kw
  - platform: custom
    lambda: |-
      auto mbus_reader = new MbusReader(id(uart_bus));
      App.register_component(mbus_reader);
      return {mbus_reader->wattage_sensor, mbus_reader->reactive_power_sensor, mbus_reader->amperage_sensor, mbus_reader->voltage_sensor, mbus_reader->energy_sensor, mbus_reader->reactive_energy_sensor};
    
    sensors:
    - name: "AMS Wattage"
      unit_of_measurement: kW
      accuracy_decimals: 2
      id: ams_kw
      filters:
        - multiply: 0.001
    - name: "AMS Reactive Power"
      unit_of_measurement: VAr
      accuracy_decimals: 0
      internal: true
    - name: "AMS Amperage"
      unit_of_measurement: A
      accuracy_decimals: 2
      filters:
        - multiply: 0.01
    - name: "AMS Voltage"
      unit_of_measurement: V
      accuracy_decimals: 0
    - name: "AMS Hourly Energy"
      unit_of_measurement: kWh
      accuracy_decimals: 2
      filters:
        - multiply: 0.001
    - name: "AMS Hourly Reactive Energy"
      unit_of_measurement: kVArh
      accuracy_decimals: 3
      internal: true
      filters:
        - multiply: 0.01

 

Tusen takk til @Preben som delte med oss :)

Endret av Mathias
  • Like 1
Lenke til kommentar
Del på andre sider

  • 8 måneder senere...
  • 4 uker senere...
On 08/11/2020 at 15:13, 1v4r said:

Strålende @Mathias og @Preben! Jeg har fått tak i de to modulene du (Mathias) viser til men skulle gjerne hatt et koblingskjema. Jeg har forresten Aidon-måler så regner med jeg må gjøre noen endringer i OBIS-parsingen for å få dette til å spille.

 

Du kan jo ta en titt her: https://www.nek.no/wp-content/uploads/2018/10/AMS-HAN-Port-Smart-Hus-og-Smart-Bygg-Gjør-det-selv-og-Pilotprosjekter-ver-1.16.pdf

 

:) 

Lenke til kommentar
Del på andre sider

  • 3 uker senere...

Tusen takk for denne tråden @Preben og takk til @Mathias for ytterligere informasjon.

 

Dette ser ut som et interessant prosjekt. Delene er jo ganske billig, men uten strømuttak i sikringsskapet kan det fort bli dyrt med elektriker. Er det noen som vet hvor mange mA man kan få fra HAN-porten og om det i det hele tatt kan være mulig å bruke strømmen herfra, eller er den altfor lav og helt umulig?

 

Alternativet er ZigBee (ZHA) (https://www.elektroimportoren.no/develco-emi-norsk-han/4514731/Product.html), noe dyr men billigere en elektriker.

Lenke til kommentar
Del på andre sider

  • 11 måneder senere...

@Preben Må få begynne med å takke deg for denne 😁

 

Jeg har dog litt issues med å få dette til å fungere skikkelig.
yaml filen validerer korrekt, den bygger helt fint (plukker opp mbus.h)
Men når den har flashet esp32'en så nekter esp32'en å koble på WIFI. Den bare står og scanner ut fra log output'en når jeg kobler til med serial.
Den scanner og finner nettverk, det den skal koble seg til er også på listen over nettverk den finner. men kobler ikke til. Står bare og scanner om og om igjen.

Flasher jeg med en helt "clean" yaml fil så kobler den seg opp helt fint opp på WIFI.

(Har også prøvd 2 forskjellige esp32'er)

 

Noen som har hatt det problemet før?

 

Ja, nå funka det... 🤦‍♂️
Tok kopi av alle yaml filene, sletta hele esphome from home assistant og startet helt på nytt.
Må ha vært noe rusk en plass.

Endret av ruant
  • Like 1
Lenke til kommentar
Del på andre sider

  • 1 måned senere...

Bli med i samtalen

Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

Gjest
Skriv svar til emnet...

×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

  Du kan kun bruke opp til 75 smilefjes.

×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.

 Del

×
×
  • Opprett ny...