본문 바로가기
Study/ESP8266(WIFI),ESP32(BLE,WIFI)

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

by Answer Choi 2016. 1. 13.
반응형

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)


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


실행모습입니다.


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




반응형

인기글