Class ругается на функцию

здравствуйте! помогите разобраться что делаю не так.

Спойлер
// создаем обект класс
class Relay
{
 private:
 /* список свойств и методов для использования внутри класса */
 public:
  
  int _mqttTopicStatusRelay1 = mqttTopicStatusRelay1;
  int _relayStatus1 = relayStatus1;
  int _mqttRelayStatusOn2 = mqttRelayStatusOn2;
  int _mqttRelayStatusOff2 = mqttRelayStatusOff2;
  int _mqttRelayStatusRetained = mqttRelayStatusRetained;
  
 /* список методов доступных другим функциям и объектам программы */
// friend mqttClient.publish(mqttTopicStatusRelay1, (relayStatus1 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
 mqttClient.publish();
 
 protected:
 /*список средств, доступных при наследовании*/
};

это кусок на который ругается компилятор далее что пишет

Спойлер

‘wifiClient’ is not a type

скетч разбит на несколько кусков по разным вкладкам. без класса все работает. хотел написать класс-объект чтобы не прописывать одно и тоже. проблема возникает иммено с mqttClient.publish хотя в начале скетча он обявлен PubSubClient mqttClient(wifiClient); пробовал обявлять как FRIEND все равно компилятор его не видет.

Как компилятор может ругаться на слово, которого вообще нет в куске кода, на который он якобы ругается?

“в начале скетча” - что значит?

извиняюсь не то написал вот ответ компилятора ‘mqttClient’ does not name a type

Компилятор врать не будет, если так пишет, значит в этой части кода он объявления mqttClient не видит.

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

Лучше карпа ! ))

весь код работает и разбитый по вкладкам. просто хотел оптемезировать добавив класс чтобы не прописывать постоянно каждое реле. с прописанием реле нет проблем! все ок не могу понять почему компилатор не видит mqttClient и именно из класса.

