invandy / Oregon_NR

Arduino library for Oregon Scientific and Explore Scientific wireless sensors decode and simulate
Other
31 stars 21 forks source link

Ошибка при компиляции в ESPHome #13

Open Igor-kr opened 3 years ago

Igor-kr commented 3 years ago

Спасибо за библиотеку. На Ардуино работает, хочу отправлять данные в HomeAssistant используя ESPHome но на первом этапе

при компиляции для ESP32 выдает ошибку:

/igor/Library/Arduino15/packages/esp32/hardware/esp32/1.0.4/variants/nodemcu-32s -I/Users/igor/Documents/Arduino/libraries/Oregon_NR /var/folders/ft/ghv3fbyd6_xbwrbg8k4pm2_r0000gn/T/arduino_build_527710/sketch/Receiver.ino.cpp -o /var/folders/ft/ghv3fbyd6_xbwrbg8k4pm2_r0000gn/T/arduino_build_527710/preproc/ctags_target_for_gcc_minus_e.cpp -DARDUINO_LIB_DISCOVERY_PHASE Receiver:3:36: error: missing expression between '(' and ')'

if defined ( ESP8266 ) || ( ESP32 )// Для Wemos

                                ^

Используем библиотеку Oregon_NR версии 20.10.10 из папки: /Users/igor/Documents/Arduino/libraries/Oregon_NR exit status 1 missing expression between '(' and ')'

invandy commented 3 years ago

Скорее всего у вас не определено ESP8266 или ESP32 Попробуйте заменить на

if defined ( ESP32 )

Если не поможет, можно попробовать убрать все предпроцессорные директивы и оставить только нужный конструктор.

invandy commented 3 years ago

Заодно скачайте библиотеку заново, там как раз для ESP только что подправил скетч.

Igor-kr commented 3 years ago

Здравствуйте,

include

define ESP32

if defined ( ESP8266 ) || ( ESP32 )// Для Wemos

выдает ошибку

include

define ESP32

if defined ( ESP32 ) || ( ESP8266 )// Для Wemos

компилируется в IDE Arduino и работает нормально

При попытке скомпилировать для ESPHOME

файл my_oregon.h

include "esphome.h"

include "Oregon_NR.h"

//Oregon_NR oregon(13, 13, 2, true); class MyOregonSensor : public PollingComponent { public: Oregon_NR oregon(13,13,2,true);

// Oregon_NR oregon(13, 13, // приёмник на выводе D7 (GPIO13) // 2, true, // Светодиод на D2 подтянут к +пит(true). Если светодиод не нужен, то номер вывода - 255 // 50, true); // Буфер на приём посылки из 50 ниблов, включена сборка пакетов для v2

Sensor temperature_sensor = new Sensor(); Sensor humidity_sensor = new Sensor();

MyOregonSensor() : PollingComponent(15000) { }

void setup() override {

oregon.start(); 

// oregon.receiver_dump = 0; //true - Включает "осциллограф" - отображение данных, полученных с приёмника }

void update() override { // This is the actual sensor reading logic. float temperature = oregon.sens_tmp; temperature_sensor->publish_state(temperature);

float humidity = oregon.sens_hmdty;
humidity_sensor->publish_state(humidity);

} };

Компилятор ругается на конструктор класса

