jplitza / esphome_components

Custom-made components that I use for ESPHome.
GNU General Public License v3.0
11 stars 12 forks source link

Can't connect to (read) OBIS meter #9

Closed evlo closed 2 years ago

evlo commented 2 years ago

I'm using this code, but I get no reading from the meter, i wonder what can be wrong

esphomeyaml:
  name: test
  platform: ESP8266
  board: esp01

logger:
  baud_rate: 0
  level: DEBUG

uart:
  id: uart_bus
  tx_pin: 1
  rx_pin: 3
  baud_rate: 300
  debug:

obis:
  uart_id: uart_bus
  force_update:
    interval: 100
    payload: "\x2F\x3F\x21\x0D\x0A"

sensor:
  - platform: obis
    channel: "1.8.0"
    name: "Power Meter"
    unit_of_measurement: "kWh"
    accuracy_decimals: 3

text_sensor:
  - platform: obis
    channel: "0.0.0"
    name: "Serial Number"

external_components:
  - source: github://jplitza/esphome_components

before that I tries esphome "SML", but it complained that "1.8.0" is not valid and anyway i can't send "\x2F\x3F\x21\x0D\x0A" or at least i do not know how to make it send that

Before this i tried tasmota

>D
>B
->sensor53 r
>M 1
+1,3,o,0,300,ZE312,1,100,2F3F210D0A

and was able to get reading, but was never able to use tasmota to parse the results into sensors and also tasmota does not like me :)

16:25:54    [I] [ota:105]   
Boot seems successful, resetting boot loop counter.
16:25:55    [D] [uart_debug:114]    
>>> 2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A
16:26:00    [D] [uart_debug:114]    
>>> 2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A
16:26:05    [D] [uart_debug:114]    
>>> 2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A
16:26:10    [D] [uart_debug:114]    
>>> 2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A:2F:3F:21:0D:0A

This is the output i'm getting, i do not understand why the message is repeated

also esp01 i have has only 1MB of memory so no OTA really, i will try some with larger memory later maybe

this is output from the meter

11:52:28.479 : �m/ZPA5ZE312.v10_022
11:52:32.179 : �C.1.0(I removed number in brackets here)
11:52:33.013 : 0.0.0(I removed number in brackets here)
11:52:33.746 : 0.3.0(10000*imp/kWh)
11:52:34.179 : F.F(000000)
11:52:34.980 : 1.8.0(0031410.557*kWh)
11:52:35.779 : 1.8.1(0016127.292*kWh)
11:52:36.580 : 1.8.2(0015283.265*kWh)
11:52:37.413 : 21.8.0(0007562.910*kWh)
11:52:38.247 : 41.8.0(0016305.829*kWh)
11:52:39.079 : 61.8.0(0007541.821*kWh)
11:52:39.879 : 2.8.0(0000000.000*kWh)
11:52:40.714 : 22.8.0(0000000.000*kWh)
11:52:41.547 : 42.8.0(0000000.000*kWh)
11:52:42.381 : 62.8.0(0000000.000*kWh)
11:52:43.014 : C.8.1(0211082009)
11:52:43.647 : C.8.2(0204240034)
11:52:44.281 : C.8.0(0400042218)
11:52:44.948 : C.82.0(0000000000)
11:52:45.515 : C.7.1(00000002)
11:52:46.080 : C.7.2(00000003)
11:52:46.647 : C.7.3(00000005)
11:52:47.615 : 0.2.1(ver.02, 100830, B526)
11:52:48.248 : C.2.1(1505031020)
11:52:48.881 : C.2.9(1505031020)
11:52:49.515 : C.3.9(0000000000)
11:52:49.615 : !
jplitza commented 2 years ago

Your output shows that the trigger is sent by esphome, but no reply is seen. To my understanding, your settings are equivalent to the Tasmota example you provided.

Can you set the dummy_receiver option under uart.debug? Maybe the meter is answering but my component somehow fails to read the answer.

jplitza commented 2 years ago

Closing since I cannot debug this without further information.

