WiFi를 통한 아두이노 활용 (15) : AP mode, IoT #2

2017. 8. 11. 14:56

Arduino/Wireless

AP mode 활용 및 IoT를 위한 준비

이전 글에 이어서 나머지 부분을 완성하도록 하겠습니다.

Web Server 구현하기

웹 페이지를 통해서 사용자의 데이터를 입력 받기 위해선 우선 Server 서비스를 구현해야 합니다.

#include <SPI.h>
#include <WiFi101.h>
//
char ssid_AP[] = "Feather_WiFi";
String ssid_STA = "";      //  your network SSID (name)
String pass_STA = "";   // your network password
//
int status = WL_IDLE_STATUS;
WiFiServer server(80);

위와 같이 server 인스턴스를 하나 생성합니다. 괄호안의 숫자는 포트 번호입니다.

if (status == WL_CONNECTED || status == WL_AP_LISTENING) {
    server.begin();
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);
  }

그리고, Server를 실행하는 코드를 setup() 함수 제일 아래쪽에 작성합니다. Station mode로 연결에 성공했다면 status 변수는 WL_CONNECTED값을 가집니다. 또, AP mode로 설정했다면 WL_AP_LISTENING값을 가지게 되어 둘 중 하나만 만족한다면 Web service가 가능하다는 의미이므로 begin() 함수로 Server 서비스를 시작합니다.

server가 시작되면 접속할 주소를 알아야 하므로 Serial monitor에 IP를 출력하도록 합니다. AP mode라면 192.168.1.1이 출력되고 이 주소는 원한다면 역시 변경할 수 있습니다. Station mode라면 공유기에서 할당 받은 주소가 출력됩니다. WiFi.config() 함수를 이용하면 고정 IP로도 설정 가능합니다.

Client Request 처리하기

이제 Client의 접속 및 Request 처리 코드를 작성할 차례입니다. 요청이 있을 때까지 항상 대기하고, 또 처리해야 하므로 loop() 함수에서 구현해야 합니다.

void loop() {
  WiFiClient client = server.available();
  //
  if (client) {
    Serial.println("new client");
    //
  }
}

loop() 함수내에서 무한 순환 하다가 server.available() 함수를 통해 Client가 접속했음을 알게 되면, WiFiClient class의 instance인 client변수를 선언하여 해당 Client를 받아 처리할 준비를 합니다.

IF문으로 client 접속이 있음을 확인하면 메시지를 출력하고 원하는 처리를 해주도록 코딩하면 됩니다.

void loop() {
  WiFiClient client = server.available();
  //
  if (client) {
    Serial.println("new client");
    String currentLine = "";
    while (client.connected()) {
    //  
    }
    client.stop(); // close the connection
    Serial.println("client disconnected");
  }
}

String type currentLine 변수는 클라이언트로부터 전송되어 온 메시지를 저장하기 위한 변수입니다. 이전 글에서 모두 처리했던 부분이므로 참고하세요. while (client.connected()) 문에 의해 연결이 지속되는 동안 들어오는 메시지를 모두 처리할 수 있도록 합니다.

연결이 끊기면 client.stop() 함수를 호출하여 열었던 소켓을 닫습니다.

while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
      }
    }

while문 안쪽을 구성하겠습니다. 우선, if (client.available()) 함수를 이용해 buffer에 도착한 문자가 있는지 체크합니다. while문 안쪽에 있기 때문에 들어오는 문자는 모두 처리할 수 있습니다. 버퍼에서 문자를 하나 읽어 디버깅을 위해 Serial monitor에 출력합니다.

이제 입력 받은 메시지를 분석하여 메시지가 끝났는지 알아내야 합니다. Client request가 끝나면 웹 페이지를 전송하기 위함입니다.

이전 글에서 다루었던 것처럼, 메시지를 분석할 때, 들어온 문자를 딱 세 가지로 구분합니다. "\n", "\r", 나머지 문자들로 나누어서 처리하면 됩니다. \n은 Line feed(LF), 줄바꿈 문자입니다. 줄바꿈 문자가 두 개 연속으로 오면 메시지가 끝났것이므로 이를 체크해야 합니다. \r은 Carrage Return(CR), 줄 처음으로 커서를 이동하는 문자인데, 처리할 내용이 없으므로 무시하도록 코딩합니다. 나머지 문자들은 currentLine에 하나씩 붙여 줍니다.

