정보나눔

오픈소스하드웨어 프로젝트에 대한 다양한 정보를 나누는 공간입니다.

weathercube에서 날씨받아오는 부분 질문드립니다
dkstnwjd | 2015-11-26

weathercube를 만들어보려고하는데 서버연결까지는 된것같은데 다음과 같이 나오고 진행지 되지 않습니다. 무엇이 문제일까요 ㅠ

프로필사진

Klant 2015-11-27 09:04:21

weather cube는 openweathermap API를 사용합니다. 

현재 API를 사용하기 위해서는 API 키를 넣어줘야 하는데요(예전에는 API키를 요구하지 않았습니다) 

혹시 API키를 넣어주셨나요 ? 

안넣어주셨다면 아래 링크에 API 키를 삽입하는 방법에 대해 나와있으니 참고하시고 넣어주시면 되구요.

http://kocoafab.cc/make/564 

집에서 사용하는 와이파이 공유기로 와이파이를 잡아주셨다면, 핸드폰 핫스팟으로 와이파이를 잡아주신 후 시도해보세요. 

공유기의 보안 설정에 관련되서 안되는 경우도 종종 있거든요. 

현재 시리얼 모니터로만 봤을 때 서버에 연결은 되는 것 같습니다. 

API 키를 검토해주세요!

프로필사진

dkstnwjd 2015-11-30 13:35:28

핫스팟으로도 해보았고 API 키도 받아서

서버접속함수부분을

client.println("GET /data/2.5/weather?q="+location+"&mode=xml"); 에서

client.println("GET /data/2.5/weather?q="+location+"=8eae77cc884c4c9fd092b3f7cafc8623&mode=xml"); 로 바꾸어서 실행시켰습니다.

그런데 저런결과가 나왔습니다.

프로필사진

dkstnwjd 2015-11-30 13:39:30

제가 사용한 weather cube의 전체 코드입니다.

 

#include "SPI.h"
#include "WiFi.h"
#include <Adafruit_NeoPixel.h>
#define PIN 6                     // 네오픽셀 할당 핀(Digital 6)
#define N_LEDS 30                 // 사용 LED 개수

Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB + NEO_KHZ800);
WiFiServer server(80);
WiFiClient client;
IPAddress hostIp;

char ssid[] = "iptime";       // 와이파이 SSID
char pass[] = "wifipassword";         // 와이파이 password 
char ON, OFF;

const unsigned long requestInterval = 60000;  // 요구 시간 딜레이(1 min)
unsigned long lastAttemptTime = 0;            // 마지막으로 서버에서 데이터를 전송받은 시간

String currentLine = "";
String weatherString = "";   
String timeString = "";
String location = "Seoul";

boolean readingWeather = false; 
boolean readingTime = false;
boolean stringComplete = false;

int weather;
int temp = 0;
int PUMP = 2;
int Cloud = 7;

uint8_t ret;

void setup()
{
  // 와이파이 접속
  Serial.begin(115200);
  delay(10);
  Serial.println("Connecting to WiFi....");  
  WiFi.begin(ssid, pass);
  server.begin();
  Serial.println("Connect success!");
  Serial.println("Waiting for DHCP address");  //DHCP주소를 기다린다
  while(WiFi.localIP() == INADDR_NONE) 
  {
    Serial.print(".");
    delay(300);
  }
  Serial.println("\n");
  printWifiData();
  connectToServer();
  
  // 기타 초기 설정
  pinMode(Cloud,OUTPUT);// 가습기 핀 출력 설정
  pinMode(PUMP,OUTPUT); // 펌프 핀 출력 설정
  strip.begin();        // 네오픽셀 초기 값
  strip.show();         // 네오픽셀 출력 함수
  Rain_PUMP(0);         // 펌프 출력 LOW
  Cloud_PUMP(0);        // 가습기(구름) 출력 LOW
}

void loop() 
{
  Data_Phasing();       // 와이파이로 부터 데이터 파싱 함수
  Animation();          // 파싱받은 데이터에 따라 이펙트 출력 함수
}

