LoginSignup
0
0

More than 3 years have passed since last update.

ESP8266/ESP32向け、htmlの入力項目をinifileに従った内容に修正する

Last updated at Posted at 2018-12-12

ESP8266の小物を作っていると、WebServer機能でのパラメータ登録機能があると
同じ小物を複数個運用するのに、設定や確認が楽だろうなぁと感じています。
今回はSPIFFSにあるhtmlファイルを読込んで、inifileに従った内容に更新するクラスを作成しました。
 =>xmlでやれば良かったと何気に後悔中です。
これだけだとイマイチなのですが、ESP8266WebServer.hを使うと良い感じになるのでは? と期待して作っています。

ESP8266環境で必要なリソース

 SPIFFS / FS等のファイルアクセスの環境
 inifile.h 私が作成したヤツです。

機能

 1. 入力項目 input type="text" の value をinifileの登録値に変更する
 2. パスワード入力項目 input type="password" の value をinifileの登録値に変更する
 3. ラジオボタンの初期値をinifileの登録値側にします。
 4. レンジ入力の初期値をinifileのものに置き換えます。
 5. コンボ入力の初期値をinifileのものに置き換えます。

使い方

ソースはこんな風にします。

usage.ino
#include <inifile.h>
const char *iniFileName = "/setup.ini"; // Inifileのファイル名
const char *iniHeader = "SETUP";
iniFiles ini(iniFileName);
#include <WebServerToolHtml.h>

//==
void setup() {
  Serial.begin(115200);  Serial.flush(); delay(1000);
  Serial.println("program start");
  if( SPIFFS.begin() )
    Serial.println("SPIFFS Initialize....ok");
  else
  {
    Serial.println("SPIFFS Initialization...failed");
    return;
  }
  WebServerToolHtml.readHtmlFile( "/index.html" );
  Serial.println( WebServerToolHtml.buffer() );
  WebServerToolHtml.release();
}

void loop() {
}

ESP8266/ESP32のSPIFFSに、このsetup.iniファイルをコピーします。

SETUP.ini
[SETUP]
SSID=TEST_SSID
PASSWORD=TEST_PASSWORD
switch=on
range=22.2
sensor=HTU21D
*

ESP8266/ESP32のSPIFFSに、このhtmlファイルをコピーします。 注) '<' を '<'に変更してあるので戻す必要があります。

index.html
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<form name='SETUP' action=SETUP method='post'>
<p>SWITCH</p>

<p>SSID:<input type="text" name="SSID" size="30" maxlength="30" value="SAMPLESSID"></p>

<p>PASS:<input type="password" name="PASSWORD" size="30" maxlength="30" value="SAMPLEPASSWORD"></p>

<p>
<input type="radio"  name="switch" value="on" >ON
<input type="radio"  name="switch" value="off">OFF
</p>

<p><input type="range" name="volume1" value="1" min="-10.0" max="29.9" step="0.1"></p>

<p>
<select name="sensor">
<option value="DHT11">DHT11</option>
<option value="LM75A">LM75A</option>
<option value="HTU21D">HTU21D</option>
<option value="SHT31">SHT31</option>
<option value="BME280">BME280</option>
<option value="BMP280">BMP280</option>
</select>
</p>

<input type=submit value=on target=tif>
</form>
</html>

ソースコード

cppには何も書いていません。

webservertoolhtml.h
#include <inifile.h>

#ifndef HTMLANDINIFILE_H
#define HTMLANDINIFILE_H