if (client.available()) {
    char c = client.read();
    Serial.write(c);
    if (c == '\n') {
        if (currentLine.length() == 0) {
        // request ended, web page print out
        } else {
          // new line, clear currentLine
            currentLine = "";
        }
    } else if (c != '\r') {
          currentLine += c;
    }
}

위와 같이 IF ELSE문으로 위에서 말한 사항을 구성하였습니다. 조건은 두 가지입니다. LF이든지 아니면 CR이 아닌 나머지 문자든지 두 가지만 따지면 됩니다.

LF가 들어오면 if (currentLine.length())문을 먼저 만납니다. 줄바꿈이 발생했는데 이전에 저장한 내용이 없다면 바로 빈 줄에 해당합니다. Client 요청의 마지막은 항상 빈 줄로 끝나기 때문에 이 시점에서 웹 페이지를 출력합니다.

이 부분을 해결하기 위해 이전 예제들에선 다른 방식을 사용했습니다. 줄바꿈 문자가 오고 바로 이어서 또 줄바꿈 문자가 온다면 역시 빈 줄을 의미하기 때문에 bool newLine이라는 변수를 선언해서 LF가 연속으로 왔는지를 체크했었습니다. 이 부분은 이전 예제를 참고하세요.

줄바꿈이 일어나고 저장된 문자들이 있다면 새로운 줄이 시작된다는 의미이므로 currentLine을 clear하여 새 문장을 받을 준비를 합니다. LF가 아니고 CR도 아니라면 문자를 저장합니다.

Web page 출력하기

