본문 바로가기

programming/Open API

옥답 OpenApi ( http://openapi.okdab.com/)

 옥답 OpenApi.. OpenApi는 알겠는데..옥답이라는건 처음 들어보시죠? 옥답은 농업정보서비스를 제공해주는 사이트입니다. 이 오픈API를 쓴 이유는 이번 선문비트 고급과정 마지막 프로젝트에서 주제가 "작물정보제공서비스"였기 때문에 옥답에서 OpenApi를 썼습니다. 다른 OpenApi와 별반 다름없이 Xml로 되어있어 끌어다 쓰면 됩니다. 자세한 설명은 지금부터~ 그리고~지금 부터 허접한 소스 공개 고고씽~ (반말인점 감안해주세요 ㅋㅋ 문서화한거라서리~)


 옥답 OpenAPI는 다양한 농업정보서비스(가격/유통, 우리농뉴스 등)를 사용자의 웹 환경에서 활용할 수 있도록 외 부에 공개한 개발자 인터페이스이다.

옥답 OpenAPI를 이용하여 옥답의 기술과 서비스를 활용할 수 있으며, 옥답 OpenAPI는 옥답 의 다양한 서비스를 웹 페이지에서 활용할 수 있도록 지원 할 뿐만 아니라, 더 나아가 여러 가지 서비스를 혼합한 창의적인 애플리케이션을 스스로 제작할 수 있도록 지원한다.

예를 들어, 옥답뉴스 API를 이용하면 전국에서 제공되는 농업/농촌의 생생한 뉴스정보를 제공 받을 수 있을 뿐만 아니라, 오픈백과 및 용어 사전 API와 결합해서 농업정보의 전문지식까지 활 용할 수 있다. 이러한 것을 서비스간 융합(mashup)이라고 하며, 이러한 융합을 통해 새로운 가치 를 창출해 낼 수 있다. 더불어 옥답은 OpenAPI 활용 방법을 상세하게 안내하기 때문에, 작은 노 력으로도 여느 정보보다 나은 농업정보를 활용할 수 있다.


<옥답에서 사용한 가격유통 사용의 예>

                                                                                                          

         

<옥답에서 사용한 내 고장 소식의 예>

먼저, 가격정보 OpenApi를 해보겠다.
 
옥답 사이트에서는 웹을 이용해 사용하였지만, 본 프로젝트에서는 WPF를 이용하여, 실시간 가격유통, 내 고장 소식을 구현하였다.


<FarmerBuddy에서 적용시킨 실행화면>



위 도형의 흐름을 살펴보면, 각각의 항목에 대한 요청URL이 있다. 또한 요청URL(Request URL)은 요청변수를 필요로 한다. 요청변수들은 예를 들어 설명하자면, 대분류를 얻기 위해선, 날짜가 필요하고, 중분류를 얻기 위해선 대분류의 코드번호가 필요하다. 따라서 각각의 항목들을 얻기 위해서는 전 항목의 코드번호가 필요하고, 차례대로의 순서가 중요하다.


l 
각각의 항목들을 담아주는 ArrayList와 변수, 그리고 RealStat의 개체를 생성하고, 전역에 선언해주었다.

ArrayList Bigcode = new ArrayList();      //대코드를 담아주는 ArryaList

ArrayList MiddleCode = new ArrayList();   //중코드를 담아주는 ArryaList

ArrayList SmallCode = new ArrayList();    //소코드를 담아주는 ArryaList

ArrayList MarketCode = new ArrayList();   //시장를 담아주는 ArryaList

ArrayList ClassCode = new ArrayList();    //등급를 담아주는 ArryaList

 

int BigNum;                               //대분류의 콤보박스 인덱스를 담는 변수

int MiddleNum;                            //중분류의 콤보박스 인덱스를 담는 변수

int SmallNum;                             //소분류의 콤보박스 인덱스를 담는 변수

int MarketNum;                            //시장의 콤보박스 인덱스를 담는 변수

int ClassNum;                             //등급의 콤보박스 인덱스를 담는 변수

 

RealStat rs = new RealStat();             //ListView의 항목과 각각의 속성들을 현 상황에 맞게 담아주는 개체 생성

 

l  시작버튼을 눌렀을 시, 그리고 프로그램이 실행될 시, 날짜를 받아 대분류로 코드번호를 넘겨준다.

l  그리고, OpenApi는 대게 XML로 되어있다. 그래서 파싱을 해주어야 되는데, XmlDocument를 이용하여, Load를 시켜주고, 각각의 항목마다 XmlNode를 선언해주고, 읽어들이면 된다. (이 부분은 계속적으로 반복된다)

private void OK()   //대분류의 코드를 얻기 위한 함수

{

    if (!(startday.Text == string.Empty || endday.Text == string.Empty))  //시작일, 기준일에  Empty string이 없을경우

     {

         BigCombo.Items.Clear();   //대분류 콤보박스 Clear

         Bigcode.Clear();          //대분류ArrayList Clear

 

         XmlDocument doc = new XmlDocument();   //XmlDocument 생성

doc.Load(String.Format("http://openapi.affis.net/price/realtime/pricexml_class_action.jsp?key=c83ca4580ed2eb6989a520412d63145a&date={0}" + "&lcode=&mcode=&scode=", startday.Text));    // 요청URL(시작일 삽입) Load시킴  

 

         String code = null;  //code 번호를 담는 String변수

         String name = null;  //name을 담는 String 변수

         int index;           //Reuslt Node Count를 담는 변수

 

         /// 여기서부터 각각의 XmlNode를 읽어들임

         XmlNode currentNode = doc.SelectSingleNode("price");  //최상위 price Node 선언 

         XmlNode result; //result Node 선언

         index = currentNode.SelectNodes("result").Count;      //result Count수를 index에 대입

 

         for (int i = 0; i < index; i++)  //result index만큼 반복

         {

             result = currentNode.SelectNodes("result")[i];  

 //result Node 선언

             code = result.SelectSingleNode("code").InnerText;

// code Node 선언 후 code 변수에 대입

             Bigcode.Add(code);

             // 대분류 ArrayList code 번호를 대입시킴

             name = result.SelectSingleNode("name").InnerText;

 // name Node 선언 후 name String 변수에 대입

             BigCombo.Items.Add(name);                        

             //대분류 ComboBox name을 추가

          }

                BigCombo.SelectedIndex = 0;

             //대분류 comboBox의 기본값을 인덱스 0으로 초기화 시켜줌

     }

     else   //시작일, 기준일에  Empty string이 있을 경우

     {

           MessageBox.Show("날짜를 입력해주세요.");

     }

}

 

l  대분류 ComboBox에서 SelectedChanged 이벤트가 일어날 때.

private void Bigcombo_SelectionChanged(object sender, SelectionChangedEventArgs e)  //대분류에서 중분류에 필요한 요청 변수를 넘겨줌

{

    ComboBox currentComboBox = sender as ComboBox; //ComboBox 생성

 

    if (currentComboBox != null)                   //현재 comboBox의 값이 null이 아닐 경우

    {

        BigNum = currentComboBox.SelectedIndex;    //현재 comboBox의 인덱스를 BigNum에 대입

        if (BigNum == -1)                          //BigNum index -1 인 경우

        {

            MiddleComBo.Items.Clear();              //중분류 comboBox를 클리어

            return;

        }

    }

MiddleComBo.Items.Clear();  //중분류 comboBox 클리어

    MiddleCode.Clear();         //중분류

 

    XmlDocument doc = new XmlDocument(); //XmlDocument 생성

 

doc.Load(String.Format("http://openapi.affis.net/price/realtime/pricexml_class_action.jsp?key=c83ca4580ed2eb6989a520412d63145a&date={0}" +

     "&lcode={1}&mcode=&scode=", startday.Text, Bigcode[BigNum]));  

 // 요청URL(시작일, 대분류code 삽입) Load시킴  

 

    String code = null;   //code 번호를 담는 String변수

    String name = null;   //name을 담는 String 변수

    int index;            //Reuslt Node Count를 담는 변수

 

/// 여기서부터 각각의 XmlNode를 읽어들임

    XmlNode currentNode = doc.SelectSingleNode("price");

    index = currentNode.SelectNodes("result").Count;

     XmlNode result;

 

     for (int i = 0; i < index; i++)

     {

        result = currentNode.SelectNodes("result")[i];

        code = result.SelectSingleNode("code").InnerText;

        MiddleCode.Add(code);                                  

// 중분류 ArrayList code 번호를 대입시킴

 

        name = result.SelectSingleNode("name").InnerText;

        MiddleComBo.Items.Add(name);                           

//중분류 comboBox name 추가

     }

     MiddleComBo.SelectedIndex = 0;

//중분류 comboBox의 기본값을 인덱스 0으로 초기화 시켜줌

}

 

l  중분류 ComboBox에서 SelectedChanged 이벤트가 일어날 때,

l  소분류, 시장,등급 항목들도 방법은 똑같다. (요청변수 주의)

private void MiddleComBo_SelectionChanged(object sender, SelectionChangedEventArgs e)  //중분류에서 소분류에 필요한 요청 변수를 넘겨줌

{

    ComboBox currentComboBox = sender as ComboBox; 

 

    if (currentComboBox != null)

    {

         MiddleNum = currentComboBox.SelectedIndex;

 //중분류 comboBox의 인덱스를 MiddleNum으로 대입

         if (MiddleNum == -1)  //MiddleNum -1인 경우

         {

             SmallCombo.Items.Clear();  //소분류 comboBox 클리어

             return;

         }

     }

 

     SmallCombo.Items.Clear(); //소분류 comboBox 클리어

     SmallCode.Clear();        //소분류 ArrayList 클리어

 

     XmlDocument doc = new XmlDocument();

 

doc.Load(String.Format("http://openapi.affis.net/price/realtime/pricexml_class_action.jsp?key=c83ca4580ed2eb6989a520412d63145a&date={0}" +

     "&lcode={1}&mcode={2}&scode=", startday.Text, Bigcode[BigNum], MiddleCode[MiddleNum]));

// 요청URL(시작일, 대분류code, 중분류 code 삽입) Load시킴 

 

String code = null;

    String name = null;

int index;

 

    XmlNode currentNode = doc.SelectSingleNode("price");

    index = currentNode.SelectNodes("result").Count;

    XmlNode result;

 

    for (int i = 0; i < index; i++)

    {

         result = currentNode.SelectNodes("result")[i];

         code = result.SelectSingleNode("code").InnerText;

         SmallCode.Add(code);                              

 // 소분류 ArrayList code 번호를 대입시킴

 

         name = result.SelectSingleNode("name").InnerText;

         SmallCombo.Items.Add(name);                       

// 소분류 comboBox name 추가

     }

     SmallCombo.SelectedIndex = 0;                         

//소분류 comboBox의 기본값을 인덱스 0으로 초기화 시켜줌
}

 

l  결과 화면을 보여줄 때 이다.

private void ClassCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)  //등급에서 결과에 필요한 요청 변수를 넘겨줌

