#define DEBUG using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Xml; using Aitex.Common.Util; using Aitex.Core.RT.ConfigCenter; using Aitex.Core.RT.DBCore; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.FAServices; namespace MECF.Framework.Common.SCCore { public class SystemConfigManager : Singleton, ISCManager { #region Variables private readonly Dictionary _items; private readonly Dictionary>> _dicValueChangedCallback; private object _itemLocker = new object(); private string _scConfigFile; private readonly string _scDataFile = PathManager.GetCfgDir() + "_sc.data"; private readonly string _scDataBackupFile = PathManager.GetCfgDir() + "_sc.data.bak"; private readonly string _scDataErrorFile = PathManager.GetCfgDir() + "_sc.data.err."; #endregion #region Constructors public SystemConfigManager() { _items = new Dictionary(StringComparer.OrdinalIgnoreCase); _dicValueChangedCallback = new Dictionary>>(); } #endregion #region Methods public List VidConfigList { get { var list = new List(); foreach (var item in _items) { list.Add(new VIDItem { DataType = "", Description = item.Value.Description, Index = 0, Name = item.Key, Unit = "" }); } return list; } } public void Initialize(string scConfigPathName) { _scConfigFile = scConfigPathName; BuildItems(_scConfigFile); BackupAndRecoverDataFile(); CustomData(); GenerateDataFile(); foreach (var item in _items) { CONFIG.Subscribe("", item.Key, () => item.Value.Value); } OP.Subscribe("System.SetConfig", InvokeSetConfig); SC.Manager = this; Singleton.Instance.StartDataCleaner(); } private bool InvokeSetConfig(string cmd, object[] parameters) { var scName = (string)parameters[0]; var scValue = parameters[1]; if (!ContainsItem(scName)) { EV.PostWarningLog("System", $"Not find SC with name {scName}"); return false; } var configValueAsObject = GetConfigValueAsObject(scName); if (InitializeItemValue(_items[scName], scValue)) { GenerateDataFile(); EV.PostInfoLog("System", $"SC {scName} value changed from {configValueAsObject} to {parameters[1]}"); } return true; } public void Terminate() { } public string GetFileContent() { if (!File.Exists(_scConfigFile)) { return ""; } var stringBuilder = new StringBuilder(); try { using var streamReader = new StreamReader(_scConfigFile); while (!streamReader.EndOfStream) { stringBuilder.Append(streamReader.ReadLine()); } } catch (Exception ex) { LOG.Write(ex); return ""; } return stringBuilder.ToString(); } private void BuildItems(string xmlFile) { var xmlDocument = new XmlDocument(); try { xmlDocument.Load(xmlFile); var xmlNodeList = xmlDocument.SelectNodes("root/configs"); foreach (XmlElement item in xmlNodeList) { BuildPathConfigs(item.GetAttribute("name"), item); } } catch (Exception ex) { LOG.Write(ex); } } private void BuildPathConfigs(string parentPath, XmlElement configElement) { var xmlNodeList = configElement.SelectNodes("configs"); foreach (XmlElement item in xmlNodeList) { if (string.IsNullOrEmpty(parentPath)) { BuildPathConfigs(item.GetAttribute("name"), item); } else { BuildPathConfigs(parentPath + "." + item.GetAttribute("name"), item); } } var xmlNodeList2 = configElement.SelectNodes("config"); foreach (XmlElement item2 in xmlNodeList2) { var sCConfigItem = new SCConfigItem { Default = item2.GetAttribute("default"), Name = item2.GetAttribute("name"), Description = item2.GetAttribute("description"), Max = item2.GetAttribute("max"), Min = item2.GetAttribute("min"), Parameter = item2.GetAttribute("paramter"), Path = parentPath, Tag = item2.GetAttribute("tag"), Type = item2.GetAttribute("type"), Unit = item2.GetAttribute("unit") }; InitializeItemValue(sCConfigItem, sCConfigItem.Default); if (_items.ContainsKey(sCConfigItem.PathName)) { LOG.Error("Duplicated SC item, " + sCConfigItem.PathName); } _items[sCConfigItem.PathName] = sCConfigItem; } } private void BackupAndRecoverDataFile() { try { if (File.Exists(_scDataFile) && IsXmlFileLoadable(_scDataFile)) { File.Copy(_scDataFile, _scDataBackupFile, overwrite: true); } else if (File.Exists(_scDataBackupFile) && IsXmlFileLoadable(_scDataBackupFile)) { if (File.Exists(_scDataFile)) { File.Copy(_scDataFile, _scDataErrorFile + DateTime.Now.ToString("yyyyMMdd_HHmmss"), overwrite: true); } File.Copy(_scDataBackupFile, _scDataFile, overwrite: true); } } catch (Exception ex) { LOG.Write(ex); } } private void CustomData() { var dictionary = new Dictionary(); try { if (!File.Exists(_scDataFile)) { return; } var xmlDocument = new XmlDocument(); xmlDocument.Load(_scDataFile); var xmlNodeList = xmlDocument.SelectNodes("root/scdata"); foreach (XmlElement item in xmlNodeList) { var attribute = item.GetAttribute("name"); if (_items.ContainsKey(attribute)) { InitializeItemValue(_items[attribute], item.GetAttribute("value")); } } } catch (Exception ex) { LOG.Write(ex); } } private void GenerateDataFile() { try { var doc = new XmlDocument(); doc.LoadXml(""); var root = doc.SelectSingleNode("root") as XmlElement; foreach (var item in _items) { var xmlElement2 = doc.CreateElement("scdata"); xmlElement2.SetAttribute("name", item.Key); xmlElement2.SetAttribute("value", item.Value.Value.ToString()); root.AppendChild(xmlElement2); } if (File.Exists(_scDataFile) && IsXmlFileLoadable(_scDataFile)) { File.Copy(_scDataFile, _scDataBackupFile, overwrite: true); } using var fileStream = new FileStream(_scDataFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 1024, FileOptions.WriteThrough); fileStream.SetLength(0L); var xmlWriterSettings = new XmlWriterSettings(); xmlWriterSettings.Indent = true; xmlWriterSettings.OmitXmlDeclaration = false; using var w = XmlWriter.Create(fileStream, xmlWriterSettings); doc.Save(w); } catch (Exception ex) { LOG.Write(ex); } } private bool IsXmlFileLoadable(string file) { try { var xmlDocument = new XmlDocument(); xmlDocument.Load(file); } catch (Exception ex) { LOG.Write(ex); return false; } return true; } public SCConfigItem GetConfigItem(string name) { if (!_items.ContainsKey(name)) { return null; } return _items[name]; } public bool ContainsItem(string name) { return _items.ContainsKey(name); } public object GetConfigValueAsObject(string name) { var configItem = GetConfigItem(name); return configItem.Type switch { "Bool" => configItem.BoolValue, "Integer" => configItem.IntValue, "Double" => configItem.DoubleValue, "String" => configItem.StringValue, _ => null, }; } public T GetValue(string name) where T : struct { try { if (typeof(T) == typeof(bool)) { return (T)(object)_items[name].BoolValue; } if (typeof(T) == typeof(int)) { return (T)(object)_items[name].IntValue; } if (typeof(T) == typeof(double)) { return (T)(object)_items[name].DoubleValue; } } catch (KeyNotFoundException) { EV.PostAlarmLog("System", "Can not find system config item " + name); return default(T); } catch (Exception) { EV.PostAlarmLog("System", "Can not get valid system config item value " + name); return default(T); } Debug.Assert(condition: false, "unsupported type"); return default(T); } public string GetStringValue(string name) { if (!_items.ContainsKey(name)) { return null; } return _items[name].StringValue; } public T SafeGetValue(string name, T defaultValue) where T : struct { try { if (typeof(T) == typeof(bool)) { return (T)(object)_items[name].BoolValue; } if (typeof(T) == typeof(int)) { return (T)(object)_items[name].IntValue; } if (typeof(T) == typeof(double)) { return (T)(object)_items[name].DoubleValue; } } catch (KeyNotFoundException) { return defaultValue; } catch (Exception) { return defaultValue; } Debug.Assert(condition: false, "unsupported type"); return defaultValue; } public string SafeGetStringValue(string name, string defaultValue) { if (!_items.ContainsKey(name)) { return defaultValue; } return _items[name].StringValue; } public List GetItemList() { return _items.Values.ToList(); } private bool InitializeItemValue(SCConfigItem scItem, object value) { return scItem?.SafeSetValue(value) ?? false; } public void SetItemValue(string name, object value) { Debug.Assert(_items.ContainsKey(name), "can not find sc name, " + name); if (!_items.ContainsKey(name)) return; if (_items[name].SetValue(value)) { GenerateDataFile(); } } /// public void SetItemValue(string name, bool value) { Debug.Assert(_items.ContainsKey(name), "can not find sc name, " + name); Debug.Assert(_items[name].Type == "Bool", "sc type not bool, defined as" + _items[name].Type); if (_items[name].SetValue(value)) { GenerateDataFile(); } } /// public void SetItemValue(string name, int value) { Debug.Assert(_items.ContainsKey(name), "can not find sc name, " + name); Debug.Assert(_items[name].Type == "Integer", "sc type not bool, defined as" + _items[name].Type); if (_items[name].SetValue(value)) { GenerateDataFile(); } } /// public void SetItemValue(string name, double value) { Debug.Assert(_items.ContainsKey(name), "can not find sc name, " + name); Debug.Assert(_items[name].Type == "Double", "sc type not bool, defined as" + _items[name].Type); if (_items[name].SetValue(value)) { GenerateDataFile(); } } /// public void SetItemValue(string name, string value) { Debug.Assert(_items.ContainsKey(name), "can not find sc name, " + name); if (_items[name].SetValue(value)) { GenerateDataFile(); } } /// /// /// /// /// public void RegisterValueChangedCallback(string name, Action callback) { if (_items.TryGetValue(name, out var scItem)) { scItem.OnValueChanged += (sender, newValue) => { try { callback.Invoke(newValue); } catch (Exception ex) { LOG.Write(ex); } }; } } #endregion } }