위즈네트 아카데미

TUTORIAL

튜토리얼

Home  > 튜토리얼

Wi-Fi 지오로케이션 (Geolocation) 시계 만들기

WIZnet Academy 2016.03.10 10:46 조회 수 : 28

이번 포스팅에서는 WizFi250과 WIZwiki-W7500을 이용하여 지오로케이션 (Geolocation) Server에 접속해서 현재 내 위치를 알아 확인하고, NTP(Network Time Protocol) Server를 통해 시간을 가져오는 예제를 설명드리겠습니다.

본 프로젝트 진행을 위한 시스템은 아래와 같이 구성합니다.

geo1

필요한 하드웨어 부품


이번 프로젝트 진행을 위해 필요한 주요 하드웨어 부품입니다.

  • WIZwiki-W7500 : Cortex-M0 기반의 MCU 플랫폼 보드입니다.geo2

  • WizFi250-EVB : WiFi 연결을 담당합니다. WizFi250 모듈의 Evaluation Board 이자 아두이노 Pin Compatible하게 설계되어 있어, 아두이노의 Wi-Fi 쉴드로 활용이 가능합니다. geo3

  • 센서쉴드 : 각종 센서가 장착되어 있는 쉴드로 WIZwiki-W7500에 꽂아서 각종 Peri 를 손쉽게 동작 및 테스트해볼 수 있습니다. geo4

  • SSD1306 OLED : 128 x 64 dot matrix panel


 

Hardware Configuration


WIZwiki-W7500 Board는 UART0 RX/TX/CTS/RTS 핀들로 WizFi250을 제어하고, I2C SDA/SCL 핀을 이용하여 SSD1306 OLED를 제어 합니다.

geo5

geo6

WizFi250 Geolocation과 NTP Example 컴파일하기


아래 주소에 접속하면 WizFi250 Geolocation NTP Example를 이용할 수 있으며, Example에서 사용하는 라이브러리들은 아래와 같습니다.

WizFi250 Geolocation_NTP Example

SSD 1306 Library

SSD1306 OLED를 사용하기 위해 Adarfruit GFX Library를 사용하였습니다. 이 라이브러리를 사용하는 중, Display() 함수에 약간의 버그가 있는 거 같아서 수정 후, 원작자에게 Pull Request를 보낸 상태입니다.

HTTP Client

HTTP Client Library는 이름에서도 알 수 있듯이, 외부에 있는 웹 서버에 Request와 Response를 송/수신 하기 위해 사용됩니다. 본 예제에서는 ip-api.com 서버에 접속해서 Geolocation(지리적 위치 코드)를 얻기 위해 사용되며, ip-api.com/csv 주소로 접속하면 csv 형태로 국가 이름, 주소, 위도(latitude), 경도(longitude), TimeZone 등의 정보를 얻을 수 있습니다.

아래 링크를 클릭하면 HTTP Client Library를 다운로드 할 수 있습니다.

HTTP Client

NTP Client

NTP Client Library는 UDP 통신을 이용하여 Network Time Server에서 UTC(협정 세계 시각)을 얻기 위해 사용됩니다. 본 예제에서는 한국의 NTP Server Domain인 kr.pool.ntp.org를 이용하였습니다. NTP Server로 받은 정보는 UTC (협정 세계 시각)이므로, 9시간을 더해야 한국 시간을 알 수 있습니다

NTP Client

Example Source Code

WizFi250-Geolocation_NTP
#include "mbed.h"
#include "Adafruit_SSD1306.h"
#include "WizFi250Interface.h"
#include "NTPClient.h"
#include "HTTPClient.h"


#define SECURE WizFi250::SEC_AUTO
#define SSID "wizohp"
#define PASS "wiznet218"


#if defined(TARGET_WIZwiki_W7500)
#define SDA PA_10
#define SCL PA_9
WizFi250Interface wizfi250(D1,D0,D7,D8,PA_12,NC,115200);
Serial pc(USBTX,USBRX);
#endif


// an SPI sub-class that provides a constructed default
class I2CPreInit : public I2C
{
public:
I2CPreInit(PinName sda, PinName scl) : I2C(sda, scl)
{
frequency(100000);
start();
};
};

I2CPreInit gI2C(SDA,SCL);
Adafruit_SSD1306_I2c gOled(gI2C,NC,0x78,64,128);
NTPClient ntpClient;
HTTPClient httpClient;
void parse(char buffer[], int *j, char *string); //FUNCTION TO PARSE HTTP GET DATA
char httpGetData[200]; //BUFFER TO HOLD DATA FROM HTTP GET REQUEST


