Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
OpenExchangeRatesService.cs
1using System;
2using System.Collections.Generic;
3using System.Threading;
4using System.Threading.Tasks;
5using Waher.Events;
10
12{
18 [Singleton]
20 {
21 #region Setup
22
23 private static string apiKey;
24 private static int rateMaxAgeSeconds;
25 private static OpenExchangeRateClient client = null;
26
27 private Dictionary<string, CurrencySymbol> currencyDictionary;
28 private Dictionary<CaseInsensitiveString, decimal> ratesReference;
29 private CurrencySymbol[] currencies;
30 private DateTime ratesTimestamp = DateTime.MinValue;
31 private readonly SemaphoreSlim syncObject = new SemaphoreSlim(1);
32
37 : this(string.Empty)
38 {
39 }
40
46 {
47 apiKey = ApiKey;
48 }
49
53 public string ApiKey => apiKey;
54
59 {
60 get
61 {
62 if (client is null)
63 client = new OpenExchangeRateClient(apiKey);
64
65 return client;
66 }
67 }
68
69 #endregion
70
71 #region IModule interface
72
76 public async Task Start()
77 {
78 await InvalidateCurrent();
79 await this.CheckCurrencies();
80
81 Gateway.OnAfterBackup += this.Gateway_OnAfterBackup;
82 }
83
88 public static async Task InvalidateCurrent()
89 {
90 apiKey = await RuntimeSettings.GetAsync("Paiwise.OpenExchangeRates.ApiKey", apiKey);
91 rateMaxAgeSeconds = (int)await RuntimeSettings.GetAsync("Paiwise.OpenExchangeRates.MaxAgeSeconds", 3600.0);
92 client = null;
93 }
94
95 private async Task Gateway_OnAfterBackup(object sender, EventArgs e)
96 {
97 if (!string.IsNullOrEmpty(apiKey))
98 {
99 try
100 {
101 await this.LoadCurrencies();
102 }
103 catch (Exception ex)
104 {
105 Log.Exception(ex);
106 }
107 }
108 }
109
110 private async Task CheckCurrencies()
111 {
112 if (this.currencies is null && !string.IsNullOrEmpty(apiKey))
113 await this.LoadCurrencies();
114 }
115
116 private async Task LoadCurrencies()
117 {
118 try
119 {
120 CurrencySymbol[] Currencies = await Client.GetCurrencies(); // Just to know what currency symbols are available.
121 Dictionary<string, CurrencySymbol> Sorted = new Dictionary<string, CurrencySymbol>();
122
123 foreach (CurrencySymbol Symbol in Currencies)
124 Sorted[Symbol.Currency] = Symbol;
125
126 this.currencies = Currencies;
127 this.currencyDictionary = Sorted;
128 }
129 catch (Exception ex)
130 {
131 Log.Exception(ex);
132 }
133 }
134
138 public Task Stop()
139 {
140 apiKey = string.Empty;
141 return Task.CompletedTask;
142 }
143
144 #endregion
145
146 #region IConfigurableModule interface
147
152 public Task<IConfigurablePage[]> GetConfigurablePages()
153 {
154 return Task.FromResult(new IConfigurablePage[]
155 {
156 new ConfigurablePage("openexchangerates.org", "/OpenExchangeRates/Settings.md")
157 });
158 }
159
160 #endregion
161
162 #region API interface
163
164 #endregion
165
166 #region ICurrencyConverterService interface
167
174 {
175 if (apiKey is null)
176 return Grade.NotAtAll;
177
178 try
179 {
180 if (!(this.currencyDictionary is null))
181 {
182 return this.currencyDictionary.ContainsKey(Object.From.Value.ToUpper()) &&
183 this.currencyDictionary.ContainsKey(Object.To.Value.ToUpper()) ? Grade.Ok : Grade.NotAtAll;
184 }
185
186 this.CheckCurrencies().Wait();
187
188 if (this.currencyDictionary is null)
189 return Grade.NotAtAll;
190
191 return this.currencyDictionary.ContainsKey(Object.From.Value.ToUpper()) &&
192 this.currencyDictionary.ContainsKey(Object.To.Value.ToUpper()) ? Grade.Ok : Grade.NotAtAll;
193 }
194 catch (Exception)
195 {
196 return Grade.NotAtAll;
197 }
198 }
199
207 public async Task<ICurrencyConverterQuote> GetCurrencyConversionQuote(CaseInsensitiveString FromCurrency, CaseInsensitiveString ToCurrency)
208 {
209 DateTime Now = DateTime.Now;
210
211 await this.syncObject.WaitAsync();
212 try
213 {
214 if (Now.Subtract(this.ratesTimestamp).TotalSeconds >= rateMaxAgeSeconds)
215 {
216 Dictionary<CaseInsensitiveString, decimal> Sorted = new Dictionary<CaseInsensitiveString, decimal>();
217 ExchangeRate[] Rates = await Client.GetLatest();
218
219 foreach (ExchangeRate Rate in Rates)
220 Sorted[Rate.ToCurrency] = Rate.Rate;
221
222 this.ratesReference = Sorted;
223 this.ratesTimestamp = Now;
224 }
225
226 if (this.ratesReference.TryGetValue(FromCurrency, out decimal FromRate) &&
227 this.ratesReference.TryGetValue(ToCurrency, out decimal ToRate))
228 {
229 return new ExchangeRate(FromCurrency, ToCurrency, ToRate / FromRate,
230 this.ratesTimestamp, "openexchangerates.org");
231 }
232 else
233 return null;
234 }
235 finally
236 {
237 this.syncObject.Release();
238 }
239 }
240
241 #endregion
242
243 }
244}
Contains a pair of currencies, for currency conversion.
Definition: CurrencyPair.cs:9
CaseInsensitiveString From
From Currency
Definition: CurrencyPair.cs:24
CaseInsensitiveString To
To Currency
Definition: CurrencyPair.cs:29
CaseInsensitiveString ToCurrency
Conversion to this currency.
Definition: ExchangeRate.cs:36
Task< CurrencySymbol[]> GetCurrencies()
Gets supported currency symbols.
Task< ExchangeRate[]> GetLatest()
Gets latest exchange rates.
Currency Converter service from openexchangerates.org.
async Task< ICurrencyConverterQuote > GetCurrencyConversionQuote(CaseInsensitiveString FromCurrency, CaseInsensitiveString ToCurrency)
Gets a Currency Exchange Rate from one currency to another.
Grade Supports(CurrencyPair Object)
If the interface understands objects such as Object .
OpenExchangeRatesService(string ApiKey)
Currency Converter service from openexchangerates.org.
static OpenExchangeRateClient Client
Reference to the API client
static async Task InvalidateCurrent()
Invalidates current settings.
Task< IConfigurablePage[]> GetConfigurablePages()
Gets an array of configurable pages for the module.
OpenExchangeRatesService()
Currency Converter service from openexchangerates.org.
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1647
Configuration page for a configurable module.
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
Static class managing persistent settings.
static async Task< string > GetAsync(string Key, string DefaultValue)
Gets a string-valued setting.
Interface for currency converter services
Interface for configurable modules.
Configuration page for a configurable module.
Grade
Grade enumeration
Definition: Grade.cs:7