// net-param-SPIFFS.ino 2024/03/10 Ver 2.2 JA3OOK
// ネットワーク接続パラメーター(Wi-Fi接続のIPアドレスなど)を内蔵不揮発性メモリーへSPIFFSを利用して
// 記憶させるツールです。(なお、内蔵不揮発性メモリーはプログラムが書き込まれても消えません)
// SSID,PW,IPアドレスなどの設定、保存、変更、読み出しなどがコマンドで可能で、
// ソースプログラムの変更やリコンパイルが不要です。
//
// 他のプログラムからこのツールを利用するは、settingMode変数に true/false を設定し
// setNetworkParameter(); を呼び出す。
// false: run mode : ファイルが無ければ既定値でファイルを作成し、既定値でreturn。
// ファイルが有ればファイルの値でreturn。
// true : setting mode : コマンドで設定し、ファイルに書き込む。
// exitコマンドでreturn。
// どちらにすべきかの切換えは、ラン実行の最初に、入力ピンの値がhighかlowかで行うのが一般的だろう。
//
// 動作確認環境 ESP32-DevKitC (ESP32-WROOM-32)
// Arduino IDE 1.8.12 + esp32 by Espressif System バージョン 1.0.4
// Arduino IDE 1.8.19 + esp32 by Espressif System バージョン 1.0.4
#include "FS.h"
#include "SPIFFS.h"
// このプログラムがWi-Fi(無線LAN)で接続するルーターの情報
/* // 次の連携データ定義をメインの.inoにコピーすること
// ここから メイン.ino と net-param-SPIFFS.ino との連携データ
bool settingMode = true;
String sketch; // メインスケッチファイル名など
int debug; // 0:本番
String myplace; // このプログラムが動作する場所(server / client)
char myssid[31]; // Wi-Fiルーターのssid (charの場合は文字数指定が必要)
char mypassword[31]; // Wi-Fiルーターのパスワード
String myportStr; // myport番号は指定しても無効(制限事項)
uint16_t myport; // myport番号は指定しても無効(制限事項)
IPAddress myip(192,168, 0, 49); //myipaddress 仮の値
IPAddress mygateway(192,168, 0, 1); //mygateway 〃
IPAddress mysubnet(255, 255,255, 0); //mysubnetmask 〃
IPAddress mydns(192,168, 0, 1); //mydns 〃
String hisNetname; // hisipのネットアドレス型式名
IPAddress hisip(49,49,49,49); //動作場所が"client"の場合に、his即ちサーバーの指定に使用
unsigned int hisport; //動作場所が"client"の場合に、his即ちサーバーの指定に使用
String appPW; //アプリレベルの認証パスワード
// ここまで連携データ
*/
#define iniFileName "/internet.ini" // 任意のファイル名(SPIFFS:不揮発性メモリー に書かれるファイル名)
// work area
String debugModeStr="0"; // 既定値:本番
String myssidStr; // ルーターのmyssid 最大30文字
String mypasswordStr; // ルーターのパスワード 最大30文字
String myipStr;
String mygatewayStr;
String mysubnetStr;
String mydnsStr;
String hisipStr;
String hisportStr;
char addr[4];
// make the file by default value
bool makeFile(){
File file = SPIFFS.open(iniFileName, FILE_WRITE); // 書き込み、存在すれば上書き
if(!file){
return false;
}
else{ // ファイルを既定値で作成する
file.println("sketch=mainaaaaa.ino 2022/05/01");
file.println("debug=0"); // 0:既定値:本番
file.println("myplace=server");
file.println("myssid=abcd");
file.println("mypw=xxxx");
file.println("myipaddr=192.168.0.40");
file.println("myport=58000"); // myport番号は指定しても無効(制限事項)
file.println("mydns=192.168.0.1");
file.println("mygateway=192.168.0.1");
file.println("mysubnet=255.255.255.0");
file.println("hisnetname=xxx.iobb.net"); // rmtKeyサーバーのネットアドレス名
file.println("hisipaddr=200.200.10.10"); // rmtKeyサーバーのIPアドレス
file.println("hisport=58000"); // rmtKeyサーバーのポート番号
file.println("apppw=applipw"); // アプリレベルの認証パスワード
file.println("endOfFile");
file.close();
return true;
}
}
// 192.168.0.1形式のアドレスを char配列addr[]に格納する
void setIPaddress(String str){
unsigned int loc[3];
loc[0] = str.indexOf('.');
loc[1] = str.indexOf('.',loc[0]+1);
loc[2] = str.indexOf('.',loc[1]+1);
addr[0] = str.substring(0,loc[0]).toInt();
addr[1] = str.substring(loc[0]+1,loc[1]).toInt();
addr[2] = str.substring(loc[1]+1,loc[2]).toInt();
addr[3] = str.substring(loc[2]+1).toInt();
}
// 192.168.0.1 形式でアドレスをプリントする
void listIPaddress(IPAddress ip){
Serial.print(ip[0], DEC);Serial.print('.');Serial.print(ip[1], DEC);Serial.print('.');
Serial.print(ip[2], DEC);Serial.print('.');Serial.print(ip[3], DEC);
}
// read file
void readFile(){
String str;
byte leng;
File file = SPIFFS.open(iniFileName, FILE_READ); // モード:読み取り
if(!file || file.isDirectory()){ // ファイルが存在しない
Serial.println("- failed to open file for writing");
Serial.print('>');
return;
}
while(file.available()){ // データがある限り
for (int i=1; i<=30; i++){
str=file.readStringUntil('\n'); // '\n'=0x0A=LF
str.replace("\r",""); // 右端の '\r'=0x0D=CR をnullに変換
leng = str.length();
// Serial.print(i); Serial.print(":"); // debug
// Serial.print(leng); Serial.print(":"); Serial.println(str); // debug
if(str.startsWith("sketch=") && leng >= 8){
sketch = str.substring(7);
}
if(str.startsWith("debug=") && leng >= 7){
debugModeStr = str.substring(6); debug = debugModeStr.toInt();
}
if(str.startsWith("myplace=") && leng >= 9){
myplace = str.substring(8);
}
if(str.startsWith("myssid=") && leng >= 8){
myssidStr = str.substring(7); myssidStr.toCharArray(myssid,31);
}
if(str.startsWith("mypw=") && leng >= 6){
mypasswordStr = str.substring(5); mypasswordStr.toCharArray(mypassword,31);
}
if(str.startsWith("myipaddr=") && leng >= 10){
myipStr = str.substring(9);
// Serial.println(myipStr);//debug
setIPaddress(myipStr); // 192.168.0.1形式から採取し、addr[]へ書き込む
myip[0]=addr[0]; myip[1]=addr[1]; myip[2]=addr[2]; myip[3]=addr[3];
// Serial.print(myip[0], DEC);Serial.print('.');Serial.print(myip[1], DEC);Serial.print('.');//debug
// Serial.print(myip[2], DEC);Serial.print('.');Serial.println(myip[3], DEC);//debug
}
if(str.startsWith("myport=") && leng >= 8){
myportStr = str.substring(7); myport = myportStr.toInt();
}
if(str.startsWith("mydns=") && leng >= 7){
mydnsStr = str.substring(6);
setIPaddress(mydnsStr); // 192.168.0.1形式から採取し、addr[]へ書き込む
mydns[0]=addr[0]; mydns[1]=addr[1]; mydns[2]=addr[2]; mydns[3]=addr[3];
}
if(str.startsWith("mygateway=") && leng >= 11){
mygatewayStr = str.substring(10);
setIPaddress(mygatewayStr); // 192.168.0.1形式から採取し、addr[]へ書き込む
mygateway[0]=addr[0]; mygateway[1]=addr[1]; mygateway[2]=addr[2]; mygateway[3]=addr[3];
}
if(str.startsWith("mysubnet=") && leng >= 10){
mysubnetStr = str.substring(9);
setIPaddress(mysubnetStr); // 192.168.0.1形式から採取し、addr[]へ書き込む
mysubnet[0]=addr[0]; mysubnet[1]=addr[1]; mysubnet[2]=addr[2]; mysubnet[3]=addr[3];
}
if(str.startsWith("hisnetname=") && leng >= 12){
hisNetname = str.substring(11);
}
if(str.startsWith("hisipaddr=") && leng >= 11){
hisipStr = str.substring(10);
setIPaddress(hisipStr); // 192.168.0.1形式から採取し、addr[]へ書き込む
hisip[0]=addr[0]; hisip[1]=addr[1]; hisip[2]=addr[2]; hisip[3]=addr[3];
}
if(str.startsWith("hisport=") && leng >= 9){
hisportStr = str.substring(8); hisport = hisportStr.toInt();
}
if(str.startsWith("apppw=") && leng >= 7){
appPW = str.substring(6);
}
if(str.startsWith("endOfFile")){
file.close(); return;
}
}//end for
}//end While
file.close();
}//end void readFile()
void setNetworkParameter(){
//ネットワークパラメターの設定 メイン処理
// false: ランモード : ファイルが無ければ既定値でファイルを作成し、既定値でreturn。
// ファイルが有ればファイルの値でreturn。
// true : 設定モード : コマンドで設定し、ファイルに書き込む。
// exitコマンドでreturn。
String str;
byte leng;
if(SPIFFS.begin(true)){
if(settingMode){
Serial.println("\nHellow! this is net-param setting tool");
Serial.print('>');
Serial.setTimeout(300000); // 300000ms=300s=5minutes後に、Enterキー押下と同じ動作になる
while(settingMode){
if(Serial.available()){
str = Serial.readStringUntil('\n'); // '\n'=0x0A=LF
Serial.println(str); // エコーを返す
str.replace("\r",""); // 右端の '\r'=0x0D=CR をnullに変換
leng = str.length();
if(str.startsWith("make") && leng == 4){ // make the file by default value
if (makeFile()){
Serial.print("made in setting "); Serial.println(iniFileName);
}
else{
Serial.println("- failed to open file for writing");
}
Serial.print('>');
}
else{
if(str.startsWith("list") && leng == 4){ // print : print contents in file
// read file
File file = SPIFFS.open(iniFileName, FILE_READ); // モード:読み取り
if(!file || file.isDirectory()){ // ファイルが存在しない
Serial.print("nothing "); Serial.println(iniFileName);
Serial.print('>');
}//end ファイルが存在しない
else{ // ファイルが存在するのでメモリーへの取り込んでプリント
file.close();
readFile();
// メモリー内容すなわちファイル内容をprint
Serial.print("sketch="); Serial.print(sketch); Serial.println(" メインスケッチファイル名など");
Serial.print("debug="); Serial.print(debug); Serial.println(" 整数値 0:本番");
Serial.print("myplace="); Serial.print(myplace); Serial.println(" server or client");
Serial.print("myssid="); Serial.print(myssid); Serial.println(" 30文字以内");
Serial.print("mypw="); Serial.print(mypassword); Serial.println(" 30文字以内");
Serial.print("myipaddr="); listIPaddress(myip); Serial.println(" 希望固定ローカルIPアドレス .で区切る");
Serial.print("myport="); Serial.print(myport); Serial.println(" myport番号は指定しても無効(制限事項)");
Serial.print("mydns="); listIPaddress(mydns); Serial.println(" .で区切る");
Serial.print("mygateway="); listIPaddress(mygateway); Serial.println(" .で区切る");
Serial.print("mysubnet="); listIPaddress(mysubnet); Serial.println(" .で区切る");
Serial.print("hisnetname="); Serial.print(hisNetname); Serial.println(" clientの場合にサーバーのネットアドレス名");
Serial.print("hisipaddr="); listIPaddress(hisip); Serial.println(" 〃 のIPアドレス(上記とどちらか)");
Serial.print("hisport="); Serial.print(hisport); Serial.println(" 〃 のポート番号");
Serial.print("apppw="); Serial.print(appPW); Serial.println(" アプリレベルの認証パスワード(serverとclientで同じであること)");
Serial.print('>');
}
}//end list
else{
if(str.startsWith("save") && leng == 4){ // save : real update file
// 書き込み、存在すれば上書き
File file = SPIFFS.open(iniFileName, FILE_WRITE);
file.print("sketch="); file.println(sketch);
file.print("debug="); file.println(debugModeStr);
file.print("myplace="); file.println(myplace);
file.print("myssid="); file.println(myssidStr);
file.print("mypw="); file.println(mypasswordStr);
file.print("myipaddr="); file.println(myipStr);
file.print("myport="); file.println(myportStr);
file.print("mydns="); file.println(mydnsStr);
file.print("mygateway="); file.println(mygatewayStr);
file.print("mysubnet="); file.println(mysubnetStr);
file.print("hisnetname="); file.println(hisNetname);
file.print("hisipaddr="); file.println(hisipStr);
file.print("hisport="); file.println(hisportStr);
file.print("apppw="); file.println(appPW);
file.println("endOfFile");
Serial.print("updated "); Serial.println(iniFileName);
Serial.print('>');
}//end save
else{
if(str.startsWith("del") && leng == 3){ // del : delete file
if(SPIFFS.remove(iniFileName)){Serial.print("deleteed "); Serial.println(iniFileName);}
else{Serial.print("failed to delete"); Serial.println(iniFileName);}
Serial.print('>');
}
else{
if(str.startsWith("exit") && leng == 4){ // exit : セッティングを終わる
settingMode = false;
Serial.println("in to run mode");
}
else{
// modify parameter of .ini file
if(str.startsWith("sketch=") && leng >= 8){ // sketch=
sketch = str.substring(7);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("debug=") && leng >= 7){ // debug=
debugModeStr = str.substring(6);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("myplace=") && leng >= 9){ // myplace=
myplace = str.substring(8);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("myssid=") && leng >= 8){ // myssid=
myssidStr = str.substring(7);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("mypw=") && leng >= 6){ // mypw=
mypasswordStr = str.substring(5);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("myipaddr=") && leng >= 10){ // myipaddr=
myipStr = str.substring(9);
// Serial.println(myipStr);//debug
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("myport=") && leng >= 8 && leng <= 12){ // myport=
myportStr = str.substring(7);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("mydns=") && leng >= 7){ // mydns=
mydnsStr = str.substring(6);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("mygateway=") && leng >= 11){ // mygateway=
mygatewayStr = str.substring(10);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("mysubnet=") && leng >= 10){ // mysubnet=
mysubnetStr = str.substring(9);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("hisnetname=") && leng >= 12){
hisNetname = str.substring(11);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("hisipaddr=") && leng >= 11){
hisipStr = str.substring(10);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("hisport=") && leng >= 9){
hisportStr = str.substring(8);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("apppw=") && leng >= 7){
appPW = str.substring(6);
Serial.println("accepted, must save after");
Serial.print('>');
}
else{
if(str.startsWith("?") || str.startsWith("help")){ // ? or help
Serial.println("list ファイルの中身をリスト出力");
Serial.println("make 既定値でファイルを作る");
Serial.println("del ファイルそのものを削除");
Serial.println("save 更新結果をファイルに書き戻す");
Serial.println("exit セッティングを抜け出る");
Serial.println("? or help コマンドの説明");
Serial.println("以下のコマンドで各データを更新、最後にsaveでファイルを上書きすること");
Serial.println("sketch= 書き込み済みのメインスケッチファイル名など");
Serial.println("debug= 整数値 0:本番");
Serial.println("myとは:このプログラムが動作する場所(server or client)や、自身についての情報");
Serial.println("myplace= server or client");
Serial.println("myssid= 30文字以内");
Serial.println("mypw= 30文字以内");
Serial.println("myipaddr= 希望固定ローカルIPアドレス .で区切る");
Serial.println("myport= myport番号は指定しても無効(制限事項)");
Serial.println("mydns= .で区切る");
Serial.println("mygateway= .で区切る");
Serial.println("mysubnet= .で区切る");
Serial.println("hisとは:client の場合に、serverについての情報");
Serial.println("hisnetname= サーバーのネットアドレス名 30文字以内");
Serial.println("hisipaddr= 〃 のIPアドレス(上記とどちらか)");
Serial.println("hisport= 〃 のポート番号");
Serial.println("appとは:アプリレベルの情報");
Serial.println("apppw= アプリレベルの認証パスワード(serverとclientで同じであること)");
Serial.print('>');
}
else{
if(leng > 0)Serial.println("ignore");
Serial.print('>');
}}}}}}}}}}}}}}}}}}}}
}//end if(Serial.available())
}//end while(settingMode)
}//end if(settingMode)
else {// runモード
File file = SPIFFS.open(iniFileName, FILE_READ); // モード:読み取り
if(!file || file.isDirectory()){ // ファイルが存在しない
// create the file
if (makeFile()){ Serial.print("made in auto"); Serial.println(iniFileName);}
else{ Serial.println("- failed to open file for writing"); }
}
}
readFile();
SPIFFS.end();
}
else{
Serial.println("SPIFFS Mount Failed");
}
}
|