{

    ComboBox currentComboBox = sender as ComboBox;

    if (currentComboBox != null)

    {

        ClassNum = currentComboBox.SelectedIndex;

//등급 comboBox의 인덱스를 ClassNum으로 대입

        if (ClassNum == -1)   //ClassNum -1인 경우

        {

            rs.Clear();                          //RealStat 개체 클리어

            return;

        }

     }

 

     rs.Clear();//RealStat 개체 클리어

     XmlDocument doc = new XmlDocument();

doc.Load(String.Format("http://openapi.affis.net/price/realtime/pricexml_search.jsp?key=c83ca4580ed2eb6989a520412d63145a&sdate={0}&edate={1}" +

      "&ccode={2}&lcode={3}&mcode={4}&scode={5}&gcode={6}&snum=&enum="

, startday.Text, endday.Text, MarketCode[MarketNum], Bigcode[BigNum], MiddleCode[MiddleNum], SmallCode[SmallNum], ClassCode[ClassNum]));

// 요청URL(시작일,기준일.시장번호, 대분류code, 중분류 code,소분류 code,등급 code 삽입) Load시킴 

 

     XmlNode currentNode = doc.SelectSingleNode("price");

int index = currentNode.SelectNodes("result").Count;  //count 돌리기

//날짜, 도매법인,품목,품종,규격,등급,평균가,최저가,최고가,거래량을 담을 변수선언

    String dates, coname, mclassname, sclassname, unitname, gradename, avgprice, maxprice, minprice, sumamt;

    XmlNode result;

 

    for (int i = 0; i < index; i++)

   {

        /// 각각의 Node들을 해당하는 변수에 대입

        result = currentNode.SelectNodes("result")[i];

        dates = result.SelectSingleNode("dates").InnerText;

        coname = result.SelectSingleNode("coname").InnerText;

        mclassname = result.SelectSingleNode("mclassname").InnerText;

        sclassname = result.SelectSingleNode("sclassname").InnerText;

        unitname = result.SelectSingleNode("unitname").InnerText;

        gradename = result.SelectSingleNode("gradename").InnerText;

        avgprice = result.SelectSingleNode("avgprice").InnerText;

        maxprice = result.SelectSingleNode("maxprice").InnerText;

        minprice = result.SelectSingleNode("minprice").InnerText;

        sumamt = result.SelectSingleNode("sumamt").InnerText;

 

        //RealStat 개체에 추가

        rs.Add(new RealTime(dates, coname, mclassname, sclassname, unitname, gradename, avgprice + "", maxprice + "", minprice + "", sumamt));

        price_list.ItemsSource = rs; //ListView에 항목들 바인딩

       }
}

 