class WebServerToolHtmlClass {
    // 空白文字の判定(タブ・スペース・改行)
    bool charSpace( char chData ) {  return ((chData == ' ' || chData == 0x9 || chData == 0xd || chData == 0xa) ? true : false);  }
    // '>' と 空白文字の判定 
    bool charDataTerminate( char chData ){  return ((charSpace(chData)==true || chData=='>')?true:false);  }
    File fp;
    char *writeBuffer;
    int writePos;
    char readCharSkip( ){  char ch = fp.read();                                            return ch;  }
    char readChar( ){      char ch = writeBuffer[writePos] = readCharSkip();  writePos++;  return ch;  }
    String upperCaseChar( char *str ){  String s = str;  s.toUpperCase();  return s;  }
    //== タグを見つけて、区切り文字列を返す ========
    String OLDTAG, TAG;
    char readTAG() {
      char chData[15], POS = 0;  TAG = "";
      while ( fp.available() ) {
        char ch = chData[POS] = readChar();  
        if ( charDataTerminate(ch) ){  chData[POS] = 0x00;  TAG = upperCaseChar(chData);         return ch;  }  // タグが読めた
        POS++;
      }
      return -1;
    }
    //== 設定内容の読込 (設定の右辺)=============
    String detailData;
    char readDetailData() {
      char chData[48], POS = 0;  detailData = "";
      while ( fp.available() ) {
        char ch = chData[POS] = readChar();
        if ( charDataTerminate(ch) ){  chData[POS] = 0x00;  detailData = upperCaseChar(chData);
//          Serial.println( detailData );
          return ch;
        }  // データが読めた
        POS++;
      }
      return -1;
    }
    //==設定内容の読込 (設定の右辺    バッファへは移さない
    char replaceDetailData( char *data ) {
      int oldWritePos = writePos;
      for( int POS=0 ; data[POS]!=0 ; POS++ ){  writeBuffer[ writePos ] = data[POS];  writePos++;  }  // データをバッファに書き出す
      while ( fp.available() ) {
        char ch = readCharSkip();
        if ( charDataTerminate(ch) ){     // データが読めた
          writeBuffer[ writePos++ ] = ch;
  //        writeBuffer[ writePos ] = 0;          Serial.print( "[rep]=" );      Serial.println( &writeBuffer[oldWritePos] );
          return ch;
        }
      }
      return -1;
    }
    //==
    String TYPE, NAME, VALUE, lineType, FORMNAME, OLDNAME;
    //============================================
    char readDetailTitle() {
    char chData[48], POS = 0;
      while ( fp.available() ) {
        char ch = readChar();
        if ( charSpace(ch) )        continue;                                                                   // 読み飛ばし
        if ( ch == '>' )                                                                         return ch;     // 検索中に終端
        chData[ POS++ ] = ch;
        while ( fp.available() ) {
          ch = readChar();
          if ( ch == '=' ) {  // タイトルが読めた
            chData[ POS ] = 0x00;
            String titleData = upperCaseChar( chData );
//            Serial.print( "LINE:" );      Serial.print( titleData );
            if( titleData=="TYPE" ){    ch = readDetailData();  TYPE = detailData.substring( 1, detailData.length()-1 );  return ch;  }
            if( titleData=="NAME" ){    ch = readDetailData();  NAME = detailData.substring( 1, detailData.length()-1 );  return ch;  }
            if( titleData=="VALUE" ){
              if ( TYPE != "TEXT" && TYPE != "PASSWORD" && TYPE != "RANGE" ){
//                Serial.print( "[noquate]" );  Serial.print( TYPE );   
                                        ch = readDetailData();  VALUE = detailData.substring( 1, detailData.length()-1 ); return ch;  }
              String tempString = "\"";
              tempString += ini.get( (char*)iniHeader, (char*)NAME.c_str(), "" );
              tempString += "\"";
              if( tempString=="\"\"" )  ch = readDetailData();  else  ch = replaceDetailData( (char*)tempString.c_str() );
                                                                                    return ch;  }
                                        ch = readDetailData();                      return ch;
          }
          if( charSpace(ch) ){
            chData[ POS ] = 0x00;
            String titleData = upperCaseChar( chData );
//            Serial.print( "SINGLE" );
//            Serial.println( titleData );
            if( titleData=="FORM" )   lineType = "FORM";
            if( titleData=="/FORM" )  FORMNAME = "";                                return ch;
          }
          if ( charDataTerminate( ch )==true  ){                                    return ch;  }  // タイトルが読めた / 読込中に終端
          chData[ POS++ ] = ch;
        }
      }
      return -1;
    }
  public:
    WebServerToolHtmlClass(){ writeBuffer=NULL; }
    ~WebServerToolHtmlClass(){ release(); }
    void release(){  if( writeBuffer!=NULL )  free( writeBuffer );  writeBuffer=NULL;  }
    char *buffer(){  return writeBuffer; }
    //============================================
    char *readHtmlFile( const char *htmlFileName ) {
      if( writeBuffer!=NULL )  release();
      fp = SPIFFS.open( htmlFileName, "r" );
      int filesize = fp.size();
      writeBuffer = (char*)malloc( filesize+1000 );
      writePos = 0;
      FORMNAME = "";
//      Serial.print( "filesize:" );      Serial.println( filesize );
      while ( fp.available() ) {
        if ( readChar() != '<' )      continue;  // 先頭文字を探す
        char ch = readTAG( );                    // タグを見つけて、区切り文字列を返す
        if( ch==-1 || ch=='>' ){
               continue;
        }else{
          TYPE = "";  NAME = "";  VALUE = ""; 
          for( ; ; )  if( !charSpace(ch=readDetailTitle()) )  break;  // データを解釈する
          if( ch=='>' ){
//            Serial.print( "LINE NAME:" );
//            Serial.print( NAME );
//            Serial.print( " VALUE:" );
//            Serial.println( VALUE );
            if( TYPE=="RADIO" ){
              String tempString = ini.get( (char*)iniHeader, (char*)NAME.c_str(), "" );
              tempString.toUpperCase();
//              Serial.print( " STRING:" );
//              Serial.println( tempString );
              if( VALUE == tempString ){
//                Serial.print( "[+checked]" );
                writeBuffer[ writePos-1 ] = ' ';
                strcpy( &writeBuffer[ writePos ], "checked>" );
                writePos += 8;
              }
            }
//            Serial.print(TAG);
            if( TAG!="OPTION" ){
              OLDTAG=TAG;  OLDNAME=NAME;
//              Serial.println("");
            }else{
//              Serial.print(OLDTAG);
//              Serial.print(OLDNAME);
              if( OLDTAG=="SELECT" ){
                String tempString = ini.get( (char*)iniHeader, (char*)OLDNAME.c_str(), "" );
                tempString.toUpperCase();
//                Serial.print(":");
//                Serial.print(VALUE);
//                Serial.print(tempString);
                if( VALUE == tempString ){
                  writeBuffer[ writePos-1 ] = ' ';
                  strcpy( &writeBuffer[ writePos ], "selected>" );
                  writePos += 9;
                }
              }
              Serial.println("");
            }
          }
        }
      }
//      Serial.println( "[EOF]" );
      writeBuffer[ writePos++ ] = 0;
      fp.close();
      return writeBuffer;
    }
    //============================================
};

WebServerToolHtmlClass WebServerToolHtml;
#endif
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0