Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/MECF/Framework/Common/SCCore/SystemConfigManager.cs

649 lines
18 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
#define DEBUG
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
2023-04-13 11:51:03 +08:00
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 DocumentFormat.OpenXml.Vml.Spreadsheet;
using DocumentFormat.OpenXml.Wordprocessing;
using MECF.Framework.Common.Equipment;
2023-04-13 11:51:03 +08:00
using MECF.Framework.Common.FAServices;
using MECF.Framework.Common.MECF.Framework.Common.SCCore;
2023-04-13 11:51:03 +08:00
namespace MECF.Framework.Common.SCCore
{
public class SystemConfigManager : Singleton<SystemConfigManager>, ISCManager
{
#region Variables
private readonly Dictionary<string, SCConfigItem> _items;
private readonly Dictionary<string, List<Action<object>>> _dicValueChangedCallback;
2023-04-13 11:51:03 +08:00
private object _itemLocker = new object();
private string _scConfigFile;
private readonly string _scDataFile = PathManager.GetCfgDir() + "_sc.data";
2023-04-13 11:51:03 +08:00
private readonly string _scDataBackupFile = PathManager.GetCfgDir() + "_sc.data.bak";
2023-04-13 11:51:03 +08:00
private readonly string _scDataErrorFile = PathManager.GetCfgDir() + "_sc.data.err.";
2023-04-13 11:51:03 +08:00
private readonly string _scConfigChangedBackupPath = PathManager.GetCfgDir() + "ConfigBackup\\";
public readonly List<ConfigChangedInfo> _itemsChanged; //ϵͳ<CFB5><CDB3><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼
#endregion
#region Constructors
public SystemConfigManager()
{
_items = new Dictionary<string, SCConfigItem>(StringComparer.OrdinalIgnoreCase);
_itemsChanged = new List<ConfigChangedInfo>();
_dicValueChangedCallback = new Dictionary<string, List<Action<object>>>();
}
#endregion
#region Methods
public List<VIDItem> VidConfigList
2023-04-13 11:51:03 +08:00
{
get
{
var list = new List<VIDItem>();
foreach (var item in _items)
2023-04-13 11:51:03 +08:00
{
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)
2023-04-13 11:51:03 +08:00
{
CONFIG.Subscribe("", item.Key, () => item.Value.Value);
}
OP.Subscribe("System.SetConfig", InvokeSetConfig);
GetConfigChangedInfo();
CONFIG.Subscribe("SystemConfig", "DataChangedList", () => _itemsChanged);
OP.Subscribe("SystemConfig.Confirm", RemoveConfigChangedInfo);
OP.Subscribe("SystemConfig.Revert", RevertConfig);
SC.Manager = this;
2023-04-13 11:51:03 +08:00
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>ԭ
/// </summary>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <returns></returns>
private bool RevertConfig(string arg1, object[] arg2)
{
foreach (var item in _itemsChanged)
{
if (_items.ContainsKey(item.Name))
{
if (InitializeItemValue(_items[item.Name], item.OldValue))
{
GenerateDataFile();
EV.PostInfoLog("System", $"SC {item.Name} value changed back to {item.OldValue}");
//DataChangedBackup(_items[item.Name], item.OldValue); //<2F><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ܶ<EFBFBD>list<73><74><EFBFBD>в<EFBFBD><D0B2><EFBFBD>
}
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>д<EFBFBD><D0B4><EFBFBD>ǰ<EFBFBD>θĶ<CEB8><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٴα<D9B4><CEB1><EFBFBD><EFBFBD>ļ<EFBFBD>
if (_itemsChanged.Exists(i=>!i.Enable))
{
RemoveConfigChangedInfo(null,null);
}
_itemsChanged.Clear();
return true;
}
/// <summary>
/// <20>ӱ<EFBFBD><D3B1>ػ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD>¼
/// 1.<2E><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ϴγ<CFB4>ʼ<EFBFBD><CABC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>backup<75><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>visible=false<73><EFBFBD><EEB2BB><EFBFBD>Աȣ<D4B1>
/// 2.<2E>͵<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>
/// </summary>
private void GetConfigChangedInfo()
{
if (!Directory.Exists(_scConfigChangedBackupPath))
{
Directory.CreateDirectory(_scConfigChangedBackupPath);
}
DirectoryInfo folder = new DirectoryInfo(@_scConfigChangedBackupPath);
List<FileInfo> files = folder.GetFiles("*.configbackup", SearchOption.TopDirectoryOnly).ToList();
if (files == null || files.Count() == 0) //<2F>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>ļ<EFBFBD>
{
RemoveConfigChangedInfo(null, null);
return;
}
var qry = from x in files
orderby x.LastWriteTime
select x;
string newestBackupPath = qry.Last().FullName;
if (!string.IsNullOrEmpty(newestBackupPath))
{
var xmlDocument = new XmlDocument();
xmlDocument.Load(newestBackupPath);
var xmlNodeList = xmlDocument.SelectNodes("root/scdata");
bool isConfigChanged = false;
foreach (XmlElement item in xmlNodeList)
{
var name = item.GetAttribute("name");
if (_items.ContainsKey(name))
{
if (!_items[name].ValueEquals(item.GetAttribute("value")) && _items[name].Visible)
{
isConfigChanged = true;
_itemsChanged.Add(new ConfigChangedInfo
{
Name = name,
OldValue = item.GetAttribute("value"),
Enable = false
});
}
}
}
//if (isConfigChanged)
//{
// File.Copy(_scDataFile, _scConfigChangedBackupPath + "\\config." +
// DateTime.Now.ToString().Replace(":", "").Replace("/", "").Replace(" ", "")+".backup");
//}
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>б䶯ʱ<E4B6AF><CAB1><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1B5AF>ȷ<EFBFBD>ϰ<EFBFBD>ť<EFBFBD><C5A5><EFBFBD>º<EFBFBD><C2BA><EFBFBD><E1BDAB><EFBFBD><EFBFBD>backup<75><70><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>˴α<CBB4><CEB1><EFBFBD><EFBFBD><EFBFBD>¼
/// </summary>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <returns></returns>
private bool RemoveConfigChangedInfo(string arg1, object[] arg2)
{
try
{
File.Copy(_scDataFile, _scConfigChangedBackupPath + "\\" +
DateTime.Now.ToString().Replace(":", "").Replace("/", "").Replace(" ", "") + ".configbackup");
return true;
}
catch (Exception)
{
return false;
}
}
private bool InvokeSetConfig(string cmd, object[] parameters)
2023-04-13 11:51:03 +08:00
{
var scName = (string)parameters[0];
var scValue = parameters[1];
if (!ContainsItem(scName))
2023-04-13 11:51:03 +08:00
{
EV.PostWarningLog("System", $"Not find SC with name {scName}");
2023-04-13 11:51:03 +08:00
return false;
}
var configValueAsObject = GetConfigValueAsObject(scName);
if (InitializeItemValue(_items[scName], scValue))
2023-04-13 11:51:03 +08:00
{
GenerateDataFile();
EV.PostInfoLog("System", $"SC {scName} value changed from {configValueAsObject} to {parameters[1]}");
DataChangedBackup(_items[scName], configValueAsObject);
}
2023-04-13 11:51:03 +08:00
return true;
}
/// <summary>
///
/// </summary>
/// <param name="item"></param>
/// <param name="oldvalue"></param>
private void DataChangedBackup(SCConfigItem item, object oldvalue)
{
bool isExist = false;
for (int i = _itemsChanged.Count - 1; i >= 0; i--)
{
if (_itemsChanged[i].Name == item.PathName)
{
isExist = true;
object newvalue = (item.Type switch
{
"Bool" => item.BoolValue,
"Integer" => item.IntValue,
"Double" => item.DoubleValue,
"String" => item.StringValue,
_ => null,
});
if (newvalue.ToString() == _itemsChanged[i].OldValue)
{
_itemsChanged.Remove(_itemsChanged[i]);
}
break;
}
}
if (!isExist)
{
_itemsChanged.Add(new ConfigChangedInfo
{
Name = item.PathName,
OldValue = oldvalue.ToString(),
Enable = true
});
}
}
public void Terminate()
2023-04-13 11:51:03 +08:00
{
}
public string GetFileContent()
{
if (!File.Exists(_scConfigFile))
{
return "";
}
var stringBuilder = new StringBuilder();
2023-04-13 11:51:03 +08:00
try
{
using var streamReader = new StreamReader(_scConfigFile);
2023-04-13 11:51:03 +08:00
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();
2023-04-13 11:51:03 +08:00
try
{
xmlDocument.Load(xmlFile);
var xmlNodeList = xmlDocument.SelectNodes("root/configs");
2023-04-13 11:51:03 +08:00
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");
2023-04-13 11:51:03 +08:00
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");
2023-04-13 11:51:03 +08:00
foreach (XmlElement item2 in xmlNodeList2)
{
var sCConfigItem = new SCConfigItem
2023-04-13 11:51:03 +08:00
{
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")
};
bool visible;
if (bool.TryParse(item2.GetAttribute("visible"),out visible))
{
sCConfigItem.Visible = visible;
}
InitializeItemValue(sCConfigItem, sCConfigItem.Default);
2023-04-13 11:51:03 +08:00
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<string, string>();
2023-04-13 11:51:03 +08:00
try
{
if (!File.Exists(_scDataFile))
{
return;
}
var xmlDocument = new XmlDocument();
2023-04-13 11:51:03 +08:00
xmlDocument.Load(_scDataFile);
var xmlNodeList = xmlDocument.SelectNodes("root/scdata");
2023-04-13 11:51:03 +08:00
foreach (XmlElement item in xmlNodeList)
{
var attribute = item.GetAttribute("name");
2023-04-13 11:51:03 +08:00
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("<?xml version=\"1.0\" encoding=\"utf-8\"?><root></root>");
var root = doc.SelectSingleNode("root") as XmlElement;
foreach (var item in _items)
2023-04-13 11:51:03 +08:00
{
var xmlElement2 = doc.CreateElement("scdata");
2023-04-13 11:51:03 +08:00
xmlElement2.SetAttribute("name", item.Key);
xmlElement2.SetAttribute("value", item.Value.Value.ToString());
root.AppendChild(xmlElement2);
2023-04-13 11:51:03 +08:00
}
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);
2023-04-13 11:51:03 +08:00
fileStream.SetLength(0L);
var xmlWriterSettings = new XmlWriterSettings();
2023-04-13 11:51:03 +08:00
xmlWriterSettings.Indent = true;
xmlWriterSettings.OmitXmlDeclaration = false;
using var w = XmlWriter.Create(fileStream, xmlWriterSettings);
doc.Save(w);
2023-04-13 11:51:03 +08:00
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
private bool IsXmlFileLoadable(string file)
{
try
{
var xmlDocument = new XmlDocument();
2023-04-13 11:51:03 +08:00
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);
2023-04-13 11:51:03 +08:00
return configItem.Type switch
{
"Bool" => configItem.BoolValue,
"Integer" => configItem.IntValue,
"Double" => configItem.DoubleValue,
"String" => configItem.StringValue,
_ => null,
};
}
public T GetValue<T>(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<T>(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<SCConfigItem> GetItemList()
{
return _items.Values.ToList();
}
private bool InitializeItemValue(SCConfigItem scItem, object value)
{
return scItem?.SafeSetValue(value) ?? false;
2023-04-13 11:51:03 +08:00
}
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))
2023-04-13 11:51:03 +08:00
{
GenerateDataFile();
}
}
/// <inheritdoc/>
public void SetItemValue(string name, bool value)
2023-04-13 11:51:03 +08:00
{
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))
2023-04-13 11:51:03 +08:00
{
GenerateDataFile();
}
}
/// <inheritdoc/>
public void SetItemValue(string name, int value)
2023-04-13 11:51:03 +08:00
{
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))
2023-04-13 11:51:03 +08:00
{
GenerateDataFile();
}
}
/// <inheritdoc/>
public void SetItemValue(string name, double value)
2023-04-13 11:51:03 +08:00
{
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))
2023-04-13 11:51:03 +08:00
{
GenerateDataFile();
}
}
/// <inheritdoc/>
public void SetItemValue(string name, string value)
2023-04-13 11:51:03 +08:00
{
Debug.Assert(_items.ContainsKey(name), "can not find sc name, " + name);
if (_items[name].SetValue(value))
2023-04-13 11:51:03 +08:00
{
GenerateDataFile();
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="name"></param>
/// <param name="callback"></param>
public void RegisterValueChangedCallback(string name, Action<object> callback)
{
if (_items.TryGetValue(name, out var scItem))
{
scItem.OnValueChanged += (sender, newValue) =>
{
try
{
callback.Invoke(newValue);
}
catch (Exception ex)
{
LOG.Write(ex);
}
};
}
}
#endregion
}
2023-04-13 11:51:03 +08:00
}