Study/ESP8266(WIFI),ESP32(BLE,WIFI)

스마트폰 연동 AP-STA 전환 using Arduino

Answer Choi 2016. 1. 13. 14:53
반응형

Arduino 소스


GMMP 라이브러리 


이전 예제와 다소 비슷하며 소스를 조금 수정하여 첨부하였습니다.


이전 예제 참고


크게 AP모드와 STATION모드의 setup()과, loop쪽으로 알아보겠습니다.


참고로 GMMP 라이브러리는 내문서\arduino\에 복사해야 됩니다.


void setup(void)-공통 setup()


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  EEPROM.begin(256);
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  pinMode(MODE_SW, INPUT);
 
  infoln(("Start setup()"));
 
  info(("Free memory size: "));
  infoln(freeRam());  
  
  infoln("read eeprom");  
  info("wifi mode=");
  cur_mode=EEPROM.read(addr_mode);
  if(!digitalRead(MODE_SW))       //ap mode button
    cur_mode=ap;
cs


기본 세팅부분입니다.


Line 1 : EEPROM 초기화하는 부분


Line 2 : serial(uart) 초기화 부분


Line 3 : LED 출력부분


Line 4 : 모드변경 스위치 입력부분


Line 8~9 : freeRam 읽어와 출력


Line 11~13 : EEPROM에서 현재 저장되어 있는 모드 값을 가져옵니다.


참고로 EEPROM의 사용 영역은 아래 그림과 같습니다.

0번지는 모드입니다.(AP모드 또는 STA모드)


10번지는 SSID의 길이 값


20번지는 PWD의 길이 값


100번지부터는 SSID


200번지부터는 PWD


Line 14~15 : 혹시 모드가 STA모드라도 버튼이 MODE버튼이 눌려지면 AP모드로 전환 됩니다.


AP모드(setup)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  if(cur_mode==ap)                //if ap mode
  {   
    Wifi8266.mode(WIFI_AP);
    infoln("ap");
          
    String macID=Wifi8266.softAPmacAddress();
    macID.toUpperCase();
 
    String AP_NameString = "JME Plug " + macID;
    char AP_NameChar[AP_NameString.length() + 1];
    memset(AP_NameChar, 0, AP_NameString.length() + 1);
    for (int i=0; i<AP_NameString.length(); i++)
      AP_NameChar[i] = AP_NameString.charAt(i);
 
    char* AP_PwdChar="1234567890";  
 
    Wifi8266.softAP(AP_NameChar, AP_PwdChar);
 
    infoln(Wifi8266.softAPIP());
    Wifiserver.begin();
  }
cs


setup에서 AP모드로 들어오게 되면 위의 코드가 실행됩니다.


앞의 포스트에도 설명되어 있으니 간단하게 설명하겠습니다.


Line 3 : AP모드로 변경합니다.


Line 6~7 : mac주소값을 대문자로 가져옵니다.


Line 9~13 : SSID값으로 JME Plug + MAC주소 값으로 설정합니다.


Line 15 : PASSWORD값으로 1234567890으로 설정합니다.


Line 17 : AP모드를 실행합니다.


Line 19 : AP의 주소값을 가져와 출력해줍니다.


Line 20 : 스마트폰으로 접속하기 위해 서버로 설정합니다.


AP모드(loop)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
if(cur_mode==ap){                   //if ap mode
    
    infoln("Waiting for connecting");
    while (!Wificlient.connected()) 
    {
        Wificlient = Wifiserver.available();
    } 
    infoln("connected");
    while(!Wificlient.available()){
        info(".");
        delay(1000);
    }
        
    String req = Wificlient.readStringUntil(0x0d);
    Serial.println(req); 
    int len_name=req.indexOf(':');
    int len_pwd=req.indexOf(0x20);
    String str_ssid=(req.substring(0,len_name));
    String str_pwd=(req.substring(len_name+1,len_pwd));
    info("str_ssid=");
    infoln(str_ssid);
    info("str_pwd=");
    infoln(str_pwd);
 
    ssid=const_cast<char*>(str_ssid.c_str());
    pwd=const_cast<char*>(str_pwd.c_str());
    info("ssid=");
    infoln((char*)ssid);
    info("pwd=");
    infoln((char*)pwd);
    infoln("rcv completed");
 
    EEPROM.write(addr_mode,station);    
    for(int i=0;i<len_name;i++)
    {
      EEPROM.write(addr_ssid+i,ssid[i]); 
      info(ssid[i]);   
    }
    for(int i=0;i<(len_pwd-len_name-1);i++)
    {
      EEPROM.write(addr_pwd+i,pwd[i]);
      info(pwd[i]);
    }    
    EEPROM.write(addr_ssid_length,len_name);
    EEPROM.write(addr_pwd_length,(len_pwd-len_name-1));   
    EEPROM.commit(); 
 
    infoln("JME Plug reboot");
    EspClass esp;
    esp.restart();    
  }