Dependency Graph |-- 1.1.1 |-- 1.0 | |-- 1.0 |-- 20.10.7 |-- 1.0 |-- 1.2.7 | |-- 1.1.1 | |-- 1.0 | |-- 1.0 |-- 1.1.0 | |-- 1.0 |-- 1.0 |-- 1.0 Compiling .pioenvs/oregon_rx/src/main.cpp.o In file included from src/main.cpp:15:0: src/my_oregon.h:6:20: error: expected identifier before numeric constant Oregon_NR oregon(13, 13, 2, true); ^ src/my_oregon.h:6:20: error: expected ',' or '...' before numeric constant In file included from src/main.cpp:15:0: src/my_oregon.h: In member function 'virtual void MyOregonSensor::setup()': src/my_oregon.h:19:5: error: '((MyOregonSensor)this)->MyOregonSensor::oregon' does not have class type oregon.start(); ^ src/my_oregon.h: In member function 'virtual void MyOregonSensor::update()': src/my_oregon.h:25:25: error: '((MyOregonSensor)this)->MyOregonSensor::oregon' does not have class type float temperature = oregon.sens_tmp; ^ src/my_oregon.h:28:22: error: '((MyOregonSensor)this)->MyOregonSensor::oregon' does not have class type float humidity = oregon.sens_hmdty; ^ src/main.cpp: In lambda function: src/main.cpp:126:28: error: expected type-specifier before 'MyCustomSensor' auto my_sensor = new MyCustomSensor(); ^ src/main.cpp:128:72: error: could not convert '{, }' from '' to 'std::vector<esphome::sensor::Sensor>' return {my_sensor->temperature_sensor, my_sensor->humidity_sensor}; ^ Compiling .pioenvs/oregon_rx/FrameworkArduino/FunctionalInterrupt.cpp.o Compiling .pioenvs/oregon_rx/FrameworkArduino/HardwareSerial.cpp.o *** [.pioenvs/oregon_rx/src/main.cpp.o] Error 1 Compiling .pioenvs/oregon_rx/FrameworkArduino/IPAddress.cpp.o ========================= [FAILED] Took 150.17 seconds =========================

invandy commented 3 years ago

Так я не понял? В Arduino IDE пример с приёмником под ESP32 тоже не компилируется?

Igor-kr commented 3 years ago

В Arduino IDE компилируется без ошибок и принимает данные (вижу в мониторе порта).

Когда пытаюсь использовать вашу библиотеку, создаю Custom Sensor для EspHome и объявляю класс Как здесь описано

https://esphome.io/components/sensor/custom.html

public:
Oregon_NR oregon(13,13,2,true);

Компилятор , они используют PlatformIO ругается на это (13,13,2,true);

Compiling .pioenvs/oregon_rx/src/main.cpp.o
In file included from src/main.cpp:15:0:
src/my_oregon.h:6:20: error: expected identifier before numeric constant
Oregon_NR oregon(13, 13, 2, true);
^
src/my_oregon.h:6:20: error: expected ',' or '...' before numeric constant

In file included from src/main.cpp:15:0:
src/my_oregon.h: In member function 'virtual void MyOregonSensor::setup()':
src/my_oregon.h:19:5: error: '((MyOregonSensor*)this)->MyOregonSensor::oregon' does not have class type
oregon.start();
^

Вот мой заголовочный файл для ESPHOME

#include "esphome.h"
#include "Oregon_NR.h"

class MyOregonSensor : public PollingComponent {
 public:

  Oregon_NR oregon(13,13,2,true);

  Sensor *temperature_sensor = new Sensor();
  Sensor *humidity_sensor = new Sensor();

  MyOregonSensor() : PollingComponent(15000) { }

  void setup() override {

    oregon.start(); 
//    oregon.receiver_dump = 0;       //true - Включает "осциллограф" - отображение данных, полученных с приёмника
  }

  void update() override {
    // This is the actual sensor reading logic.
    float temperature = oregon.sens_tmp;
    temperature_sensor->publish_state(temperature);

    float humidity = oregon.sens_hmdty;
    humidity_sensor->publish_state(humidity);
  }
};
esphome:
  name: oregon_rx
  platform: ESP32
  board: nodemcu-32s
  includes:
    - "my_oregon.h"
  libraries:
    - "https://github.com/invandy/Oregon_NR.git"  

wifi:
  ssid: secret
  password: secret

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

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

# Example configuration entry
sensor:
- platform: custom
  lambda: |-
    auto my_sensor = new MyOregonSensor();
    App.register_component(my_sensor);
    return {my_sensor->temperature_sensor, my_sensor->humidity_sensor};

  sensors:
  - name: "My Custom Temperature Sensor"
    unit_of_measurement: °C
    accuracy_decimals: 1
  - name: "My Custom Humidity Sensor"
    unit_of_measurement: "%"
    accuracy_decimals: 1

Может быть как то по другому можно инициализировать класс? Извиняюсь за глупые вопросы но не програмист я :)

invandy commented 3 years ago

Так вот сходу не скажу, как решить ваш вопрос, надо же тщательно разобраться в вашей инструкции по подключению