void Animation()        // 파싱해오는 weather값에 따라 이펙트 출력 함수
{
  /*Lightening Rain*/
  if(weather <= 232 && weather >= 200)
  {
    Rain_PUMP(1);
    Lightening_LED();
    Cloud_PUMP(1);//Cloud Effect
  }
  /*Light Rain*/
  else if(weather <= 321 && weather >= 300)
  {
    Rain_PUMP(1);
    Light_Rainy_LED();
    Cloud_PUMP(0);  
  }
  /*White Snow*/
  else if(weather <= 622 && weather >= 600)
  {
    Rain_PUMP(1);
    Snowy_LED();
  }
  /*Fog*/
  else if(weather <= 721 && weather >= 701 || (weather == 741))
  {
    Rain_PUMP(0);
    Cloud_PUMP(1);//Cloud Effect
    //No LED
  }
  /*Dark Cloudy*/
  else if((weather == 731) || (weather == 751) || (weather == 761) || (weather == 781))
  {
    Rain_PUMP(0);
    Cloudy_LED();
    Cloud_PUMP(1);// Cloud Effect
  }
  /*General Cloud*/
  else if(weather <= 804 && weather >= 800)
  {
    Rain_PUMP(0);
    Fine_LED();
    Cloud_PUMP(1);// Cloud Effect
  }
  // Extreme Weather ---> Storm : Fast Dimming LED and Rain
}


void Data_Phasing()               // 데이터 파싱 함수(WIFI)
{
  if (client.connected()) {
     delay(1000);
     while (client.available()) {
       //전송된 데이터가 있을 경우 데이터를 읽어들인다.
       char inChar = client.read();
       // 읽어온 데이터를 inChar에 저장한다.
       currentLine += inChar; 
       //inChar에 저장된 Char변수는 currentLine이라는 String변수에 쌓이게 된다.
       Serial.print(currentLine);
       
       
       //라인피드(줄바꿈)문자열이 전송되면 데이터를 보내지 않는다.
       if (inChar == '\n') {
         //Serial.print("clientReadLine = ");
         //Serial.println(currentLine);
         currentLine = "";
       } 
       
       //온도 데이터가 전송되었는지 확인
      if ( currentLine.endsWith("<weather number=")) {
         //현재 스트링이 "<temperature value="로 끝났다면 온도데이터를 받을 준비를 한다.
         Serial.println("h");
         readingWeather = true; 
         weatherString = "";
       }      

      //<temperature value=뒤에 오는 문자열을 tempString에 저장한다.
       if (readingWeather) {
         if (inChar != 'v') { //전송될 문자가 'm'이 올때까지 온도값으로 인식
          weatherString += inChar;
         } 
         else { //전송된 문자가 'm'이라면 온도데이터를 그만 저장하고 온도값 출력
          readingWeather = false;
           weather = getInt(weatherString);
           Serial.print("-  weathercode: ");
           Serial.print(weather);
         }
       }

      if ( currentLine.endsWith("</current>")) { //현재 스트링이 </current>로 끝났다면 연결을 끊고 다시 서버와 연결을 준비한다.
         delay(10000); //10초뒤에 서버와 연결을 끊고 재연결을 시도한다.
         client.stop(); 
         connectToServer();
         //Serial.println("Disconnected from Server.\n");
       }
     }   

  }
   else if (millis() - lastAttemptTime > requestInterval) {
     //연결을 실패했다면 requestInterval(60초)이후에 다시 연결을 시도한다.
     connectToServer();
   }
 
}
  
void connectToServer()               // 서버 접속 함수
{
  Serial.println("");
  Serial.println("connecting to server...");
  String content = "";
  if (client.connect(hostIp, 80)) 
  {
    Serial.println("Connected! Making HTTP request to api.openweathermap.org for "+location+"...");
    client.println("GET /data/2.5/weather?q="+location+"=8eae77cc884c4c9fd092b3f7cafc8623&mode=xml"); 
    client.print("HOST: api.openweathermap.org\n");
    client.println("User-Agent: launchpad-wifi");
    client.println("Connection: close");
    client.println();
    Serial.println("Weather information for "+location);
  }
  lastAttemptTime = millis();
}


void printHex(int num, int precision)
{
  char tmp[16];
  char format[128];
  sprintf(format, "%%.%dX", precision);
  sprintf(tmp, format, num);
  Serial.print(tmp);
}