// Управление реле без класса
void relayControl()
{
  // Новое состояние реле 1 отличается от текущего, требуется переключение
  if (relayCommand1 != relayStatus1) {
    relayStatus1 = relayCommand1;
    digitalWrite(gpioRelay1, relayStatus1);
    
    // Отправляем подтверждение, что команда получена и обработана
    mqttClient.publish(mqttTopicStatusRelay1, (relayStatus1 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
    
    // Можно вывести сообщение в лог
    Serial.print("Relay 1 has changed its state: ");
    Serial.println(relayStatus1 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2);
  };

  // Новое состояние реле 2 отличается от текущего, требуется переключение
  if (relayCommand2 != relayStatus2) {
    relayStatus2 = relayCommand2;
    digitalWrite(gpioRelay2, relayStatus2);

    // Отправляем подтверждение, что команда получена и обработана
    mqttClient.publish(mqttTopicStatusRelay2, (relayStatus2 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
    
    // Можно вывести сообщение в лог
    Serial.print("Relay 2 has changed its state: ");
    Serial.println(relayStatus2 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2);
  };

  // Новое состояние реле 3 отличается от текущего, требуется переключение
  if (relayCommand3 != relayStatus3) {
    relayStatus3 = relayCommand3;
    digitalWrite(gpioRelay3, relayStatus3);

    // Отправляем подтверждение, что команда получена и обработана
    mqttClient.publish(mqttTopicStatusRelay3, (relayStatus3 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
    
    // Можно вывести сообщение в лог
    Serial.print("Relay 3 has changed its state: ");
    Serial.println(relayStatus3 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2);
  };
}

вот так все работает

Честно говоря, я компилятор понимаю, потому что эту часть кода - тоже нифига не понимаю ))

Что это? Почему ЭТО стоит как метод класса Relay?

1 лайк

Не вижу противоречий. Внутри функции вы можете вызывать любые доступные методы любых доступных объектов. Но внутри класса объявить метод стороннего объекта методом своего класса? Может я чего не знаю?

1 лайк

Надо в свой класс по ссылке объект mqtt передавать.
Причем каждый раз новый, как только свой новый создаешь (вроде бы)…

значит надо передать в класс указатель на внешний обьект mqttClient

Только я вижу другой косяк в коде. Почему без класса вы вызываете метод publish() с парметрами

а в классе описали его без:

какой смысл в этом вызове?

1 лайк

Ну чтоже вот вся программа по вкладкам как есть
первая вкладка "основная’

Спойлер
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <OneWire.h>
PubSubClient mqttClient(wifiClient);
class Relay;

// Корневой сертификат ISRG Root x1, действителен до 4 июня 2035 года
static const char ISRG_Root_x1[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)EOF";
// Корневой сертификат
BearSSL::X509List certISRG(ISRG_Root_x1);
BearSSL::WiFiClientSecure wifiClient;
PubSubClient mqttClient(wifiClient);
/**************************************************************************
 * Настройки проекта
 *************************************************************************/
// Номера выводов для датчиков
const int gpioDHT22   = 5;
// Номера выводов для цифровых входов
const int gpioInput1  = 4;
// Номера выводов для подключения реле
const int gpioRelay1  = 12;
const int gpioRelay2  = 13;
const int gpioRelay3  = 15;

// Логические уровни для включения реле
// в данном случае предполагается, что реле включается высоким уровнем на выходе
const char lvlRelayOn  = 0x1;
const char lvlRelayOff = 0x0;

// Параметры подключения к WiFi
const char* wifiSSID  = "имя сети";
const char* wifiPASS  = "пароль";

// Параметры подключения к MQTT брокеру 
// Примечание: использовать статический mqttClientId оптимальнее с точки зрения фрагментации кучи, только не забывайте изменять его на разных устройствах
const char* mqttServer   = "wqtt";
const int   mqttPort     = 96;
const int   mqttPortTLS  = 87;
const char* mqttClientId = "esp8266";
const char* mqttUser     = "wqtt";
const char* mqttPass     = "wqtt";

// Топик LWT, одновременно это топик статуса устройства:
// - в рабочем состоянии в этом топике будет сообщение "online"
// - когда устройство по какой-либо причине отключится от сервера, сервер примерно через 60 секунд опубликует LWT "offline"
const char* mqttTopicDeviceStatus    = "demo/status";
const char* mqttDeviceStatusOn       = "online";    
const char* mqttDeviceStatusOff      = "offline";
const int   mqttDeviceStatusQos      = 1;
const bool  mqttDeviceStatusRetained = true; 

// Топики для внешнего управления реле
const char* mqttTopicControlRelay1   = "demo/relay1/control";
const char* mqttTopicControlRelay2   = "demo/relay2/control";
const char* mqttTopicControlRelay3   = "demo/relay3/control";
const int   mqttRelayControlQos      = 1;

// Топики для публикации состояния реле
const char* mqttTopicStatusRelay1    = "demo/relay1/status";
const char* mqttTopicStatusRelay2    = "demo/relay2/status";
const char* mqttTopicStatusRelay3    = "demo/relay3/status";

// Текстовое отображение для состояния реле
const char* mqttRelayStatusOn1       = "1";
const char* mqttRelayStatusOn2       = "on";
const char* mqttRelayStatusOff1      = "0";
const char* mqttRelayStatusOff2      = "off";
const bool  mqttRelayStatusRetained  = false; 

// Топики для публикации состояния цифровых входов
const char* mqttTopicStatusInput1    = "demo/input1/status";
const bool  mqttInputStatusRetained  = false; 
const char* mqttInputStatusHigh      = "0";
const char* mqttInputStatusLow       = "1";

// Топики для публикации температуры и влажности
const char* mqttTopicTemperature     = "demo/dht22/temperature";
const char* mqttTopicHumidity        = "demo/dht22/humidity";
const bool  mqttSensorsRetained      = false; 


/**************************************************************************
 * Глобальные переменные
 *************************************************************************/



// Текущее состояние реле
char relayStatus1 = lvlRelayOff;
char relayStatus2 = lvlRelayOff;
char relayStatus3 = lvlRelayOff;

// Полученное с MQTT ("новое") состояние реле
char relayCommand1 = lvlRelayOff;
char relayCommand2 = lvlRelayOff;
char relayCommand3 = lvlRelayOff;

// Текущее состояние цифровых входов
// Последнее опубликованное состояние реле
// Здесь маленькая хитрость: публикация в топик происходит только при наличии изменений
// (то есть когда inputStatus1 != digitalRead()), то при первом подключении ничего не будет опубликовано
// Дабы форсировать события, проинициализируем переменные заведомо ложными данными, которых не будет при любом состоянии входов
char inputStatus1 = 2;

// Датчик температуры и влажности
DHT dht(gpioDHT22, DHT22);

void setup() {
  // Настройка COM-порта
  Serial.begin(9600);
  Serial.println();
  Serial.println("Demo project FOR ESP8266");

  // Настройка выводов на вход
  pinMode(gpioInput1, INPUT);

  // Настройка выводов на выход
  pinMode(gpioRelay1, OUTPUT);
  pinMode(gpioRelay2, OUTPUT);
  pinMode(gpioRelay3, OUTPUT);

  // Сброс всех реле в исходное состояние "отключено"
  digitalWrite(gpioRelay1, relayStatus1);
  digitalWrite(gpioRelay2, relayStatus2);
  digitalWrite(gpioRelay3, relayStatus3);

  // Инициализация датчика температуры
  dht.begin();
}

void loop() {
  // Проверяем подключение к WiFi
  if (wifiConnected()) {
    // Подключение к WiFi установлено 
    if (mqttConnected()) {
      // Подключение к MQTT установлено 
      mqttClient.loop();
    };
  };

  // Управление реле
  relayControl();
  // Контроль состояния входов
 //readDigitalInputs();
  // температура влажность
 // temp_hum ();
}

вторая вкладка “работа с реле”

Спойлер
// Управление реле
void relayControl()
{
  // Новое состояние реле 1 отличается от текущего, требуется переключение
  if (relayCommand1 != relayStatus1) {
    relayStatus1 = relayCommand1;
    digitalWrite(gpioRelay1, relayStatus1);
    
    // Отправляем подтверждение, что команда получена и обработана
    mqttClient.publish(mqttTopicStatusRelay1, (relayStatus1 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
    
    // Можно вывести сообщение в лог
    Serial.print("Relay 1 has changed its state: ");
    Serial.println(relayStatus1 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2);
  };

  // Новое состояние реле 2 отличается от текущего, требуется переключение
  if (relayCommand2 != relayStatus2) {
    relayStatus2 = relayCommand2;
    digitalWrite(gpioRelay2, relayStatus2);

    // Отправляем подтверждение, что команда получена и обработана
    mqttClient.publish(mqttTopicStatusRelay2, (relayStatus2 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
    
    // Можно вывести сообщение в лог
    Serial.print("Relay 2 has changed its state: ");
    Serial.println(relayStatus2 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2);
  };

  // Новое состояние реле 3 отличается от текущего, требуется переключение
  if (relayCommand3 != relayStatus3) {
    relayStatus3 = relayCommand3;
    digitalWrite(gpioRelay3, relayStatus3);

    // Отправляем подтверждение, что команда получена и обработана
    mqttClient.publish(mqttTopicStatusRelay3, (relayStatus3 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
    
    // Можно вывести сообщение в лог
    Serial.print("Relay 3 has changed its state: ");
    Serial.println(relayStatus3 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2);
  };
}

третья вкладка "считывание состояния цифрового выхода "

Спойлер
void readDigitalInputs()
{
  // Читаем вход 1
  char gpioNewStatus1 = digitalRead(gpioInput1);
  if (gpioNewStatus1 != inputStatus1) {
    inputStatus1 = gpioNewStatus1;
  
    mqttClient.publish(mqttTopicStatusInput1, (inputStatus1 == HIGH ? mqttInputStatusHigh : mqttInputStatusLow), mqttInputStatusRetained);

    Serial.print("Input 1 has changed its state: ");
    Serial.println(inputStatus1 == HIGH ? mqttInputStatusHigh : mqttInputStatusLow);
  };
}

четвертая вкладка "работа с mqtt "

Спойлер
// Подключение к MQTT брокеру :: версия для PubSubClient от knolleary ("стандартная")
bool mqttConnected()
{
  if (!mqttClient.connected()) {
    Serial.print("Connecting to MQTT broker: ");
    // Настраиваем MQTT клиент
    mqttClient.setServer(mqttServer, mqttPortTLS);
    mqttClient.setCallback(mqttOnIncomingMsg);

    // Пробуем подключиться с LWT сообщением "offline"
    if (mqttClient.connect(mqttClientId, mqttUser, mqttPass, 
                           mqttTopicDeviceStatus, mqttDeviceStatusQos, mqttDeviceStatusRetained, mqttDeviceStatusOff)) {
      Serial.println("ok");

      // Публикуем статус устройства в тот же топик, что и LWT, но с содержимым "online"
      mqttClient.publish(mqttTopicDeviceStatus, mqttDeviceStatusOn, mqttDeviceStatusRetained);

      // Подписываемся на топики управления реле: поскольку топики заранее известны, никаких # и + здесь не нужно!
      mqttClient.subscribe(mqttTopicControlRelay1, mqttRelayControlQos);
      mqttClient.subscribe(mqttTopicControlRelay2, mqttRelayControlQos);
      mqttClient.subscribe(mqttTopicControlRelay3, mqttRelayControlQos);

      // Опубликуем текущие состояния реле
      mqttClient.publish(mqttTopicStatusRelay1, (relayStatus1 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
      mqttClient.publish(mqttTopicStatusRelay2, (relayStatus2 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
      mqttClient.publish(mqttTopicStatusRelay3, (relayStatus3 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
    } else {
      Serial.print("failed, error code: ");
      Serial.print(mqttClient.state());
      Serial.println("!");
    };
    return mqttClient.connected();
  };
  return true;
}
// Функция обратного вызова при поступлении входящего сообщения от брокера
void mqttOnIncomingMsg(char* topic, byte* payload, unsigned int length)
{
  // Для более корректного сравнения строк приводим их к нижнему регистру и обрезаем пробелы с краев
  String _payload;
  for (unsigned int i = 0; i < length; i++) {
    _payload += String((char)payload[i]);
  };
  _payload.toLowerCase();
  _payload.trim();

  // Вывод поступившего сообщения в лог, больше никакого смысла этот блок кода не несет, можно исключить
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("]: ");
  Serial.print(_payload.c_str());
  Serial.println();

  // Сравниваем с топиками
  String _topic(topic);
  if (_topic.equals(mqttTopicControlRelay1)) {
    // это топик управления реле 1
    if (_payload.equals(mqttRelayStatusOn1) || _payload.equals(mqttRelayStatusOn2)) {
      relayCommand1 = lvlRelayOn;
    };
    if (_payload.equals(mqttRelayStatusOff2) || _payload.equals(mqttRelayStatusOff2)) {
      relayCommand1 = lvlRelayOff;
    };
  } else if (_topic.equals(mqttTopicControlRelay2)) {
    // это топик управления реле 2
    if (_payload.equals(mqttRelayStatusOn1) || _payload.equals(mqttRelayStatusOn2)) {
      relayCommand2 = lvlRelayOn;
    };
    if (_payload.equals(mqttRelayStatusOff2) || _payload.equals(mqttRelayStatusOff2)) {
      relayCommand2 = lvlRelayOff;
    };
  } else if (_topic.equals(mqttTopicControlRelay3)) {
    // это топик управления реле 3
    if (_payload.equals(mqttRelayStatusOn1) || _payload.equals(mqttRelayStatusOn2)) {
      relayCommand3 = lvlRelayOn;
    };
    if (_payload.equals(mqttRelayStatusOff2) || _payload.equals(mqttRelayStatusOff2)) {
      relayCommand3 = lvlRelayOff;
    };
  } else {
    Serial.println("Failed to recognize incoming topic!");
  };
}

пятая вкладка “рабата с WI-FI”

Спойлер
bool wifiConnected()
{
  // Если подключение активно, то просто выходим и возвращаем true
  if (WiFi.status() != WL_CONNECTED) {
    // ... иначе пробуем подключиться к сети
    Serial.print("Connecting to WiFi AP ");
    Serial.print(wifiSSID);
    Serial.print(" ");
    
    // Настраиваем WiFi
    WiFi.mode(WIFI_STA);
    WiFi.begin(wifiSSID, wifiPASS);

    // И ждем подключения 60 циклов по 0,5 сек - это 30 секунд
    int i = 0;
    while (WiFi.status() != WL_CONNECTED) {
      i++;
      if (i > 60) {
        // Если в течение этого времени не удалось подключиться - выходим с false
        // Бескорнечно ждать подключения опасно - если подключение было разорвано во время работы
        // нужно всё равно "обслуживать" реле и датчики, иначе может случиться беда
        Serial.println("");
        Serial.println("Connection failed!");
        return false;
      };
      Serial.print(".");
      delay(500);
    };

    // Подключение успешно установлено
    Serial.println(" ок");
    Serial.print("WiFi connected, obtained IP address: ");
    Serial.println(WiFi.localIP());

    // Для работы TLS-соединения нужны корректные дата и время, получаем их с NTP серверов
    configTime("GMT+6", "pool.ntp.org", "time.nist.gov");
    // Ждем, пока локальное время синхронизируется
    Serial.print("Waiting for NTP time sync: ");
    i = 0;
    time_t now = time(nullptr);
    while (now < 1000000000) {
      now = time(nullptr);
      i++;
      if (i > 60) {
        // Если в течение этого времени не удалось подключиться - выходим с false
        // Бескорнечно ждать подключения опасно - если подключение было разорвано во время работы
        // нужно всё равно "обслуживать" реле и датчики, иначе может случиться беда
        Serial.println("");
        Serial.println("Time sync failed!");
        return false;
      };
      Serial.print(".");
      delay(500);
    }
        // Время успешно синхронизировано, выводим его в монитор порта
    // Только для целей отладки, этот блок можно исключить
    Serial.println(" ok");
    struct tm timeinfo;
    localtime_r(&now, &timeinfo);
    Serial.print("Current time: ");
    Serial.print(asctime(&timeinfo));

    // Теперь можно привязать корневой сертификат к клиенту WiFi
    wifiClient.setTrustAnchors(&certISRG);
  };
  return true;
}

шестая вкладка “работа с датчиком”

Спойлер

void readTemperature()
{
  // Читаем данные с сенсора
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // Вывод считанных данных в лог
  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.println(F("°C "));

  // Публикуем данные на сервере
  String str_temp(t);
  mqttClient.publish(mqttTopicTemperature, str_temp.c_str(), mqttSensorsRetained);
  String str_humd(h);
  mqttClient.publish(mqttTopicHumidity, str_humd.c_str(), mqttSensorsRetained);
}

void temp_hum (){
  
  // Чтение и публикация температуры каждые 10 секунд
  static unsigned long lastTempRead = 0;
  if ((millis() - lastTempRead) >= 10000) {
    lastTempRead = millis();
    readTemperature();
  };
}

Мда… Не читатель, исключительно - писатель! )))

Зачем оно мне? Это у вас проблема, а не у меня

Вы сообщение #8 внимательно прочитали?

значит надо передать в класс указатель на внешний обьект mqttClient
не подскажите как это сделать ? читал статью там писалось

friend mqttClient.publish()

я так конечно пробовал

Ппц…

class1 tm1;
class2 tm2(&tm1);

Ппц…

class1 tm1;
class2 tm2(&tm1);

как мне кажется тут вы опссали что то другое.
в соем случае (класс реле(внешний класс для передачи данных на mqtt)

Создаете метод класса, например relayControl() и в качестве аргумента передаете в него ссылку или указатель на ваш mqttClient

void relayControl(type *mqtt)
{
  mqtt->publish(mqttTopicStatusRelay1, (relayStatus1 == 1 ? mqttRelayStatusOn2 : mqttRelayStatusOff2), mqttRelayStatusRetained);
    
}

type - это тип вашего mqttClient, уж простите, я его не знаю )) Использование

relay.relayControl(&mqttClient);
1 лайк

Вы сообщение #8 внимательно прочитали?
читал и также как вы меня не поняли я вас не понял.
в этой статье описано что можно вызвать внешний класс из своего класса если конечно я не путаю.
https://ravesli.com/urok-126-druzhestvennye-funktsii-i-klassy/

Боюсь, вы и статью не поняли ))

3 лайка

спасибо попробую :handshake: