优化rpc;设备在线、离线状态上传

This commit is contained in:
dd 2022-04-15 16:49:58 +08:00
parent ca6f298bf2
commit c916cf1a04
14 changed files with 334 additions and 251 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -11,5 +11,5 @@
<wt:combobox field="Searcher.IsSuccess" empty-text="@Localizer["Sys.All"]" /> <wt:combobox field="Searcher.IsSuccess" empty-text="@Localizer["Sys.All"]" />
</wt:row> </wt:row>
</wt:searchpanel> </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" /> <wt:grid vm="@Model" url="/Rpc/RpcLog/Search" hidden-checkbox="true" hidden-grid-index="true" />

View File

@ -69,7 +69,7 @@
<span class="login-error">@Model.MSD.GetFirstError()</span> <span class="login-error">@Model.MSD.GetFirstError()</span>
<button type="submit" class="login-button" style="cursor:pointer">@Model.Localizer["Login.Login"]</button> <button type="submit" class="login-button" style="cursor:pointer">@Model.Localizer["Login.Login"]</button>
<div class="login-button" style="cursor:pointer"> <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> </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"]" />*@ @*<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.

View File

@ -21,7 +21,6 @@ namespace DriverModbusMaster
private SerialPort port = null; private SerialPort port = null;
private Modbus.Device.ModbusMaster master = null; private Modbus.Device.ModbusMaster master = null;
private SerialPortAdapter adapter = null; private SerialPortAdapter adapter = null;
private object locker=new object();
#region #region
[ConfigParameter("设备Id")] [ConfigParameter("设备Id")]
@ -199,135 +198,119 @@ namespace DriverModbusMaster
[Method("功能码:03", description: "ReadHoldingRegisters读保持寄存器")] [Method("功能码:03", description: "ReadHoldingRegisters读保持寄存器")]
public DriverReturnValueModel ReadHoldingRegisters(DriverAddressIoArgModel ioarg) public DriverReturnValueModel ReadHoldingRegisters(DriverAddressIoArgModel ioarg)
{ {
lock (locker) DriverReturnValueModel ret = new();
try
{ {
DriverReturnValueModel ret = new(); if (IsConnected)
try ret = ReadRegistersBuffers(3, ioarg);
else
{ {
if (IsConnected) ret.StatusType = VaribaleStatusTypeEnum.Bad;
ret = ReadRegistersBuffers(3, ioarg); ret.Message = "TCP连接异常";
else
{
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读输入寄存器")] [Method("功能码:04", description: "ReadHoldingRegisters读输入寄存器")]
public DriverReturnValueModel ReadInputRegisters(DriverAddressIoArgModel ioarg) public DriverReturnValueModel ReadInputRegisters(DriverAddressIoArgModel ioarg)
{ {
lock (locker) DriverReturnValueModel ret = new();
try
{ {
DriverReturnValueModel ret = new(); if (IsConnected)
try ret = ReadRegistersBuffers(4, ioarg);
else
{ {
if (IsConnected) ret.StatusType = VaribaleStatusTypeEnum.Bad;
ret = ReadRegistersBuffers(4, ioarg); ret.Message = "TCP连接异常";
else
{
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读线圈")] [Method("功能码:01", description: "ReadCoil读线圈")]
public DriverReturnValueModel ReadCoil(DriverAddressIoArgModel ioarg) public DriverReturnValueModel ReadCoil(DriverAddressIoArgModel ioarg)
{ {
lock (locker) DriverReturnValueModel ret = new();
try
{ {
DriverReturnValueModel ret = new(); if (IsConnected)
try
{ {
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 (retBool)
if (ioarg.ValueType == DataTypeEnum.Bit) ret.Value = 1;
{
if (retBool)
ret.Value = 1;
else
ret.Value = 0;
}
else else
ret.Value = retBool; ret.Value = 0;
ret.StatusType = VaribaleStatusTypeEnum.Good;
} }
else else
{ ret.Value = retBool;
ret.StatusType = VaribaleStatusTypeEnum.Bad; ret.StatusType = VaribaleStatusTypeEnum.Good;
ret.Message = "TCP连接异常";
}
} }
catch (Exception ex) else
{ {
ret.StatusType = VaribaleStatusTypeEnum.UnKnow; ret.StatusType = VaribaleStatusTypeEnum.Bad;
ret.Message = ex.Message; ret.Message = "TCP连接异常";
} }
return ret;
} }
catch (Exception ex)
{
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
ret.Message = ex.Message;
}
return ret;
} }
[Method("功能码:02", description: "ReadInput读输入")] [Method("功能码:02", description: "ReadInput读输入")]
public DriverReturnValueModel ReadInput(DriverAddressIoArgModel ioarg) public DriverReturnValueModel ReadInput(DriverAddressIoArgModel ioarg)
{ {
lock (locker) DriverReturnValueModel ret = new();
try
{ {
DriverReturnValueModel ret = new(); if (IsConnected)
try
{ {
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 (retBool)
if (ioarg.ValueType == DataTypeEnum.Bit) ret.Value = 1;
{
if (retBool)
ret.Value = 1;
else
ret.Value = 0;
}
else else
ret.Value = retBool; ret.Value = 0;
ret.StatusType = VaribaleStatusTypeEnum.Good;
} }
else else
{ ret.Value = retBool;
ret.StatusType = VaribaleStatusTypeEnum.Bad; ret.StatusType = VaribaleStatusTypeEnum.Good;
ret.Message = "TCP连接异常";
}
} }
catch (Exception ex) else
{ {
ret.StatusType = VaribaleStatusTypeEnum.UnKnow; ret.StatusType = VaribaleStatusTypeEnum.Bad;
ret.Message = ex.Message; 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) public async Task<RpcResponse> WriteAsync(string RequestId, string Method, DriverAddressIoArgModel Ioarg)
{ {
lock (locker) RpcResponse rpcResponse = new() { IsSuccess = false };
try
{ {
RpcResponse rpcResponse = new() { IsSuccess = false }; ushort address = ushort.Parse(Ioarg.Address);
try if (!IsConnected)
rpcResponse.Description = "设备连接已断开";
else
{ {
ushort address = ushort.Parse(Ioarg.Address); //功能码01
if (!IsConnected) if (Method == nameof(ReadCoil))
rpcResponse.Description = "设备连接已断开";
else
{ {
//功能码01 bool value = Ioarg.Value.ToString() == "1" || Ioarg.Value.ToString().ToLower() == "true";
if (Method == nameof(ReadCoil)) master.WriteSingleCoilAsync(SlaveAddress, address, value);
{ rpcResponse.IsSuccess = true;
bool value = Ioarg.Value.ToString() == "1" || Ioarg.Value.ToString().ToLower() == "true"; return rpcResponse;
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}";
} }
//功能码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 public enum PLC_TYPE

View File

@ -37,7 +37,6 @@ namespace Plugin
_DrvierManager = drvierManager; _DrvierManager = drvierManager;
_MyMqttClient = myMqttClient; _MyMqttClient = myMqttClient;
_MqttServer = mqttServer; _MqttServer = mqttServer;
try try
{ {
using (var DC = new DataContext(connnectSetting, DBType)) using (var DC = new DataContext(connnectSetting, DBType))

View File

@ -1,19 +1,11 @@
using Microsoft.EntityFrameworkCore; using PluginInterface;
using PluginInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using IoTGateway.DataAccess; using IoTGateway.DataAccess;
using IoTGateway.Model; using IoTGateway.Model;
using WalkingTec.Mvvm.Core;
using DynamicExpresso; using DynamicExpresso;
using MQTTnet.Server; using MQTTnet.Server;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PluginInterface.IoTSharp;
namespace Plugin namespace Plugin
{ {
@ -29,7 +21,8 @@ namespace Plugin
private DateTime TsStartDt = new DateTime(1970, 1, 1); private DateTime TsStartDt = new DateTime(1970, 1, 1);
private CancellationTokenSource tokenSource = new CancellationTokenSource(); private CancellationTokenSource tokenSource = new CancellationTokenSource();
private Interpreter Interpreter = null; 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) public DeviceThread(Device device, IDriver driver, string ProjectId, MyMqttClient myMqttClient, Interpreter interpreter, IMqttServer mqttServer, ILogger logger)
{ {
_myMqttClient = myMqttClient; _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)); myMqttClient.UploadAttributeAsync(device.DeviceName, device.DeviceConfigs.Where(x => x.DataSide == DataSide.ClientSide).ToDictionary(x => x.DeviceConfigName, x => x.Value));
task = Task.Run(() => task = Task.Run(() =>
{ {
while (true) Thread.Sleep(5000);
while (true)
{ {
if (tokenSource.IsCancellationRequested) if (tokenSource.IsCancellationRequested)
{ {
@ -67,92 +61,103 @@ namespace Plugin
return; return;
} }
try lock (_lock)
{ {
Dictionary<string, List<PayLoad>> sendModel = new() { { _device.DeviceName, new() } }; try
var payLoad = new PayLoad() { Values = new() };
if (driver.IsConnected)
{ {
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(); foreach (var item in _device.DeviceVariables)
var ioarg = new DriverAddressIoArgModel
{ {
ID = item.ID, var ret = new DriverReturnValueModel();
Address = item.DeviceAddress, var ioarg = new DriverAddressIoArgModel
ValueType = item.DataType {
}; ID = item.ID,
var method = Methods.Where(x => x.Name == item.Method).FirstOrDefault(); Address = item.DeviceAddress,
if (method == null) ValueType = item.DataType
ret.StatusType = VaribaleStatusTypeEnum.MethodError; };
else var method = Methods.Where(x => x.Name == item.Method).FirstOrDefault();
ret = (DriverReturnValueModel)method.Invoke(_driver, new object[1] { ioarg }); 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 payLoad.Values = null;
{ payLoad.DeviceStatus = DeviceStatusTypeEnum.Bad;
ret.CookedValue = interpreter.Eval(DealMysqlStr(item.Expressions).Replace("raw", ret.Value?.ToString()));
}
catch (Exception)
{
ret.StatusType = VaribaleStatusTypeEnum.ExpressionError;
}
} }
else 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())
{ {
//这是设备变量列表要用的 payLoad.DeviceStatus = DeviceStatusTypeEnum.Good;
mqttServer.PublishAsync($"internal/v1/gateway/telemetry/{_device.DeviceName}/{item.Name}", JsonConvert.SerializeObject(ret)); sendModel[_device.DeviceName] = new List<PayLoad> { payLoad };
//这是在线组态要用的 myMqttClient.PublishTelemetry(_device, sendModel);
mqttServer.PublishAsync($"v1/gateway/telemetry/{_device.DeviceName}/{item.Name}", JsonConvert.SerializeObject(ret.CookedValue));
} }
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; lastConnected = false;
payLoad.DeviceStatus = DeviceStatusTypeEnum.Bad; _myMqttClient.DeviceDisconnected(_device.DeviceName);
}
else
{
payLoad.DeviceStatus = DeviceStatusTypeEnum.Good;
sendModel[_device.DeviceName] = new List<PayLoad> { payLoad };
myMqttClient.PublishTelemetry(_device, sendModel);
} }
} }
} }
else catch (Exception ex)
{ {
driver.Connect(); _logger.LogError($"线程循环异常,{_device.DeviceName}", ex);
} }
} }
catch (Exception ex)
{
_logger.LogError($"线程循环异常,{_device.DeviceName}", ex);
}
Thread.Sleep((int)_driver.MinPeriod); Thread.Sleep((int)_driver.MinPeriod);
} }
}); });
} }
else
_myMqttClient.DeviceDisconnected(_device.DeviceName);
} }
private void MyMqttClient_OnExcRpc(object? sender, RpcRequest e) private void MyMqttClient_OnExcRpc(object? sender, RpcRequest e)
@ -173,47 +178,55 @@ namespace Plugin
//执行写入变量RPC //执行写入变量RPC
if (e.Method.ToLower() == "write") if (e.Method.ToLower() == "write")
{ {
//没连接就连接 lock (_lock)
if (!_driver.IsConnected)
_driver.Connect();
//连接成功就尝试一个一个的写入,注意:目前写入地址和读取地址是相同的对于PLC来说没问题其他的要自己改........
if (_driver.IsConnected)
{ {
foreach (var para in e.Params) bool RpcConnected = false;
//没连接就连接
if (!_driver.IsConnected)
if (_driver.Connect())
RpcConnected = true;
//连接成功就尝试一个一个的写入,注意:目前写入地址和读取地址是相同的对于PLC来说没问题其他的要自己改........
if (_driver.IsConnected)
{ {
//先查配置项,要用到配置的地址、数据类型、方法(方法最主要是用于区分写入数据的辅助判断比如modbus不同的功能码) foreach (var para in e.Params)
var deviceVariable = _device.DeviceVariables.Where(x => x.Name == para.Key).FirstOrDefault();
if (deviceVariable != null)
{ {
DriverAddressIoArgModel ioArgModel = new() //先查配置项,要用到配置的地址、数据类型、方法(方法最主要是用于区分写入数据的辅助判断比如modbus不同的功能码)
var deviceVariable = _device.DeviceVariables.Where(x => x.Name == para.Key).FirstOrDefault();
if (deviceVariable != null)
{ {
Address = deviceVariable.DeviceAddress, DriverAddressIoArgModel ioArgModel = new()
Value = para.Value, {
ValueType = deviceVariable.DataType Address = deviceVariable.DeviceAddress,
}; Value = para.Value,
var writeResponse = _driver.WriteAsync(e.RequestId, deviceVariable.Method, ioArgModel).Result; ValueType = deviceVariable.DataType
rpcResponse.IsSuccess = writeResponse.IsSuccess; };
if (!writeResponse.IsSuccess) 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; break;
} }
} }
else if (RpcConnected)
{ _driver.Close();
rpcResponse.IsSuccess = false;
rpcResponse.Description = $"未能找到变量:{para.Key}";
break;
}
}
}
else//连接失败
{
rpcResponse.IsSuccess = false;
rpcResponse.Description = $"{e.DeviceName} 连接失败";
}
} }
else//连接失败
{
rpcResponse.IsSuccess = false;
rpcResponse.Description = $"{e.DeviceName} 连接失败";
}
} }
//其他RPC TODO //其他RPC TODO
else else
@ -227,7 +240,7 @@ namespace Plugin
//纪录入库 //纪录入库
rpcLog.IsSuccess = rpcResponse.IsSuccess; rpcLog.IsSuccess = rpcResponse.IsSuccess;
rpcLog.Description = rpcResponse.Description; rpcLog.Description = rpcResponse.Description;
rpcLog.EndTime=DateTime.Now; rpcLog.EndTime = DateTime.Now;
using (var DC = new DataContext(IoTBackgroundService.connnectSetting, IoTBackgroundService.DBType)) using (var DC = new DataContext(IoTBackgroundService.connnectSetting, IoTBackgroundService.DBType))
@ -241,6 +254,7 @@ namespace Plugin
public void StopThread() public void StopThread()
{ {
_logger.LogInformation($"线程停止:{_device.DeviceName}"); _logger.LogInformation($"线程停止:{_device.DeviceName}");
_myMqttClient.DeviceDisconnected(_device.DeviceName);
if (task != null) if (task != null)
{ {
_myMqttClient.OnExcRpc -= MyMqttClient_OnExcRpc; _myMqttClient.OnExcRpc -= MyMqttClient_OnExcRpc;

View File

@ -101,21 +101,39 @@ namespace Plugin
} }
} }
private readonly string tbRpcTopic = "v1/gateway/rpc";
private void OnConnected() private void OnConnected()
{ {
//v1/gateway/attributes switch (_systemConfig.IoTPlatformType)
//Message: {"device": "Device A", "data": {"attribute1": "value1", "attribute2": 42}} {
case IoTPlatformType.ThingsBoard:
//v1/gateway/rpc //{"device": "Device A", "data": {"id": $request_id, "method": "toggle_gpio", "params": {"pin":1}}}
//{"device": "Device A", "data": {"id": $request_id, "method": "toggle_gpio", "params": {"pin":1}}} Client.SubscribeAsync(tbRpcTopic, MqttQualityOfServiceLevel.ExactlyOnce);
Client.SubscribeAsync(tbRpcTopic, MqttQualityOfServiceLevel.ExactlyOnce);//tb server side rpc //Message: {"id": $request_id, "device": "Device A", "value": "value1"}
Client.SubscribeAsync($"devices/+/rpc/request/+/+", MqttQualityOfServiceLevel.ExactlyOnce); Client.SubscribeAsync("v1/gateway/attributes/response", MqttQualityOfServiceLevel.ExactlyOnce);
Client.SubscribeAsync($"devices/Modbus/attributes/update/", MqttQualityOfServiceLevel.ExactlyOnce); //Message: {"device": "Device A", "data": {"attribute1": "value1", "attribute2": 42}}
Client.SubscribeAsync($"devices/+/attributes/response/+", MqttQualityOfServiceLevel.ExactlyOnce); 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 "); _logger.LogInformation($"MQTT CONNECTED WITH SERVER ");
} }
private readonly string tbRpcTopic = @"v1/gateway/rpc";
private Task Client_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e) 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 try
// Message: { "id": $request_id, "device": "Device A", "client": true, "key": "attribute1"} {
//Topic: v1/gateway/attributes/response string id = Guid.NewGuid().ToString();
//Message: {"id": $request_id, "device": "Device A", "value": "value1"} switch (_systemConfig.IoTPlatformType)
string id = Guid.NewGuid().ToString(); {
string topic = $"devices/{_device}/attributes/request/{id}"; case IoTPlatformType.ThingsBoard:
Dictionary<string, string> keys = new Dictionary<string, string>(); //{"id": $request_id, "device": "Device A", "client": true, "key": "attribute1"}
keys.Add(anySide ? "anySide" : "server", string.Join(",", args)); Dictionary<string, object> tbRequestData = new Dictionary<string, object>
Client.SubscribeAsync($"devices/{_device}/attributes/response/{id}", MqttQualityOfServiceLevel.ExactlyOnce); {
return Client.PublishAsync(topic, Newtonsoft.Json.JsonConvert.SerializeObject(keys), MqttQualityOfServiceLevel.ExactlyOnce); { "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) 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 try
//Message: { "device":"Device A"} {
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 try
//Message: { "device":"Device A"} {
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.