void printWifiData() 
{
  // Wifi쉴드의 IP주소를 출력
  Serial.println();
  Serial.println("IP Address Information:");  
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  byte mac[6];  
  WiFi.macAddress(mac);
  Serial.print("MAC address: ");
  printHex(mac[5], 2);
  Serial.print(":");
  printHex(mac[4], 2);
  Serial.print(":");
  printHex(mac[3], 2);
  Serial.print(":");
  printHex(mac[2], 2);
  Serial.print(":");
  printHex(mac[1], 2);
  Serial.print(":");
  printHex(mac[0], 2);
  Serial.println();
  IPAddress subnet = WiFi.subnetMask();
  Serial.print("NetMask: ");
  Serial.println(subnet);

  IPAddress gateway = WiFi.gatewayIP();
  Serial.print("Gateway: ");
  Serial.println(gateway);

  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  ret = WiFi.hostByName("api.openweathermap.org", hostIp);

  Serial.print("ret: ");
  Serial.println(ret);

  Serial.print("Host IP: ");
  Serial.println(hostIp);
  Serial.println("");
}

int getInt(String input)
{
  int i = 2;
  while(input[i] != '"')
  {
    i++;
  }
  input = input.substring(2,i);
  char carray[20];
  input.toCharArray(carray, sizeof(carray));
  temp = atoi(carray);
  return temp;
}


void Cloud_PUMP(byte state)           // 구름(가습기)구동 함수
{
  if(state == 1){digitalWrite(Cloud,HIGH);}
  else if(state == 0){digitalWrite(Cloud,LOW);}  
}
void Rain_PUMP(byte state)            // 펌프 구동 함수
{
  if(state == 0){digitalWrite(PUMP,HIGH);}
  else if(state == 1){digitalWrite(PUMP,LOW);}
}

void Fine_LED()                       // '맑은 날' LED 출력
{
  int i;
  for(i=0;i<201;i++)
  {
    LED_ON(strip.Color(255,i,0));
  }
  for(i=0;i<47;i++)
  {
    LED_ON(strip.Color(255,200,i));    
  }
  for(i=0;i<56;i++)
  {
    LED_ON(strip.Color(255,200+i,46));
  }
  for(i=0;i<210;i++)
  {
    LED_ON(strip.Color(255,255,46+i));
  }
  for(i=0;i<256;i++)
  {
    LED_ON(strip.Color(255,255-i,255-i));
  }
}

void Cloudy_LED()                     // '구름 낀 날' LED 출력
{
  int i,j;
  for(j=30;j<255;j++)
  {
    LED_ON(strip.Color(j, j, j));
  }
  for(j=255;j>30;j--)
  {
    LED_ON(strip.Color(j, j, j));

  }
  delay(3000);
}

void Snowy_LED()                      // '눈 오는 날' LED 출력
{
  LED_ON(strip.Color(150, 150, 150));
  delay(2000);
  LED_ON(strip.Color(0,0,0));
  delay(10);
  LED_ON(strip.Color(150, 150, 150));
}
void Light_Rainy_LED()                // '약한 비' LED 출력
{
  int i;
  for(i=0;i<201;i++)
  {
    LED_ON(strip.Color(0,234-i,234-i));
  }
  for(i=0;i<201;i++)
  {
     LED_ON(strip.Color(0,34+i,34+i));
  }
}

void Lightening_LED()                  // '뇌우' LED 출력
{
  int i,j,k;
    for(i=0;i<15;i++)
  {
    LED_ON(strip.Color(80, 80, 250));
    delay(10);
    LED_ON(strip.Color(0, 0, 0));
    delay(5);
  }
  for(i=0;i<5;i++)
  {
    LED_ON(strip.Color(80, 80, 250));
    delay(500);
    LED_ON(strip.Color(0, 0, 0));
    delay(100);
  } 
  for(i=0;i<8;i++)
  {
    LED_ON(strip.Color(80, 80, 250));
    delay(1000);
    LED_ON(strip.Color(0, 0, 0));
    delay(50);
  }
}