cs


Line 4~12 : 클라이언트(스마트폰)가 접속하길 기다립니다.


Line 14~15 : 클라이언트로 부터 데이터를 전송받아 출력합니다.

(CR문자를 수신할때까지 계속 수신합니다.)


Line 16~23 : 수신한 문자열을 파싱하여 문자열 str_ssidstr_pwd에 나눠서 저장합니다.


Line 25~31 : 문자열(str_ssidstr_pwd)을 char pointer(ssidpwd)로 변환합니다.


Line 33 : 모드를 station으로 바꿔 EEPROM에 저장합니다.


Line 34~38 : ssid를 EEPROM에 저장합니다.


Line 39~43 : pwd를 EEPROM에 저장합니다.


Line 44~45 : ssid와 pwd의 길이를 EEPROM에 저장합니다.


Line 46 : EEPROM write를 실행합니다.(commit이 빠지면 저장이 되지 않습니다.)


Line 48~50 : ESP8266을 부팅합니다.(부팅후엔 sta모드로 바뀌겠죠?)


여기까지의 실행 모습입니다.


STATION모드(setup)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
else{                            //if sta mode
    infoln("sta");
    Wifi8266.mode(WIFI_AP);
    int ssid_length=EEPROM.read(addr_ssid_length);
    int pw_length=EEPROM.read(addr_pwd_length);
    infoln(ssid_length);
    infoln(pw_length);
 
    String str_ssid;
    for(int i=0;i<ssid_length;i++)
    {
      str_ssid+=(char)(EEPROM.read(addr_ssid+i));   
    }
    infoln("");  
    info("str_ssid : ");
    infoln(str_ssid);
 
    String str_pwd;
    for(int i=0;i<pw_length;i++)
    {
      str_pwd+=(char)(EEPROM.read(addr_pwd+i));     
    }
    infoln("");  
    info("str_pwd : ");
    infoln(str_pwd);
        
    ssid=const_cast<char*>(str_ssid.c_str());
    pwd=const_cast<char*>(str_pwd.c_str());
    info("ssid=");
    infoln((char*)ssid);
    info("pwd=");
    infoln((char*)pwd);
    infoln("setting completed");
 
    info(F("Getting IP"));
    Wifi8266.begin(ssid,pwd); //ans
    while(Wifi8266.status()!=WL_CONNECTED){ //waiting for conneting
      delay(1000);
      info(".");
    }
    infoln("");
    info(F("Obtained IP: "));
    infoln(Wifi8266.localIP());     //ans
    delay(3000);      //ans
    
    Initialize(serverIp, nServerPort, pszDomainCode, pszGWAuthID, mac);
    SetCallFunction(Recv);
  
  int ret = GO_Reg(NULL, pszGWMFID);
 
  if (ret != GMMP_SUCCESS) {
    errorln(F("RegReq Error!!"));
    for(;;);
  }
 
  infoln(F("GW RegReq has been sent."));
  }
 
cs

Line 4~7 : ssid와 pwd의 길이값을 EEPROM에서 읽어옵니다.


Line 9~16 : 읽어 온 ssid길이값을 바탕으로 ssid를 EEPROM에서 문자열로 읽어옵니다.


Line 18~25 : pwd길이값으로 pwd를 EEPROM에서 문자열로 읽어옵니다.


Line 27~33 : 문자열 ssid와 pwd를 char pointer로 변환합니다.


Line 35~44 : station모드로 AP에 접속하는 부분인데 원래는 GMMP.cpp에 있던 코드를 밖으로 


뺐습니다. ssid와 pwd를 GMMP.cpp로 전달해도 됩니다.


Line 46~56 : AP로부터 IP까지 부여받았으니 서버로 접속합니다.


STATION모드(loop)


이 부분은 이전 포스트에서 바뀐게 없으므로 생략합니다.^^(첨부된 소스를 참고해 주세요.)


실행모습입니다.


다음 포스팅에는 스마트폰 앱쪽을 변경해보겠습니다.




반응형