if (currentLine.length() == 0) {
            // request ended, web page print out
            Serial.println("Client Request Ended!");
            Serial.println("Web page transfer Start!");
            //
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            //
            client.println("<!DOCTYPE html>");
            client.println("<html>");
            client.println("<head>");
            client.println("<title>Network Info</title>");
            client.println("</head>");
            client.println("<body>");
            client.println("<h1>WiFi Connection Status</h1>");
            client.println("<p>IP Address : ");
            IPAddress ip = WiFi.localIP();
            client.println(ip);
            client.println("</p>");
            client.print("<p>SSID : ");
            client.print(WiFi.SSID());
            client.print("</p>");
            client.print("<p>RSSI : ");
            client.print(WiFi.RSSI());
            client.print(" dBm</p>");
            client.println("</body>");
            client.println("</html>");
            break;
          } else {
            // new line, clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }

웹페이지 출력 코드를 작성하였습니다. 이전 예제에서 그대로 복사해온 부분이라 따로 설명은 하지 않겠습니다.

웹페이지 출력이 모두 끝나면 더이상 입력 받을 필요가 없기 때문에 break문을 통해 while문을 빠져나가고 클라이언트는 close()하게 됩니다.

왼쪽은 AP mode로 실행한 결과이고, 오른쪽은 STA mode의 결과입니다. STA(Station) mode 결과 확인을 위해 SSID와 패스워드를 미리 입력해 주었습니다. 출력할 내용이 따로 없어서 위와 같이 간단한 네트워크 정보를 출력하도록 했습니다.

이제 웹 화면을 통해 Station mode를 위한 SSID와 Password를 입력받는 화면을 구성하기 위해 우선 HTML Tag 먼저 작성해 보겠습니다.

<form>
</form>

웹화면을 통해 사용자의 입력을 받는 부분은 단순한 GET 방식일 경우 아주 쉽게 처리할 수 있습니다. 위와 같은 <form></form> 태그안에 Form Elements를 배치하면 끝입니다. 우선 Text input이 두 개 필요합니다.

<input type="text" name="ssid" placeholder="SSID">
<input type="password" name="pass" placeholder="Password">

<input> 태그의 type attribute를 text로 하면 일반적인 텍스트 입력 칸을 의미합니다. type이 password이면 text와 동일하지만 입력 내용만 보이지 않도록 검은색 점으로 바꿔 줍니다. 어느 입력 칸에 있는 값인지 구별하기 위해 name attribute를 꼭 입력해 줘야 합니다. placeholder attribute는 입력할 내용에 대한 힌트를 주기 위해 입력 칸에 미리 들어 있는 텍스트를 말합니다. 아주 일반적인 사항들이라 실행해보시면 바로 알 수 있습니다.

<input type="submit" value="Submit">
<input type="reset" value="Reset">

인터넷 폼 화면에서 흔히 보는 버튼 두 가지입니다. submit 버튼을 누르면 폼 태그안에 있는 사용자 입력값이 모두 서버에 전송됩니다. value attribute는 생략도 가능합니다.

client.println("<form>");
client.println("<input type=\"text\" name=\"ssid\" placeholder=\"SSID\">");
client.println("<input type=\"password\" name=\"pass\" placeholder=\"PASSWORD\">");
client.println("<input type=\"submit\" value=\"Submit\">");
client.println("<input type=\"reset\" value=\"Reset\">");
client.println("</form>");

여기까지 4개의 elements를 출력하도록 코딩했습니다. println() 함수 내에서 큰 따옴표 자체를 출력하기 위해선 이스케이프 문자 \(역슬래시)를 붙여야 합니다. 위 코드를 적용한 결과 화면은 아래와 같습니다.

오른쪽 화면은 <hr>, <br> 태그 등으로 정리한 모습입니다.

여기까지 전체 소스

#include <SPI.h>
#include <WiFi101.h>
//
char ssid_AP[] = "Feather_WiFi";
String ssid_STA = "";      //  your network SSID (name)
String pass_STA = "";   // your network password
//
int status = WL_IDLE_STATUS;
WiFiServer server(80);
//
void setup() {
  WiFi.setPins(8,7,4,2); // SPI pin setting
  Serial.begin(9600);
  delay(1000); 
  if (WiFi.status() == WL_NO_SHIELD) {
        Serial.println("WiFi shield not present");
        while (true);
  }
  if (ssid_STA.length() != 0) {
    connect_STA();
  } else {
    Serial.println("SSID is not setted!");
  }
  if (status != WL_CONNECTED) {
    connect_AP();
  }
  if (status == WL_CONNECTED || status == WL_AP_LISTENING) {
    server.begin();
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);
  }
}
//
void loop() {
  WiFiClient client = server.available();
  if (client) {
    Serial.println("new client");
    String currentLine = "";
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n') {
          if (currentLine.length() == 0) {
            // request ended, web page print out
            Serial.println("Client Request Ended!");
            Serial.println("Web page transfer Start!");
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            client.println("<!DOCTYPE html>");
            client.println("<html>");
            client.println("<head>");
            client.println("<title>Network Info</title>");
            client.println("</head>");
            client.println("<body>");
            client.println("<h1>WiFi Connection Status</h1>");
            client.println("<p>IP Address : ");
            IPAddress ip = WiFi.localIP();
            client.println(ip);
            client.println("</p>");
            client.print("<p>SSID : ");
            client.print(WiFi.SSID());
            client.print("</p>");
            client.print("<p>RSSI : ");
            client.print(WiFi.RSSI());
            client.println(" dBm</p>");
            client.println("<hr>");
            client.println("<h2>Network Credentials</h2>");
            client.println("<form>");
            client.println("<input type=\"text\" name=\"ssid\" placeholder=\"SSID\"><br>");
            client.println("<input type=\"password\" name=\"pass\" placeholder=\"PASSWORD\"><br>");
            client.println("<input type=\"submit\" value=\"Submit\">");
            client.println("<input type=\"reset\" value=\"Reset\">");
            client.println("</form>");
            client.println("</body>");
            client.println("</html>");
            break;
          } else {
            // new line, clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }
      }
    }
    client.stop(); // close the connection
    Serial.println("client disconnected");
  }
}
//
void connect_AP() {
  int count = 0;
  while (status != WL_AP_LISTENING) {
    count++;
    Serial.print(count);
    Serial.print(" Creating access point named: ");
    Serial.println(ssid_AP);
    status = WiFi.beginAP(ssid_AP);
    if (count > 3) {
      Serial.println("Creating access point failed!");
      return;
    }
  }
}
//
void connect_STA() {
  int count = 0;
  while (status != WL_CONNECTED) {
    count++;
    Serial.print(count);
    Serial.print(" Attempting to connect to Network named: ");
    Serial.println(ssid_STA);                   // print the network name (SSID);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid_STA, pass_STA);
    if (count > 3) return; 
    // wait 2 seconds for connection:
    delay(2000);
  }
}

SSID, Password 입력받아 처리하기

