优化rpc;设备在线、离线状态上传
This commit is contained in:
parent
ca6f298bf2
commit
c916cf1a04
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -11,5 +11,5 @@
|
||||
<wt:combobox field="Searcher.IsSuccess" empty-text="@Localizer["Sys.All"]" />
|
||||
</wt:row>
|
||||
</wt:searchpanel>
|
||||
<wt:quote>注意:不同平台的rpc的topic和payload均不同,后期教程会更新到<a href="http://iotgateway.net/" target="_blank">http://iotgateway.net/</a></wt:quote>
|
||||
<wt:quote>注意:不同平台的rpc的topic和payload均不同,后期教程会更新到<a href="http://42.193.160.84/" target="_blank">http://iotgateway.net/</a></wt:quote>
|
||||
<wt:grid vm="@Model" url="/Rpc/RpcLog/Search" hidden-checkbox="true" hidden-grid-index="true" />
|
||||
|
@ -69,7 +69,7 @@
|
||||
<span class="login-error">@Model.MSD.GetFirstError()</span>
|
||||
<button type="submit" class="login-button" style="cursor:pointer">@Model.Localizer["Login.Login"]</button>
|
||||
<div class="login-button" style="cursor:pointer">
|
||||
<a href="http://iotgateway.net/" target="_blank">跳转教程文档,持续更新,收藏不迷路</a>
|
||||
<a href="http://42.193.160.84/" target="_blank">跳转教程文档,持续更新,收藏不迷路</a>
|
||||
</div>
|
||||
|
||||
@*<wt:linkbutton window-title="@Model.Localizer["Login.Register"]" class="login-button" style="cursor:pointer" target="ButtonTargetEnum.Layer" window-width="500" window-height="500" url="/Login/Reg" text="@Model.Localizer["Login.Register"]" />*@
|
||||
|
Binary file not shown.
@ -21,7 +21,6 @@ namespace DriverModbusMaster
|
||||
private SerialPort port = null;
|
||||
private Modbus.Device.ModbusMaster master = null;
|
||||
private SerialPortAdapter adapter = null;
|
||||
private object locker=new object();
|
||||
#region 配置参数
|
||||
|
||||
[ConfigParameter("设备Id")]
|
||||
@ -199,135 +198,119 @@ namespace DriverModbusMaster
|
||||
[Method("功能码:03", description: "ReadHoldingRegisters读保持寄存器")]
|
||||
public DriverReturnValueModel ReadHoldingRegisters(DriverAddressIoArgModel ioarg)
|
||||
{
|
||||
lock (locker)
|
||||
DriverReturnValueModel ret = new();
|
||||
try
|
||||
{
|
||||
DriverReturnValueModel ret = new();
|
||||
try
|
||||
if (IsConnected)
|
||||
ret = ReadRegistersBuffers(3, ioarg);
|
||||
else
|
||||
{
|
||||
if (IsConnected)
|
||||
ret = ReadRegistersBuffers(3, ioarg);
|
||||
else
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Bad;
|
||||
ret.Message = "TCP连接异常";
|
||||
}
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Bad;
|
||||
ret.Message = "TCP连接异常";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
|
||||
ret.Message = ex.Message;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
|
||||
ret.Message = ex.Message;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
[Method("功能码:04", description: "ReadHoldingRegisters读输入寄存器")]
|
||||
public DriverReturnValueModel ReadInputRegisters(DriverAddressIoArgModel ioarg)
|
||||
{
|
||||
lock (locker)
|
||||
DriverReturnValueModel ret = new();
|
||||
try
|
||||
{
|
||||
DriverReturnValueModel ret = new();
|
||||
try
|
||||
if (IsConnected)
|
||||
ret = ReadRegistersBuffers(4, ioarg);
|
||||
else
|
||||
{
|
||||
if (IsConnected)
|
||||
ret = ReadRegistersBuffers(4, ioarg);
|
||||
else
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Bad;
|
||||
ret.Message = "TCP连接异常";
|
||||
}
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Bad;
|
||||
ret.Message = "TCP连接异常";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
|
||||
ret.Message = ex.Message;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
|
||||
ret.Message = ex.Message;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
[Method("功能码:01", description: "ReadCoil读线圈")]
|
||||
public DriverReturnValueModel ReadCoil(DriverAddressIoArgModel ioarg)
|
||||
{
|
||||
lock (locker)
|
||||
DriverReturnValueModel ret = new();
|
||||
try
|
||||
{
|
||||
DriverReturnValueModel ret = new();
|
||||
try
|
||||
if (IsConnected)
|
||||
{
|
||||
if (IsConnected)
|
||||
var retBool = master.ReadCoils(SlaveAddress, ushort.Parse(ioarg.Address), 1)[0];
|
||||
if (ioarg.ValueType == DataTypeEnum.Bit)
|
||||
{
|
||||
var retBool = master.ReadCoils(SlaveAddress, ushort.Parse(ioarg.Address), 1)[0];
|
||||
if (ioarg.ValueType == DataTypeEnum.Bit)
|
||||
{
|
||||
if (retBool)
|
||||
ret.Value = 1;
|
||||
else
|
||||
ret.Value = 0;
|
||||
}
|
||||
if (retBool)
|
||||
ret.Value = 1;
|
||||
else
|
||||
ret.Value = retBool;
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Good;
|
||||
ret.Value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Bad;
|
||||
ret.Message = "TCP连接异常";
|
||||
}
|
||||
ret.Value = retBool;
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Good;
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
|
||||
ret.Message = ex.Message;
|
||||
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Bad;
|
||||
ret.Message = "TCP连接异常";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
|
||||
ret.Message = ex.Message;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
[Method("功能码:02", description: "ReadInput读输入")]
|
||||
public DriverReturnValueModel ReadInput(DriverAddressIoArgModel ioarg)
|
||||
{
|
||||
lock (locker)
|
||||
DriverReturnValueModel ret = new();
|
||||
try
|
||||
{
|
||||
DriverReturnValueModel ret = new();
|
||||
try
|
||||
if (IsConnected)
|
||||
{
|
||||
if (IsConnected)
|
||||
var retBool = master.ReadInputs(SlaveAddress, ushort.Parse(ioarg.Address), 1)[0];
|
||||
if (ioarg.ValueType == DataTypeEnum.Bit)
|
||||
{
|
||||
var retBool = master.ReadInputs(SlaveAddress, ushort.Parse(ioarg.Address), 1)[0];
|
||||
if (ioarg.ValueType == DataTypeEnum.Bit)
|
||||
{
|
||||
if (retBool)
|
||||
ret.Value = 1;
|
||||
else
|
||||
ret.Value = 0;
|
||||
}
|
||||
if (retBool)
|
||||
ret.Value = 1;
|
||||
else
|
||||
ret.Value = retBool;
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Good;
|
||||
ret.Value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Bad;
|
||||
ret.Message = "TCP连接异常";
|
||||
}
|
||||
ret.Value = retBool;
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Good;
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
|
||||
ret.Message = ex.Message;
|
||||
|
||||
ret.StatusType = VaribaleStatusTypeEnum.Bad;
|
||||
ret.Message = "TCP连接异常";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
|
||||
ret.Message = ex.Message;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -463,42 +446,38 @@ namespace DriverModbusMaster
|
||||
|
||||
public async Task<RpcResponse> WriteAsync(string RequestId, string Method, DriverAddressIoArgModel Ioarg)
|
||||
{
|
||||
lock (locker)
|
||||
RpcResponse rpcResponse = new() { IsSuccess = false };
|
||||
try
|
||||
{
|
||||
RpcResponse rpcResponse = new() { IsSuccess = false };
|
||||
try
|
||||
ushort address = ushort.Parse(Ioarg.Address);
|
||||
if (!IsConnected)
|
||||
rpcResponse.Description = "设备连接已断开";
|
||||
else
|
||||
{
|
||||
ushort address = ushort.Parse(Ioarg.Address);
|
||||
if (!IsConnected)
|
||||
rpcResponse.Description = "设备连接已断开";
|
||||
else
|
||||
//功能码01
|
||||
if (Method == nameof(ReadCoil))
|
||||
{
|
||||
//功能码01
|
||||
if (Method == nameof(ReadCoil))
|
||||
{
|
||||
bool value = Ioarg.Value.ToString() == "1" || Ioarg.Value.ToString().ToLower() == "true";
|
||||
master.WriteSingleCoilAsync(SlaveAddress, address, value);
|
||||
rpcResponse.IsSuccess = true;
|
||||
return rpcResponse;
|
||||
}
|
||||
//功能码03
|
||||
else if (Method == nameof(ReadHoldingRegisters))
|
||||
{
|
||||
master.WriteSingleRegisterAsync(SlaveAddress, address, ushort.Parse(Ioarg.Value.ToString()));
|
||||
rpcResponse.IsSuccess = true;
|
||||
return rpcResponse;
|
||||
}
|
||||
else
|
||||
rpcResponse.Description = $"不支持写入:{Method}";
|
||||
bool value = Ioarg.Value.ToString() == "1" || Ioarg.Value.ToString().ToLower() == "true";
|
||||
master.WriteSingleCoilAsync(SlaveAddress, address, value);
|
||||
rpcResponse.IsSuccess = true;
|
||||
return rpcResponse;
|
||||
}
|
||||
//功能码03
|
||||
else if (Method == nameof(ReadHoldingRegisters))
|
||||
{
|
||||
master.WriteSingleRegisterAsync(SlaveAddress, address, ushort.Parse(Ioarg.Value.ToString()));
|
||||
rpcResponse.IsSuccess = true;
|
||||
return rpcResponse;
|
||||
}
|
||||
else
|
||||
rpcResponse.Description = $"不支持写入:{Method}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
rpcResponse.Description = $"写入失败:{Method},{Ioarg}";
|
||||
}
|
||||
return rpcResponse;
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
rpcResponse.Description = $"写入失败:{Method},{Ioarg}";
|
||||
}
|
||||
return rpcResponse;
|
||||
}
|
||||
}
|
||||
public enum PLC_TYPE
|
||||
|
@ -37,7 +37,6 @@ namespace Plugin
|
||||
_DrvierManager = drvierManager;
|
||||
_MyMqttClient = myMqttClient;
|
||||
_MqttServer = mqttServer;
|
||||
|
||||
try
|
||||
{
|
||||
using (var DC = new DataContext(connnectSetting, DBType))
|
||||
|
@ -1,19 +1,11 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PluginInterface;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PluginInterface;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using IoTGateway.DataAccess;
|
||||
using IoTGateway.Model;
|
||||
using WalkingTec.Mvvm.Core;
|
||||
using DynamicExpresso;
|
||||
using MQTTnet.Server;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PluginInterface.IoTSharp;
|
||||
|
||||
namespace Plugin
|
||||
{
|
||||
@ -29,7 +21,8 @@ namespace Plugin
|
||||
private DateTime TsStartDt = new DateTime(1970, 1, 1);
|
||||
private CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||
private Interpreter Interpreter = null;
|
||||
|
||||
private object _lock = new object();
|
||||
private bool lastConnected = false;
|
||||
public DeviceThread(Device device, IDriver driver, string ProjectId, MyMqttClient myMqttClient, Interpreter interpreter, IMqttServer mqttServer, ILogger logger)
|
||||
{
|
||||
_myMqttClient = myMqttClient;
|
||||
@ -58,8 +51,9 @@ namespace Plugin
|
||||
myMqttClient.UploadAttributeAsync(device.DeviceName, device.DeviceConfigs.Where(x => x.DataSide == DataSide.ClientSide).ToDictionary(x => x.DeviceConfigName, x => x.Value));
|
||||
|
||||
task = Task.Run(() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(5000);
|
||||
while (true)
|
||||
{
|
||||
if (tokenSource.IsCancellationRequested)
|
||||
{
|
||||
@ -67,92 +61,103 @@ namespace Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
lock (_lock)
|
||||
{
|
||||
Dictionary<string, List<PayLoad>> sendModel = new() { { _device.DeviceName, new() } };
|
||||
|
||||
var payLoad = new PayLoad() { Values = new() };
|
||||
|
||||
if (driver.IsConnected)
|
||||
try
|
||||
{
|
||||
if (_device.DeviceVariables != null)
|
||||
Dictionary<string, List<PayLoad>> sendModel = new() { { _device.DeviceName, new() } };
|
||||
|
||||
var payLoad = new PayLoad() { Values = new() };
|
||||
|
||||
if (driver.IsConnected)
|
||||
{
|
||||
foreach (var item in _device.DeviceVariables)
|
||||
if (_device.DeviceVariables != null)
|
||||
{
|
||||
var ret = new DriverReturnValueModel();
|
||||
var ioarg = new DriverAddressIoArgModel
|
||||
foreach (var item in _device.DeviceVariables)
|
||||
{
|
||||
ID = item.ID,
|
||||
Address = item.DeviceAddress,
|
||||
ValueType = item.DataType
|
||||
};
|
||||
var method = Methods.Where(x => x.Name == item.Method).FirstOrDefault();
|
||||
if (method == null)
|
||||
ret.StatusType = VaribaleStatusTypeEnum.MethodError;
|
||||
else
|
||||
ret = (DriverReturnValueModel)method.Invoke(_driver, new object[1] { ioarg });
|
||||
var ret = new DriverReturnValueModel();
|
||||
var ioarg = new DriverAddressIoArgModel
|
||||
{
|
||||
ID = item.ID,
|
||||
Address = item.DeviceAddress,
|
||||
ValueType = item.DataType
|
||||
};
|
||||
var method = Methods.Where(x => x.Name == item.Method).FirstOrDefault();
|
||||
if (method == null)
|
||||
ret.StatusType = VaribaleStatusTypeEnum.MethodError;
|
||||
else
|
||||
ret = (DriverReturnValueModel)method.Invoke(_driver, new object[1] { ioarg });
|
||||
|
||||
if (ret.StatusType == VaribaleStatusTypeEnum.Good && !string.IsNullOrWhiteSpace(item.Expressions?.Trim()))
|
||||
if (ret.StatusType == VaribaleStatusTypeEnum.Good && !string.IsNullOrWhiteSpace(item.Expressions?.Trim()))
|
||||
{
|
||||
try
|
||||
{
|
||||
ret.CookedValue = interpreter.Eval(DealMysqlStr(item.Expressions).Replace("raw", ret.Value?.ToString()));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.ExpressionError;
|
||||
}
|
||||
}
|
||||
else
|
||||
ret.CookedValue = ret.Value;
|
||||
|
||||
payLoad.Values[item.Name] = ret.CookedValue;
|
||||
|
||||
ret.VarId = item.ID;
|
||||
|
||||
//变化了才推送到mqttserver,用于前端展示
|
||||
if (DeviceValues[item.ID].StatusType != ret.StatusType || DeviceValues[item.ID].Value?.ToString() != ret.Value?.ToString() || DeviceValues[item.ID].CookedValue?.ToString() != ret.CookedValue?.ToString())
|
||||
{
|
||||
//这是设备变量列表要用的
|
||||
mqttServer.PublishAsync($"internal/v1/gateway/telemetry/{_device.DeviceName}/{item.Name}", JsonConvert.SerializeObject(ret));
|
||||
//这是在线组态要用的
|
||||
mqttServer.PublishAsync($"v1/gateway/telemetry/{_device.DeviceName}/{item.Name}", JsonConvert.SerializeObject(ret.CookedValue));
|
||||
}
|
||||
|
||||
DeviceValues[item.ID] = ret;
|
||||
|
||||
}
|
||||
payLoad.TS = (long)(DateTime.UtcNow - TsStartDt).TotalMilliseconds;
|
||||
|
||||
if (DeviceValues.Any(x => x.Value.Value == null))
|
||||
{
|
||||
try
|
||||
{
|
||||
ret.CookedValue = interpreter.Eval(DealMysqlStr(item.Expressions).Replace("raw", ret.Value?.ToString()));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
ret.StatusType = VaribaleStatusTypeEnum.ExpressionError;
|
||||
}
|
||||
payLoad.Values = null;
|
||||
payLoad.DeviceStatus = DeviceStatusTypeEnum.Bad;
|
||||
}
|
||||
else
|
||||
ret.CookedValue = ret.Value;
|
||||
|
||||
payLoad.Values[item.Name] = ret.CookedValue;
|
||||
|
||||
ret.VarId = item.ID;
|
||||
|
||||
//变化了才推送到mqttserver,用于前端展示
|
||||
if (DeviceValues[item.ID].StatusType != ret.StatusType || DeviceValues[item.ID].Value?.ToString() != ret.Value?.ToString() || DeviceValues[item.ID].CookedValue?.ToString() != ret.CookedValue?.ToString())
|
||||
{
|
||||
//这是设备变量列表要用的
|
||||
mqttServer.PublishAsync($"internal/v1/gateway/telemetry/{_device.DeviceName}/{item.Name}", JsonConvert.SerializeObject(ret));
|
||||
//这是在线组态要用的
|
||||
mqttServer.PublishAsync($"v1/gateway/telemetry/{_device.DeviceName}/{item.Name}", JsonConvert.SerializeObject(ret.CookedValue));
|
||||
payLoad.DeviceStatus = DeviceStatusTypeEnum.Good;
|
||||
sendModel[_device.DeviceName] = new List<PayLoad> { payLoad };
|
||||
myMqttClient.PublishTelemetry(_device, sendModel);
|
||||
}
|
||||
|
||||
DeviceValues[item.ID] = ret;
|
||||
|
||||
}
|
||||
payLoad.TS = (long)(DateTime.Now - TsStartDt).TotalMilliseconds;
|
||||
|
||||
if (DeviceValues.Any(x => x.Value.Value == null))
|
||||
}
|
||||
else
|
||||
{
|
||||
if (driver.Connect())
|
||||
_myMqttClient.DeviceConnected(_device.DeviceName);
|
||||
else if (lastConnected)
|
||||
{
|
||||
payLoad.Values = null;
|
||||
payLoad.DeviceStatus = DeviceStatusTypeEnum.Bad;
|
||||
}
|
||||
else
|
||||
{
|
||||
payLoad.DeviceStatus = DeviceStatusTypeEnum.Good;
|
||||
sendModel[_device.DeviceName] = new List<PayLoad> { payLoad };
|
||||
myMqttClient.PublishTelemetry(_device, sendModel);
|
||||
lastConnected = false;
|
||||
_myMqttClient.DeviceDisconnected(_device.DeviceName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
driver.Connect();
|
||||
_logger.LogError($"线程循环异常,{_device.DeviceName}", ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"线程循环异常,{_device.DeviceName}", ex);
|
||||
}
|
||||
|
||||
|
||||
Thread.Sleep((int)_driver.MinPeriod);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
else
|
||||
_myMqttClient.DeviceDisconnected(_device.DeviceName);
|
||||
}
|
||||
|
||||
private void MyMqttClient_OnExcRpc(object? sender, RpcRequest e)
|
||||
@ -173,47 +178,55 @@ namespace Plugin
|
||||
//执行写入变量RPC
|
||||
if (e.Method.ToLower() == "write")
|
||||
{
|
||||
//没连接就连接
|
||||
if (!_driver.IsConnected)
|
||||
_driver.Connect();
|
||||
|
||||
//连接成功就尝试一个一个的写入,注意:目前写入地址和读取地址是相同的,对于PLC来说没问题,其他的要自己改........
|
||||
if (_driver.IsConnected)
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var para in e.Params)
|
||||
bool RpcConnected = false;
|
||||
//没连接就连接
|
||||
if (!_driver.IsConnected)
|
||||
if (_driver.Connect())
|
||||
RpcConnected = true;
|
||||
|
||||
//连接成功就尝试一个一个的写入,注意:目前写入地址和读取地址是相同的,对于PLC来说没问题,其他的要自己改........
|
||||
if (_driver.IsConnected)
|
||||
{
|
||||
//先查配置项,要用到配置的地址、数据类型、方法(方法最主要是用于区分写入数据的辅助判断,比如modbus不同的功能码)
|
||||
var deviceVariable = _device.DeviceVariables.Where(x => x.Name == para.Key).FirstOrDefault();
|
||||
if (deviceVariable != null)
|
||||
foreach (var para in e.Params)
|
||||
{
|
||||
DriverAddressIoArgModel ioArgModel = new()
|
||||
//先查配置项,要用到配置的地址、数据类型、方法(方法最主要是用于区分写入数据的辅助判断,比如modbus不同的功能码)
|
||||
var deviceVariable = _device.DeviceVariables.Where(x => x.Name == para.Key).FirstOrDefault();
|
||||
if (deviceVariable != null)
|
||||
{
|
||||
Address = deviceVariable.DeviceAddress,
|
||||
Value = para.Value,
|
||||
ValueType = deviceVariable.DataType
|
||||
};
|
||||
var writeResponse = _driver.WriteAsync(e.RequestId, deviceVariable.Method, ioArgModel).Result;
|
||||
rpcResponse.IsSuccess = writeResponse.IsSuccess;
|
||||
if (!writeResponse.IsSuccess)
|
||||
DriverAddressIoArgModel ioArgModel = new()
|
||||
{
|
||||
Address = deviceVariable.DeviceAddress,
|
||||
Value = para.Value,
|
||||
ValueType = deviceVariable.DataType
|
||||
};
|
||||
var writeResponse = _driver.WriteAsync(e.RequestId, deviceVariable.Method, ioArgModel).Result;
|
||||
rpcResponse.IsSuccess = writeResponse.IsSuccess;
|
||||
if (!writeResponse.IsSuccess)
|
||||
{
|
||||
rpcResponse.Description = writeResponse.Description;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rpcResponse.Description = writeResponse.Description;
|
||||
rpcResponse.IsSuccess = false;
|
||||
rpcResponse.Description = $"未能找到变量:{para.Key}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rpcResponse.IsSuccess = false;
|
||||
rpcResponse.Description = $"未能找到变量:{para.Key}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (RpcConnected)
|
||||
_driver.Close();
|
||||
|
||||
}
|
||||
else//连接失败
|
||||
{
|
||||
rpcResponse.IsSuccess = false;
|
||||
rpcResponse.Description = $"{e.DeviceName} 连接失败";
|
||||
}
|
||||
}
|
||||
else//连接失败
|
||||
{
|
||||
rpcResponse.IsSuccess = false;
|
||||
rpcResponse.Description = $"{e.DeviceName} 连接失败";
|
||||
}
|
||||
|
||||
}
|
||||
//其他RPC TODO
|
||||
else
|
||||
@ -227,12 +240,12 @@ namespace Plugin
|
||||
//纪录入库
|
||||
rpcLog.IsSuccess = rpcResponse.IsSuccess;
|
||||
rpcLog.Description = rpcResponse.Description;
|
||||
rpcLog.EndTime=DateTime.Now;
|
||||
rpcLog.EndTime = DateTime.Now;
|
||||
|
||||
|
||||
using (var DC = new DataContext(IoTBackgroundService.connnectSetting, IoTBackgroundService.DBType))
|
||||
{
|
||||
DC.Set<RpcLog>().Add(rpcLog);
|
||||
DC.Set<RpcLog>().Add(rpcLog);
|
||||
DC.SaveChanges();
|
||||
}
|
||||
}
|
||||
@ -241,6 +254,7 @@ namespace Plugin
|
||||
public void StopThread()
|
||||
{
|
||||
_logger.LogInformation($"线程停止:{_device.DeviceName}");
|
||||
_myMqttClient.DeviceDisconnected(_device.DeviceName);
|
||||
if (task != null)
|
||||
{
|
||||
_myMqttClient.OnExcRpc -= MyMqttClient_OnExcRpc;
|
||||
|
@ -101,21 +101,39 @@ namespace Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private readonly string tbRpcTopic = "v1/gateway/rpc";
|
||||
private void OnConnected()
|
||||
{
|
||||
//v1/gateway/attributes
|
||||
//Message: {"device": "Device A", "data": {"attribute1": "value1", "attribute2": 42}}
|
||||
|
||||
//v1/gateway/rpc
|
||||
//{"device": "Device A", "data": {"id": $request_id, "method": "toggle_gpio", "params": {"pin":1}}}
|
||||
Client.SubscribeAsync(tbRpcTopic, MqttQualityOfServiceLevel.ExactlyOnce);//tb server side rpc
|
||||
Client.SubscribeAsync($"devices/+/rpc/request/+/+", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
Client.SubscribeAsync($"devices/Modbus/attributes/update/", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
Client.SubscribeAsync($"devices/+/attributes/response/+", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
switch (_systemConfig.IoTPlatformType)
|
||||
{
|
||||
case IoTPlatformType.ThingsBoard:
|
||||
//{"device": "Device A", "data": {"id": $request_id, "method": "toggle_gpio", "params": {"pin":1}}}
|
||||
Client.SubscribeAsync(tbRpcTopic, MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
//Message: {"id": $request_id, "device": "Device A", "value": "value1"}
|
||||
Client.SubscribeAsync("v1/gateway/attributes/response", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
//Message: {"device": "Device A", "data": {"attribute1": "value1", "attribute2": 42}}
|
||||
Client.SubscribeAsync("v1/gateway/attributes", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
break;
|
||||
case IoTPlatformType.IoTSharp:
|
||||
Client.SubscribeAsync("devices/+/rpc/response/+/+", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
Client.SubscribeAsync("devices/+/attributes/update", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
//Message: {"device": "Device A", "data": {"attribute1": "value1", "attribute2": 42}}
|
||||
Client.SubscribeAsync("devices/+/attributes/response/+", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
break;
|
||||
case IoTPlatformType.AliCloudIoT:
|
||||
break;
|
||||
case IoTPlatformType.TencentIoTHub:
|
||||
break;
|
||||
case IoTPlatformType.BaiduIoTCore:
|
||||
break;
|
||||
case IoTPlatformType.OneNET:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_logger.LogInformation($"MQTT CONNECTED WITH SERVER ");
|
||||
}
|
||||
|
||||
private readonly string tbRpcTopic = @"v1/gateway/rpc";
|
||||
|
||||
private Task Client_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
|
||||
{
|
||||
@ -299,18 +317,47 @@ namespace Plugin
|
||||
|
||||
}
|
||||
|
||||
public Task RequestAttributes(string _device, bool anySide, params string[] args)
|
||||
public Task RequestAttributes(string _devicename, bool anySide, params string[] args)
|
||||
{
|
||||
//Topic: v1/gateway/attributes/request
|
||||
// Message: { "id": $request_id, "device": "Device A", "client": true, "key": "attribute1"}
|
||||
//Topic: v1/gateway/attributes/response
|
||||
//Message: {"id": $request_id, "device": "Device A", "value": "value1"}
|
||||
string id = Guid.NewGuid().ToString();
|
||||
string topic = $"devices/{_device}/attributes/request/{id}";
|
||||
Dictionary<string, string> keys = new Dictionary<string, string>();
|
||||
keys.Add(anySide ? "anySide" : "server", string.Join(",", args));
|
||||
Client.SubscribeAsync($"devices/{_device}/attributes/response/{id}", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
return Client.PublishAsync(topic, Newtonsoft.Json.JsonConvert.SerializeObject(keys), MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
try
|
||||
{
|
||||
string id = Guid.NewGuid().ToString();
|
||||
switch (_systemConfig.IoTPlatformType)
|
||||
{
|
||||
case IoTPlatformType.ThingsBoard:
|
||||
//{"id": $request_id, "device": "Device A", "client": true, "key": "attribute1"}
|
||||
Dictionary<string, object> tbRequestData = new Dictionary<string, object>
|
||||
{
|
||||
{ "id",id},
|
||||
{ "device",_devicename},
|
||||
{ "client",true},
|
||||
{ "key",args[0]}
|
||||
};
|
||||
return Client.PublishAsync("v1/gateway/attributes/request", JsonConvert.SerializeObject(tbRequestData), MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
case IoTPlatformType.IoTSharp:
|
||||
string topic = $"devices/{_devicename}/attributes/request/{id}";
|
||||
Dictionary<string, string> keys = new Dictionary<string, string>();
|
||||
keys.Add(anySide ? "anySide" : "server", string.Join(",", args));
|
||||
Client.SubscribeAsync($"devices/{_devicename}/attributes/response/{id}", MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
return Client.PublishAsync(topic, JsonConvert.SerializeObject(keys), MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
case IoTPlatformType.AliCloudIoT:
|
||||
break;
|
||||
case IoTPlatformType.TencentIoTHub:
|
||||
break;
|
||||
case IoTPlatformType.BaiduIoTCore:
|
||||
break;
|
||||
case IoTPlatformType.OneNET:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
_logger.LogError($"RequestAttributes:{_devicename}", ex);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void PublishTelemetry(Device device, Dictionary<string, List<PayLoad>> SendModel)
|
||||
@ -353,16 +400,60 @@ namespace Plugin
|
||||
|
||||
}
|
||||
|
||||
public void DeviceConnected()
|
||||
public async Task DeviceConnected(string DeviceName)
|
||||
{
|
||||
//Topic: v1/gateway/connect
|
||||
//Message: { "device":"Device A"}
|
||||
try
|
||||
{
|
||||
switch (_systemConfig.IoTPlatformType)
|
||||
{
|
||||
case IoTPlatformType.ThingsBoard:
|
||||
case IoTPlatformType.IoTSharp:
|
||||
await Client.PublishAsync("v1/gateway/connect", JsonConvert.SerializeObject(new Dictionary<string, string> { { "device", DeviceName } }));
|
||||
break;
|
||||
case IoTPlatformType.AliCloudIoT:
|
||||
break;
|
||||
case IoTPlatformType.TencentIoTHub:
|
||||
break;
|
||||
case IoTPlatformType.BaiduIoTCore:
|
||||
break;
|
||||
case IoTPlatformType.OneNET:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"DeviceConnected:{DeviceName}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeviceDisconnected()
|
||||
public async Task DeviceDisconnected(string DeviceName)
|
||||
{
|
||||
//Topic: v1/gateway/connect
|
||||
//Message: { "device":"Device A"}
|
||||
try
|
||||
{
|
||||
switch (_systemConfig.IoTPlatformType)
|
||||
{
|
||||
case IoTPlatformType.ThingsBoard:
|
||||
case IoTPlatformType.IoTSharp:
|
||||
await Client.PublishAsync("v1/gateway/disconnect", JsonConvert.SerializeObject(new Dictionary<string, string> { { "device", DeviceName } }));
|
||||
break;
|
||||
case IoTPlatformType.AliCloudIoT:
|
||||
break;
|
||||
case IoTPlatformType.TencentIoTHub:
|
||||
break;
|
||||
case IoTPlatformType.BaiduIoTCore:
|
||||
break;
|
||||
case IoTPlatformType.OneNET:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"DeviceDisconnected:{DeviceName}", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
BIN
iotgateway.db
BIN
iotgateway.db
Binary file not shown.
Loading…
Reference in New Issue
Block a user