Firewall for Internet of Things

Intro

** What is a firewall for IoT ?**
– We will compare the traditional method and the proposed method under DoS Attack (SYN-flood attack).

IoT Platform: mbed NXP LPC1768

mbed LPC1768

It is based on the NXP LPC1768, with a 32-bit ARM Cortex-M3 core running at 96MHz. It includes 512KB FLASH, 32KB RAM and lots of interfaces including built-in Ethernet, USB Host and Device, CAN, SPI, I2C, ADC, DAC, PWM and other I/O interfaces. The pinout above shows the commonly used interfaces and their locations. Note that all the numbered pins (p5-p30) can also be used as DigitalIn and DigitalOut interfaces.
– Link1: For more detail

Traditional method: LwIP (TCP/IP software stack) + Ethernet MAC (LPC1768) + Ethernet PHY (DP83848J)@mbed application board (Ethernet connector)

mbed application board
* Feature list
* 128×32 Graphics LCD
* 5 way joystick
* 2 x Potentiometers
* 3.5mm Audio jack (Analog Out)
* Speaker, PWM connected
* 3 Axis /1 1.5g Accelerometer
* 3.5mm Audio jack (Analog In)
* 2x Servo motor headers
* RGB LED, PWM connected
* USB-mini-B Connector
* Temperature sensor
* Socket for for Xbee (Zigbee) or RN-XV (Wifi)
* RJ45 Ethernet Connector
* USB-A Connector
* 1.3mm DC Jack input

Proposed method: WIZ550io (TOE + Ethernet MAC + Ethernet PHY)

WIZ550io
– Link3: WIZ550io components in mbed.org
– Link4: W5500 components in mbed.org

Application for iperf

Recv only code for Software stack

  • fixed an echo server on mbed.
#include "mbed.h"
#include "EthernetInterface.h"

EthernetInterface eth;
int main() 
{
    printf("Trying rn");
    // as your env. change to real IP address and so on.
    int ret = eth.init("192.168.77.34", "255.255.255.0", "192.168.77.1");    

    if (!ret) {
        printf("Initialized, MAC: %snr", eth.getMACAddress());
        printf("Connected, IP: %s, MASK: %s, GW: %snr",
               eth.getIPAddress(), eth.getNetworkMask(), eth.getGateway());
    } else {
        printf("Error eth.init() - ret = %dnr", ret);
        return -1;
    }

  eth.connect();
  printf("IP Address is %sn", eth.getIPAddress());

    TCPSocketServer server;
    server.bind(5000);
    server.listen();

    while (true) {
        printf("nWait for new connection...n");
        TCPSocketConnection client;
        server.accept(client);
        client.set_blocking(false, 1500); // Timeout after (1.5)s

        printf("Connection from: %sn", client.get_address());

        char buffer[2048];
        while (true) {
            int n = client.receive(buffer, sizeof(buffer));

            if (n < 0) break; // !_is_connected

        }
        client.close();
    }
}

Recv only code for TOE

#include <stdio.h>
#include <string.h>
#include "mbed.h"
#include "EthernetInterface.h"


//DigitalOut myled(LED1);
//Serial pc(USBTX , USBRX);
int main() {

    printf("Test - WIZ550iorn");

    /** Set the spi bus clock frequency
     *
     *  @param hz SCLK frequency in hz (default = 1MHz)
     *  Maximum SPI data bit rate of 12.5 Mbit/s in LPC176X
    */
    spi.frequency(12500000);     
    SPI spi(p5, p6, p7); // mosi, miso, sclk
    EthernetInterface eth(&spi, p8, p11); // spi, cs, reset

    // as your env. change to real IP address and so on.
    int ret = eth.init("192.168.77.34", "255.255.255.0", "192.168.77.1");    
    if (!ret) {
        printf("Initialized, MAC: %snr", eth.getMACAddress());
        printf("Connected, IP: %s, MASK: %s, GW: %snr",
               eth.getIPAddress(), eth.getNetworkMask(), eth.getGateway());
    } else {
        printf("Error eth.init() - ret = %dnr", ret);
        return -1;
    }

    printf("IP Address is %sn", eth.getIPAddress());

    TCPSocketServer server;
    server.bind(5000);
    server.listen();

    while (true) {
        printf("nWait for new connection...n");
        TCPSocketConnection client;
        server.accept(client);
        client.set_blocking(false, 1500); // Timeout after (1.5)s

        printf("Connection from: %sn", client.get_address());

        char buffer[2048];
        while (true) {
            int n = client.receive(buffer, sizeof(buffer));

            if (n < 0) break; // !_is_connected
        }
        client.close();
    }
}

