Многофайловый скетч arduino esp8266 со ссылкой на сервер

По мере того, как мои скетчи становятся больше, код выглядит ужасно как один файл, а количество глобальных переменных слишком велико.

Для части веб-конфигурации моего скетча устройство пытается подключиться к сети, и если это не удается, оно сканирует доступные сети Wi-Fi, переходит в режим точки доступа, запускает сервер, отправляет список ssid и ожидает ответа от пары ssid/passwd. . Сервер только для настройки.

В идеале я бы хотел, чтобы очищенный файл main.ino выглядел так:

#include "config.h"
void setup(){
    Serial.begin(115200);
    Serial.println();
    Serial.println("--------------------------");
  Serial.println("ESP8266 multifile");
  Serial.println("--------------------------");
  getOnline();
}
void loop(){
    if(IN_CONFIG_MODE){
       server.handleClient();
    }
}

с config.h что-то вроде ..

    #ifndef config_h
    #define config_h
        #include <ESP8266WiFi.h>
        #include <ESP8266WebServer.h>
        ESP8266WebServer server;
        void getOnline();
    #endif

а затем config.cpp, где он делает все, что описано выше, но дает программе main.ino доступ к экземпляру server, чтобы она могла прослушивать основной цикл.

#include "config.h"
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

char *espssid = "espAPsb";
char *ssid = "street_no_vale2";
char *pwd = "jjjjjjjjx";
char ssids[300];

extern server(80);

void handleRoot(){
    server.send(200, "text/html", "<h1>root of espAPsb AP server</h1>");
    //send json of available ssids
}

void scan(){
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  int n = WiFi.scanNetworks();
  Serial.println("scan done");  
  if (n == 0)
    Serial.println("no networks found");
  else
  {
    Serial.print(n);
    Serial.println(" networks found");
    for (int i = 0; i < n; ++i)
    {
      // Print SSID and RSSI for each network found
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
      delay(10);
    }
  }
  Serial.println("");   
}

void setupAP(){
    WiFi.softAP(espssid);
    server.on("/", handleRoot);
    server.begin();
  Serial.println();
  Serial.print("connected as AP ");
  Serial.println(espssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.softAPIP());  
}

void getOnline(){
    WiFi.begin(ssid, pwd);
  int tries =0;
  int success=1;
  while (WiFi.status() != WL_CONNECTED ) {
    delay(500);
    Serial.print(".");
    tries++;
    if (tries==15){
      success=0;
      Serial.println("WiFi not connected");
      scan();
      setupAP();
      break;
    }
  }
  if (success){
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());    
  } 
}

person mcktimo    schedule 14.03.2016    source источник
comment
Это не C-код. Arduino — это не C или (стандартный) C++.   -  person too honest for this site    schedule 15.03.2016
comment
Верно, но моя проблема связана с «c-подобными» частями, файлами заголовков, объявлениями внешних переменных и классов, которые я вижу во многих библиотеках, поддерживающих эти микроконтроллеры. Это больше похоже на C, чем на javascript :)   -  person mcktimo    schedule 15.03.2016
comment
Языков программирования больше, чем C и JavaScript. C не имеет классов. Пожалуйста, проведите небольшое исследование. Обработка основана на C++ (но не совсем так, как C++).   -  person too honest for this site    schedule 15.03.2016
comment
Вау мир меняется. В наши дни проблемы Github таковы, где они есть. extern ESP8266WebServer server; идет в файле .h, а ESP8266WebServer server(80) — в файле .cpp. Так же было бы и в С++.   -  person mcktimo    schedule 15.03.2016


Ответы (1)


Вы можете создать собственную библиотеку из своего сетевого кода, которую легко использовать повторно. https://www.arduino.cc/en/Hacking/LibraryTutorial

В качестве альтернативы вы можете использовать несколько «вкладок» в Arduino IDE, которая работает как стандартный проект с несколькими источниками. http://arduino.land/FAQ/content/7/43/en/breaking-a-sketch-into-multiple-files.html

(Кстати, StackExchange размещает специальный микросайт Ardunio здесь: https://arduino.stackexchange.com/ Получайте удовольствие :)

person Gee Bee    schedule 14.03.2016
comment
скопировано на arduino.stackechange по совету @Gee_Bee. Я могу получить arduino.cc/en/Hacking/ LibraryTutorial для работы, а также arduino.land/FAQ/content/7/43/en/ и arduinoetcetera.blogspot.com/2011/01/ Я даже могу заставить работать внешние ссылки на переменные, но ссылаться на экземпляр ESP8266WebServer в разных файлах мне все еще не под силу. - person mcktimo; 15.03.2016
comment
О, тогда ваш вопрос заключается в том, как ссылаться на переменную, объявленную в другом исходном файле, вместо того, чтобы лучше структурировать мой код в нескольких исходных файлах/библиотеках. Заметано. Вы объявляете переменную (т. е. экземпляр ESP8266WebServer) в одном файле, и вы можете сослаться на нее по ключевому слову extern в другом файле, см. forum.arduino.cc/index.php?topic=43507.0 - person Gee Bee; 16.03.2016
comment
Однако если вы хотите, чтобы все было хорошо, я бы сделал собственный класс cpp со специальным кодом ESP8266 и использовал бы его из моего эскиза Arduino. Например, ваш новый класс cpp может иметь один метод connect() (также известный как getOnline), который вы можете легко вызвать из своего основного скетча. Это гораздо лучший подход, чем позволить экземпляру ESP8266WebServer ссылаться во всех других исходных кодах — это действительно нарушило бы концепцию модульного программирования. - person Gee Bee; 16.03.2016
comment
Да, вот куда я направлялся. Моя проблема заключалась в том, что мне все еще нужно было использовать сервер, handleClient() в основном цикле, поэтому мне нужна была ссылка на сервер. Я полагаю, что я мог бы также обернуть это внутри класса Config, а затем просто вызвать cfg.getOnline() в настройке и cfg.handleConfig() в цикле. - person mcktimo; 16.03.2016
comment
В яблочко. Как только вы пойдете дальше в программировании, вы получите более строгие советы по этому поводу, говорящие, что никогда не сливайте свои ссылки ;-) Для справки (без каламбура), проверьте, например. как сериал сделан. У него есть один метод начала, который вы вызываете в настройках, а затем у него есть методы, которые вы вызываете в цикле. То же самое должно работать здесь :) - person Gee Bee; 16.03.2016