evlo commented 2 years ago
uart:
  id: uart_bus
  tx_pin: GPIO21
  rx_pin: GPIO20  
  baud_rate: 300
  data_bits: 7
  stop_bits: 1
  parity: EVEN
  debug: 
    direction: BOTH
    dummy_receiver: false
    after:
      delimiter: "\n"
    sequence:
      - lambda: UARTDebug::log_string(direction, bytes);

this is what i do get with

interval:
  - interval: 61sec
    then:
      - uart.write:
          id: uart_bus
          data: [0x2F, 0x3F, 0x21, 0x0D, 0x0A]

image

I think the main issue is that

void OBISBase::read_line() {
  while (this->available()) {     while (this->available()) {

never actually happens - "it is never available"

jplitza commented 2 years ago

Is that with the obis component included in the config, or without? Because to my understanding, with dummy_receiver: false, something has to read the uart bus in order for the debug to actually be printed.

What's the output without the interval component, only with obis?

evlo commented 2 years ago

image

It works! Sorry, I was being stupid and confused and was trying to modify your code while what i missed was this part

  baud_rate: 300
  data_bits: 7
  stop_bits: 1
  parity: EVEN

really. And when i figured that out i did not try again with your original code.

current config:

uart:
  id: uart_bus
  tx_pin: GPIO21
  rx_pin: GPIO20  
  baud_rate: 300
  data_bits: 7
  stop_bits: 1
  parity: EVEN
  debug: 
    direction: BOTH
    dummy_receiver: false
    after:
      delimiter: "\n"
    sequence:
      - lambda: UARTDebug::log_string(direction, bytes);

obis:
  uart_id: uart_bus
  force_update:  # optional
    interval: 10000
    payload: "\x2F\x3F\x21\x0D\x0A"

sensor:
  - platform: obis
    name: "L1"
    channel: "21.8.0"
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

text_sensor:
  - platform: obis
    channel: "0.0.0"
    name: "Serial Number"

I do not understand why it sends payload for each line or if it reads each line after interval, but at least now it works. I guess 300 baud is also quite slow, but that is only way this meter communicates with me.

Thank you so much for your help.

evlo commented 2 years ago

I'm thinking that maybe the code should be more like this so it does parse all the lines in the obs_buffer

ESP_LOGVV(TAG, "Received: '%s'", this->buf);
      this->handle_line(this->buf);

      this->index = 0;

      ESP_LOGD(TAG, "Iterating return from meter");
      read_line();

      break;
    }    

but again, thi is the first time i'm trying to do anything with cpp

jplitza commented 2 years ago

Great that it works now!

You are right, there is a logic bug in the part that sends the trigger and then only reads one line. And maybe just removing the break you cited would fix that (instead of causing the recursion you suggest). BUT I'm more inclined to go a different path: You mentioned the interval: component earlier (which I didn't know about). Is it possible to simply use them together like this?

uart:
  id: uart_bus
  tx_pin: GPIO21
  rx_pin: GPIO20  
  baud_rate: 300
  data_bits: 7
  stop_bits: 1
  parity: EVEN
  debug: 
    direction: BOTH
    dummy_receiver: false
    after:
      delimiter: "\n"
    sequence:
      - lambda: UARTDebug::log_string(direction, bytes);

interval:
  - interval: 10sec
    then:
      - uart.write:
          id: uart_bus
          data: [0x2F, 0x3F, 0x21, 0x0D, 0x0A]

obis:
  uart_id: uart_bus

sensor:
  - platform: obis
    name: "L1"
    channel: "21.8.0"
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

text_sensor:
  - platform: obis
    channel: "0.0.0"
    name: "Serial Number"

Because it sure sounds like ESPhome is already providing everything that is needed to trigger the meter to send the data, and I could just add that to the example config and get rid of the PollingOBISComponent again (which I cannot test anyway since my meter sends the data periodically).

evlo commented 2 years ago

That works too, i thought that the obis component would only parse uart after it sends the payload, so i did not even tried it like that.

Thanks again.

jplitza commented 2 years ago

Thank you for testing! I've documented the use of the interval component in 891e392bf462cf0839cfed2ec4104992ea1fe203 and removed the force_update stuff again.