You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
8.7 KiB
C#

using IoTSharp.Gateways.Data;
using IoTSharp.MqttSdk;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
using Quartz;
using OpcUaHelper;
using Opc.Ua;
namespace IoTSharp.Gateways.Jobs
{
public class OPCUAJob : IJob
{
private ILogger _logger;
private ApplicationDbContext _dbContext;
private MQTTClient _client;
private IMemoryCache _cache;
private readonly ILoggerFactory _factory;
private IServiceScope _serviceScope;
public OPCUAJob(ILoggerFactory factory, IServiceScopeFactory scopeFactor, MQTTClient client, IMemoryCache cache)
{
_factory = factory;
_serviceScope = scopeFactor.CreateScope();
_dbContext = _serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
_client = client;
_cache = cache;
}
public async Task Execute(IJobExecutionContext context)
{
var slave_id = new Guid(context.Trigger.JobDataMap.GetString(SchedulerJob.client_id));
var slave_name = context.Trigger.JobDataMap.GetString(SchedulerJob.client_name);
var slave = await _dbContext.Clients.FirstOrDefaultAsync(m => m.Id == slave_id);
if (slave != null)
{
_logger = _factory.CreateLogger($"Slaver:{slave_name}({slave.Address})");
OpcUaClient m_OpcUaClient = new OpcUaClient();
try
{
var uri = slave.Address;
if (!string.IsNullOrEmpty(uri.UserInfo))
{
var inf = uri.UserInfo.Split(':');
switch (inf.Length)
{
case 1:
m_OpcUaClient.UserIdentity = new UserIdentity();
break;
case 2:
m_OpcUaClient.UserIdentity = new UserIdentity(inf[0], inf[1]);
break;
default:
m_OpcUaClient.UserIdentity = new UserIdentity(new AnonymousIdentityToken());
break;
}
}
else
{
m_OpcUaClient.UserIdentity = new UserIdentity(new AnonymousIdentityToken());
}
await m_OpcUaClient.ConnectServer($"opc.tcp://{uri.Host}/{uri.PathAndQuery}");
if (m_OpcUaClient.Connected)
{
List<NodeId> nodes = new List<NodeId>();
var nodeIds = await _dbContext.OPCUAMappings.Include(p => p.Owner).Where(p => p.Owner == slave).ToListAsync();
nodeIds.ForEach(m => nodes.Add(new NodeId(m.NodeId)));
List<DataValue> dataValues = m_OpcUaClient.ReadNodes(nodes.ToArray());
for (int i = 0; i < dataValues.Count; i++)
{
var nodevalue = dataValues[i];
var nodeid = nodes[i];
var nodempa = nodeIds[i];
await UploadNodeData(slave, nodevalue, nodempa);
}
}
}
catch (Exception ex)
{
var msg = $"SlaveId:{slave_id},Device:{slave.DeviceName},IsConnected:{m_OpcUaClient.Connected},Message:{ex.Message}";
_logger.LogError(ex, msg);
throw new Exception(msg, ex);
}
finally
{
}
}
else
{
_logger.LogWarning($"未能找到从机{slave_id}");
}
}
private async Task UploadNodeData(Client slave, DataValue nodevalue, OPCUAMapping nodempa)
{
switch (nodevalue.WrappedValue.TypeInfo.BuiltInType)
{
case BuiltInType.Null:
break;
case BuiltInType.Boolean:
await UploadData(slave, nodempa, nodevalue.GetValue(false));
break;
case BuiltInType.SByte:
await UploadData(slave, nodempa, nodevalue.GetValue((sbyte)0));
break;
case BuiltInType.Byte:
await UploadData(slave, nodempa, nodevalue.GetValue((byte)0));
break;
case BuiltInType.Int16:
await UploadData(slave, nodempa, nodevalue.GetValue((short)0));
break;
case BuiltInType.UInt16:
await UploadData(slave, nodempa, nodevalue.GetValue((ushort)0));
break;
case BuiltInType.Int32:
await UploadData(slave, nodempa, nodevalue.GetValue(0));
break;
case BuiltInType.UInt32:
await UploadData(slave, nodempa, nodevalue.GetValue((uint)0));
break;
case BuiltInType.Int64:
await UploadData(slave, nodempa, nodevalue.GetValue((long)0));
break;
case BuiltInType.UInt64:
await UploadData(slave, nodempa, nodevalue.GetValue((ulong)0));
break;
case BuiltInType.Float:
await UploadData(slave, nodempa, nodevalue.GetValue((float)0));
break;
case BuiltInType.Double:
await UploadData(slave, nodempa, nodevalue.GetValue((double)0));
break;
case BuiltInType.String:
await UploadData(slave, nodempa, nodevalue.GetValue(string.Empty));
break;
case BuiltInType.DateTime:
await UploadData(slave, nodempa, nodevalue.GetValue(new DateTime(1970, 1, 1, 0, 0, 0)));
break;
case BuiltInType.Guid:
await UploadData(slave, nodempa, nodevalue.GetValue(Guid.NewGuid()));
break;
case BuiltInType.ByteString:
//await UploadData(slave, nodempa, nodevalue.GetValue(byte[]);
break;
case BuiltInType.XmlElement:
break;
case BuiltInType.NodeId:
await UploadData(slave, nodempa, nodevalue.GetValue(string.Empty));
break;
case BuiltInType.ExpandedNodeId:
break;
case BuiltInType.StatusCode:
break;
case BuiltInType.QualifiedName:
break;
case BuiltInType.LocalizedText:
break;
case BuiltInType.ExtensionObject:
break;
case BuiltInType.DataValue:
break;
case BuiltInType.Variant:
break;
case BuiltInType.DiagnosticInfo:
break;
case BuiltInType.Number:
await UploadData(slave, nodempa, nodevalue.GetValue((float)0));
break;
case BuiltInType.Integer:
await UploadData(slave, nodempa, nodevalue.GetValue(0));
break;
case BuiltInType.UInteger:
await UploadData(slave, nodempa, nodevalue.GetValue((uint)0));
break;
case BuiltInType.Enumeration:
break;
default:
break;
}
}
private async Task UploadData<T>(Client slave, OPCUAMapping point, T? value)
{
if (value != null)
{
JObject jo = new()
{
{ point.DataName, new JValue(value) }
};
switch (point.DataCatalog)
{
case DataCatalog.AttributeData:
await _client.UploadAttributeAsync(slave.DeviceName, jo);
break;
case DataCatalog.TelemetryData:
await _client.UploadTelemetryDataAsync(slave.DeviceName, jo);
break;
default:
break;
}
}
}
}
}