invandy commented 3 years ago
#include "esphome.h"
#include "Oregon_NR.h"

class MyOregonSensor  : public Component, public Sensor 
{
  public:
   Oregon_NR oregon{13,13,2,true};
   Sensor *temperature_sensor = new Sensor();
   Sensor *humidity_sensor = new Sensor();

   void setup() override {oregon.start();}

   void loop() override 
   {
     oregon.capture(0);
     if (oregon.captured) 
     {
      temperature_sensor -> publish_state(oregon.sens_tmp);
      humidity_sensor -> publish_state(oregon.sens_hmdty);
     }
   }
};
Igor-kr commented 3 years ago

Спасибо ! Все с компилировалось, вечером проверю с реальными датчиками.

invandy commented 3 years ago

Тут вот ещё что хотелось отметить.

  1. Концептуально вы немого неверно пытаетесь зарегистрировать датчик в системе. Дело в том, что вы регистрируете канал данных, по которому можно получать информацию от целого комплекса датчиков., поэтому, для регистрации одного датчика надо делать вот так:

if (oregon.captured && oregon.sens_type == THGN132) { temperature_sensor -> publish_state(oregon.sens_tmp); humidity_sensor -> publish_state(oregon.sens_hmdty); }

т.к. захват пакета ещё не означает, что он есть. Просто приёмнику показалось, что в эфире появилась преамбула. Надо обозначить - от какого датчика считывать данные.

  1. В сильно нагруженном процессоре приём может ухудшиться по банальной причине, что просто не будет хватать времени следить за каналом. В таком случае правильным будет решить этот вопрос аппаратно - выделить отдельную платку, которая будет заниматься только этим вопросом
Igor-kr commented 3 years ago

Добрый день,

Вобщем этот код почти заработал

#include "esphome.h"
#include "Oregon_NR.h"

class MyOregonSensor : public Component, public Sensor 
{
public:
Oregon_NR oregon{13,13,2,true};
Sensor *temperature_sensor = new Sensor();
Sensor *humidity_sensor = new Sensor();
Sensor *battery_sensor = new Sensor();

void setup() override 
{
//вкючение прослушивания радиоканала  
  oregon.start(); 
}
void loop() override
{
  oregon.capture(0); // 1 - выводить в Serial сервисную информацию

  if (oregon.captured && oregon.sens_type == THGN132)  {
  temperature_sensor -> publish_state(oregon.sens_tmp); 
  humidity_sensor -> publish_state(oregon.sens_hmdty);
  battery_sensor -> publish_state(oregon.sens_battery);
  };
yield();  
}
};

Компилируется, в мониторе USB вижу


[redacted]▂▄▆█
[10:41:21][W][wifi:394]: No matching network found!
[10:41:21][D][sensor:092]: 'My Custom Temperature Sensor': Sending state 23.30000 °C with 1 decimals of accuracy
[10:41:21][D][sensor:092]: 'My Custom Humidity Sensor': Sending state 13.00000 % with 1 decimals of accuracy
[10:41:21][D][sensor:092]: 'Battery': Sending state 1.00000  with 0 decimals of accuracy
[10:41:26][D][wifi:324]: Starting scan...
[10:41:28][D][wifi:339]: Found networks:

даже выводит результаты на OLED дисплей, но ровно до того момента пока нет подключения к WiFi сети. Как только соединение установлено, прием прекращается, Видимо какая то не совместимость с WiFi билиотекой от EspHome.

Кстати когда создаешь новый проект при первой компиляции ругается на ошибки:

.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:1622:25: warning: extra tokens at end of #ifdef directive
 #ifdef ADD_SENS_SUPPORT == 1
                         ^
In file included from .piolibdeps/oregon_rx/Oregon_NR/Oregon_TM.cpp:1:0:
.piolibdeps/oregon_rx/Oregon_NR/Oregon_TM.h:49:11: warning: ISO C++11 requires whitespace after the macro name
 #define THТ800    0xС844
           ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp: In member function 'void Oregon_NR::get_tacts(byte*, int)':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:710:10: warning: value computed is not used [-Wunused-value]
    *cdp++;
          ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:730:12: warning: value computed is not used [-Wunused-value]
      *cdp++;
            ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:813:10: warning: value computed is not used [-Wunused-value]
    *cdp++;
          ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:826:10: warning: value computed is not used [-Wunused-value]
    *cdp++;
          ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:867:12: warning: value computed is not used [-Wunused-value]
      *cdp++;
            ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp: In member function 'int Oregon_NR::get_info_data(byte*, byte*, byte*)':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:1255:11: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses]
   if (ver == 2 & csm > 22) return 0; 
           ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:1257:11: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses]
   if (ver == 3 & csm > 30) return 0; 
           ^