이제 사용자로부터 입력 받아 처리하는 부분을 작성하겠습니다. 바로 위에서 완성한 소스를 실행하고 웹페이지에 접속하여 SSID와 Password를 입력한 후 Submit 버튼을 클릭합니다.

Client로 부터 온 Request message는 모두 Serial monitor에 출력되도록 코딩했습니다. SSID와 Password를 입력한 후 Submit 버튼을 누르면 위와 같이 Reuqest message에 그 내용이 같이 전송됩니다. default로 GET method를 이용하기 때문입니다. 그림에서 표시된 부분을 분석하여 필요한 정보를 뽑아 냅니다.

if (c == '\n') {
        if (currentLine.length() == 0) {
        // request ended, web page print out
        } else {
          // <--- message processing
          // new line, clear currentLine
            currentLine = "";
        }
    } else if (c != '\r') {
          currentLine += c;
    }

client request message를 분석하는 부분을 볼 때, 오렌지색으로 주석처리된 부분이 한 문장이 완성되고 새로운 문장이 시작할 시점입니다. 이 부분에서 currentLine을 처리하고 끝나면 다음 문장을 입력 받기 위해 클리어 해주면 됩니다. 원하는 부분을 추출하는 것은 String class 함수들을 이용하면 쉽게 처리할 수 있습니다.

bool ssidSet = false;
bool passSet = false;
int indexSsid = currentLine.indexOf("ssid=");
int indexAmp = currentLine.indexOf("&");
if (indexSsid != -1 && indexAmp != -1) {
//              
}

우선, SSID를 추출하는 코드입니다. indexOf() 함수는 인수로 주어진 문자열을 찾으면 첫 글자의 인덱스값(몇 번째인지)을 리턴하고 찾지 못하면 -1을 리턴합니다. int indexSsid변수는 그 값을 저장하구요. 저장된 메시지에 "ssid=" 문자열이 있어야만 추출할 값이 존재하는 것이므로 indexSsid 값이 -1이 아닌지 꼭 확인해야 합니다.

indexSsid는 찾으려는 문자열 "ssid="의 첫 번째 문자 "s"의 위치값을 가지게 되고, 추출할 값인 "TURTLE"은 "ssid="이 다섯 글자이므로 indexSsid + 5번째 부터 잘라내야 합니다. 잘라내야할 값이 몇 글자인지 미리 알수 없기 때문에, "&"기호를 찾아서 그 앞까지 잘라내면 됩니다. "&"기호는 Client가 Submit 클릭시 제출되는 Form 요소들을 나열할 때 쓰는 구분기호입니다.

indexAmp 변수는 이 구분기호의 위치값을 저장합니다. 그리고, 이 기호가 있는지도 꼭 체크해야 하구요! IF문에 의해 찾으려는 값이 모두 존재하면 필요한 처리를 하도록 구성하였습니다.

ssidSet, passSet 변수는 SSID와 Password가 추출되었는지 기억하기 위한 변수입니다.

bool ssidSet = false;
bool passSet = false;
int indexSsid = currentLine.indexOf("ssid=");
int indexAmp = currentLine.indexOf("&");
if (indexSsid != -1 && indexAmp != -1) {
  ssid_STA = currentLine.substring(indexSsid + 5, indexAmp);
  ssidSet = true;
}

이제 SSID를 찾아서 추출하고 프로그램 처음에 선언한 ssid_STA 변수에 저장합니다. substring() 함수는 문자열에서 일부만 잘라내는 기능을 합니다. 이 함수에 두 개의 인수가 주어진다면 각각 자르려는 문자열의 시작과 끝을 알려주는 인덱스값입니다. 단, 이 때 두 번째 인덱스에 있는 문자는 제외됩니다. 즉, 첫 번째 인덱스부터 두 번째 인덱스 전까지 추출합니다. SSID를 추출하였으므로 ssidSet에 true를 저장합니다.

int indexPass = currentLine.indexOf("pass=");
int indexHttp = currentLine.indexOf("HTTP/1.1");
if (indexPass != -1 && indexHttp != -1) {
pass_STA = currentLine.substring(indexPass + 5, indexHttp);
pass_STA.trim();
      passSet = true;
}

