Files
KinginfoGateway/framework/ThingsGateway.Application/Plugin/UpLoadBase.cs
Kimdiego2098 13be91e78b 2.0.0
2023-08-07 15:09:53 +08:00

159 lines
6.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://diego2098.gitee.io/thingsgateway-docs/
// QQ群605534569
//------------------------------------------------------------------------------
#endregion
using Furion;
using Microsoft.Extensions.Logging;
using TouchSocket.Core;
namespace ThingsGateway.Application;
/// <summary>
/// 上传插件
/// <para></para>
/// 约定:
/// <para></para>
/// 如果设备属性需要密码输入属性名称中需包含Password字符串
/// <para></para>
/// 如果设备属性需要大文本输入属性名称中需包含BigText字符串
/// <br></br>
/// 因为自定义上传插件需求比较大,这里着重解释代码运行原理
/// 继承<see cref="UpLoadBase"/>后,可以看到需要实现各类虚方法/属性<br></br>
/// <see cref="UploadVariables"/> <br></br>
/// <see cref="VariablePropertys"/><br></br>
/// <see cref="DriverBase.DriverPropertys"/><br></br>
/// <see cref="BeforStartAsync"/><br></br>
/// <see cref="ExecuteAsync"/><br></br>
/// <see cref="DriverBase.IsConnected"/><br></br>
/// <see cref="Init(UploadDeviceRunTime)"/><br></br>
/// 含义可看注释,下面看看网关上传插件的生命周期<br></br>
/// 1、构造函数<see cref="UpLoadBase()"/> 传入参数服务工厂,在需要获取服务时使用<see cref="App.GetService{TService}(IServiceProvider)"/><br></br>
/// 2、<see cref="Init(UploadDeviceRunTime)"/>初始化函数传入上传设备参数只执行一次在这个方法内一般会初始化一些必要的实例比如new MqttClient以及一些必要的实现属性比如<see cref="UploadVariables"/><br></br>
/// 3、<see cref="BeforStartAsync"/>开始前执行的方法比如连接mqtt等只执行一次<br></br>
/// 4、<see cref="ExecuteAsync"/>核心执行的方法,需实现上传方法,在插件结束前会一直循环调用<br></br>
/// 5、<see cref="DisposableObject.Dispose(bool)"/> 结束时调用的方法,实现资源释放方法<br></br>
/// 网关的数据是如何传入到上传插件的下面会以Mqtt上传为例<br></br>
/// 1、如何获取采集变量值在初始化函数中<see cref="Init(UploadDeviceRunTime)"/>获取全局设备/变量<br></br>
/// 通过<see cref="App.GetService{TService}(IServiceProvider)"/>获取单例服务<see cref="GlobalDeviceData"/><br></br>
/// 可以看到在这个单例服务中,已经拥有全部的采集设备与变量<br></br>
/// 2、如何获取采集变量中的上传属性UploadBase中封装了通用方法<see cref="GetPropertyValue(DeviceVariableRunTime, string)"/><br></br>
/// 比如定义了变量属性Enable只有设置为true的变量才会用作某逻辑执行方法GetPropertyValue(tag,"Enable")也可用硬编码传入propertyName参数<br></br>
/// 3、如何定义自己的上传实体第一步中获取获取单例服务<see cref="GlobalDeviceData"/>,在拥有全局变量下,可以使用<see cref="Mapster"/> 或者 手动赋值到DTO实体<br></br>
/// 4、完整的参考可以查看MqttClient插件ThingsGateway\src\Plugins\ThingsGateway.Mqtt\ThingsGateway.Mqtt.csproj<br></br>
/// </summary>
public abstract class UpLoadBase : DriverBase
{
/// <summary>
/// 当前上传设备
/// </summary>
public UploadDeviceRunTime CurDevice { get; protected set; }
/// <summary>
/// 返回插件的上传变量,一般在<see cref="Init(UploadDeviceRunTime)"/>后初始化
/// </summary>
public abstract List<DeviceVariableRunTime> UploadVariables { get; }
/// <summary>
/// 插件配置项 ,继承实现<see cref="VariablePropertyBase"/>后返回继承类如果不存在返回null
/// </summary>
public abstract VariablePropertyBase VariablePropertys { get; }
/// <summary>
/// 离线缓存
/// </summary>
protected CacheDb CacheDb { get; set; }
/// <summary>
/// 结束通讯后执行的方法
/// </summary>
/// <returns></returns>
public abstract Task AfterStopAsync();
/// <summary>
/// 开始执行的方法
/// </summary>
/// <returns></returns>
public abstract Task BeforStartAsync(CancellationToken token);
/// <summary>
/// 循环执行
/// </summary>
public abstract Task ExecuteAsync(CancellationToken token);
/// <summary>
/// 获取设备的属性值
/// </summary>
public virtual string GetDevicePropertyValue(CollectDeviceRunTime collectDeviceRunTime, string propertyName)
{
if (collectDeviceRunTime == null)
return null;
return collectDeviceRunTime.DevicePropertys.FirstOrDefault(a => a.PropertyName == propertyName).Value;
}
/// <summary>
/// 获取变量的属性值
/// </summary>
public virtual string GetPropertyValue(DeviceVariableRunTime variableRunTime, string propertyName)
{
if (variableRunTime == null)
return null;
if (variableRunTime.VariablePropertys.ContainsKey(CurDevice.Id))
{
var data = variableRunTime.VariablePropertys[CurDevice.Id].FirstOrDefault(a =>
a.PropertyName == propertyName);
if (data != null)
{
return data.Value;
}
}
return null;
}
/// <summary>
/// 初始化
/// </summary>
public void Init(ILogger logger, UploadDeviceRunTime device)
{
_logger = logger;
IsLogOut = device.IsLogOut;
CurDevice = device;
CacheDb = new(CurDevice.Id.ToString());
Init(device);
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="device">设备</param>
protected abstract void Init(UploadDeviceRunTime device);
/// <summary>
/// 底层日志输出
/// </summary>
protected override void Log_Out(TouchSocket.Core.LogLevel arg1, object arg2, string arg3, Exception arg4)
{
if (arg1 >= TouchSocket.Core.LogLevel.Warning)
{
CurDevice.SetDeviceStatus(lastErrorMessage: arg3);
}
if (IsLogOut || arg1 >= TouchSocket.Core.LogLevel.Warning)
{
_logger.Log_Out(arg1, arg2, arg3, arg4);
}
}
}