增加属性上传、整合日志

This commit is contained in:
dd 2022-03-24 21:38:11 +08:00
parent bb28946f19
commit 27c0433458
30 changed files with 1334 additions and 219 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,801 @@
// <auto-generated />
using System;
using IoTGateway.DataAccess;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace IoTGateway.DataAccess.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20220323063908_attribut")]
partial class attribut
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.1");
modelBuilder.Entity("IoTGateway.Model.Device", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<bool>("AutoStart")
.HasColumnType("INTEGER");
b.Property<string>("CreateBy")
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("Description")
.HasColumnType("TEXT");
b.Property<string>("DeviceName")
.HasColumnType("TEXT");
b.Property<int>("DeviceTypeEnum")
.HasColumnType("INTEGER");
b.Property<Guid?>("DriverId")
.HasColumnType("TEXT");
b.Property<uint>("Index")
.HasColumnType("INTEGER");
b.Property<Guid?>("ParentId")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("DriverId");
b.HasIndex("ParentId");
b.ToTable("Devices");
});
modelBuilder.Entity("IoTGateway.Model.DeviceConfig", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<int>("DataSide")
.HasColumnType("INTEGER");
b.Property<string>("Description")
.HasColumnType("TEXT");
b.Property<string>("DeviceConfigName")
.HasColumnType("TEXT");
b.Property<Guid?>("DeviceId")
.HasColumnType("TEXT");
b.Property<string>("EnumInfo")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.Property<string>("Value")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("DeviceId");
b.ToTable("DeviceConfigs");
});
modelBuilder.Entity("IoTGateway.Model.DeviceVariable", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<int>("DataType")
.HasColumnType("INTEGER");
b.Property<string>("Description")
.HasColumnType("TEXT");
b.Property<string>("DeviceAddress")
.HasColumnType("TEXT");
b.Property<Guid?>("DeviceId")
.HasColumnType("TEXT");
b.Property<string>("Expressions")
.HasColumnType("TEXT");
b.Property<string>("Method")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<int>("ProtectType")
.HasColumnType("INTEGER");
b.HasKey("ID");
b.HasIndex("DeviceId");
b.ToTable("DeviceVariables");
});
modelBuilder.Entity("IoTGateway.Model.Driver", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("AssembleName")
.HasColumnType("TEXT");
b.Property<int>("AuthorizesNum")
.HasColumnType("INTEGER");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("DriverName")
.HasColumnType("TEXT");
b.Property<string>("FileName")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("Drivers");
});
modelBuilder.Entity("IoTGateway.Model.SystemConfig", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("GatewayName")
.HasColumnType("TEXT");
b.Property<int>("IoTPlatformType")
.HasColumnType("INTEGER");
b.Property<string>("MqttIp")
.HasColumnType("TEXT");
b.Property<int>("MqttPort")
.HasColumnType("INTEGER");
b.Property<string>("MqttUName")
.HasColumnType("TEXT");
b.Property<string>("MqttUPwd")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("SystemConfig");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.ActionLog", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ActionName")
.HasMaxLength(255)
.HasColumnType("TEXT");
b.Property<DateTime>("ActionTime")
.HasColumnType("TEXT");
b.Property<string>("ActionUrl")
.HasMaxLength(250)
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<double>("Duration")
.HasColumnType("REAL");
b.Property<string>("IP")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("ITCode")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<int>("LogType")
.HasColumnType("INTEGER");
b.Property<string>("ModuleName")
.HasMaxLength(255)
.HasColumnType("TEXT");
b.Property<string>("Remark")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("ActionLogs");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.DataPrivilege", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("Domain")
.HasColumnType("TEXT");
b.Property<string>("GroupCode")
.HasColumnType("TEXT");
b.Property<string>("RelateId")
.HasColumnType("TEXT");
b.Property<string>("TableName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.Property<string>("UserCode")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("DataPrivileges");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FileAttachment", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ExtraInfo")
.HasColumnType("TEXT");
b.Property<byte[]>("FileData")
.HasColumnType("BLOB");
b.Property<string>("FileExt")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("TEXT");
b.Property<string>("FileName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("HandlerInfo")
.HasColumnType("TEXT");
b.Property<long>("Length")
.HasColumnType("INTEGER");
b.Property<string>("Path")
.HasColumnType("TEXT");
b.Property<string>("SaveMode")
.HasColumnType("TEXT");
b.Property<DateTime>("UploadTime")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("FileAttachments");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkGroup", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("GroupCode")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<string>("GroupName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("GroupRemark")
.HasColumnType("TEXT");
b.Property<string>("TenantCode")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("FrameworkGroups");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkMenu", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ActionName")
.HasColumnType("TEXT");
b.Property<string>("ClassName")
.HasColumnType("TEXT");
b.Property<int?>("DisplayOrder")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<string>("Domain")
.HasColumnType("TEXT");
b.Property<bool>("FolderOnly")
.HasColumnType("INTEGER");
b.Property<string>("Icon")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<bool>("IsInherit")
.HasColumnType("INTEGER");
b.Property<bool?>("IsInside")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<bool>("IsPublic")
.HasColumnType("INTEGER");
b.Property<string>("MethodName")
.HasColumnType("TEXT");
b.Property<string>("ModuleName")
.HasColumnType("TEXT");
b.Property<string>("PageName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<Guid?>("ParentId")
.HasColumnType("TEXT");
b.Property<bool>("ShowOnMenu")
.HasColumnType("INTEGER");
b.Property<string>("Url")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("ParentId");
b.ToTable("FrameworkMenus");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkRole", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("RoleCode")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<string>("RoleName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("RoleRemark")
.HasColumnType("TEXT");
b.Property<string>("TenantCode")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("FrameworkRoles");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkUser", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("Address")
.HasMaxLength(200)
.HasColumnType("TEXT");
b.Property<string>("CellPhone")
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("Email")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<int?>("Gender")
.HasColumnType("INTEGER");
b.Property<string>("HomePhone")
.HasMaxLength(30)
.HasColumnType("TEXT");
b.Property<string>("ITCode")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<bool>("IsValid")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("TEXT");
b.Property<Guid?>("PhotoId")
.HasColumnType("TEXT");
b.Property<string>("TenantCode")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.Property<string>("ZipCode")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("PhotoId");
b.ToTable("FrameworkUsers");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkUserGroup", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("GroupCode")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.Property<string>("UserCode")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("FrameworkUserGroups");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkUserRole", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<string>("RoleCode")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.Property<string>("UserCode")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("FrameworkUserRoles");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FunctionPrivilege", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<bool?>("Allowed")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<string>("CreateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<Guid>("MenuItemId")
.HasColumnType("TEXT");
b.Property<string>("RoleCode")
.HasColumnType("TEXT");
b.Property<string>("UpdateBy")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("MenuItemId");
b.ToTable("FunctionPrivileges");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.PersistedGrant", b =>
{
b.Property<Guid>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTime>("CreationTime")
.HasColumnType("TEXT");
b.Property<DateTime>("Expiration")
.HasColumnType("TEXT");
b.Property<string>("RefreshToken")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("UserCode")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("PersistedGrants");
});
modelBuilder.Entity("IoTGateway.Model.Device", b =>
{
b.HasOne("IoTGateway.Model.Driver", "Driver")
.WithMany()
.HasForeignKey("DriverId");
b.HasOne("IoTGateway.Model.Device", "Parent")
.WithMany("Children")
.HasForeignKey("ParentId");
b.Navigation("Driver");
b.Navigation("Parent");
});
modelBuilder.Entity("IoTGateway.Model.DeviceConfig", b =>
{
b.HasOne("IoTGateway.Model.Device", "Device")
.WithMany("DeviceConfigs")
.HasForeignKey("DeviceId");
b.Navigation("Device");
});
modelBuilder.Entity("IoTGateway.Model.DeviceVariable", b =>
{
b.HasOne("IoTGateway.Model.Device", "Device")
.WithMany("DeviceVariables")
.HasForeignKey("DeviceId");
b.Navigation("Device");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkMenu", b =>
{
b.HasOne("WalkingTec.Mvvm.Core.FrameworkMenu", "Parent")
.WithMany("Children")
.HasForeignKey("ParentId");
b.Navigation("Parent");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkUser", b =>
{
b.HasOne("WalkingTec.Mvvm.Core.FileAttachment", "Photo")
.WithMany()
.HasForeignKey("PhotoId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Photo");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FunctionPrivilege", b =>
{
b.HasOne("WalkingTec.Mvvm.Core.FrameworkMenu", "MenuItem")
.WithMany("Privileges")
.HasForeignKey("MenuItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("MenuItem");
});
modelBuilder.Entity("IoTGateway.Model.Device", b =>
{
b.Navigation("Children");
b.Navigation("DeviceConfigs");
b.Navigation("DeviceVariables");
});
modelBuilder.Entity("WalkingTec.Mvvm.Core.FrameworkMenu", b =>
{
b.Navigation("Children");
b.Navigation("Privileges");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IoTGateway.DataAccess.Migrations
{
public partial class attribut : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "DataSide",
table: "DeviceConfigs",
type: "INTEGER",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DataSide",
table: "DeviceConfigs");
}
}
}

View File

@ -78,6 +78,9 @@ namespace IoTGateway.DataAccess.Migrations
b.Property<DateTime?>("CreateTime")
.HasColumnType("TEXT");
b.Property<int>("DataSide")
.HasColumnType("INTEGER");
b.Property<string>("Description")
.HasColumnType("TEXT");

View File

@ -17,4 +17,11 @@ namespace IoTGateway.Model
[Display(Name = "读写")]
ReadAndWrite = 1
}
public enum DataSide
{
AnySide=0,
//ServerSide=1,
ClientSide=2,
}
}

View File

@ -8,6 +8,8 @@ namespace IoTGateway.Model
{
[Display(Name = "名称")]
public string DeviceConfigName { get; set; }
[Display(Name = "属性侧")]
public DataSide DataSide { get; set; }
[Display(Name = "描述")]
public string Description { get; set; }
[Display(Name = "值")]

View File

@ -51,6 +51,7 @@ namespace IoTGateway.ViewModel.BasicData.DeviceConfigVMs
{
return new List<GridColumn<DeviceConfig_View>>{
this.MakeGridHeader(x => x.DeviceConfigName).SetWidth(100),
this.MakeGridHeader(x => x.DataSide).SetWidth(100),
this.MakeGridHeader(x => x.Description).SetWidth(100),
this.MakeGridHeader(x => x.Value).SetWidth(100),
this.MakeGridHeader(x => x.DeviceName_view).SetWidth(100),
@ -62,25 +63,28 @@ namespace IoTGateway.ViewModel.BasicData.DeviceConfigVMs
public override IOrderedQueryable<DeviceConfig_View> GetSearchQuery()
{
var query = DC.Set<DeviceConfig>()
.CheckContain(Searcher.DeviceConfigName, x=>x.DeviceConfigName)
.CheckContain(Searcher.Value, x=>x.Value)
.CheckEqual(Searcher.DeviceId, x=>x.DeviceId)
.CheckContain(Searcher.DeviceConfigName, x => x.DeviceConfigName)
.CheckContain(Searcher.Value, x => x.Value)
.CheckEqual(Searcher.DeviceId, x => x.DeviceId)
.CheckEqual(Searcher.DataSide, x => x.DataSide)
.Select(x => new DeviceConfig_View
{
ID = x.ID,
ID = x.ID,
DeviceConfigName = x.DeviceConfigName,
DataSide = x.DataSide,
Description = x.Description,
Value = x.Value,
EnumInfo = x.EnumInfo,
DeviceName_view = x.Device.DeviceName,
})
.OrderBy(x => x.DeviceName_view).ThenBy(x=>x.DeviceConfigName);
.OrderBy(x => x.DeviceName_view).ThenBy(x => x.DeviceConfigName);
return query;
}
}
public class DeviceConfig_View : DeviceConfig{
public class DeviceConfig_View : DeviceConfig
{
[Display(Name = "设备名")]
public String DeviceName_view { get; set; }

View File

@ -14,6 +14,8 @@ namespace IoTGateway.ViewModel.BasicData.DeviceConfigVMs
{
[Display(Name = "名称")]
public String DeviceConfigName { get; set; }
[Display(Name = "属性侧")]
public DataSide? DataSide { get; set; }
[Display(Name = "值")]
public String Value { get; set; }
public List<ComboSelectListItem> AllDevices { get; set; }

View File

@ -0,0 +1,56 @@
using Microsoft.EntityFrameworkCore;
using Plugin;
using System;
using System.Collections.Generic;
using System.Linq;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using IoTGateway.Model;
namespace IoTGateway.ViewModel.BasicData.DeviceVMs
{
public class AttributeVM : BaseVM
{
public string { get; set; }
public string { get; set; }
public void Request()
{
using (var transaction = DC.BeginTransaction())
{
try
{
var device = DC.Set<Device>().Where(x => x.ID == Guid.Parse(FC["id"].ToString())).Include(x => x.Parent).Include(x=>x.DeviceConfigs).Include(x => x.Driver).FirstOrDefault();
if (device == null)
= "复制失败,找不到设备";
else
{
var myMqttClient = Wtm.ServiceProvider.GetService(typeof(MyMqttClient)) as MyMqttClient;
myMqttClient.RequestAttributes(device.DeviceName, true, device.DeviceConfigs.Where(x => x.DataSide == DataSide.AnySide).Select(x => x.DeviceConfigName).ToArray());
}
DC.SaveChanges();
transaction.Commit();
= "请求成功";
var pluginManager = Wtm.ServiceProvider.GetService(typeof(DeviceService)) as DeviceService;
pluginManager?.UpdateDevice(device);
}
catch (Exception ex)
{
transaction.Rollback();
= $"请求超时,{ex}";
}
}
}
protected override void InitVM()
{
var device = DC.Set<Device>().AsNoTracking().Include(x => x.Parent).Where(x => x.ID == Guid.Parse(FC["id"].ToString())).FirstOrDefault();
= $"{device?.Parent?.DeviceName}===>{device?.DeviceName}";
base.InitVM();
}
}
}

View File

@ -18,6 +18,7 @@ namespace IoTGateway.ViewModel.BasicData.DeviceVMs
return new List<GridAction>
{
this.MakeAction("Device","Copy","设备复制","设备复制", GridActionParameterTypesEnum.SingleId,"BasicData",600).SetIconCls("layui-icon layui-icon-template-1").SetPromptMessage("你确定复制设备,包括配置参数和变量?").SetDialogTitle("复制设备确认").SetHideOnToolBar(true).SetShowInRow(true).SetBindVisiableColName("copy"),
this.MakeAction("Device","Attribute","请求属性","请求属性", GridActionParameterTypesEnum.SingleId,"BasicData",600).SetIconCls("layui-icon layui-icon-download-circle").SetPromptMessage("你确定请求客户端属性和共享属性吗?").SetDialogTitle("请求属性确认").SetHideOnToolBar(true).SetShowInRow(true).SetBindVisiableColName("attribute"),
this.MakeAction("Device","CreateGroup","创建组","创建组", GridActionParameterTypesEnum.NoId,"BasicData",600).SetIconCls("_wtmicon _wtmicon-zuzhiqunzu").SetDialogTitle("创建组").SetShowInRow(false),
this.MakeStandardAction("Device", GridActionStandardTypesEnum.Create, "创建设备","BasicData", dialogWidth: 800,name:"创建设备").SetIconCls("layui-icon layui-icon-senior"),
this.MakeStandardAction("Device", GridActionStandardTypesEnum.Edit, Localizer["Sys.Edit"], "BasicData", dialogWidth: 800),
@ -45,6 +46,10 @@ namespace IoTGateway.ViewModel.BasicData.DeviceVMs
if(a.DeviceTypeEnum== DeviceTypeEnum.Device)
return "true";
return "false";
}),this.MakeGridHeader(x=>"attribute").SetHide().SetFormat((a,b)=>{
if(a.DeviceTypeEnum== DeviceTypeEnum.Device)
return "true";
return "false";
}),
this.MakeGridHeaderAction(width: 280)
};

View File

@ -44,10 +44,10 @@ namespace IoTGateway.ViewModel.BasicData.DeviceVariableVMs
{
foreach (var item in device.Children)
{
var deviceThread = deviceService.DeviceThreads.Where(x => x.Device.ID.ToString() == (string)item.Value).FirstOrDefault();
var deviceThread = deviceService.DeviceThreads.Where(x => x._device.ID.ToString() == (string)item.Value).FirstOrDefault();
item.Text = item.Text;
item.Icon = deviceThread.Device.AutoStart ? (deviceThread.Driver.IsConnected ? "layui-icon-link" : "layui-icon-unlink") : "layui-icon-pause";
item.Icon = deviceThread._device.AutoStart ? (deviceThread._driver.IsConnected ? "layui-icon-link" : "layui-icon-unlink") : "layui-icon-pause";
item.Expended = true;
}
}
@ -86,7 +86,7 @@ namespace IoTGateway.ViewModel.BasicData.DeviceVariableVMs
var deviceService = Wtm.ServiceProvider.GetService(typeof(DeviceService)) as DeviceService;
foreach (var item in EntityList)
{
var DapThread = deviceService.DeviceThreads.Where(x => x.Device.ID == item.DeviceId).FirstOrDefault();
var DapThread = deviceService.DeviceThreads.Where(x => x._device.ID == item.DeviceId).FirstOrDefault();
if (DapThread?.DeviceValues != null && DapThread.DeviceValues.ContainsKey(item.ID))
{
item.Value = DapThread.DeviceValues[item.ID].Value?.ToString();

View File

@ -32,7 +32,7 @@ namespace IoTGateway.ViewModel.BasicData.DeviceVariableVMs
{
var deviceService = Wtm.ServiceProvider.GetService(typeof(DeviceService)) as DeviceService;
AllMethods = deviceService.GetDriverMethods(Entity.DeviceId);
var DapThread = deviceService.DeviceThreads.Where(x => x.Device.ID == Entity.DeviceId).FirstOrDefault();
var DapThread = deviceService.DeviceThreads.Where(x => x._device.ID == Entity.DeviceId).FirstOrDefault();
}
}

View File

@ -23,8 +23,8 @@ namespace IoTGateway.ViewModel.BasicData.DriverVMs
public override void DoAdd()
{
var drvierService = Wtm.ServiceProvider.GetService(typeof(DrvierService)) as DrvierService;
Entity.AssembleName = drvierService.GetAssembleNameByFileName(Entity.FileName);
var DriverService = Wtm.ServiceProvider.GetService(typeof(DriverService)) as DriverService;
Entity.AssembleName = DriverService.GetAssembleNameByFileName(Entity.FileName);
if (string.IsNullOrEmpty(Entity.AssembleName))
{
MSD.AddModelError("", "程序集获取失败");

View File

@ -78,7 +78,7 @@ namespace IoTGateway.ViewModel.BasicData
case FromVM.Device:
foreach (var deviceId in Ids)
{
var device = DC.Set<Device>().AsNoTracking().Include(x => x.Parent).Where(x => x.ID == deviceId).Include(x => x.DeviceVariables).Include(x => x.Driver).SingleOrDefault();
var device = DC.Set<Device>().AsNoTracking().Include(x => x.Parent).Where(x => x.ID == deviceId).Include(x => x.DeviceVariables).Include(x => x.Driver).Include(x=>x.DeviceConfigs).SingleOrDefault();
if (!devices.Where(x => x.ID == device.ID).Any())
devices.Add(device);
}

View File

@ -30,7 +30,7 @@ namespace IoTGateway.ViewModel.Config.SystemConfigVMs
{
base.DoEdit(updateAllFields);
var myMqttClient = Wtm.ServiceProvider.GetService(typeof(MyMqttClient)) as MyMqttClient;
myMqttClient.InitClient();
myMqttClient.ConnectAsync();
}
public override void DoDelete()

View File

@ -280,7 +280,29 @@ namespace IoTGateway.Controllers
}
#endregion
#region
[ActionDescription("获取属性")]
public ActionResult Attribute()
{
var vm = Wtm.CreateVM<AttributeVM>();
return PartialView(vm);
}
[HttpPost]
[ActionDescription("获取属性")]
public ActionResult Attribute(AttributeVM vm)
{
if (!ModelState.IsValid)
{
return PartialView(vm);
}
else
{
vm.Request();
return FFResult().CloseDialog().RefreshGrid().Alert($"{vm.请求结果}");
}
}
#endregion
public IActionResult GetMethods(Guid? ID)
{
return JsonMore(_DeviceService.GetDriverMethods(ID));

View File

@ -0,0 +1,14 @@
@model IoTGateway.ViewModel.BasicData.DeviceVMs.AttributeVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model" >
<wt:row items-per-row="ItemsPerRowEnum.One">
<wt:quote>@Model.设备名称</wt:quote>
</wt:row>
<wt:row align="AlignEnum.Right">
<wt:submitbutton text="获取属性" />
<wt:closebutton text="取消" />
</wt:row>
</wt:form>

View File

@ -1,10 +1,12 @@
@model IoTGateway.ViewModel.BasicData.DeviceConfigVMs.DeviceConfigVM
@using IoTGateway.Model
@model IoTGateway.ViewModel.BasicData.DeviceConfigVMs.DeviceConfigVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model">
<wt:row items-per-row="ItemsPerRowEnum.Two">
<wt:combobox field="Entity.DeviceId" items="AllDevices"/>
<wt:textbox field="Entity.DeviceConfigName" />
<wt:combobox field="Entity.DataSide" default-value="@DataSide.ClientSide" />
<wt:textbox field="Entity.Description" />
<wt:textbox field="Entity.Value" />
<wt:textbox field="Entity.EnumInfo" />

View File

@ -53,21 +53,21 @@ namespace IoTGateway.Controllers
data.Add(new ChartData
{
Value = _deviceService.DeviceThreads.Where(x => !x.Device.AutoStart).Count(),
Value = _deviceService.DeviceThreads.Where(x => !x._device.AutoStart).Count(),
Category = "停止",
Series = "Device"
});
data.Add(new ChartData
{
Value = _deviceService.DeviceThreads.Where(x => x.Device.AutoStart && x.Driver.IsConnected).Count(),
Value = _deviceService.DeviceThreads.Where(x => x._device.AutoStart && x._driver.IsConnected).Count(),
Category = "运行",
Series = "Device",
});
data.Add(new ChartData
{
Value = _deviceService.DeviceThreads.Where(x => x.Device.AutoStart && !x.Driver.IsConnected).Count(),
Value = _deviceService.DeviceThreads.Where(x => x._device.AutoStart && !x._driver.IsConnected).Count(),
Category = "异常",
Series = "Device"
});
@ -78,18 +78,18 @@ namespace IoTGateway.Controllers
public IActionResult GetDeviceVariableChart()
{
var data = new List<ChartData>();
foreach (var deviceThread in _deviceService.DeviceThreads.OrderBy(x => x.Device.DeviceName))
foreach (var deviceThread in _deviceService.DeviceThreads.OrderBy(x => x._device.DeviceName))
{
data.Add(new ChartData
{
Category = deviceThread.Device.DeviceName,
Category = deviceThread._device.DeviceName,
Value = deviceThread.DeviceValues.Where(x => x.Value.StatusType != VaribaleStatusTypeEnum.Good).Count(),
Series = "Others"
});
data.Add(new ChartData
{
Category = deviceThread.Device.DeviceName,
Category = deviceThread._device.DeviceName,
Value = deviceThread.DeviceValues.Where(x => x.Value.StatusType == VaribaleStatusTypeEnum.Good).Count(),
Series = "Good"
});

View File

@ -46,18 +46,20 @@ namespace IoTGateway
{
options.UseWtmMvcOptions();
})
.AddJsonOptions(options => {
.AddJsonOptions(options =>
{
options.UseWtmJsonOptions();
})
.ConfigureApiBehaviorOptions(options =>
{
options.UseWtmApiOptions();
})
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddWtmDataAnnotationsLocalization(typeof(Program));
services.AddWtmContext(ConfigRoot, (options)=> {
services.AddWtmContext(ConfigRoot, (options) =>
{
options.DataPrivileges = DataPrivilegeSettings();
options.CsSelector = CSSelector;
options.FileSubDirSelector = SubDirSelector;
@ -75,7 +77,7 @@ namespace IoTGateway
services.AddHostedService<IoTBackgroundService>();
services.AddSingleton<DeviceService>();
services.AddSingleton<DrvierService>();
services.AddSingleton<DriverService>();
services.AddSingleton<UAService>();
services.AddSingleton<MyMqttClient>();
services.AddSingleton<ModbusSlaveService>();
@ -137,7 +139,7 @@ namespace IoTGateway
app.UseWtmContext();
}
/// <summary>

View File

@ -3,13 +3,13 @@
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Error"
"Default": "Information"
}
},
"Debug": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Error"
"Default": "Information"
}
},
"WTM": {

Binary file not shown.

View File

@ -16,12 +16,14 @@ using IoTGateway.DataAccess;
using IoTGateway.Model;
using DynamicExpresso;
using MQTTnet.Server;
using Microsoft.Extensions.Logging;
namespace Plugin
{
public class DeviceService : IDisposable
{
public DrvierService _DrvierManager;
private readonly ILogger<DeviceService> _logger;
public DriverService _DrvierManager;
public List<DeviceThread> DeviceThreads = new List<DeviceThread>();
private MyMqttClient _MyMqttClient;
@ -29,9 +31,9 @@ namespace Plugin
private string connnectSetting = IoTBackgroundService.connnectSetting;
private DBTypeEnum DBType = IoTBackgroundService.DBType;
private Interpreter interpreter = new();
public DeviceService(IConfiguration ConfigRoot, DrvierService drvierManager, MyMqttClient myMqttClient, UAService uAService, IMqttServer mqttServer )
public DeviceService(IConfiguration ConfigRoot, DriverService drvierManager, MyMqttClient myMqttClient, UAService uAService, IMqttServer mqttServer, ILogger<DeviceService> logger)
{
_logger = logger;
_DrvierManager = drvierManager;
_MyMqttClient = myMqttClient;
_MqttServer = mqttServer;
@ -41,6 +43,7 @@ namespace Plugin
using (var DC = new DataContext(connnectSetting, DBType))
{
var Devices = DC.Set<Device>().Where(x => x.DeviceTypeEnum == DeviceTypeEnum.Device).Include(x => x.Parent).Include(x => x.Driver).Include(x => x.DeviceConfigs).Include(x => x.DeviceVariables).AsNoTracking().ToList();
_logger.LogInformation($"Loaded Devices Count:{Devices.Count()}");
foreach (var Device in Devices)
{
CreateDeviceThread(Device);
@ -50,6 +53,7 @@ namespace Plugin
catch (Exception ex)
{
_logger.LogError($"LoadDevicesError", ex);
}
}
@ -57,12 +61,14 @@ namespace Plugin
{
try
{
_logger.LogInformation($"UpdateDevice Start:{device.DeviceName}");
RemoveDeviceThread(device);
CreateDeviceThread(device);
_logger.LogInformation($"UpdateDevice End:{device.DeviceName}");
}
catch (Exception ex)
{
Console.WriteLine($"{device.DeviceName},更新失败");
_logger.LogError($"UpdateDevice Error:{device.DeviceName}", ex);
}
}
@ -75,13 +81,12 @@ namespace Plugin
public void CreateDeviceThread(Device Device)
{
using (var DC = new DataContext(connnectSetting, DBType))
try
{
var systemManage = DC.Set<SystemConfig>().FirstOrDefault();
if (systemManage == null)
Console.WriteLine("配置信息错误,无法启动");
else
_logger.LogInformation($"CreateDeviceThread Start:{Device.DeviceName}");
using (var DC = new DataContext(connnectSetting, DBType))
{
var systemManage = DC.Set<SystemConfig>().FirstOrDefault();
var driver = _DrvierManager.DriverInfos.Where(x => x.Type.FullName == Device.Driver.AssembleName).SingleOrDefault();
var settings = DC.Set<DeviceConfig>().Where(x => x.DeviceId == Device.ID).AsNoTracking().ToList();
Type[] types = new Type[1] { typeof(Guid) };
@ -137,10 +142,17 @@ namespace Plugin
p.SetValue(DeviceObj, value);
}
var deviceThread = new DeviceThread(Device, DeviceObj, systemManage.GatewayName, _MyMqttClient, interpreter, _MqttServer);
var deviceThread = new DeviceThread(Device, DeviceObj, systemManage.GatewayName, _MyMqttClient, interpreter, _MqttServer, _logger);
DeviceThreads.Add(deviceThread);
}
_logger.LogInformation($"CreateDeviceThread End:{Device.DeviceName}");
}
catch (Exception ex)
{
_logger.LogInformation($"CreateDeviceThread Error:{Device.DeviceName}", ex);
}
}
@ -155,7 +167,7 @@ namespace Plugin
{
if (Device != null)
{
var DeviceThread = DeviceThreads.Where(x => x.Device.ID == Device.ID).FirstOrDefault();
var DeviceThread = DeviceThreads.Where(x => x._device.ID == Device.ID).FirstOrDefault();
if (DeviceThread != null)
{
DeviceThread.StopThread();
@ -174,21 +186,32 @@ namespace Plugin
public List<ComboSelectListItem> GetDriverMethods(Guid? DeviceId)
{
List<ComboSelectListItem> driverFilesComboSelect = new List<ComboSelectListItem>();
foreach (var method in DeviceThreads.Where(x => x.Device.ID == DeviceId).FirstOrDefault()?.Methods)
try
{
var Attribute = method.CustomAttributes.ToList().FirstOrDefault().ConstructorArguments;
var item = new ComboSelectListItem
_logger.LogInformation($"GetDriverMethods Start:{DeviceId}");
foreach (var method in DeviceThreads.Where(x => x._device.ID == DeviceId).FirstOrDefault()?.Methods)
{
Text = method.Name,
Value = method.Name,
};
driverFilesComboSelect.Add(item);
var Attribute = method.CustomAttributes.ToList().FirstOrDefault().ConstructorArguments;
var item = new ComboSelectListItem
{
Text = method.Name,
Value = method.Name,
};
driverFilesComboSelect.Add(item);
}
_logger.LogInformation($"GetDriverMethods End:{DeviceId}");
}
catch (Exception ex)
{
_logger.LogInformation($"GetDriverMethods Error:{DeviceId}");
}
return driverFilesComboSelect;
}
public void Dispose()
{
int t = 0;
_logger.LogInformation("Dispose");
}
public Task StartAsync(CancellationToken cancellationToken)

View File

@ -12,13 +12,15 @@ using WalkingTec.Mvvm.Core;
using DynamicExpresso;
using MQTTnet.Server;
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;
namespace Plugin
{
public class DeviceThread : IDisposable
{
public Device Device { get; set; }
public IDriver Driver { get; set; }
private readonly ILogger _logger;
public readonly Device _device;
public readonly IDriver _driver;
public Dictionary<Guid, DriverReturnValueModel> DeviceValues { get; set; } = new();
internal List<MethodInfo> Methods { get; set; }
private Task task { get; set; } = null;
@ -26,140 +28,141 @@ namespace Plugin
private CancellationTokenSource tokenSource = new CancellationTokenSource();
private Interpreter Interpreter = null;
public DeviceThread(Device device, IDriver driver, string ProjectId, MyMqttClient myMqttClient, Interpreter interpreter, IMqttServer mqttServer)
public DeviceThread(Device device, IDriver driver, string ProjectId, MyMqttClient myMqttClient, Interpreter interpreter, IMqttServer mqttServer, ILogger logger)
{
Device = device;
Driver = driver;
_device = device;
_driver = driver;
Interpreter = interpreter;
Methods = Driver.GetType().GetMethods().Where(x => x.GetCustomAttribute(typeof(MethodAttribute)) != null).ToList();
if (Device.AutoStart)
_logger = logger;
Methods = _driver.GetType().GetMethods().Where(x => x.GetCustomAttribute(typeof(MethodAttribute)) != null).ToList();
if (_device.AutoStart)
{
Console.WriteLine($"采集线程已启动:{Device.DeviceName}");
_logger.LogInformation($"线程已启动:{_device.DeviceName}");
using (var DC = new DataContext(IoTBackgroundService.connnectSetting, IoTBackgroundService.DBType))
{
if (Device.DeviceVariables != null)
if (_device.DeviceVariables != null)
{
foreach (var item in Device.DeviceVariables)
foreach (var item in _device.DeviceVariables)
{
DeviceValues[item.ID] = new() { StatusType = VaribaleStatusTypeEnum.Bad };
}
}
}
myMqttClient.UploadAttributeAsync(device.DeviceName, device.DeviceConfigs.Where(x => x.DataSide == DataSide.ClientSide).ToDictionary(x => x.DeviceConfigName, x => x.Value));
task = Task.Run(() =>
{
while (true)
{
if (tokenSource.IsCancellationRequested)
{
Console.WriteLine($"{Device.DeviceName},停止线程");
return;
}
{
while (true)
{
if (tokenSource.IsCancellationRequested)
{
_logger.LogInformation($"停止线程:{_device.DeviceName}");
return;
}
try
{
Dictionary<string, List<PayLoad>> sendModel = new() { { Device.DeviceName, new() } };
try
{
Dictionary<string, List<PayLoad>> sendModel = new() { { _device.DeviceName, new() } };
var payLoad = new PayLoad() { Values = new() };
if (false)//Device.DeviceConfigs != null 配置数据先不上传
foreach (var DeviceConfig in Device.DeviceConfigs)
payLoad.Values[DeviceConfig.DeviceConfigName] = DeviceConfig.Value;
var payLoad = new PayLoad() { Values = new() };
if (driver.IsConnected)
{
if (Device.DeviceVariables != null)
{
foreach (var item in Device.DeviceVariables)
{
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 (driver.IsConnected)
{
if (_device.DeviceVariables != null)
{
foreach (var item in _device.DeviceVariables)
{
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()))
{
try
{
ret.CookedValue = interpreter.Eval(DealMysqlStr(item.Expressions).Replace("raw", ret.Value?.ToString()));
}
catch (Exception)
{
ret.StatusType = VaribaleStatusTypeEnum.ExpressionError;
}
}
else
ret.CookedValue = ret.Value;
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;
payLoad.Values[item.Name] = ret.CookedValue;
ret.VarId = item.ID;
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));
}
//变化了才推送到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;
DeviceValues[item.ID] = ret;
}
payLoad.TS = (long)(DateTime.Now - TsStartDt).TotalMilliseconds;
}
payLoad.TS = (long)(DateTime.Now - TsStartDt).TotalMilliseconds;
if (DeviceValues.Any(x => x.Value.Value ==null))
{
payLoad.Values = null;
payLoad.DeviceStatus = DeviceStatusTypeEnum.Bad;
}
else
{
payLoad.DeviceStatus = DeviceStatusTypeEnum.Good;
sendModel[Device.DeviceName] = new List<PayLoad> { payLoad };
myMqttClient.Publish(Device,sendModel);
}
}
if (DeviceValues.Any(x => x.Value.Value == null))
{
payLoad.Values = null;
payLoad.DeviceStatus = DeviceStatusTypeEnum.Bad;
}
else
{
payLoad.DeviceStatus = DeviceStatusTypeEnum.Good;
sendModel[_device.DeviceName] = new List<PayLoad> { payLoad };
myMqttClient.PublishTelemetry(_device, sendModel);
}
}
}
else
{
driver.Connect();
}
}
catch (Exception ex)
{
Console.WriteLine($"线程循环异常,{Device.DeviceName},{ex}");
}
}
else
{
driver.Connect();
}
}
catch (Exception ex)
{
_logger.LogError($"线程循环异常,{_device.DeviceName}", ex);
}
Thread.Sleep((int)Driver.MinPeriod);
}
});
Thread.Sleep((int)_driver.MinPeriod);
}
});
}
}
public void StopThread()
{
_logger.LogInformation($"线程停止:{_device.DeviceName}");
if (task != null)
{
Driver.Close();
_driver.Close();
tokenSource.Cancel();
}
}
public void Dispose()
{
Driver.Dispose();
Console.WriteLine($"{Device.DeviceName},释放");
_driver.Dispose();
_logger.LogInformation($"线程释放,{_device.DeviceName}");
}
//mysql会把一些符号转义没找到原因先临时处理下

View File

@ -11,23 +11,28 @@ using System.Threading.Tasks;
using WalkingTec.Mvvm.Core;
using IoTGateway.DataAccess;
using IoTGateway.Model;
using Microsoft.Extensions.Logging;
namespace Plugin
{
public class DrvierService//: IDependency
public class DriverService//: IDependency
{
private readonly ILogger<DriverService> _logger;
string DriverPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"drivers/net6.0");
string[] driverFiles;
public List<DriverInfo> DriverInfos = new List<DriverInfo>();
public DrvierService(IConfiguration ConfigRoot)
public DriverService(IConfiguration ConfigRoot, ILogger<DriverService> logger)
{
_logger = logger;
try
{
driverFiles = Directory.GetFiles(DriverPath).Where(x => Path.GetExtension(x) == ".dll").ToArray();
_logger.LogInformation("LoadDriverFiles Start");
driverFiles = Directory.GetFiles(DriverPath).Where(x => Path.GetExtension(x) == ".dll").ToArray();
_logger.LogInformation($"LoadDriverFiles EndCount{driverFiles.Count()}");
}
catch (Exception)
catch (Exception ex)
{
_logger.LogError("LoadDriverFiles Error", ex);
}
LoadAllDrivers();
}
@ -91,6 +96,7 @@ namespace Plugin
ID = Guid.NewGuid(),
DeviceId = dapID,
DeviceConfigName = property.Name,
DataSide= DataSide.AnySide,
Description = ((ConfigParameterAttribute)config).Description,
Value = property.GetValue(iObj)?.ToString()
};
@ -112,6 +118,7 @@ namespace Plugin
{
try
{
_logger.LogInformation("LoadAllDrivers Start");
foreach (var file in driverFiles)
{
var dll = Assembly.LoadFrom(file);
@ -125,10 +132,11 @@ namespace Plugin
DriverInfos.Add(driverInfo);
}
}
_logger.LogInformation($"LoadAllDrivers End,Count{DriverInfos.Count}");
}
catch (Exception ex)
{
Console.WriteLine("驱动加载失败一般是驱动项目引用的nuget或dll没有复制到驱动文件夹");
_logger.LogError("LoadAllDrivers Error一般是驱动项目引用的nuget或dll没有复制到驱动文件夹", ex);
}
}

View File

@ -1,4 +1,5 @@
using Modbus.Data;
using Microsoft.Extensions.Logging;
using Modbus.Data;
using Modbus.Device;
using System;
using System.Collections.Generic;
@ -12,13 +13,15 @@ namespace Plugin
{
public class ModbusSlaveService : IDisposable
{
private readonly ILogger<ModbusSlaveService> _logger;
TcpListener slaveTcpListener;
private Timer m_simulationTimer;
private object Lock=new object();
private ModbusSlave slave;
private Task task { get; set; } = null;
public ModbusSlaveService()
public ModbusSlaveService(ILogger<ModbusSlaveService> logger)
{
_logger = logger;
byte slaveId = 1;
int port = 503;
IPAddress address = IPAddress.Any;
@ -30,6 +33,7 @@ namespace Plugin
slave.DataStore = DataStoreFactory.CreateDefaultDataStore();
slave.ListenAsync();
m_simulationTimer = new Timer(DoSimulation, null, 1000, 1000);
_logger.LogInformation($"Modbus Server Started");
}
private void DoSimulation(object state)
@ -53,11 +57,12 @@ namespace Plugin
}
catch (Exception ex)
{
Console.WriteLine($"modbus模拟数据失败了,{ex}");
_logger.LogError($"Modbus Server Error", ex);
}
}
public void Dispose()
{
_logger.LogError($"Modbus Server Dispose");
m_simulationTimer.Dispose();
slaveTcpListener.Stop();
}

View File

@ -1,91 +1,221 @@
using Microsoft.Extensions.Configuration;
using IoTGateway.DataAccess;
using IoTGateway.Model;
using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Disconnecting;
using MQTTnet.Client.Options;
using MQTTnet.Client.Receiving;
using System;
using MQTTnet.Protocol;
using Newtonsoft.Json;
using WalkingTec.Mvvm.Core;
using System.Collections.Generic;
using IoTGateway.DataAccess;
using IoTGateway.Model;
using System.Linq;
using PluginInterface;
using Microsoft.Extensions.DependencyInjection;
using Quickstarts.ReferenceServer;
using Opc.Ua;
namespace Plugin
{
public class MyMqttClient//: IDependency
public class MyMqttClient
{
private IMqttClient _mqttClient = null;
private ReferenceNodeManager _uaNodeManager = null;
private MqttClientOptionsBuilder builder = null;
private SystemConfig systemConfig = null;
public MyMqttClient(UAService uaService)
private readonly ILogger<MyMqttClient> _logger;
private readonly ReferenceNodeManager _uaNodeManager = null;
private SystemConfig? _systemConfig;
private IMqttClientOptions clientOptions;
public bool IsConnected => (Client?.IsConnected).GetValueOrDefault();
private IMqttClient Client { get; set; }
public event EventHandler<RpcRequest> OnExcRpc;
public event EventHandler<AttributeResponse> OnReceiveAttributes;
public MyMqttClient(UAService uaService, ILogger<MyMqttClient> logger)
{
_logger = logger;
_uaNodeManager = uaService.server.m_server.nodeManagers[0] as ReferenceNodeManager;
InitClient();
ConnectAsync();
}
public void InitClient()
public async Task<bool> ConnectAsync()
{
bool initok = false;
try
{
using (var DC = new DataContext(IoTBackgroundService.connnectSetting, IoTBackgroundService.DBType))
{
_systemConfig = DC.Set<SystemConfig>().FirstOrDefault();
if (_systemConfig == null)
{
_systemConfig = new SystemConfig()
{
ID = Guid.NewGuid(),
GatewayName = "iotgateway",
MqttIp = "localhost",
MqttPort = 1888,
MqttUName = "user",
MqttUPwd = "pwd",
IoTPlatformType = IoTPlatformType.IoTSharp
};
DC.Set<SystemConfig>().Add(_systemConfig);
DC.SaveChanges();
}
var factory = new MqttFactory();
Client = (MqttClient)factory.CreateMqttClient();
clientOptions = new MqttClientOptionsBuilder()
.WithClientId(_systemConfig.GatewayName + Guid.NewGuid().ToString())
.WithTcpServer(_systemConfig.MqttIp, _systemConfig.MqttPort)
.WithCredentials(_systemConfig.MqttUName, _systemConfig.MqttUPwd)
.WithCommunicationTimeout(TimeSpan.FromSeconds(30))
.WithKeepAlivePeriod(TimeSpan.FromSeconds(20))
.Build();
Client.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(Client_ApplicationMessageReceived);
Client.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected());
Client.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnectedAsync());
try
{
Client.ConnectAsync(clientOptions);
initok = true;
}
catch (Exception exception)
{
_logger.LogError("MQTT CONNECTING FAILED", exception);
}
_logger.LogInformation("MQTT WAITING FOR APPLICATION MESSAGES");
}
}
catch (Exception exception)
{
_logger.LogError("MQTT CONNECTING FAILED", exception);
}
return initok;
}
private async Task OnDisconnectedAsync()
{
try
{
if (_mqttClient != null)
_mqttClient.Dispose();
await Client.ConnectAsync(clientOptions);
}
catch (Exception exception)
{
_logger.LogError("MQTT CONNECTING FAILED", exception);
}
}
using (var DC = new DataContext(IoTBackgroundService.connnectSetting, IoTBackgroundService.DBType))
private void OnConnected()
{
Client.SubscribeAsync($"devices/+/rpc/request/+/+", MqttQualityOfServiceLevel.ExactlyOnce);
Client.SubscribeAsync($"devices/Modbus/attributes/update/", MqttQualityOfServiceLevel.ExactlyOnce);
Client.SubscribeAsync($"devices/+/attributes/response/+", MqttQualityOfServiceLevel.ExactlyOnce);
_logger.LogInformation($"MQTT CONNECTED WITH SERVER ");
}
private Task Client_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
{
_logger.LogDebug($"ApplicationMessageReceived Topic {e.ApplicationMessage.Topic} QualityOfServiceLevel:{e.ApplicationMessage.QualityOfServiceLevel} Retain:{e.ApplicationMessage.Retain} ");
try
{
if (e.ApplicationMessage.Topic.StartsWith($"devices/") && e.ApplicationMessage.Topic.Contains("/response/"))
{
systemConfig = DC.Set<SystemConfig>().FirstOrDefault();
if (systemConfig == null)
Console.WriteLine("配置信息错误,无法启动");
else
ReceiveAttributes(e);
}
else if (e.ApplicationMessage.Topic.StartsWith($"devices/") && e.ApplicationMessage.Topic.Contains("/rpc/request/"))
{
var tps = e.ApplicationMessage.Topic.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var rpcmethodname = tps[4];
var rpcdevicename = tps[1];
var rpcrequestid = tps[5];
_logger.LogInformation($"rpcmethodname={rpcmethodname} ");
_logger.LogInformation($"rpcdevicename={rpcdevicename } ");
_logger.LogInformation($"rpcrequestid={rpcrequestid} ");
if (!string.IsNullOrEmpty(rpcmethodname) && !string.IsNullOrEmpty(rpcdevicename) && !string.IsNullOrEmpty(rpcrequestid))
{
_mqttClient = new MqttFactory().CreateMqttClient();
_mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected());
_mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected());
_mqttClient.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(OnReceived);
builder = new MqttClientOptionsBuilder()
.WithCommunicationTimeout(TimeSpan.FromSeconds(60))
.WithKeepAlivePeriod(TimeSpan.FromSeconds(20))
.WithTcpServer(systemConfig.MqttIp, systemConfig.MqttPort)
.WithClientId(systemConfig.MqttUName + Guid.NewGuid().ToString())
.WithCredentials(systemConfig.MqttUName, systemConfig.MqttUPwd);
_mqttClient.ConnectAsync(builder.Build());
OnExcRpc?.Invoke(Client, new RpcRequest()
{
Method = rpcmethodname,
DeviceId = rpcdevicename,
RequestId = rpcrequestid,
Params = e.ApplicationMessage.ConvertPayloadToString()
});
}
}
}
catch (Exception ex)
{
_logger.LogError($"ClientId:{e.ClientId} Topic:{e.ApplicationMessage.Topic},Payload:{e.ApplicationMessage.ConvertPayloadToString()}", ex);
}
return Task.CompletedTask;
}
public void Publish(Device device, Dictionary<string, List<PayLoad>> SendModel)
private void ReceiveAttributes(MqttApplicationMessageReceivedEventArgs e)
{
var tps = e.ApplicationMessage.Topic.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var rpcmethodname = tps[2];
var rpcdevicename = tps[1];
var rpcrequestid = tps[4];
_logger.LogInformation($"rpcmethodname={rpcmethodname} ");
_logger.LogInformation($"rpcdevicename={rpcdevicename } ");
_logger.LogInformation($"rpcrequestid={rpcrequestid} ");
if (!string.IsNullOrEmpty(rpcmethodname) && !string.IsNullOrEmpty(rpcdevicename) && !string.IsNullOrEmpty(rpcrequestid))
{
if (e.ApplicationMessage.Topic.Contains("/attributes/"))
{
OnReceiveAttributes?.Invoke(Client, new AttributeResponse()
{
KeyName = rpcmethodname,
DeviceName = rpcdevicename,
Id = rpcrequestid,
Data = e.ApplicationMessage.ConvertPayloadToString()
});
}
}
}
public Task UploadAttributeAsync(string _devicename, object obj)
{
return Client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic($"devices/{_devicename}/attributes").WithPayload(Newtonsoft.Json.JsonConvert.SerializeObject(obj)).Build());
}
public Task UploadTelemetryDataAsync(string _devicename, object obj)
{
return Client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic($"devices/{_devicename}/telemetry").WithPayload(Newtonsoft.Json.JsonConvert.SerializeObject(obj)).Build());
}
public Task ResponseExecommand(RpcResponse rpcResult)
{
///IoTSharp/Clients/RpcClient.cs#L65 var responseTopic = $"/devices/{deviceid}/rpc/response/{methodName}/{rpcid}";
string topic = $"devices/{rpcResult.DeviceId}/rpc/response/{rpcResult.Method.ToString()}/{rpcResult.ResponseId}";
return Client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(rpcResult.Data.ToString()).WithQualityOfServiceLevel(MqttQualityOfServiceLevel.ExactlyOnce).Build());
}
public Task RequestAttributes(string _device, bool anySide, params string[] args)
{
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);
}
public void PublishTelemetry(Device device, Dictionary<string, List<PayLoad>> SendModel)
{
try
{
switch (systemConfig.IoTPlatformType)
switch (_systemConfig.IoTPlatformType)
{
case IoTPlatformType.ThingsBoard:
_mqttClient.PublishAsync("v1/gateway/telemetry", JsonConvert.SerializeObject(SendModel));
Client.PublishAsync("v1/gateway/telemetry", JsonConvert.SerializeObject(SendModel));
break;
case IoTPlatformType.IoTSharp:
foreach (var payload in SendModel[device.DeviceName])
{
_mqttClient.PublishAsync($"devices/{device.DeviceName}/telemetry", JsonConvert.SerializeObject(payload.Values));
UploadTelemetryDataAsync(device.DeviceName, payload.Values);
}
break;
case IoTPlatformType.AliCloudIoT:
case IoTPlatformType.TencentIoTHub:
case IoTPlatformType.BaiduIoTCore:
case IoTPlatformType.OneNET:
default:
default:
break;
}
foreach (var payload in SendModel[device.DeviceName])
@ -93,7 +223,7 @@ namespace Plugin
foreach (var kv in payload.Values)
{
//更新到UAService
_uaNodeManager?.UpdateNode($"{device.Parent.DeviceName}.{device.DeviceName}.{kv.Key}", kv.Value);
_uaNodeManager.UpdateNode($"{device.Parent.DeviceName}.{device.DeviceName}.{kv.Key}", kv.Value);
}
}
@ -106,27 +236,27 @@ namespace Plugin
}
private void Update2UAService()
{
int i = 0;
}
}
public class RpcRequest
{
public string DeviceId { get; set; }
public string Method { get; set; }
public string RequestId { get; set; }
public string Params { get; set; }
}
public class RpcResponse
{
public string DeviceId { get; set; }
public string Method { get; set; }
public string ResponseId { get; set; }
public string Data { get; set; }
}
public class AttributeResponse
{
public string Id { get; set; }
public string DeviceName { get; set; }
public string KeyName { get; set; }
private void OnReceived(MqttApplicationMessageReceivedEventArgs obj)
{
var topic = obj.ApplicationMessage.Topic;
var msg = System.Text.Encoding.UTF8.GetString(obj.ApplicationMessage.Payload);
Console.WriteLine($"{topic}: {msg}");
}
private void OnDisconnected()
{
Console.WriteLine("Mqtt连接断开");
_mqttClient.ConnectAsync(builder.Build());
}
private void OnConnected()
{
Console.WriteLine("Mqtt连接正常");
}
public string Data { get; set; }
}
}