159 lines
6.5 KiB
C#
159 lines
6.5 KiB
C#
#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);
|
||
}
|
||
}
|
||
}
|
||
|
||
|