1: using System;
2: using System.Collections.Generic;
3: using System.Configuration;
4: using System.Runtime.Serialization;
5: using System.Web.Http;
6: using System.Xml.Linq;
7:
8: namespace Ia.Ngn.Cl.Model.Api.Controller
9: {
10: ////////////////////////////////////////////////////////////////////////////
11:
12: /// <summary publish="true">
13: /// OpenWeatherMap API Controller class.
14: /// </summary>
15: ///
16: /// <remarks>
17: /// Copyright © 2001-2020 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
18: ///
19: /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
20: /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
21: ///
22: /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
23: /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
24: ///
25: /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
26: ///
27: /// Copyright notice: This notice may not be removed or altered from any source distribution.
28: /// </remarks>
29: public class WeatherController : ApiController
30: {
31: private static string weatherTick;
32: private static List<Ia.Ngn.Cl.Model.Api.Controller.WeatherController.Forecast> weather;
33:
34: ////////////////////////////////////////////////////////////////////////////
35:
36: /// <summary>
37: /// Structure is take from OpenWeatherMap response
38: /// </summary>
39: [DataContract]
40: public class Forecast
41: {
42: /// <summary/>
43: [DataMember]
44: public DateTime TimeFrom { get; set; }
45:
46: /// <summary/>
47: [DataMember]
48: public DateTime TimeTo { get; set; }
49:
50: /// <summary/>
51: [DataMember]
52: public int SymbolNumber { get; set; }
53:
54: /// <summary/>
55: [DataMember]
56: public string SymbolName { get; set; }
57:
58: /// <summary/>
59: [DataMember]
60: public string SymbolVariable { get; set; }
61:
62: /// <summary/>
63: [DataMember]
64: public string Precipitation { get; set; }
65:
66: /// <summary/>
67: [DataMember]
68: public float WindDirectionDegree { get; set; }
69:
70: /// <summary/>
71: [DataMember]
72: public string WindDirectionCode { get; set; }
73:
74: /// <summary/>
75: [DataMember]
76: public string WindDirectionName { get; set; }
77:
78: /// <summary/>
79: [DataMember]
80: public float WindSpeedMps { get; set; }
81:
82: /// <summary/>
83: [DataMember]
84: public string WindSpeedName { get; set; }
85:
86: /// <summary/>
87: [DataMember]
88: public string TemperatureUnit { get; set; }
89:
90: /// <summary/>
91: [DataMember]
92: public float TemperatureValue { get; set; }
93:
94: /// <summary/>
95: [DataMember]
96: public float TemperatureMin { get; set; }
97:
98: /// <summary/>
99: [DataMember]
100: public float TemperatureMax { get; set; }
101:
102: /// <summary/>
103: [DataMember]
104: public string PressureUnit { get; set; }
105:
106: /// <summary/>
107: [DataMember]
108: public float PressureValue { get; set; }
109:
110: /// <summary/>
111: [DataMember]
112: public int HumidityValue { get; set; }
113:
114: /// <summary/>
115: [DataMember]
116: public string HumidityUnit { get; set; }
117:
118: /// <summary/>
119: [DataMember]
120: public string CloudsValue { get; set; }
121:
122: /// <summary/>
123: [DataMember]
124: public int CloudsAll { get; set; }
125:
126: /// <summary/>
127: [DataMember]
128: public string CloudsUnit { get; set; }
129: }
130:
131: ////////////////////////////////////////////////////////////////////////////
132:
133: /// <summary>
134: ///
135: /// </summary>
136: public WeatherController()
137: {
138: }
139:
140: ////////////////////////////////////////////////////////////////////////////
141:
142: /// <summary>
143: /// Reads OpenWeatherMap.org API Service for weather information in Kuwait.
144: /// </summary>
145: [HttpGet]
146: [Route("api/weather/kuwait")]
147: public List<Ia.Ngn.Cl.Model.Api.Controller.WeatherController.Forecast> ReadKuwait()
148: {
149: long ticks;
150: DateTime lastTime, now;
151: List<Ia.Ngn.Cl.Model.Api.Controller.WeatherController.Forecast> forecastList, savedForcastList;
152:
153: now = DateTime.UtcNow.AddHours(3);
154:
155: if (weather != null && weatherTick != null)
156: {
157: savedForcastList = weather;
158: ticks = long.Parse(weatherTick);
159: lastTime = new DateTime(ticks);
160:
161: // check that 60 minutes had passed:
162: if (now.Ticks > lastTime.AddMinutes(60).Ticks)
163: {
164: forecastList = Retrieve(387990); // Kuwait city id: 387990
165:
166: weather = forecastList;
167: weatherTick = now.Ticks.ToString();
168: }
169: else
170: {
171: // if an hour did not pass, return the saved value;
172: forecastList = savedForcastList;
173: }
174: }
175: else
176: {
177: forecastList = Retrieve(387990); // Kuwait city id: 387990
178: weather = forecastList;
179: weatherTick = now.Ticks.ToString();
180: }
181:
182: return forecastList;
183: }
184:
185: ////////////////////////////////////////////////////////////////////////////
186:
187: /// <summary>
188: ///
189: /// </summary>
190: private List<Ia.Ngn.Cl.Model.Api.Controller.WeatherController.Forecast> Retrieve(int cityId)
191: {
192: /*
193: <appSettings>
194: <add key="openWeatherMapApiKey" value="{API Key}" />
195: </appSettings>
196: */
197:
198: string apiKey, line;
199: XDocument xdd;
200: Ia.Ngn.Cl.Model.Api.Controller.WeatherController.Forecast forecast;
201: List<Ia.Ngn.Cl.Model.Api.Controller.WeatherController.Forecast> forecastList;
202:
203: apiKey = ConfigurationManager.AppSettings["openWeatherMapApiKey"].ToString();
204:
205: line = Ia.Cl.Model.Http.Request("https://api.openweathermap.org/data/2.5/forecast?id="+ cityId + "&mode=xml&units=metric&APPID=" + apiKey);
206:
207: try
208: {
209: forecastList = null;
210:
211: xdd = XDocument.Parse(line);
212:
213: if (xdd != null)
214: {
215: forecastList = new List<Ia.Ngn.Cl.Model.Api.Controller.WeatherController.Forecast>();
216:
217: foreach (XElement xe in xdd.Element("weatherdata").Element("forecast").Elements("time"))
218: {
219: forecast = new Ia.Ngn.Cl.Model.Api.Controller.WeatherController.Forecast();
220:
221: // <time from="2016-06-13T03:00:00" to="2016-06-13T06:00:00">
222: forecast.TimeFrom = DateTime.Parse(xe.Attribute("from").Value);
223: forecast.TimeTo = DateTime.Parse(xe.Attribute("to").Value);
224:
225: // <symbol number="800" name="clear sky" var="01d"/>
226: forecast.SymbolNumber = int.Parse(xe.Element("symbol").Attribute("number").Value);
227: forecast.SymbolName = xe.Element("symbol").Attribute("name").Value;
228: forecast.SymbolVariable = xe.Element("symbol").Attribute("var").Value;
229:
230: // <precipitation/>
231: forecast.Precipitation = (xe.Element("precipitation").Attribute("variable") != null) ? xe.Element("precipitation").Attribute("variable").Value : null;
232:
233: // <windDirection deg="322.501" code="NW" name="Northwest"/>
234: forecast.WindDirectionDegree = float.Parse(xe.Element("windDirection").Attribute("deg").Value);
235: forecast.WindDirectionCode = xe.Element("windDirection").Attribute("code").Value;
236: forecast.WindDirectionName = xe.Element("windDirection").Attribute("name").Value;
237:
238: // <windSpeed mps="6.05" name="Moderate breeze"/>
239: forecast.WindSpeedMps = float.Parse(xe.Element("windSpeed").Attribute("mps").Value);
240: forecast.WindSpeedName = xe.Element("windSpeed").Attribute("name").Value;
241:
242: // <temperature unit="celsius" value="37.14" min="33.12" max="37.14"/>
243: forecast.TemperatureUnit = xe.Element("temperature").Attribute("unit").Value;
244: forecast.TemperatureValue = float.Parse(xe.Element("temperature").Attribute("value").Value);
245: forecast.TemperatureMin = float.Parse(xe.Element("temperature").Attribute("min").Value);
246: forecast.TemperatureMax = float.Parse(xe.Element("temperature").Attribute("max").Value);
247:
248: // <pressure unit="hPa" value="1017.48"/>
249: forecast.PressureUnit = xe.Element("pressure").Attribute("unit").Value;
250: forecast.PressureValue = float.Parse(xe.Element("pressure").Attribute("value").Value);
251:
252: // <humidity value="46" unit="%"/>
253: forecast.HumidityValue = int.Parse(xe.Element("humidity").Attribute("value").Value);
254: forecast.HumidityUnit = xe.Element("humidity").Attribute("unit").Value;
255:
256: // <clouds value="clear sky" all="0" unit="%"/>
257: forecast.CloudsValue = xe.Element("clouds").Attribute("value").Value;
258: forecast.CloudsAll = int.Parse(xe.Element("clouds").Attribute("all").Value);
259: forecast.CloudsUnit = xe.Element("clouds").Attribute("unit").Value;
260:
261: forecastList.Add(forecast);
262: }
263: }
264: }
265: catch (Exception)
266: {
267: forecastList = null;
268: }
269:
270: return forecastList;
271: }
272:
273: ////////////////////////////////////////////////////////////////////////////
274: ////////////////////////////////////////////////////////////////////////////
275: }
276:
277: ////////////////////////////////////////////////////////////////////////////
278: ////////////////////////////////////////////////////////////////////////////
279: }