int main()
{
time_t ctTime; //system time structure
char success[10]={0}; //success first
char countryFull[20]={0}; //Full Country Name
char countryAbrv[5]={0}; //Abbreviated Country Name or country Code
char stateAbrv[5]={0}; //Abbreviated State or region code
char stateFull[15]={0}; //Full State Name
char city[15]={0}; //City Name
char zip[6]={0}; //ZIP CODE
char latitude[10]={0}; //latitude
char longitude[10]={0}; //longitude
char timeZone[30]={0}; //timeZone
int j=0, returnCode;

pc.baud(115200);
gOled.begin();
gOled.clearDisplay();

wizfi250.init();
returnCode = wizfi250.connect(SECURE, SSID, PASS);

if ( returnCode == 0 )
{
printf(" - WiFi Readyrn");
printf("IP Address is %srn", wizfi250.getIPAddress());
}
else
{
printf(" - Could not initialize WiFi - endingrn");
return 0;
}

//HANDLES THE HTTP GET REQUEST THE WAY THE FUNCTION IS CALLED HERE IS THE FOLLOWING
// get(DOMAIN_NAME,BUFFER,TIMEOUT_VAL)
//DOMAIN_NAME= domain name that get request is sent to
//BUFFER= buffer to store data returned from the server
//TIMEOUT_VAL= Time before the request times out
HTTPResult r = httpClient.get("http://ip-api.com/csv",httpGetData,128); //GET GEOLOCATION DATA (CSV)

if (r==HTTP_OK) { //IF THE DATA WAS RECIEVED
j=0;
//parse and display each of the API's location information strings on the LCD
parse(httpGetData, &j, success);
parse(httpGetData,&j,countryFull);
parse(httpGetData,&j,countryAbrv);
parse(httpGetData,&j,stateAbrv);
parse(httpGetData,&j,stateFull);
parse(httpGetData,&j,city);
parse(httpGetData,&j,zip);
parse(httpGetData,&j,latitude);
parse(httpGetData,&j,longitude);
parse(httpGetData,&j,timeZone);
gOled.printf("HTTP Data Receivedrn");
gOled.display();
}
else { //HTTP GET REQUEST ERRORED
gOled.printf("HTTP Error %drn", r);
gOled.display();
return -1;
}
printf("Reading Time...rn");
char* domainName="kr.pool.ntp.org"; //SET TO DOMAIN NAME OF SERVER GETTING TIME FROM
//GETS THE TIME FROM THE SERVER
//setTime(DOMAIN_NAME,PORT_NUMBER,TIME_OUT)
//DOMAIN_NAME= domain name
//PORT NUMBER=port number (123 for NTP)
//TIME_OUT= timeout value for request
ntpClient.setTime(domainName,123,0x00005000);
printf("Time Setrn");
//Delay for human time to read LCD display
wait(3.0);

char buffer[80]; //BUFFER TO HOLD FORMATTED TIME DATA
gOled.printf("%s, %s %s, %srn",city,stateAbrv,zip,countryAbrv); //PRINT CITY STATE AND ZIP INFORMATION AND COUNTRY
gOled.printf("LAT:%srnLONG:%srn",latitude,longitude); //PRINT LATITUDE AND LONGITUDE
gOled.printf("Timezone:%srn",timeZone); //PRINT TIMEZONE

wizfi250.disconnect(); //DISCONNECT FROM THE NETWORK
while (1) {
//ctTime = time(NULL)-(3600*4); //TIME with offset for eastern time US
ctTime = time(NULL)+(3600*9); //TIME with offset for eastern time KR
//FORMAT TIME FOR DISPLAY AND STORE FORMATTED RESULT IN BUFFER
strftime(buffer,80,"%a %b %drn%T %p %zrn %Zrn",localtime(&ctTime));
gOled.printf("Univ Time Clockrn%srn", buffer);
gOled.display();
gOled.setTextCursor(0,40);
wait(1);
}
}

//SET FOR CSV FORMAT: NEEDS TO BE EDITED IF DIFFERENT FORMAT
void parse(char buffer[], int *j, char *string) {
//extracts next location string data item from buffer
int i=0;
for (i=0; i<=strlen(buffer); i++) { //TOTAL SIZE OF RETURNED DATA
if ((buffer[*j+i] == ',')||(buffer[*j+i] == '' )) { //IF comma or end of string
//comma is the string field delimiter
string[i]=0; //SETS END OF SRTRING TO 0
*j=*j+i+1; //UPDATES to 1 after comma seperated value
break;
} else string[i]=buffer[*j+i]; //Keep adding to the string
}
}

아래는 데모 영상입니다.