l  ListView Xaml 부분

<ListView Margin="37,176,0,0" Name="price_list" BorderThickness="1" Grid.IsSharedSizeScope="True"ItemsSource="{Binding Source={StaticResource totalview}}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalAlignment="Left" Width="875" Height="265" VerticalAlignment="Top" FontFamily="맑은고딕">

<ListView.View>

    <GridView AllowsColumnReorder="True"ColumnHeaderToolTip="Total">

       <GridViewColumn DisplayMemberBinding="{Binding Path=Date}" Header="날짜" Width="70"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Domae}" Header="도매법인" Width="80"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Pummok}" Header="품목" Width="100"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Pumjong}" Header="품종" Width="100"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Size}" Header="규격" Width="100"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Rate}" Header="등급" Width="100"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Avg}" Header="평균가" Width="80"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Minmoney}" Header="최저가" Width="80"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Maxmoney}" Header="최고가" Width="80"/>

       <GridViewColumn DisplayMemberBinding="{Binding Path=Gurae}" Header="거래량" Width="80"/>

     </GridView>

   </ListView.View>
</ListView>

 

l  ListView에 채워주는 RealTime 클래스 소스 부분

public class RealTime : INotifyPropertyChanged

{

   public string date;      //날짜

   public string domae;     //도매법인

