我尝试将动态方式添加到我的草图中,以从配置文件(config.txt)设置以太网信息(mac,ip,网关,子网)。因此,运行网络服务器并从sd卡提供htm文件,用户可以转到设置页面,用这些信息填写表单,并在发布时,网络服务器解析http表单并保存(更新)config.txt文件。在该系统重新启动之后,为了开始新的设置(通过读取config.txt文件)
我已经通过读取config.txt文件成功创建了除获取参数之外的所有部分(sd,以太网,web服务器,webclient,从发布的表单数据创建配置文件)。
我可以逐行读取配置,我可以将行拆分为参数和值,现在我需要用读取的数据填充一些字节变量。我可以(经过一个月的Google搜索)将IP(十进制值)读取到字节数组。 Im堆栈将MAC 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(),请不要回答。我发现了数百条建议,但没有一条可以正常读取所有参数(十进制,十六进制,字符串)。经过一个月的努力和搜索,我想知道为什么社区中不存在如此必要和有用的东西,它们完全可以正常工作!
最诚挚的问候
好的,这是一整套完成所需操作的例程-我认为您误解了char数组与单个char [0]的概念。这些例程已记录在案并且具有自我解释性。我建议不要用完结;但是在您的示例中仍然存在“ \ n”(您也看不到换行符)要获取mac地址,我需要三行:
if (strncmp(cfgLine, "mac=", 4) == 0) {
strcpy (macAddr, cfgLine + 4);
}
第一行比较前4个字符,如果为0(表示适合)第二行将第5个字符从lineBuffer的最后一个字符复制到目标数组,该数组实际上可以用作函数的参数。文件结构应为no;就像你必须解析的一样;和\ n
mac=8f:2c:2b:19:e0:b7
ip=192.168.1.200
....
postport=8080
[将char数组转换为int,我们使用atoi(),将单个char [0]转换为单个数字,我们使用int singleDigit = 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
}
我将例程划分为小的独立函数,因此它很容易适应不同的用途。很抱歉,我不深入您的代码,因为它很难遵循并且不清楚您想做什么。