arduino, настройка ethe rnet и сеть с использованием данных из файла конфигурации SD - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь добавить к своему эскизу динамический c способ настройки информации rnet (ma c, ip, gateway, su bnet) из файла конфигурации (config.txt). Таким образом, запустив веб-сервер и предоставив htm-файлы с SD-карты, пользователь может go настроить страницу, заполнить форму с этой информацией, и, когда она будет опубликована, веб-сервер проанализирует http-форму и сохранит (обновит) файл config.txt. После этого система перезагрузится, чтобы начать с новыми настройками (прочитав файл config.txt)

Я успешно создал все части (sd, ethe rnet, webserver, webclient, create файл конфигурации из опубликованных данных формы), за исключением получения параметров, читая файл config.txt.

Я могу построчно читать конфигурацию, я могу разбить строку на param & value, и теперь мне нужно заполните некоторые байтовые переменные прочитанными данными. Я могу (после месяца поиска в Google) читать IP-адреса (десятичные значения) в байтовом массиве. Я стек, чтобы прочитать гекс MA C ADDRESS в байтовый массив. Файл конфигурации содержит:

mac=8f:2c:2b:19:e0:b7;
ip=192.168.1.200;
netmask=255.255.255.0;
gateway=192.168.1.254;
dns=8.8.8.8;
posturl=192.168.1.157;
postport=8080;
postscript=/itherm/update.php;
interval=60000;

и код, который я использую для чтения:

byte myMAC[6];
byte myIP[4];

  File fset;
  fset = SD.open("config.txt");
  if (fset){
    char ff[40];
    while (fset.available()>1){
      bool eol=false;
      for (int i=0; !eol;i++){
        ff[i]=fset.read();
        if (ff[i]=='\n'){
           eol=true;
        }
      }
      String par="";
      bool DONE=false;
      for (int i=0; !DONE;i++){
        par+=ff[i];
        if (ff[i]== '='){DONE=true;}
      }
      String pval="";
      DONE=false;
//------------------------

      if (par=="ip=" ){
        int x=0;
        while(!DONE){
          for(int i=3;i<=i+21;i++){
            if(ff[i]=='.'){
              myIP[x]=pval.toInt();
              x++;
              i++;
              pval="";
            }
            else if(ff[i]==';' || i>20){
              myIP[x]=pval.toInt();
              DONE=true;
              break;
            }
            pval+=ff[i];
          }
        }
      }

    } //while (fset.available()>1)
  } //if (fset)

Я буду признателен за любую помощь. Пожалуйста, не отвечайте с простым использованием Serial.print (). Я нашел сотни предложений, но ни одного, которые работают правильно, чтобы прочитать все параметры (de c, hex, строки). После месяца усилий и поисков я удивляюсь, почему чего-то столь необходимого и полезного не существует в качестве примера в сообществе, полностью работоспособного !!

С наилучшими пожеланиями

1 Ответ

1 голос
/ 22 апреля 2020

Хорошо, так вот полный набор процедур, чтобы делать то, что вы хотите - я думаю, что вы неправильно поняли концепцию массивов символов против одного символа [0]. Процедуры документированы и не требуют пояснений. Я не рекомендую заканчивать строки sh; но с '\ n', который в вашем примере есть в любом случае (также вы не можете видеть терминатор новой строки) Чтобы получить адрес ma c, мне нужно три строки:

  if (strncmp(cfgLine, "mac=", 4) == 0) {
    strcpy (macAddr, cfgLine + 4);
  }

строка первая сравнивает первые 4 символа и, если это строка 0 (что означает соответствие), две копируют символы с пятого на последний символ из lineBuffer в целевой массив, который фактически может использоваться в качестве параметра для функций.
Структура файла должно быть с нет; как бы вам пришлось разбирать; и \ n

mac=8f:2c:2b:19:e0:b7
ip=192.168.1.200
....
postport=8080

Чтобы преобразовать массив символов в, например, int, мы используем atoi (), чтобы преобразовать один символ [0] в одно число, мы используем int singleDi git = char [0] -48;

const char configurationFilePath [] = "/someconfig.txt";
char cfgLine[128] = {'\0'};  // this is a global temp char array to hold the read lines (lenght= chars longest line +1)
char numBuffer[16] = {'\0'};  // this is a global temo char array to help to convert char to number

char macAddr [18] =  {'\0'};  // this is a global char array to hold the mac address
char ipAddr [16] =  {'\0'};  // this is a global char array to hold the IP address - max xxx.xxx.xxx.xxx
int postport=0;
// .... you can easyly implement for all other data you want to store/retrieve

// Counts the lines of a file 
uint16_t countLines() {
  uint16_t currentLineCount = 0;
  File cfgFile = SD.open(configurationFilePath, "r");
  if (!cfgFile) {
    Serial.println(F("Config file open failed on read"));
  } else {
    while (cfgFile.available()) {
      /** Lets read line by line from the file */
      if (cfgFile.read() == '\n') currentLineCount ++; // Lines are delimited by '\n'
    }
    cfgFile.close();
  }
  return currentLineCount;
}

//Load the config file from SD/SPIFFS/LittleFS
bool loadConfigFile() {
  uint16_t lineCounter = countLines();
  if (lineCounter <= 0)  {
    Serial.print(F("No config data stored in file ")); Serial.println(configurationFilePath);
    return false;
  }
  else {
    File cfgFile = SD.open(configurationFilePath, "r");
    while (cfgFile.available()) {
      strcpy (cfgLine, (cfgFile.readStringUntil('\n').c_str()));  // normaly you use new line, we copy one line at a time
//      Serial.println(cfgLine); /** Printing for debuging purpose */
      while (cfgLine[0] != '\0') { /* Block refilling of cfgLine till processed */
        loadSingleCfgLine();
      }
    }
    cfgFile.close();
    Serial.println(F("[Success] Loaded config !"));
    return true;
  }
}
//Load the data of a single line into a char array
void loadSingleCfgLine() {
  if (strncmp(cfgLine, "mac=", 4) == 0) {
    strcpy (macAddr, cfgLine + 4);
  }
  if (strncmp(cfgLine, "ip=", 3) == 0) {
    strcpy (ipAddr, cfgLine + 3);
  }
  if (strncmp(cfgLine, "postport=", 9) == 0) {
    strcpy (numBuffer, cfgLine + 9);
    postport = atoi(numBuffer); // One extra step to convert to int
  }

// ... easy to implement for all other data
}

Я разделил подпрограммы на небольшие независимые функции, так что их легко адаптировать для различных целей. Я прошу прощения за то, что не копался в вашем коде, так как трудно следовать и неясно, что вы хотите сделать.
В качестве дополнительного бонуса мы не используем класс String. Эти строки имеют тенденцию фрагментировать кучу, вызывая сброс / сбой, в то время как глобальные массивы символов компилируются в fla sh и не показывают это поведение.

...