123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- using Edge.Core.Database;
- using Microsoft.Extensions.Configuration;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using System.Linq;
- using System.Reflection;
- using RestSharp;
- using Newtonsoft.Json;
- using System.Threading.Tasks;
- using System.Xml;
- using System.Threading;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Logging.Abstractions;
- using System.Xml.Serialization;
- namespace Edge.Core.Configuration
- {
- public class Configurator
- {
- public event Action<string> OnReadConfigInfo;
- private static Configurator instance = new Configurator();
- private Timer timelyCheckRemoteConfig;
-
-
-
-
- public event EventHandler OnConfigFileChanged;
- private IConfigurationRoot configurationRoot = null;
- public ILogger logger = NullLogger.Instance;
- private IConfigurationBuilder builder;
- public async Task<bool> LoadAsync()
- {
- try
- {
-
- this.builder = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- .AddJsonFile("noExistsNow.json", optional: true, reloadOnChange: true)
- .AddXmlFile("settings.xml", optional: false, reloadOnChange: true);
- this.configurationRoot = this.builder.Build();
- }
- catch (FileNotFoundException fnf)
- {
- Console.WriteLine(fnf);
- logger.LogError("Could not find local settings.xml");
- this.OnReadConfigInfo?.Invoke("Could not find local settings.xml");
- return false;
- }
- this.MetaConfiguration = this.RebindMetaFromFile();
- string enableAndRetrieveConfigFromConfigServiceUrl =
- this.MetaConfiguration.Parameter?.FirstOrDefault(p => p.Name
- == "enableAndRetrieveConfigFromConfigServiceUrl")?.Value;
- if (string.IsNullOrEmpty(enableAndRetrieveConfigFromConfigServiceUrl))
- {
-
-
-
- return this.LoadFromLocalFile();
- }
- else
- {
-
- logger.LogInformation("Use Remote Config against ConfigService url: " + enableAndRetrieveConfigFromConfigServiceUrl ?? "");
- this.OnReadConfigInfo?.Invoke("Use Remote Config: " + enableAndRetrieveConfigFromConfigServiceUrl ?? "");
- var loadResult = await this.LoadFromRemote(enableAndRetrieveConfigFromConfigServiceUrl);
- if (!loadResult) return false;
-
- if (this.timelyCheckRemoteConfig != null) this.timelyCheckRemoteConfig.Dispose();
- this.timelyCheckRemoteConfig = new Timer(async (o) =>
- {
- await this.LoadFromRemote(enableAndRetrieveConfigFromConfigServiceUrl);
- },
- null, 20000, 20000);
- return true;
- }
- }
- private bool LoadFromLocalFile()
- {
- this.configurationRoot.GetReloadToken().RegisterChangeCallback((o) =>
- {
- this.MetaConfiguration = this.RebindMetaFromFile();
- this.NozzleExtraInfoConfiguration = this.RebindNozzleProductFromFile();
- this.DeviceProcessorConfiguration = this.RebindDeviceProcessorFromFile();
- this.OnConfigFileChanged?.Invoke(this, null);
- this.configurationRoot = builder.Build();
- this.LoadFromLocalFile();
-
-
-
-
- }, null);
- this.MetaConfiguration = this.RebindMetaFromFile();
- this.NozzleExtraInfoConfiguration = this.RebindNozzleProductFromFile();
- this.DeviceProcessorConfiguration = this.RebindDeviceProcessorFromFile();
- return true;
- }
-
-
-
-
-
- private async Task<bool> LoadFromRemote(string enableAndRetrieveConfigFromConfigServiceUrl)
- {
- try
- {
- var newReadNozzleProductConfig = await this.ReadRemoteNozzleProductConfig(
- enableAndRetrieveConfigFromConfigServiceUrl,
- "LiteFccCoreSettings_NozzleProduct");
- if (newReadNozzleProductConfig != null)
- if (!newReadNozzleProductConfig.Equals(this.NozzleExtraInfoConfiguration))
- {
- logger.LogInformation("Remote Nozzle product config changed to:" + Environment.NewLine
- + this.ConvertObjectToString(newReadNozzleProductConfig) ?? ""
- + " will fire ChangeCallbacks...");
- this.OnReadConfigInfo?.Invoke("Remote Nozzle Product Config changed(read mapping count: " + newReadNozzleProductConfig.Mapping.Count + ")...");
- this.NozzleExtraInfoConfiguration = newReadNozzleProductConfig;
- this.OnConfigFileChanged?.Invoke(this, null);
-
- }
- var newReadProcessorConfig = await this.ReadRemoteProcessorsConfig(
- enableAndRetrieveConfigFromConfigServiceUrl,
- "LiteFccCoreSettings_Processor");
- if (newReadProcessorConfig != null)
- if (!newReadProcessorConfig.Equals(this.DeviceProcessorConfiguration))
- {
- logger.LogInformation("Remote processors config changed to:" + Environment.NewLine
- + this.ConvertObjectToString(newReadProcessorConfig) ?? ""
- + " will fire ChangeCallbacks...");
- this.OnReadConfigInfo?.Invoke("Remote Processor Config changed(read processor count: " + newReadProcessorConfig.Processor.Count + ")...");
- this.DeviceProcessorConfiguration = newReadProcessorConfig;
- this.OnConfigFileChanged?.Invoke(this, null);
-
- }
- return true;
- }
- catch (Exception exx)
- {
- logger.LogError("Configurator LoadFromRemote exceptioned: " + exx);
- this.OnReadConfigInfo?.Invoke("Read Remote Config error...");
- return false;
- }
- }
- private string ConvertObjectToString<T>(T config) where T : class
- {
- var loggingSerializer = new XmlSerializer(typeof(T));
- MemoryStream ms = new MemoryStream();
- loggingSerializer.Serialize(ms, config);
- ms.Position = 0;
- return new StreamReader(ms).ReadToEnd();
- }
-
-
- private DeviceProcessorConfiguration RebindDeviceProcessorFromFile()
- {
- var deviceProcessorConfiguration = new DeviceProcessorConfiguration();
- this.configurationRoot.GetSection("deviceProcessor").Bind(deviceProcessorConfiguration);
- return deviceProcessorConfiguration;
- }
-
-
- private NozzleExtraInfoConfiguration RebindNozzleProductFromFile()
- {
- var nozzleProductConfigurationFull = new NozzleExtraInfoConfiguration();
- this.configurationRoot.GetSection("nozzleProduct").Bind(nozzleProductConfigurationFull);
- return nozzleProductConfigurationFull;
- }
-
-
- private MetaConfiguration RebindMetaFromFile()
- {
- var metaConfigurationFull = new MetaConfiguration();
- configurationRoot.GetSection("meta").Bind(metaConfigurationFull);
- return metaConfigurationFull;
- }
-
-
-
-
-
-
- private async Task<DeviceProcessorConfiguration> ReadRemoteProcessorsConfig(
- string configServiceBaseUrl,
- string settingsGroupName)
- {
- RestClient restClient = new RestClient(configServiceBaseUrl);
- RestRequest configDescRequest = new RestRequest("api/Config/description", Method.GET);
- configDescRequest.AddHeader("Content-Type", "application/json");
- configDescRequest.AddQueryParameter("configGroupName", settingsGroupName);
- configDescRequest.AddQueryParameter("configOwnerIds", this.MetaConfiguration.Parameter.First(p => p.Name == "serialNumber").Value);
- configDescRequest.RequestFormat = DataFormat.Json;
- var configDescResponse = await restClient.ExecuteTaskAsync(configDescRequest);
- if (configDescResponse.StatusCode != System.Net.HttpStatusCode.OK)
- {
- logger.LogInformation("Remote config service(api/Config/description) returned with Status code: " + configDescResponse.StatusCode);
- throw new ArgumentException("Remote config service(api/Config/description) returned with Status code: " + configDescResponse.StatusCode);
- }
- var configDescriptions = JsonConvert.DeserializeObject<ConfigDescription[]>(configDescResponse.Content);
- var deviceProcessorConfiguration = new DeviceProcessorConfiguration() { Processor = new List<Processor>() };
- foreach (var configDesc in configDescriptions.Where(d => d.Enabled))
- {
- var configRequest = new RestRequest("api/Config/", Method.GET);
- configRequest.AddHeader("Content-Type", "application/json");
- configRequest.AddHeader("configName", configDesc.Name);
- configRequest.AddHeader("configOwnerId", this.MetaConfiguration.Parameter.First(p => p.Name == "clientId").Value);
- configRequest.RequestFormat = DataFormat.Json;
- var configResponse = await restClient.ExecuteTaskAsync(configRequest);
- if (configResponse.StatusCode == System.Net.HttpStatusCode.OK)
- {
- var config =
- JsonConvert.DeserializeObject<Edge.Core.Configuration.Configuration[]>(
- configResponse.Content).First();
- XmlDocument xmlDocument = new XmlDocument();
- xmlDocument.LoadXml(config.Value);
- var processorNode = xmlDocument.GetElementsByTagName("processor")[0];
- deviceProcessorConfiguration.Processor.Add(new Edge.Core.Configuration.Processor()
- {
- Name = processorNode.Attributes["name"].Value,
-
- DeviceProcessorType = processorNode.Attributes["deviceProcessorType"].Value,
- Complex = bool.Parse(processorNode.Attributes["complex"]?.Value ?? "false"),
- ConstructorArg = processorNode.Attributes["constructorArg"]?.Value,
- Parameter = processorNode.SelectNodes("parameter").Cast<XmlNode>()
- .Select(n => new ProcessorParameter()
- {
- Complex = bool.Parse(n.Attributes["complex"]?.Value ?? "false"),
- Name = n.Attributes["name"].Value,
- Value = n.Attributes["value"]?.Value,
- ConstructorArg = n.Attributes["constructorArg"]?.Value,
- Description = n.Attributes["description"]?.Value
- }).ToList()
- });
- }
- else
- {
- logger.LogInformation("Remote config service(api/Config/) returned with Status code: " + configResponse.StatusCode
- + " for Config with Name: " + configDesc.Name ?? "");
- }
- }
- return deviceProcessorConfiguration;
- }
-
-
-
-
-
-
- private async Task<NozzleExtraInfoConfiguration> ReadRemoteNozzleProductConfig(
- string configServiceBaseUrl,
- string configName)
- {
- var nozzleProductConfiguration = new NozzleExtraInfoConfiguration() { Mapping = new List<NozzleExtraInfo>() };
- RestClient restClient = new RestClient(configServiceBaseUrl);
- var configRequest = new RestRequest("api/Config/", Method.GET);
- configRequest.AddHeader("Content-Type", "application/json");
- configRequest.AddHeader("configName", configName);
- configRequest.AddHeader("configOwnerId", this.MetaConfiguration.Parameter.First(p => p.Name == "clientId").Value);
- configRequest.RequestFormat = DataFormat.Json;
- var configResponse = await restClient.ExecuteTaskAsync(configRequest);
- if (configResponse.StatusCode == System.Net.HttpStatusCode.NotFound)
- {
- logger.LogInformation("Remote config service(api/Config/) retunred with Status Code: NotFound for config with name: " + configName);
- return null;
- }
- else if (configResponse.StatusCode != System.Net.HttpStatusCode.OK)
- {
- logger.LogInformation("Remote config service(api/Config/) returned with Status code: " + configResponse.StatusCode + " for config with name: " + configName);
- throw new ArgumentException("Remote config service(api/Config/) returned with Status code: " + configResponse.StatusCode);
- }
- var config =
- JsonConvert.DeserializeObject<Edge.Core.Configuration.Configuration[]>(
- configResponse.Content).First();
- if (!config.Enabled) return nozzleProductConfiguration;
- XmlDocument xmlDocument = new XmlDocument();
- xmlDocument.LoadXml(config.Value);
- var mappingNodes = xmlDocument.GetElementsByTagName("mapping");
- foreach (var node in mappingNodes.Cast<XmlNode>())
- {
- nozzleProductConfiguration.Mapping.Add(new NozzleExtraInfo()
- {
- Description = node.Attributes["description"]?.Value,
- PumpId = int.Parse(node.Attributes["pumpId"]?.Value ?? "-1"),
- NozzleLogicalId = int.Parse(node.Attributes["nozzleLogicalId"]?.Value ?? "-1"),
- ProductBarcode = int.Parse(node.Attributes["productBarcode"]?.Value ?? "-1"),
- SiteLevelNozzleId = int.Parse(node.Attributes["siteLevelNozzleId"]?.Value ?? "-1"),
- });
- }
- return nozzleProductConfiguration;
- }
- public static Configurator Default => instance;
-
-
-
-
-
-
-
-
-
- public DeviceProcessorConfiguration DeviceProcessorConfiguration { get; set; }
- public NozzleExtraInfoConfiguration NozzleExtraInfoConfiguration { get; set; }
- public MetaConfiguration MetaConfiguration { get; set; }
- }
- }
|