ESP Home - Java script issue

Im not great at Java script, however someone might know why I am getting errors when trying to install my config to the ESP8266 D1 mini

These are the files.

The first one is the ESPhome yaml file that references the second file.
The error is at the bottom of this post.
Any help would be appreciated

ESP Home Yaml file - xantrex.yaml

esphome:
  name: xantrex
  friendly_name: xantrex
  includes:
  - xantrex.h

esp8266:
  board: d1_mini


# Enable logging
logger:
  level: DEBUG
  esp8266_store_log_strings_in_flash: False

# Enable Home Assistant API
api:
  encryption:
    key: ""-------------------------------"

ota:
  password: "----------------------------------------"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Xantrex Fallback Hotspot"
    password: "------------------------"

captive_portal:

uart:
  id: uart_bus
  baud_rate: 9600
  tx_pin: D4
  rx_pin: D3

sensor:
  - platform: custom 
    lambda: |-
      auto my_xantrex = new Xantrex(id(uart_bus));
      App.register_component(my_xantrex);
      return {my_xantrex->kwhlife_sensor, my_xantrex->kwhtoday_sensor,
        my_xantrex->pin_sensor, my_xantrex->pout_sensor,
        my_xantrex->vin_sensor, my_xantrex->vout_sensor,
        my_xantrex->iin_sensor, my_xantrex->iout_sensor,
        my_xantrex->freq_sensor, my_xantrex->time_sensor, my_xantrex->temp_sensor,
        };
      
    sensors:
    - name: "PV kWh life"
      unit_of_measurement: "kWh"
      accuracy_decimals: 0
    - name: "PV kWh today"
      unit_of_measurement: "kWh"
      accuracy_decimals: 3
    - name: "PV Power In"
      unit_of_measurement: "W"
      accuracy_decimals: 0
      id: 'watts_in'
    - name: "PV Power Out"
      unit_of_measurement: "W"
      accuracy_decimals: 0
    - name: "PV Voltage In"
      unit_of_measurement: "V"
      accuracy_decimals: 1
    - name: "PV Voltage Out"
      unit_of_measurement: "V"
      accuracy_decimals: 1
    - name: "PV Current In"
      unit_of_measurement: "A"
      accuracy_decimals: 2
    - name: "PV Current Out"
      unit_of_measurement: "A"
      accuracy_decimals: 2
    - name: "PV Frequency"
      unit_of_measurement: "Hz"
      accuracy_decimals: 3
    - name: "PV Time"
      unit_of_measurement: "seconds"
      accuracy_decimals: 0
    - name: "PV Temperature"
      unit_of_measurement: "Ā°C"
      accuracy_decimals: 1  
      
#Calculate kWh of Solar Generation
  - platform: template
    name: Solar kWh Generation
    id: solar_kWh
    lambda: return id(watts_in).state * 1 / 1000;
    accuracy_decimals: 2
    unit_of_measurement: kWh
    update_interval: 60s 

The second file xantrex.h is referenced by the Yaml file above

#include "esphome.h"


class Xantrex : public Component, public UARTDevice {

 public:
  Sensor *kwhlife_sensor = new Sensor();
  Sensor *kwhtoday_sensor = new Sensor();
  Sensor *pin_sensor = new Sensor();
  Sensor *pout_sensor = new Sensor();
  Sensor *vin_sensor = new Sensor();
  Sensor *vout_sensor = new Sensor();
  Sensor *iin_sensor = new Sensor();
  Sensor *iout_sensor = new Sensor();
  Sensor *freq_sensor = new Sensor();
  Sensor *time_sensor = new Sensor();
  Sensor *temp_sensor = new Sensor();

  Xantrex(UARTComponent *parent) : Component(), UARTDevice(parent) {}

  bool response_pending = false;
  unsigned long poll_time, response_time;
  const int RESPONSE_WAIT = 2500; // Wait for reply to each rs232 command
  const int POLL_WAIT = 300000;   // Overall poll cycle for Xantrex sensor values
                                  // Should be at least as long as RESPONSE_WAIT * number of sensors
  int elapsed_time;

  const char *queries[11] = { "KWHLIFE?\r", "KWHTODAY?\r", "PIN?\r", "POUT?\r",
    "VIN?\r", "VOUT?\r", "IIN?\r", "IOUT?\r",
    "FREQ?\r", "TIME?\r", "MEASTEMP?\r" };
  int queryNum = 0;

  void setup() override {
    // Start the timers
    poll_time = millis()-POLL_WAIT;
    response_time = poll_time;
    response_pending = false;
    // So the readStringUntil doesn't block if no response
    setTimeout(30);
  }