   public string pummok;    //품목

   public string pumjong;   //품종

   public string size;      //규격

   public string rate;      //등급

   public string avg;       //평균가

   public string minmoney;  //최소가

   public string maxmoney;  //최대가

   public string gurae;     //거래량

 

   /// <summary>

   /// 위에 있는 변수들을 각각 get,set 속성으로...

   /// </summary>

public RealTime() { }

  public RealTime(string _date, string _domae, string _pummok, string _pumjong, string _size, string _rate, string _avg, string _minmoney, string _maxmoney, string _gurae)  //생성자

  {

     date = _date;

     domae = _domae;

     pummok = _pummok;

     pumjong = _pumjong;

     size = _size;

     rate = _rate;

     avg = _avg;

     minmoney = _minmoney;

     maxmoney = _maxmoney;

     gurae = _gurae;

  }

 

  public string Date

  {

      set

      {

         date = value;

         OnPropertyChanged("Date");

      }

      get

      {

         return date;

      }

}

//이런 식으로, 각각의 항목들을 OnPropertyChanged 인터페이스를 사용하고, 속성을 정해준다.

//(생략) 

  private void OnPropertyChanged(string p) //데이터를 바인딩 하기 위한 인터페이스

{

     PropertyChangedEventHandler handler = PropertyChanged;

      if (handler != null)

      {

           handler(this, new PropertyChangedEventArgs(p));

      }

   }

 

  #region INotifyPropertyChanged 멤버

public event PropertyChangedEventHandler PropertyChanged;

#endregion

}

public class RealStat : ObservableCollection<RealTime>

  {

     public RealStat() { }

     public void AddRealStat(RealTime r)

     {

          Add(r);  //추가 함수

     }
 }

 

l  달력 컨트롤에 대한 소스 부분

public partial class Calendar : Window

{

    public string myday = string.Empty;  // ,,일 을 담을 string 변수 선언

public Calendar()

    {

        InitializeComponent();

    }

 

    private void Window_Loaded(object sender, RoutedEventArgs e)

    {

        WinCalendarDll.Calendar c = new WinCalendarDll.Calendar(); 

//WinForm에서 가져온 달력컨트롤을 생성

        windowsFormsHost1.Child = c; 

c.Mytoday += new WinCalendarDll.Calendar.GetToday(c_Mytoday); 

//,,일을 가져오는 이벤트를 발생

    }

void c_Mytoday(string day)