Comparison of memory Size

Software stack TOE (W5500)
Codes  sw stack codes TOE codes
Memory usage sw memory usage sw memory usage

35.2kB(110%) : The LPC1768 has 3 RAM banks: One general purpose one of 32kB, and two additional ones of 16kB each for Ethernet/USB/CAN purposes. Ethernet completely fills one of those additional banks. The online compiler does take this into account for the total RAM usage, but assumes only 32kB is available, so it gets over the 100% what it displays, still will work fine though. (from mbed.org: http://developer.mbed.org/questions/3579/mbed-LPC-1768-RAM-Usage-128-what-does-th/)

** TOE can reduce the flash and RAM usage of by 7% and 119% respectively. **

DoS Attack (Syn-flood attack)

We used the scapy based on python library for DoS Attack.

from scapy.all import

inter = input('inter(time in seconds to wait between 2packets) :')

def synFlood(src, tgt, inter):
    IPlayer = IP(src, dst=tgt)
    TCPlayer= TCP(sport=3000, dport=3000) # as your env. change source and destination port
    pkt = IPlayer / TCPlayer
    send(pkt, loop=1, inter=inter) #

#send(pkts, inter=0, loop=0, verbose=None)
#  Send packets at layer 3, using the conf.L3socket supersocket. pkts can
#  be a packet, an implicit packet or a list of them.
#
#  loop: send the packets endlessly if not 0.
#  inter: time in seconds to wait between 2 packets
#  verbose: override the level of verbosity. Make the function totally silent when 0.
#   * Refer to http://www.secdev.org/projects/scapy/files/scapydoc.pdf for more detail.


# as your env. change to real IP address and so on.
src = "192.168.77.253" # PC IP address
tgt = "192.168.77.34"  # target board (LPC1768)

synFlood(src, tgt, inter)

How to use iperf

Iperf is a tool to measure maximum TCP bandwidth, allowing the tuning of various parameters and UDP characteristics. Iperf reports bandwidth, delay jitter, datagram loss

# ex.) host IP(192.168.77.34):port[5000], display format is Mbit/sec, interval 1 sec.
>iperf.exe -c 192.168.77.34 -p 5000 -f m -i 1
  • -c : –client host, -c will connect to the host specified.
  • -p : –port #, the server port for the server to listen.
  • -f : –format [], ‘m’ = Mbit/sec
  • -i : –interval #, Sets the interval time in seconds between periodic bandwidth
    Through performance

Network Configuration

  • **Fig. Network configurations to measure performance **
    SW Bandwidth

Network performance

  • Fig. Traditional method: lwIP performance according to traffic of SYN packet
    SW Bandwidth

  • Fig. Proposed method: TOE(W5500) performance according to traffic of SYN packet.
    TOE(W5500) Bandwidth

**The network performance of traditional method is better the proposed method when DoS attack is weak. Because, the traditional method used the bus-interface for MAC. (The proposed method doesn’t used spi-dma.)
However, The proposed method kept up the network performance under SYN-flood attack.
Otherwise, the network performance of the traditional method is became extremely worse according to the interval of SYN-attack.
**

Note9 – WebServer controlled LED Sketch

ArduinoNote List-page
PREVIOUS: Note8 – WebServer controlled LED Demo

Web Server controlled LED Sketch

/*
  Web Server 

 A simple web server that shows the value of the analog input pins.
 using an Arduino Wiznet Ethernet shield. 

 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Analog inputs attached to pins A0 through A5 (optional)

 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 modified 15 Nov 2014
 by Soohwan Kim 
*/

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io
;
#else
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
#endif

//#define __USE_DHCP__

IPAddress ip(192,168,1,20);
IPAddress gateway( 192, 168, 1, 1 );
IPAddress subnet( 255, 255, 255, 0 );
// fill in your Domain Name Server address here:
IPAddress myDns(8, 8, 8, 8); // google puble dns

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);
void check_led_status();
// Define the LED PORT NUMBER
#define LED_PORT 53

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // initialize the LED PORT 
  pinMode(LED_PORT, OUTPUT);
  // initaial value is HIGH
  digitalWrite(LED_PORT, HIGH);

  // initialize the ethernet device
#if defined __USE_DHCP__
#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io
  Ethernet.begin();
#else
  Ethernet.begin(mac);
