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.Cl.Model
9: {
10: ////////////////////////////////////////////////////////////////////////////
11:
12: /// <summary publish="true">
13: /// Weather 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: [DataContract(IsReference = true, Namespace = "kw.com.ia.api.weather", Name = "weather")]
30: public class Weather
31: {
32: private static string weatherTick;
33: private static List<Ia.Cl.Model.Weather.Forecast> forecast;
34:
35: ////////////////////////////////////////////////////////////////////////////
36:
37: /// <summary>
38: ///
39: /// </summary>
40: public Weather()
41: {
42: }
43:
44: ////////////////////////////////////////////////////////////////////////////
45:
46: /// <summary>
47: /// Structure is take from OpenWeatherMap response
48: /// </summary>
49: [DataContract]
50: public class Forecast
51: {
52: /// <summary/>
53: [DataMember]
54: public DateTime TimeFrom { get; set; }
55:
56: /// <summary/>
57: [DataMember]
58: public DateTime TimeTo { get; set; }
59:
60: /// <summary/>
61: [DataMember]
62: public int SymbolNumber { get; set; }
63:
64: /// <summary/>
65: [DataMember]
66: public string SymbolName { get; set; }
67:
68: /// <summary/>
69: [DataMember]
70: public string SymbolVariable { get; set; }
71:
72: /// <summary/>
73: [DataMember]
74: public string Precipitation { get; set; }
75:
76: /// <summary/>
77: [DataMember]
78: public float WindDirectionDegree { get; set; }
79:
80: /// <summary/>
81: [DataMember]
82: public string WindDirectionCode { get; set; }
83:
84: /// <summary/>
85: [DataMember]
86: public string WindDirectionName { get; set; }
87:
88: /// <summary/>
89: [DataMember]
90: public float WindSpeedMps { get; set; }
91:
92: /// <summary/>
93: [DataMember]
94: public string WindSpeedName { get; set; }
95:
96: /// <summary/>
97: [DataMember]
98: public string TemperatureUnit { get; set; }
99:
100: /// <summary/>
101: [DataMember]
102: public float TemperatureValue { get; set; }
103:
104: /// <summary/>
105: [DataMember]
106: public float TemperatureMin { get; set; }
107:
108: /// <summary/>
109: [DataMember]
110: public float TemperatureMax { get; set; }
111:
112: /// <summary/>
113: [DataMember]
114: public string PressureUnit { get; set; }
115:
116: /// <summary/>
117: [DataMember]
118: public float PressureValue { get; set; }
119:
120: /// <summary/>
121: [DataMember]
122: public int HumidityValue { get; set; }
123:
124: /// <summary/>
125: [DataMember]
126: public string HumidityUnit { get; set; }
127:
128: /// <summary/>
129: [DataMember]
130: public string CloudsValue { get; set; }
131:
132: /// <summary/>
133: [DataMember]
134: public int CloudsAll { get; set; }
135:
136: /// <summary/>
137: [DataMember]
138: public string CloudsUnit { get; set; }
139: }
140:
141: ////////////////////////////////////////////////////////////////////////////
142:
143: /// <summary>
144: /// Reads OpenWeatherMap.org API Service for weather information in Kuwait.
145: /// </summary>
146: [HttpGet]
147: [Route("api/weather/kuwait")]
148: public List<Ia.Cl.Model.Weather.Forecast> ReadKuwait()
149: {
150: long ticks;
151: DateTime lastTime, now;
152: List<Ia.Cl.Model.Weather.Forecast> forecastList, savedForcastList;
153:
154: now = DateTime.UtcNow.AddHours(3);
155:
156: if (forecast != null && weatherTick != null)
157: {
158: savedForcastList = forecast;
159: ticks = long.Parse(weatherTick);
160: lastTime = new DateTime(ticks);
161:
162: // check that 60 minutes had passed:
163: if (now.Ticks > lastTime.AddMinutes(60).Ticks)
164: {
165: forecastList = Retrieve(387990); // Kuwait city id: 387990
166:
167: forecast = forecastList;
168: weatherTick = now.Ticks.ToString();
169: }
170: else
171: {
172: // if an hour did not pass, return the saved value;
173: forecastList = savedForcastList;
174: }
175: }
176: else
177: {
178: forecastList = Retrieve(387990); // Kuwait city id: 387990
179: forecast = forecastList;
180: weatherTick = now.Ticks.ToString();
181: }
182:
183: return forecastList;
184: }
185:
186: ////////////////////////////////////////////////////////////////////////////
187:
188: /// <summary>
189: ///
190: /// </summary>
191: private List<Ia.Cl.Model.Weather.Forecast> Retrieve(int cityId)
192: {
193: /*
194: <appSettings>
195: <add key="openWeatherMapApiKey" value="{API Key}" />
196: </appSettings>
197: */
198:
199: string apiKey, line;
200: XDocument xdd;
201: Ia.Cl.Model.Weather.Forecast forecast;
202: List<Ia.Cl.Model.Weather.Forecast> forecastList;
203:
204: apiKey = ConfigurationManager.AppSettings["openWeatherMapApiKey"].ToString();
205:
206: line = Ia.Cl.Model.Http.Request("https://api.openweathermap.org/data/2.5/forecast?id=" + cityId + "&mode=xml&units=metric&APPID=" + apiKey);
207:
208: try
209: {
210: forecastList = null;
211:
212: xdd = XDocument.Parse(line);
213:
214: if (xdd != null)
215: {
216: forecastList = new List<Ia.Cl.Model.Weather.Forecast>();
217:
218: foreach (XElement xe in xdd.Element("weatherdata").Element("forecast").Elements("time"))
219: {
220: forecast = new Ia.Cl.Model.Weather.Forecast();
221:
222: // <time from="2016-06-13T03:00:00" to="2016-06-13T06:00:00">
223: forecast.TimeFrom = DateTime.Parse(xe.Attribute("from").Value);
224: forecast.TimeTo = DateTime.Parse(xe.Attribute("to").Value);
225:
226: // <symbol number="800" name="clear sky" var="01d"/>
227: forecast.SymbolNumber = int.Parse(xe.Element("symbol").Attribute("number").Value);
228: forecast.SymbolName = xe.Element("symbol").Attribute("name").Value;
229: forecast.SymbolVariable = xe.Element("symbol").Attribute("var").Value;
230:
231: // <precipitation/>
232: forecast.Precipitation = (xe.Element("precipitation").Attribute("variable") != null) ? xe.Element("precipitation").Attribute("variable").Value : null;
233:
234: // <windDirection deg="322.501" code="NW" name="Northwest"/>
235: forecast.WindDirectionDegree = float.Parse(xe.Element("windDirection").Attribute("deg").Value);
236: forecast.WindDirectionCode = xe.Element("windDirection").Attribute("code").Value;
237: forecast.WindDirectionName = xe.Element("windDirection").Attribute("name").Value;
238:
239: // <windSpeed mps="6.05" name="Moderate breeze"/>
240: forecast.WindSpeedMps = float.Parse(xe.Element("windSpeed").Attribute("mps").Value);
241: forecast.WindSpeedName = xe.Element("windSpeed").Attribute("name").Value;
242:
243: // <temperature unit="celsius" value="37.14" min="33.12" max="37.14"/>
244: forecast.TemperatureUnit = xe.Element("temperature").Attribute("unit").Value;
245: forecast.TemperatureValue = float.Parse(xe.Element("temperature").Attribute("value").Value);
246: forecast.TemperatureMin = float.Parse(xe.Element("temperature").Attribute("min").Value);
247: forecast.TemperatureMax = float.Parse(xe.Element("temperature").Attribute("max").Value);
248:
249: // <pressure unit="hPa" value="1017.48"/>
250: forecast.PressureUnit = xe.Element("pressure").Attribute("unit").Value;
251: forecast.PressureValue = float.Parse(xe.Element("pressure").Attribute("value").Value);
252:
253: // <humidity value="46" unit="%"/>
254: forecast.HumidityValue = int.Parse(xe.Element("humidity").Attribute("value").Value);
255: forecast.HumidityUnit = xe.Element("humidity").Attribute("unit").Value;
256:
257: // <clouds value="clear sky" all="0" unit="%"/>
258: forecast.CloudsValue = xe.Element("clouds").Attribute("value").Value;
259: forecast.CloudsAll = int.Parse(xe.Element("clouds").Attribute("all").Value);
260: forecast.CloudsUnit = xe.Element("clouds").Attribute("unit").Value;
261:
262: forecastList.Add(forecast);
263: }
264: }
265: }
266: catch (Exception)
267: {
268: forecastList = null;
269: }
270:
271: return forecastList;
272: }
273:
274: ////////////////////////////////////////////////////////////////////////////
275: ////////////////////////////////////////////////////////////////////////////
276: }
277:
278: ////////////////////////////////////////////////////////////////////////////
279: ////////////////////////////////////////////////////////////////////////////
280: }