#改造思路#
1.业务系统尽量保持纯粹,不直接处理设备协议及通信。
2.抽象出常用设备操作功能(抄表、拉合闸、清零、校时等),定义接口
3.以插件的形式融入系统,绑定对应的品牌型号,利用反射调用不同的插件。
接口定义如下
public interface IAggrementPlugin
{
/// <summary>
/// 启动
/// </summary>
public (bool success, string msg) Start(string @params);
/// <summary>
/// 停止
/// </summary>
public (bool success, string msg) Stop();
/// <summary>
/// 是否正在运行
/// </summary>
/// <returns></returns>
public bool IsRunning();
/// <summary>
/// 透传
/// </summary>
/// <param name="imei">序列号</param>
/// <param name="valueCmd">自定义指令</param>
/// <returns></returns>
public Task<string> Transform(string imei, string valueCmd);
/// <summary>
/// 打开继电器,断闸
/// </summary>
/// <returns></returns>
public bool PowerOff(string sn, string addr, string code, string baseCmd);
/// <summary>
/// 关闭继电器,断闸
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <returns></returns>
public bool PowerOn(string sn, string addr, string code, string baseCmd);
/// <summary>
/// 读取组合有功数据块电能
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <returns></returns>
public string ReadCombinedAllTotal(string sn, string addr, string code);
/// <summary>
/// 读取组合有功总电能
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <returns></returns>
public string ReadCombinedTotalE(string sn, string addr, string code);
/// <summary>
/// 读取正向有功数据块电能
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <returns></returns>
public string ReadPositiveAllTotal(string sn, string addr, string code);
/// <summary>
/// 读取正向有功总电能
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <returns></returns>
public string ReadPositiveTotalE(string sn, string addr, string code);
/// <summary>
/// 读取反向有功数据块电能
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <returns></returns>
public string ReadReverseAllTotal(string sn, string addr, string code);
/// <summary>
/// 读取反向有功总电能
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <returns></returns>
public string ReadReverseTotalE(string sn, string addr, string code);
/// <summary>
/// 电表清零
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <param name="code"></param>
/// <returns></returns>
public string ClearMeter(string sn, string addr, string code);
/// <summary>
/// 校时
/// </summary>
/// <param name="sn"></param>
/// <param name="addr"></param>
/// <param name="code"></param>
/// <returns></returns>
public string Timing(string sn, string addr, string code);
/// <summary>
/// 配置参数
/// </summary>
/// <param name="sn">序列号</param>
/// <param name="addrs">地址列表</param>
/// <param name="code">编码</param>
/// <returns></returns>
public (bool success, string body) Configuration(string sn, List<string> addrs);
}
接口插件相关工具类
/// <summary>
/// 协议插件--工具类
/// </summary>
public static class AggrementPluginUtil
{
public static ConcurrentDictionary<string, IAggrementPlugin> _pluginDic = new ConcurrentDictionary<string, IAggrementPlugin>();
// 启动(卸载原dll)、停止、重新加载(卸载全部,重新加载)、清理dll(卸载不在系统中的dll、例如删除等)
public static IAggrementPlugin? GetPluginService(string assemblyName, string filePath, string className = "Aggrement", bool fg = false)
{
IAggrementPlugin? docking = null;
if (fg == false && _pluginDic.ContainsKey(assemblyName))
{
return _pluginDic[assemblyName];
}
filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, filePath);
if (File.Exists(filePath))
{
//Assembly assembly = Assembly.LoadFile(filePath);
//docking = assembly.CreateInstance($"{assemblyName}.{className}") as IDocking;
if (!_pluginDic.ContainsKey(assemblyName))
{
byte[] assemblyBuf = File.ReadAllBytes(filePath);
Assembly assembly = Assembly.Load(assemblyBuf);
//Assembly assembly = Assembly.LoadFrom(assemblyName);
docking = assembly.CreateInstance($"{assemblyName}.{className}") as IAggrementPlugin;
if (docking != null)
{
_pluginDic.TryAdd(assemblyName, docking);
}
return docking;
}
else
{
if (fg == true)
{
_pluginDic[assemblyName] = docking;
}
return _pluginDic[assemblyName];
}
}
else
{
throw new Exception("当前程序集不存在");
}
}
public static void Init(Dictionary<string, string> plugins, out string msg)
{
msg = "";
foreach (var plugin in plugins)
{
if (_pluginDic.ContainsKey(plugin.Key))
{
_pluginDic.Remove(plugin.Key, out IAggrementPlugin _p);
if (_p != null)
{
_p.Stop();
_p = null;
}
}
var _plugin = GetPluginService(plugin.Key, plugin.Value);
if (_plugin == null)
{
msg += $"当前插件初始化失败{plugin.Key}请检查插件是否合理/r/n";
}
}
}
/// <summary>
/// 根据电表信息获取插件
/// </summary>
/// <param name="device"></param>
/// <param name="isDTU">判断是否是dtu</param>
/// <returns></returns>
public static (IAggrementPlugin, BrandModel) GetPlugin(ElectricMeter device, bool isDTU = false)
{
// 获取品牌型号缓存
// 获取插件缓存
var _cache = App.GetService<SysCacheService>();
var brandModels = _cache.Get<List<BrandModel>>("BrandModels");
var plugins = _cache.Get<List<AggrementPluginManage>>("AggrementPlugins");
if (brandModels.Count == 0 || plugins.Count == 0)
{
throw Oops.Bah("插件服务缓存失败,请稍后重试");
}
BrandModel currentModel = null;
AggrementPluginManage currentPlugin=null;
if (isDTU == false)
{
currentModel = brandModels.Where(w => w.Id == device.BrandId).FirstOrDefault();
if (currentModel == null)
{
throw Oops.Bah("当前插件服务缓存失败,请稍后重试");
}
currentPlugin = plugins
.Where(w => w.Id == currentModel.AggrementPluginId)
.FirstOrDefault();
if (currentPlugin == null)
{
throw Oops.Bah("当前插件服务缓存失败,请稍后重试");
}
}
else
{
//Admin.NET.Plugin.Dtu
currentPlugin = plugins
.Where(w => w.AssemblyName == "Admin.NET.Plugin.Dtu")
.FirstOrDefault();
if (currentPlugin == null)
{
throw Oops.Bah("当前插件服务缓存失败,请稍后重试");
}
}
var pluginService = GetPluginService(currentPlugin.AssemblyName, currentPlugin.Path);
if (pluginService == null)
{
throw Oops.Bah("当前插件获取失败");
}
if (pluginService.IsRunning() == false)
{
throw Oops.Bah("当前插件未运行");
}
return (pluginService, currentModel);
}
}