#endif  
#else
#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io
  Ethernet.begin(ip, myDns, gateway, subnet);
#else
  Ethernet.begin(mac, ip, myDns, gateway, subnet);
#endif  
#endif 

  // start the Ethernet connection and the server:
  server.begin();
  Serial.println("WebServerControlLED");
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    String buffer = ""; // Declare the buffer variable 
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        buffer += c;    // Assign to the buffer
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == 'n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          //client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<body>");

          // check the LED status
          if (digitalRead(LED_PORT)>0){
             client.println("LED is <font color='green'>ON</font>");
          }else{
             client.println("LED is <font color='red'>OFF</font>");
          }

          // generate the Form 
          client.println("<br />");
          client.println("<FORM method="get" action="/led.cgi">");
          client.println("<P> <INPUT type="radio" name="status" value="1">ON");
          client.println("<P> <INPUT type="radio" name="status" value="0">OFF");
          client.println("<P> <INPUT type="submit" value="Submit"> </FORM>");

          client.println("</body>");
          client.println("</html>");
          break;
        }
        if (c == 'n') {
          // you're starting a new line
          currentLineIsBlank = true;
          buffer="";
        } 
        else if ( c == 'r') {
            //do cgi parser for LED-On
            if(buffer.indexOf("GET /led.cgi?status=1")>=0){
                // cgi action : LED-On
                digitalWrite(LED_PORT, HIGH);
                // send web-page
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/html");
                client.println();
                client.println("<html>");
                client.println("<body>");
                // check the LED status
                if (digitalRead(LED_PORT)>0){
                  client.println("LED is <font color='green'>ON</font>");
                }else{
                  client.println("LED is <font color='red'>OFF</font>");
                }
                client.println("<br />");
                client.println("<a href="/led.htm">Go to control-page</a>");

                client.println("</body>");
                client.println("</html>");
                currentLineIsBlank = false;
                break;
            }

            //do cgi parser for LED-Off
            if(buffer.indexOf("GET /led.cgi?status=0")>=0){
                // action : LED-Off
                digitalWrite(LED_PORT ,LOW);
                // send web-page
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/html");
                client.println();
                client.println("<html>");
                client.println("<body>");
                // check the LED status
                if (digitalRead(LED_PORT)>0){
                  client.println("LED is <font color='green'>ON</font>");
                }else{
                  client.println("LED is <font color='red'>OFF</font>");
                }
                client.println("<br />");
                client.println("<a href="/led.htm">Go to control-page</a>");

                client.println("</body>");
                client.println("</html>");
                currentLineIsBlank = false;
                break;
            }
        }
        else{ //if( c != 'r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

Note7 – WebServer controlled LED

ArduinoNote List-page
PREVIOUS: Note6 – WebServer

Hand-on #4: WebServer controlled LED

-Ethernet Shield를 이용한 Remote Control(LED On/Off)과 Monitoring(LED Status)을 함께 해보자

Common Gateway Interface

WWW 서버와 서버 상에서 등장하는 다른 프로그램이나 스크립트와의 인터페이스. 폼을 사용한 메일의 송신이나 게임 등, HTML에서는 불가능한 인터랙티브(interactive)한 요소를 홈페이지에 받아들여 쓸 수 있다.
[네이버 지식백과] CGI [common gateway interface] (컴퓨터인터넷IT용어대사전, 2011.1.20, 일진사)

  • Get Request / Receive Req. / CGI parser
    Get Request:cgi

  • Run the CGI App: run CGI scripts
    Run the CGI App.

  • Response: call web_server_send from CGI app. and back to Response
    Web Response

Hardware

Arduino / WIZ550io / LED
* LED를 적절한 포트에 연결한다. 이때, LED에 과전류를 방지하기 위해 저항을 달아준다.

Install Ethenret Library

Network Configuration

Network Configuration

  • Network Configuration on PC side
    Network Configuration
    위와 같이 “Internet Protocol Properies”에서 Network구성을 Test를 위해 아래와 같이 설정해보자
    IP address : 192.168.1.2
    Subnet mask : 255.255.255.0

Default gateway : 192.168.1.1

WebServerControlLED Skeleton

  • Fixed IP address
//#define __USE_DHCP__

IPAddress ip(192,168,1,20);
IPAddress gateway( 192, 168, 1, 1 );
IPAddress subnet( 255, 255, 255, 0 );
// fill in your Domain Name Server address here:
IPAddress myDns(8, 8, 8, 8); // google puble dns
}
  • Port Setting
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
  • setup()