void LED_ON(uint32_t c)                
 {
   for(uint16_t i=0; i<strip.numPixels(); i++) {
       strip.setPixelColor(i, c);
       strip.show();
   }

 

프로필사진

Klant 2015-12-01 10:31:05

안녕하세요!

현재 올려주신 소스에서 서버 접속이 불안정하여, 아두이노 예제 중 WiFiClinent repeating을 활용해 날씨 데이터 받아오게 수정하였습니다.

우선 APPID도 잘못 넣어주셨구요. 현재 APPID= 빠져있네요. 

날씨 데이터를 가져오는 소스는 아래와 같습니다.

위 소스와 마찬가지로 openweathermap API를 이용해 날씨 데이터를 가져오는 소스이구요.

확인해 보시면 weathercode를 반복적으로 받아오는 것을 확인하실 수 있습니다. 

나머지 기능 동작에 해당하는 변수와 함수들은 위치에 맞게 넣어주시면 되구요.

아래 소스를 base로 활용하시면 됩니다.

 

/*
  Repeating Wifi Web Client

 This sketch connects to a a web server and makes a request
 using an Arduino Wifi shield.

 Circuit:
 * WiFi shield attached to pins SPI pins and pin 7

 created 23 April 2012
 modified 31 May 2012
 by Tom Igoe
 modified 13 Jan 2014
 by Federico Vanzati

 http://www.arduino.cc/en/Tutorial/WifiWebClientRepeating
 This code is in the public domain.
 */

#include <SPI.h>
#include <WiFi.h>
 
char ssid[] = "";      //  your network SSID (name)
char pass[] = "";   // your network password
int keyIndex = 0;            // your network key Index number (needed only for WEP)
int temp=0;

int status = WL_IDLE_STATUS;

// Initialize the Wifi client library
WiFiClient client;

// server address:
char server[] = "api.openweathermap.org";
//IPAddress server(64,131,82,241);

unsigned long lastConnectionTime = 0;            // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 10L * 1000L; // delay between updates, in milliseconds

String location = "seoul";
String currentLine = "";
String weatherString = "";   

boolean readingWeather = false;

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

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if ( fv != "1.1.0" )
    Serial.println("Please upgrade the firmware");

  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  // you're connected now, so print out the status:
  printWifiStatus();
}

void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  while (client.available()) {
    char inChar = client.read();
    //Serial.write(inChar);
    currentLine += inChar; 

      if (inChar == '\n') {
         //Serial.print("clientReadLine = ");
         //Serial.println(currentLine);
         currentLine = "";
       } 
       
       //온도 데이터가 전송되었는지 확인
      if ( currentLine.endsWith("<weather number=")) {
         readingWeather = true; 
         weatherString = "";
       }      
       if (readingWeather) {
         if (inChar != 'v') {
          weatherString += inChar;
         } 
         else { 
          readingWeather = false;
           int weather = getInt(weatherString);
           Serial.print("-  weathercode: ");
           Serial.print(weather);
         }
       }
  }

  // if ten seconds have passed since your last connection,
  // then connect again and send data:
  if (millis() - lastConnectionTime > postingInterval) {
    httpRequest();
  }

}

// this method makes a HTTP connection to the server:
void httpRequest() {
  // close any connection before send a new request.
  // This will free the socket on the WiFi shield
  client.stop();

  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // send the HTTP PUT request:
    client.println("GET /data/2.5/weather?q="+location+"&mode=xml&APPID=ece3f16628536ea9b95ea7adc2a5b595");
    client.println("HOST: api.openweathermap.org\n");
    client.println("User-Agent: ArduinoWiFi/1.1");
    client.println("Connection: close");
    client.println();

    // note the time that the connection was made:
    lastConnectionTime = millis();
  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
  }
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

int getInt(String input)
{
  int i = 2;
  while(input[i] != '"')
  {
    i++;
  }
  input = input.substring(2,i);
  char carray[20];
  input.toCharArray(carray, sizeof(carray));
  temp = atoi(carray);
  return temp;
}

이전글   |    하나의 아두이노에 두 개 이상의 RFID 사용은 어떻게 하나요? ... 2015-11-26
다음글   |    안녕하십니까~ 2015-11-27