  void loop() override {
 
    String line = "";

    if (response_pending) {
      // wait after command before checking for a response
      elapsed_time = (millis() - response_time);
      if (elapsed_time > RESPONSE_WAIT) {
        if (available()>0) {
          line = readStringUntil('\r');
          int space = 0;
          String celsius = "";
          switch(queryNum) {
            case 0:
              kwhlife_sensor->publish_state(line.toFloat());
              break;
            case 1:
              kwhtoday_sensor->publish_state(line.toFloat());
              break;
            case 2:
              pin_sensor->publish_state(line.toFloat());
              break;
            case 3:
              pout_sensor->publish_state(line.toFloat());
              break;
            case 4:
              vin_sensor->publish_state(line.toFloat());
              break;
            case 5:
              vout_sensor->publish_state(line.toFloat());
              break;
            case 6:
              iin_sensor->publish_state(line.toFloat());
              break;
            case 7:
              iout_sensor->publish_state(line.toFloat());
              break;
            case 8:
              freq_sensor->publish_state(line.toFloat());
              break;
            case 9:
              time_sensor->publish_state(line.toFloat());
              break;
            case 10:
              // Temp response format is: C:0.0 F:32.0
              // Extract the celsius part
              space = line.indexOf(" ");
              celsius = line.substring(2, space-2);
              temp_sensor->publish_state(celsius.toFloat());
              break;
            default:
              break;
          }
          line = "";
        }
        queryNum++;
        if (queryNum > 10) {
          queryNum=0;
        }
        response_pending = false;
      }
    }

    // check if polling wait time has elapsed for 1st command or 
    // subsequent command is due to be issued
    elapsed_time = (millis() - poll_time);
    if (elapsed_time > POLL_WAIT || (queryNum > 0 && !response_pending)) {
      // Issue next command
      write_str(queries[queryNum]);
      flush();
      response_pending = true;
      // Reset poll timer and start response timer
      response_time = millis();
      // Keep the overall cycle timer aligned to the 1st command
      if (queryNum == 0) {
        poll_time = millis();
      }
    }

  }
};

This is the error I get when trying to install

INFO ESPHome 2023.5.5
INFO Reading configuration /config/esphome/xantrex.yamlā€¦
INFO Generating C++ sourceā€¦
INFO Compiling appā€¦
Processing xantrex (board: d1_mini; framework: arduino; platform: platformio/[email protected])

HARDWARE: ESP8266 80MHz, 80KB RAM, 4MB Flash
Dependency Graph
|-- ESPAsyncTCP-esphome @ 1.2.3
|-- ESPAsyncWebServer-esphome @ 2.1.0
| |-- ESPAsyncTCP-esphome @ 1.2.3
| |-- Hash @ 1.0
| |-- ESP8266WiFi @ 1.0
|-- DNSServer @ 1.1.1
|-- ESP8266WiFi @ 1.0
|-- ESP8266mDNS @ 1.2
|-- noise-c @ 0.1.4
| |-- libsodium @ 1.10018.1
Compiling /data/xantrex/.pioenvs/xantrex/src/main.cpp.o
In file included from src/main.cpp:41:
src/xantrex.h: In member function ā€˜virtual void Xantrex::setup()ā€™:
src/xantrex.h:39:5: error: ā€˜setTimeoutā€™ was not declared in this scope; did you mean ā€˜set_timeoutā€™?
39 | setTimeout(30);
| ^~~~~~~~~~
| set_timeout
src/xantrex.h: In member function ā€˜virtual void Xantrex::loop()ā€™:
src/xantrex.h:51:18: error: ā€˜readStringUntilā€™ was not declared in this scope
51 | line = readStringUntil(ā€™\rā€™);
| ^~~~~~~~~~~~~~~
*** [/data/xantrex/.pioenvs/xantrex/src/main.cpp.o] Error 1
========================== [FAILED] Took 2.68 seconds ==========================

Thanks Danny

Not a problem, since we are talking C++, here :wink:
The only reference to readStringUntil I find is related to serial, which doesnā€™t seem relevant here.

I assume you copied that code from somewhere? If so, youā€™re likely missing a bit.

Thats how good I am, cant even work out whcih language it is. :grinning:
I got this from this site. Have bought all the parts, but just cant get around those 2 errors

https://www.google.com/url?sa=t&source=web&rct=j&url=https://thehomeautomator.com.au/xantrex-logging/amp/&ved=2ahUKEwjUjY2z9rf9AhWsA7cAHWpXCmoQFnoECAkQAQ&usg=AOvVaw13PSkVebzCpXZKkkUN0IAh

Code is too old :wink: Issue looks similar to

Thanks Chris. It does look very similar. A little above my skills to fix. Thanks for your help

If you try using my code from https://github.com/clockbrain/xantrex/tree/master rather than the code from https://thehomeautomator.com.au/xantrex-logging/ it will compile ok. I fixed that readStringUntil compile issue after The Home Automator had copied my original code and he hasnā€™t updated his copy.

My code also has class declarations in the yaml to support Home Assistant energy monitoring.

1 Like

Not too nice to have taken your code without attribution.
Besides the moral aspect, you run in exactly that kind of situations when ā€œstaticatingā€ code.

1 Like

Thanks Don and Chris for your replies. Don, I should have tried your code first. At least getting somewhere now.
The code is compiling on the D1mini and I can see each sensor in the logs each 2.5 seconds, but the state is showing 0 for each. I have checked all connections as well as switching the DB9 send and receive, but still canā€™t get anything to come through
Iā€™ll keep trying to see what I can find out.
Regards Danny

Its working now.

Again should have looked Donā€™s connection between the serial adaptor and the D1 mini.
Basically TX to D3 and RX to D4 and it worked.
Thanks Again

1 Like