Password를 추출하는 부분도 동일합니다. 단지, 잘라낸 부분의 끝쪽에 공백이 포함되기 때문에 trim()함수를 한 번 실행하였습니다. 이제 SSID와 Password를 입력 받아 사용할 준비까지 완료하였습니다.

if (ssidSet == true || passSet == true) {
client.stop();
WiFi.end();
}

SSID나 Password 둘 중 하나만 입력되어도 실행되는 IF문입니다. 새로운 네트워크 접속 정보가 들어 왔으므로 다시 접속하기 위해 WiFi를 끝내도록 코딩하였습니다. WiFi.end() 함수는 AP mode일 경우 종료하고, Station mode일 경우 WiFi에서 disconnect 합니다.

Network ReConnect

이제 AP mode가 종료되었거나 Network connection이 해제되었을 경우 다시 연결을 시도하도록 코딩하겠습니다. 반복적인 부분이므로 당연히 loop() 함수내에 작성합니다.

WL_CONNECTED
WL_AP_LISTENING
WL_AP_CONNECTED

우선, 네트워크가 해제되었는 지 알아낼 방법이 있어야 합니다. 위에 나열된 3가지는 WiFi module의 상태값을 나타내는 상수값입니다. 이전 글에서 다룬 적이 있는데, WiFi101.h 헤더파일에 보면 모든 상태값을 알 수 있습니다.

WL_CONNECTED는 Station mode 상태에서 WiFi에 연결되어 있음을 나타냅니다. WL_AP_LISTENING는 AP mode가 정상적으로 실행되고 Device의 접속을 기다리고 있는 상태이며, WL_AP_CONNECTED는 Device가 AP에 접속했음을 의미합니다. 3가지 모두 네트워크가 가능한 상태이므로 위 3가지 경우가 아닐 경우를 체크하면 됩니다.

if (status != WL_CONNECTED && status != WL_AP_LISTENING && status != WL_AP_CONNECTED) {
}

위와 같이 구성한다면 가능할 듯 한데, 이 보다 더 쉬운 방법이 있습니다.

if (WiFi.SSID() == 0) {
}

위 코드로 간단히 체크할 수 있습니다. WiFi.SSID() 함수는 위 3가지 상태값이 맞으면 현재 SSID값을 반환하고 아니라면 숫자 0을 반환합니다. WiFi101 라이브러리에서 WiFi.cpp 파일을 열어 보면 확인할 수 있습니다.

void loop() { 
  if (WiFi.SSID() == 0) {
    connectSet();
  } else {
    webService();
  }
}

위 코드를 적용하고 loop() 함수를 변경했습니다. 네트워크가 성립되지 않았다면 connectSet() 함수를 실행하고 성립되었다면 웹서비스를 제공합니다. 또, loop() 함수를 간단히 하기 위해 웹서비스 부분은 그대로 잘라내어 webService() 함수에 넣었습니다.

connectSet() 함수는 connect_STA()함수와 connect_AP() 함수를 이용해 네트워크를 설정합니다. setup() 함수에 있던 부분을 그대로 connectSet() 함수내에 잘라서 넣어주면 됩니다.

업로드 후 기동하면, 처음엔 SSID, Password가 비어 있기 때문에 AP모드를 실행합니다. 스마트폰 등을 이용해 WiFi 연결 화면을 보면, 프로그램 소스 상단에서 기술한 AP용 SSID인 "Feather_WiFi"를 볼 수 있습니다. 해당 WiFi를 선택하면 비밀번호 없이 바로 연결이 성립됩니다.

그런 후, 웹브라우저에서 192.168.1.1로 접속하면 웹페이지를 확인할 수 있고, Station mode용 SSID와 Password를 입력하고 Submit을 클릭하면 해당 내용이 셋팅되고, AP mode가 끝납니다. 그리고 자동으로 무선공유기의 WiFi에 입력된 SSID와 Password로 접속할 것입니다.

역시, 스마트폰을 이용해 동일한 WiFi망에 연결한 후, 아두이노가 할당받은 IP에 접속하여 웹 페이지를 전송받을 수 있습니다.

또, 이렇게 연결되었을 때, 무선공유기의 전원을 내려보면, 네트워크 연결이 끊어진 것을 인식하고 다시 재 연결을 시도합니다. 물론, 무선 공유기가 꺼져 있기 때문에 AP mode로 들어 갑니다.