Archiving .pioenvs/oregon_rx/libd94/libWiFi.a
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp: In member function 'int Oregon_NR::get_data(int, byte, byte*)':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:1001:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp: In member function 'float Oregon_NR::get_temperature(byte*)':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:1323:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
Indexing .pioenvs/oregon_rx/libd94/libWiFi.a
.piolibdeps/oregon_rx/Oregon_NR/Oregon_TM.cpp: In member function 'void Oregon_TM::setChannel(byte)':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_TM.cpp:527:43: warning: 'channel_code' may be used uninitialized in this function [-Wmaybe-uninitialized]
       SendBuffer[2] += channel_code & 0xF0;
                                           ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp: In member function 'int Oregon_NR::get_info_data(byte*, byte*, byte*)':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:1278:37: warning: 'multipl' may be used uninitialized in this function [-Wmaybe-uninitialized]
     if (*code < 128 ) *vd += multipl;
                                     ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp: In member function 'float Oregon_NR::get_temperature(byte*)':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:1317:34: warning: 'tmprt' may be used uninitialized in this function [-Wmaybe-uninitialized]
     tmprt += *(oregon_data) * 0.1;
                                  ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp: In member function 'float Oregon_NR::get_rain_rate()':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:1547:34: warning: 'tmprt' may be used uninitialized in this function [-Wmaybe-uninitialized]
     tmprt += *(packet + 8) * 1000;
                                  ^
Compiling .pioenvs/oregon_rx/lib1e0/FS/FS.cpp.o
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp: In member function 'void Oregon_NR::capture(bool)':
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:480:46: warning: 'secresingV' may be used uninitialized in this function [-Wmaybe-uninitialized]
       for (int www = 0; www < (packet_length - secresingV + 2); www++)
                                              ^
.piolibdeps/oregon_rx/Oregon_NR/Oregon_NR.cpp:471:22: warning: 'result_data' may be used uninitialized in this function [-Wmaybe-uninitialized]
     if (get_info_data(result_data, packet, valid_p))
                      ^

Не знаю имеет это значение или нет.

invandy commented 3 years ago

Предупреждения компилятора по возможности подправлю в следующей версии. Не критично, но аккуратность прежде всего :) Потерю связи можно объяснить двумя причинами:

  1. Помехи. ESP и без того шумный проц, а с включённым вайфаем может давать много шума в широком диапазоне частот. Я бы отнёс приёмник с антенной от ESP подальше.
  2. Как я и говорил, ESP может быть в вашем случае сильно нагружен и у него просто нет времени, чтобы вовремя отслеживать сигнал с приёмника. Решение тут одно - ставить отдельный микроконтроллер для радиоприёмника, чтобы он занимался ловлей пакетов и их буферизацией.
Igor-kr commented 3 years ago

Добрый день, спасибо за помощь! Вчера проверил - приемник на проводах отодвинул метра на 2 результат тот же. Видимо ЕСП шке не хватает времени обработать все правильно когда WiFi включен. Отрицательный результат - тоже результат! Решил принимать на Ардуину и по serial закину в HomeAssistant

   StaticJsonDocument<100> jsonBuffer;

  jsonBuffer["temperature"] = oregon.sens_tmp;
  jsonBuffer["humidity"] = oregon.sens_hmdty;
  jsonBuffer["battery"] = oregon.sens_battery;

  serializeJson(jsonBuffer, Serial);
  Serial.println();   

Должно сработать.

Попутно возник вопрос можно ли при помощи вашей библиотеки принять и декодировать синалы от этого устройства:

https://github.com/JackKelly/rfm_edf_ecomanager/wiki/Technical-details-of-Current-Cost-RF-protocol

Было бы здорово!

invandy commented 3 years ago