    {

        string year = DateTime.Today.Year.ToString();  //현재 년도

string month = DateTime.Today.Month.ToString();  //현재 월

        if (month.Length == 1)

        {

           month = "0" + month;

        }

int Nowday = DateTime.Today.Day;  //현재 일

string days = string.Empty;

if (Nowday < 10) //10일 미만일 경우

    {

         days = "0" + Nowday; //앞에 0을 붙여줌

         string today = year + month + days;

 

         if (int.Parse(today) >= int.Parse(day))  //현재 날짜보다 작을 경우

         {

              myday = day;

              Close();

         }

         else  //현재 날짜보다 클 경우

         {

              MessageBox.Show("이전 데이터만 볼 수 있습니다");

              return;

         }

    }

    else

    {

        string today = year + month + Nowday;

if (int.Parse(today) >= int.Parse(day))  //현재 날짜보다 작을 경우

        {

             myday = day;

             Close();

         }

         else  //현재 날짜보다 클 경우

          {

                MessageBox.Show("이전 데이터만 볼 수 있습니다");

                return;

          }

      }

    }
}

 

l  달력보기 버튼을 눌렀을 시

private void button1_Click(object sender, RoutedEventArgs e)  //달력보기

{

     Calendar cal = new Calendar();  //달력 개체를 생성

     cal.ShowDialog();               //달력을 보여줌

     endday.Text = cal.myday;        //달력에서 클릭한 년,,일을 대입함
}


l  첫 화면에 기준일을 현재일자로 초기값을 넣어주는 함수이다.

Ex) 20100819 이런식으로 들어가야 하기 때문에 0을 붙여준다.

private void standardTime()  //기준일

{

    string year = DateTime.Today.Year.ToString();   //현재 년도 가져옴

    string month = DateTime.Today.Month.ToString(); //현재 월 가져옴

 

    if (month.Length == 1)  //현재 월이 1~9월일때

    {

         month = "0" + month;  //앞에 0을 붙여줌 [ex) 08]

    }

    int day = DateTime.Today.Day;  //현재 일 가져옴

 

    string days = string.Empty;

 

    if (day < 10)   //현재 일이 1~9일 경우

    {

         days = "0" + day;                    //앞에 0을 붙여줌 [ex)08]

         string today = year + month + days;  // 최종으로 현재 년,,일을 대입함
                                              // (ex) 20100808

         endday.Text = today;                 //기준일 TextBox에 대입

    }

    else  //현재일이 10일 이상일 경우

    {

         string today = year + month + day;  // 최종으로 현재 년,,일을 대입함
                                             // (ex) 20100808

         endday.Text = today;                //기준일 TextBox에 대입

     }
}



l  시작일을 초기값을 넣어주는 함수

private void StartTime()  //시작일

{

     int year = DateTime.Now.Year;    // 현재 년도 가져옴

     int month = DateTime.Now.Month;  // 현재 월 가져옴

     int day = DateTime.Now.Day;      // 현재 일 가져옴

     int result = 0;

     string days = string.Empty;

 

     if (day == 1) // 1일일 때

      {

         if (month == 1)  //1월 일때

         {

              month = 12; // 12월로 초기화

              year -= 1; // 1년을 뺀다.

         }

         else //1월이 아닐 경우

         {

              month -= 1;

         }

 

         //Day 계산

         result = DateTime.DaysInMonth(year, month);

         result -= 2;

 

         day = result;

         }

 

         else if (day == 2) //2일일 경우

         {

             if (month == 1)  //1월일 경우

             {

                 month = 12; // 12월로 초기화

                 year -= 1; // 1년을 뺀다.

             }

             else //1월이 아닐 때

             {

                  month -= 1;

             }

 

             result = DateTime.DaysInMonth(year, month);

             result -= 1;

 

             day = result;

          }

          else if (day > 2)

          {

              day -= 3; //현지일로부터 3일을 빼줘, 시작일을 현재일로부터 -3일을 해준다.

          }

 

          string MonthResult = string.Empty;

          if (month < 10)

          {

              MonthResult = "0" + month;

          }

 

          if (day < 10)  //9일 이하 일때

          {

              days = "0" + day;  //앞에 0을 붙여줌

              string today = year + MonthResult + days;

              startday.Text = today;

          }

          else  //10일 이상일 경우

          {

              string today = year + MonthResult + day;

              startday.Text = today;

          }

}

 

'programming > Open API' 카테고리의 다른 글

[WPF] 구글 날씨 OpenApi  (3) 2011.07.28
옥답OpenApi 두 번째 (지역 뉴스 정보)  (0) 2010.08.19