여기 까지의 전체 소스는 펼쳐서 확인하세요! 내용이 길어져서 나머지 부분은 다음 글에서 계속하겠습니다.

#include <SPI.h>
#include <WiFi101.h>
//
char ssid_AP[] = "Feather_WiFi";
String ssid_STA = "";      //  your network SSID (name)
String pass_STA = "";   // your network password
//
int status = WL_IDLE_STATUS;
WiFiServer server(80);
//
void setup() {
  WiFi.setPins(8,7,4,2); // SPI pin setting
  Serial.begin(9600);
  delay(1000);
  //
  if (WiFi.status() == WL_NO_SHIELD) {
        Serial.println("WiFi shield not present");
        while (true);
  }
  //
  connectSet();
}
//
void loop() {
  //
  if (WiFi.SSID() == 0) {
    connectSet();
  } else {
    webService();
  }
}
//
void connectSet() {
  status = WiFi.status();
  if (ssid_STA.length() != 0) {
    connect_STA();
  } else {
    Serial.println("SSID is not setted!");
  }
  //
  if (status != WL_CONNECTED) {
    connect_AP();
  }
  //
  if (status == WL_CONNECTED || status == WL_AP_LISTENING) {
    server.begin();
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);
  }
}
//
void webService() {
  WiFiClient client = server.available();
  //
  if (client) {
    Serial.println("new client");
    String currentLine = "";
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n') {
          if (currentLine.length() == 0) {
            // request ended, web page print out
            Serial.println("Client Request Ended!");
            Serial.println("Web page transfer Start!");
            //
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            //
            client.println("<!DOCTYPE html>");
            client.println("<html>");
            client.println("<head>");
            client.println("<title>Network Info</title>");
            client.println("</head>");
            client.println("<body>");
            client.println("<h1>WiFi Connection Status</h1>");
            client.println("<p>IP Address : ");
            IPAddress ip = WiFi.localIP();
            client.println(ip);
            client.println("</p>");
            client.print("<p>SSID : ");
            client.print(WiFi.SSID());
            client.print("</p>");
            client.print("<p>RSSI : ");
            client.print(WiFi.RSSI());
            client.println(" dBm</p>");
            client.println("<hr>");
            client.println("<h2>Network Credentials</h2>");
            client.println("<form>");
            client.println("<input type=\"text\" name=\"ssid\" placeholder=\"SSID\"><br>");
            client.println("<input type=\"password\" name=\"pass\" placeholder=\"PASSWORD\"><br>");
            client.println("<input type=\"submit\" value=\"Submit\">");
            client.println("<input type=\"reset\" value=\"Reset\">");
            client.println("</form>");
            client.println("</body>");
            client.println("</html>");
            break;
          } else {
            bool ssidSet = false;
            bool passSet = false;
            //
            int indexSsid = currentLine.indexOf("ssid=");
            int indexAmp = currentLine.indexOf("&");
            if (indexSsid != -1 && indexAmp != -1) {
              ssid_STA = currentLine.substring(indexSsid + 5, indexAmp);
              ssidSet = true;
            }
            int indexPass = currentLine.indexOf("pass=");
            int indexHttp = currentLine.indexOf("HTTP/1.1");
            if (indexPass != -1 && indexHttp != -1) {
              pass_STA = currentLine.substring(indexPass + 5, indexHttp);
              pass_STA.trim();
              passSet = true;
            }
            if (ssidSet == true || passSet == true) {
              client.stop();
              WiFi.end();
            }
            // new line, clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }
      }
    }
    client.stop(); // close the connection
    Serial.println("client disconnected");
  }
}
//
void connect_AP() {
  int count = 0;
  while (status != WL_AP_LISTENING) {
    count++;
    Serial.print(count);
    Serial.print(" Creating access point named: ");
    Serial.println(ssid_AP);
    //
    status = WiFi.beginAP(ssid_AP);
    //
    if (count >= 3) {
      Serial.println("Creating access point failed!");
      return;
    }
  }
}
//
void connect_STA() {
  int count = 0;
  while (status != WL_CONNECTED) {
    count++;
    Serial.print(count);
    Serial.print(" Attempting to connect to Network named: ");
    Serial.println(ssid_STA);                   // print the network name (SSID);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid_STA, pass_STA);
    if (count >= 3) return; 
    // wait 2 seconds for connection:
    delay(2000);
  }
}

Comments