// Define the LED PORT NUMBER
// ...insert codes...  #define LED_PORT XX

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // initialize the LED PORT 
  // ...insert codes ...
  // initaial value is HIGH
  // ...insert codes ...


  // initialize the ethernet device
#if defined __USE_DHCP__
#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io
  Ethernet.begin();
#else
  Ethernet.begin(mac);
#endif  
#else
#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io
  Ethernet.begin(ip, myDns, gateway, subnet);
#else
  Ethernet.begin(mac, ip, myDns, gateway, subnet);
#endif  
#endif 

  // start the Ethernet connection and the server:
  server.begin();
  // ...insert codes ...  Welcome messages
  Serial.print("server is at ");
  // ...insert codes ...  print localIP
}

  • loop()
void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    String buffer = ""; // Declare the buffer variable 
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        buffer += c;    // Assign to the buffer
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == 'n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          //client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<body>");

          // check the LED status
          // ...insert codes ...

          // generate the Form 
          // ...insert codes ...

          client.println("</body>")
          client.println("</html>");
          break;
        }
        if (c == 'n') {
          // you're starting a new line
          currentLineIsBlank = true;
          buffer="";
        } 
        else if ( c == 'r') {
            //do cgi parser for LED-On
            //if(...insert codes ...
                //  action : LED-On
                //digitalWrite(...insert codes ...
                // send web-page
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/html");
                client.println();
                client.println("<html>");
                client.println("<body>");
                // check the LED status
                // ...insert codes ...
                client.println("<br />");
                client.println("<a href="/led.htm">Go to control-page</a>");

                client.println("</body>");
                client.println("</html>");
                currentLineIsBlank = false;
                break;
            }

            //do cgi parser for LED-Off
            //if(...insert codes ...
                //  action : LED-Off
                //digitalWrite(...insert codes ...
                // send web-page
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/html");
                client.println();
                client.println("<html>");
                client.println("<body>");
                // check the LED status
                // ...insert codes ...
                client.println("<br />");
                client.println("<a href="/led.htm">Go to control-page</a>");

                client.println("</body>");
                client.println("</html>");
                currentLineIsBlank = false;
                break;
            }
        }
        else{ //if( c != 'r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

NEXT : Note8 – WebServer controlled LED Demo

Note5 – ioShield-A

ArduinoNote List-page
PREVIOUS: Note4 – Ethernet shield

ioShield-A

ioSheild-A

ioShield-A는 Arduino Platform을 Internet에 연결하게 해주는 Ethernet Shield의 하나이다. Ethernet Shield는 TCP/IPCore Chip으로 W5100의 기반으로 하였으나, ioShield는 W5500을 적용하였다. W5500은 동시에 W5100보다 많은 소켓 수(8Socket)지원 할 수 있으며, Fast SPI (upto 80MHz)를 지원한다. 특별히, 이 Ethenret Shield는 WIZ550io와 Installing Board로 구성되어 있으며, WIZ550io에서 embedded된 MAC Address를 지원하기 때문에 별도의 MAC Address구매없이 Real MAC Address를 사용할 수 있다.

ioShield-A
* WIZ550io: wizwiki
* Schematic: ioshield-a_v1.1_sch.pdf
* Ethernet Library: WIZ_Ethernet_Library
* SPI port: ICSP Header사용
* Github: frizing project for WIZ550io

WIZ Ethernet Library Install

  • Download Library: WIZ_Ethernet_Library-master.zip

  • 압축해제 한뒤 Ethernet폴더를 Copy한다.
    Ethernet폴더

  • 기존의 Sketch IDE를 설치하고 생긴 C:/Program Files/Arduino/Ethernet폴더와 Replace한다.
    Ethernet폴더 replace

  • Ethernet Library에 /Arduino/Ethernet/examples 아래와 같이 다양한 example들이 포함되어 있다.
    Ethernet Library

NEXT : Note6 – WebServer

Create my part on fritzing

fritzing

1000 new parts!

what is fritzing ? [http://en.wikipedia.org/wiki/Fritzing]

Create my part @frizing

Reference : [http://fritzing.org/learning/tutorials/creating-custom-parts/]

  • preparation materials
  • 2D Tool : be able to support a file type of ‘*.svg’ as like Inkscape [https://inkscape.org/en/]
  • Download and Install : fritzing version upto 0.7.x (verion 0.7.2 is used.)
  • Download font and tmeplates : [http://fritzing.org/media/uploads/learning/graphic_standards/fontsandtemplates.zip]
  • Hardware demension : as like
    WIZ550io Demension
  • Hardware Pin : as like
    WIZ550io Pins

  • Do it

  • Draw grahpics and save file type of ‘*.svg’
  • for Breadboard View : Refer to BreadboardViewGraphic_Template on “FontsAndTempllates/Templates”
    WIZ550io Breadboard View
  • for Schemetic View : Refer to PCBViewGraphic_Template on “FontsAndTempllates/Templates”
    WIZ550io Schemetic View
  • for PCB View : Refer to SchemeticViewGraphic_Template on “FontsAndTempllates/Templates”
    WIZ550io Breadboard View
  • Use fonts in “FontsAndTempllates/Fonts”; DroidSans, OCR A

  • Creat a New Part

  • open the Fritzing application and Part > Create a New part
  • load images in each tab; Breadbaord(left), Schemetic(middle) and PCB(right)
    Create a New part
  • input metadata information in metadata tab; Title, data, Author, Descriptoin, Label…
  • add connectors and set connector of type, name and desciption in connectors tab
    set connectors tab

  • Save

  • Load New part

  • open Frizting application
  • Click part>load in menu bar
  • load pre-make “*.fzpz”
  • enjoy your project
    Arduino WIZ550io on Fritzing

WIZ550io.fzpz Link
I ~~will upload~~ have uploaded WIZ550io.fzpz on gitHub and attch link.

ARDUINO with TEMBOO

-www.temboo.com

템부(Temboo)는 기업들은 API 관리 전문업체 중 하나이다. 보안 API 접속 서비스는 물론이고 일부는 API 호환 서비스를, 또 일부는 클라우드 기반의 API 접근경로를 제공한다.

 

-Program hardware for the Internet of Things

위의 그림처럼 IoT의 hardware 들을 위한 API (Agent+SDK), Cloud service까지 그 영역을 넓혀가는 중이며 Open Hardware의 선두주가 Arduino와 LaunchPad를 중심으로한 Texas Instruments사의 Platform을 현재 지원중이다.

글보단 한편의 동영상으로 Temboo를 이해해 보자

IoT Hardware을 위한 API를 살펴보면서 그 막강한 기능을 체험해보자.

Yahoo Weather를 Temboo와 Arduino를 이용한다.

*Preparation materials

-Arduino board : Arduino Due
-Ethernet Shield : WIZ550io (W5500 with MAC address)
-IDE : IDE 1.5.7
-Lib. : Ethernet Lib. and Temboo Lib

1. 먼저 Temboo에 로그인 한뒤 아래의 페이지에서 “Arudino” 클릭 

-Select Arduino on Program hardware for the Internet of Things

2. ARDUINO+TEMBOO에서 자신이 사용하려는 Hardware선택 

- Select Device: Arduino Yun or Other Arduino Boards + Internet Shield

3. 이제 Temboo Arduino Library의 설치를 위해 아래의 그림에서 우측상단의 “Download”클릭 

- ARDUINO+TEMBOO

4. Installing에 관한 대용은 아래의 사이트를 참고하며 간단하게 download된 Temboo Arduino Library를 “C:\Program Files\Arduino\libraries” 에 압축을 푼다. IDE1.5.7기준! 

- Installing the Temboo Arduino Library

5. 이제 예제를 선택한다 여기서는 GetWeatherByAddress! 

- Select GetWeatherByAddress with Temboo Arduino Library

6. 이제 몇가지 설정으로 GetWeatherByAddress.ino를 생성 시키자
-우측상단의 “IoT Mode”를 “ON”으로 활성화
-GetWeatherByAddress란에서 “The address to be searched”밑의 박스에 “Seoul”를 입력 뒤 코드의 생성을 위해 Run을 클릭
-CODE란에 생성된 코드 확인 및 복사 

- Configuration and Generation of CODE

7. IDE에서 Compile 및 다운로드
-“C:\Program Files\Arduino\libraries\Temboo\”폴더 밑에 아래와 같이 examples\YahooWeather폴더를 생성한다.
-“C:\Program Files\Arduino\libraries\Temboo\examples\YahooWeather”에 복사한 코드를 폴더명과 같은 이름으로 복사한다.
– 컴파일 후 다운로드

8. Demo: Serial Monitoring
아래와 같이 Seoul의 날씨를 HTTP Get을 통해 해당 웹페이지를 다운받아 Serial로 출력시키는 것을 볼 수 있다.

-Get Seoul Weather http message on Serial Monitoring