Как сделать переменную, объявленную внутри функции(цикла) глобальной?

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

Всем привет! Я использую код для отправки сообщений Telegram боту, совместимый с библиотекой "Universal Telegram Bot" и платой ESP32. Я инициализирую объект определяющий Telegram бот в void setup(), после того как я прочитываю токен Telegram бота, название WiFi сети и её пароль из файловой системы SPIFFS, а затем сохраняю эти данные в переменные. Если объявить этот объект внутри void setup(), сразу после того как мы прочитали нужные для отправки сообщений Telegram боту данные, то этот объект будет локальным, и его не получится использовать в других циклах. Я хотел бы узнать, как сделать его глобальным? PS: мой код может показаться для вас непонятным, поэтому если у вас возникнут вопросы, то задавайте их) Также, для проверки этого скетча вам понадобится немного ознакомится с SPIFFS. Буду рад вашим подсказкам)

#include <WiFi.h>
#include <WiFiClientSecure.h>

#include "SPIFFS.h"

#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>

String network_name = "";
String network_pass = "";
String telegram_bot = "";
String my_settings  = "-";

int settings_length;
int first_hash;
int second_hash;
int third_hash;

int Bot_mtbs = 1000;
long Bot_lasttime;

WiFiClientSecure client;

void setup() {
  Serial.begin(115200);
  
  if(!SPIFFS.begin(true)){
    Serial.println("Ошибка при монтировании SPIFFS :(");
    return;
  } else {
    Serial.println("Монтирование SPIFFS прошло успешно!");  
  }

  File settings = SPIFFS.open("/Settings.txt"); 
  if (!settings) {
    Serial.println("Не удалось открыть файл с настройками для чтения :(");
    return;
  } else {
    Serial.println("Файл с настройками успешно открыт для чтения!");
  }

  Serial.print("Содержимое файла: ");
  while (settings.available()) {
    my_settings = settings.readString();
    Serial.println(my_settings);

    settings_length = my_settings.length();
    first_hash      = my_settings.indexOf('#');
    second_hash     = my_settings.indexOf('#', first_hash + 1);
    third_hash      = my_settings.indexOf('#', second_hash + 1);

    network_name = my_settings.substring(0, first_hash);
    network_pass = my_settings.substring(first_hash + 1, second_hash);
    telegram_bot = my_settings.substring(second_hash + 1, third_hash);
    flash_onoff  = my_settings.substring(third_hash + 1, settings_length);
   
    Serial.print("Название WiFi сети: ");  Serial.println(network_name);
    Serial.print("Пароль WiFi сети: ");    Serial.println(network_pass);
    Serial.print("Токен Telegram бота: "); Serial.println(telegram_bot);
    Serial.print("Включение вспышки: ");   Serial.println(flash_onoff);
  }

  settings.close();
  Serial.println("Файл с настройками закрыт!");

  if (my_settings != "-") {
    Serial.println("Режим WiFi сети запущен!");
    Serial.print("Подключаемся к WiFi сети: ");
    Serial.println(network_name);

    WiFi.mode(WIFI_STA);
    WiFi.begin((const char*)network_name.c_str(), (const char*)network_pass.c_str());

    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
    }
    
    Serial.println("Подключились к WiFi сети!");
    Serial.print("IP адрес платы ESP32 CAM: ");
    Serial.println(WiFi.localIP());
    UniversalTelegramBot bot(telegram_bot, client);
  }
}

void loop() {
  bot.longPoll = 1;
  
  if (millis() > Bot_lasttime + Bot_mtbs)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages) {
      Serial.println("Получен ответ от Telegram пользователя!");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    Bot_lasttime = millis();
  }
}

void handleNewMessages(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    String text = bot.messages[i].text;

    String from_name = bot.messages[i].from_name;
    if (from_name == "") from_name = "Гость";

    if (text == "/start") {
      bot.sendMessage(chat_id, "Telegram бот запущен!", "Markdown");
    }
  }
}

 

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

В показанном мной коде, строки 55 и 60 лишние. Я взял этот скетч из моего другого, более сложного скетча

sadman41
Offline
Зарегистрирован: 19.10.2016

Надо этот объект заранее объявить глобальным.

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

В данном случае, нужно объявить этот объект после того как мы прочитали данные из SPIFFS памяти. Я пытался объявить этот объект после void setup(), но тогда этот код не работал, плата не подключалась к Telegram боту

sadman41
Offline
Зарегистрирован: 19.10.2016

Чем обусловлена такая последовательность объявлений?

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Мир Ардуинщиков пишет:

Я пытался объявить этот объект после void setup(), 

Надо объявить до setup()

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

Это обусловлено тем, что команду "UniversalTelegramBot bot(telegram_bot, client);" нужно объявить после того как в переменную "telegram_bot" мы сохраним токен Telegram бота

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Про вот такие операторы ( https://docs.microsoft.com/ru-ru/cpp/cpp/new-and-delete-operators?view=m... ) чего нибудь знаете ? 

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

Только, что узнал) Сейчас почитаю вашу статью

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

Насколько я понял, операторы new и delete нужны для выделения памяти. Вот только, как это можно применить в моём случае?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Мир Ардуинщиков, память для всех глобальных объектов выделяется ДО первого исполняемого оператора вне зависимости от места объявления в программе. Что именно Вы подразумеваете под "что команду "UniversalTelegramBot bot(telegram_bot, client);" нужно объявить после того как в переменную "telegram_bot" мы сохраним токен..."?

Обычно если размер некоторого неизвестного на момент старта программы элемента известен, этот объект объявляется обычным образом. Если примерно известен - можно объявить с максимальным размером. Если неизвестен даже ориентировочно, но заведомо влезает в ОЗУ, вместо объекта объявляется указатель на него, а память выделяется уже после того, как размер станет известным. Если же размер объекта может превышать объем свободного ОЗУ, объект не читается в память целиком, а разбирается на отдельные элементы по мере поступления.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

brokly пишет:

Про вот такие операторы ( https://docs.microsoft.com/ru-ru/cpp/cpp/new-and-delete-operators?view=m... ) чего нибудь знаете ? 

ты уже для микрософта доки пописываешь? )))

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

brokly пишет:

Про вот такие операторы ( https://docs.microsoft.com/ru-ru/cpp/cpp/new-and-delete-operators?view=m... ) чего нибудь знаете ? 

Правильно - мелкомягкие это зло!