Попутно возник вопрос можно ли при помощи вашей библиотеки принять и декодировать синалы от этого устройства:

https://github.com/JackKelly/rfm_edf_ecomanager/wiki/Technical-details-of-Current-Cost-RF-protocol

Ну, если вы найдёте подходящий приёмник с FSK модуляцией, то теоретически можно. Но надо будет с нуля писать декодировщик

macros0 commented 3 years ago

Вчера проверил - приемник на проводах отодвинул метра на 2 результат тот же. Видимо ЕСП шке не хватает времени обработать все правильно когда WiFi включен. Отрицательный результат - тоже результат!

Но ведь на esp8266 у меня работает передача в https://blynk.io/ не ужели на столько проседает производительность из-за интеграции с HA? Просто метод loop() вызывается 60 раз в секунду, и публиковать значение в нем нельзя!

Мне кажется нужно использовать:

  1. PollingComponent вместо Component
  2. в методе loop() оставить только oregon.capture(0);
  3. в методе update(): if (oregon.captured && oregon.sens_type == THGN132) { temperature_sensor -> publish_state(oregon.sens_tmp); humidity_sensor -> publish_state(oregon.sens_hmdty); battery_sensor -> publish_state(oregon.sens_battery); };

наверное в п.2 лучше сохранять в переменные (обернув проверками (oregon.captured) и (oregon.crc_c)) и в п.3 выводить уже переменные

eagle23 commented 3 years ago

Если кому еще интересно данный вопрос. То вот мои изыскания )) Никак не мог заставить работать связку esp8266 + ESPHome + Oregon_NR В итоге выяснил, что задержка в методе loop равна 16ms, что для библиотеки Oregon_NS очень высока. Понизив ее, мы заставим работать обе библиотеки работать как надо. Тут приходит на помощь два варианта: Добавить в метод setup своего компонента строчку: App.set_loop_interval(1);

Либо сделать так, как предлагают в комментарий исходного кода (в документации этого не нашел):

  • Each component can request a high frequency loop execution by using the HighFrequencyLoopRequester
  • helper in helpers.h

https://github.com/esphome/esphome/blob/5c86f332b269fd3e4bffcbdf3359a021419effdd/esphome/core/application.h#L111

Добавляем HighFrequencyLoopRequester и стартуем в его в setup В итоге мой компонент выглядит так:

#include "esphome.h"
#include "Oregon_NR.h"

static char const *TAG = "custom.oregon";

class MyOregonSensor : public Component, public Sensor
{
public:
    Oregon_NR oregon = Oregon_NR{14, 14, 2, true};
    HighFrequencyLoopRequester high_freq_;

    Sensor *temperature_sensor = new Sensor();
    Sensor *humidity_sensor = new Sensor();
    Sensor *battery_sensor = new Sensor();

    float get_setup_priority() const override { return esphome::setup_priority::LATE; }

    void setup() override
    {
        // App.set_loop_interval(1); // так тоже работает
        this->high_freq_.start();
        ESP_LOGD(TAG, "SETUP OREGON SENSOR");
        oregon.start();
    }

    void loop() override
    {
        oregon.capture(0); // 1 - выводить в Serial сервисную информацию

        if (oregon.captured && oregon.crc_c)
        {
            ESP_LOGD(TAG, "OREGON SENSOR CAPTURED");

            temperature_sensor->publish_state(oregon.sens_tmp);
            humidity_sensor->publish_state(oregon.sens_hmdty);
            battery_sensor->publish_state(oregon.sens_battery);
        }

        yield();
    }
};

После чего у меня все заработало.

invandy commented 3 years ago

Это, ИМХО, работоспособное, но не идеальное решение. При наличии большого количества разношёрстных датчиков в системе времени на прослушивание радиоэфира будет оставаться всё меньше и меньше, что приведёт к пропускам пакетов от радиодатчиков. Они же не по запросу данные выдают, а по таймеру. Тут нужно уже либо реализовывать тайм-слоты и слушать радиоэфир в нужные моменты времени, либо решать вопрос аппаратно, как я предлагал раньше.

eagle23 commented 3 years ago

К сожалению, мои познания в c++ очень скромны, поэтому довольствуюсь, тем что есть )