From c1aeddc8b22a64e97d75ed0358208223d151e202 Mon Sep 17 00:00:00 2001 From: ccongli <1441652193@qq.com> Date: Wed, 27 Sep 2023 15:32:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E8=AE=BE=E5=A4=87=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E9=9A=94=E7=A6=BB=E4=B8=9A=E5=8A=A1v1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vol-net6/VOL.Core/BaseProvider/ServiceBase.cs | 2 +- vol-net6/VOL.Core/Tenancy/TenancyManager.cs | 14 +- .../config/Partial/IData_ConfigService.cs | 4 + .../IServices/modbus/IDataProcessing.cs | 3 + .../config/Partial/Data_ConfigService.cs | 10 +- .../machine/Partial/Data_MachineService.cs | 2 +- .../Services/modbus/DataProcessing.cs | 20 +- .../produce/Partial/Data_ProduceService.cs | 2 +- .../System/Partial/ISys_DepartmentService.cs | 3 + .../System/Partial/Sys_DepartmentService.cs | 18 ++ .../Controllers/Data/DataCaptureController.cs | 148 ----------- .../Controllers/Data/NKNCaptureController.cs | 244 ++++++++++++++++++ .../Partial/Sys_DepartmentController.cs | 14 + .../Partial/Sys_QuartzOptionsController.cs | 3 + vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs | 11 +- .../Tables/Sys_User/202309270810424470/yz.png | Bin 0 -> 12517 bytes vol-vue3/src/views/Index.vue | 17 +- 17 files changed, 339 insertions(+), 176 deletions(-) delete mode 100644 vol-net6/VOL.WebApi/Controllers/Data/DataCaptureController.cs create mode 100644 vol-net6/VOL.WebApi/Controllers/Data/NKNCaptureController.cs create mode 100644 vol-net6/VOL.WebApi/wwwroot/Upload/Tables/Sys_User/202309270810424470/yz.png diff --git a/vol-net6/VOL.Core/BaseProvider/ServiceBase.cs b/vol-net6/VOL.Core/BaseProvider/ServiceBase.cs index d9978e7..1f79f5f 100644 --- a/vol-net6/VOL.Core/BaseProvider/ServiceBase.cs +++ b/vol-net6/VOL.Core/BaseProvider/ServiceBase.cs @@ -73,7 +73,7 @@ namespace VOL.Core.BaseProvider protected virtual void Init(IRepository repository) { - + IsMultiTenancy = true; // 开启租户隔离 } protected virtual Type GetRealDetailType() diff --git a/vol-net6/VOL.Core/Tenancy/TenancyManager.cs b/vol-net6/VOL.Core/Tenancy/TenancyManager.cs index 6d714cc..40fd8c7 100644 --- a/vol-net6/VOL.Core/Tenancy/TenancyManager.cs +++ b/vol-net6/VOL.Core/Tenancy/TenancyManager.cs @@ -16,16 +16,16 @@ namespace VOL.Core.Tenancy { string multiTenancyString = $"select * from {tableName}"; //超级管理员不限制 - //if (UserContext.Current.IsSuperAdmin) - //{ - // return multiTenancyString; - //} + if (UserContext.Current.IsSuperAdmin) + { + return multiTenancyString; + } switch (tableName) { //例如:指定用户表指定查询条件 - //case "Sys_User": - // multiTenancyString += $" where UserId='{UserContext.Current.UserId}'"; - // break; + case "Sys_User": + multiTenancyString += $" where UserId='{UserContext.Current.UserId}'"; + break; default: //开启数租户数据隔离,用户只能看到自己的表数据(自己根据需要写条件做租户数据隔离) multiTenancyString += $" where CreateID='{UserContext.Current.UserId}'"; diff --git a/vol-net6/VOL.Data/IServices/config/Partial/IData_ConfigService.cs b/vol-net6/VOL.Data/IServices/config/Partial/IData_ConfigService.cs index 8090314..655874a 100644 --- a/vol-net6/VOL.Data/IServices/config/Partial/IData_ConfigService.cs +++ b/vol-net6/VOL.Data/IServices/config/Partial/IData_ConfigService.cs @@ -11,5 +11,9 @@ namespace VOL.Data.IServices { // 获取设备配置列表 List getConfigList(); + + // 根据主键查询设备 + + Data_Config GetConfigById(int id); } } diff --git a/vol-net6/VOL.Data/IServices/modbus/IDataProcessing.cs b/vol-net6/VOL.Data/IServices/modbus/IDataProcessing.cs index 4cf2b05..0381af9 100644 --- a/vol-net6/VOL.Data/IServices/modbus/IDataProcessing.cs +++ b/vol-net6/VOL.Data/IServices/modbus/IDataProcessing.cs @@ -20,6 +20,9 @@ namespace VOL.Data.IServices.modbus Dictionary> readGSKData(IModbusService modbus); + // 获取设备配置信息 + Data_Config GetDataConfig(int deviceId); + // 保存设备数据 bool saveMachineData(Data_Machine machine, out string message); diff --git a/vol-net6/VOL.Data/Services/config/Partial/Data_ConfigService.cs b/vol-net6/VOL.Data/Services/config/Partial/Data_ConfigService.cs index ce52b68..4428e07 100644 --- a/vol-net6/VOL.Data/Services/config/Partial/Data_ConfigService.cs +++ b/vol-net6/VOL.Data/Services/config/Partial/Data_ConfigService.cs @@ -35,14 +35,18 @@ namespace VOL.Data.Services _httpContextAccessor = httpContextAccessor; _repository = dbRepository; //多租户会用到这init代码,其他情况可以不用 - //base.Init(dbRepository); + base.Init(dbRepository); } public List getConfigList() { - var list = _repository.DbContext.Set().Select(x => new Data_Config(){ + var list = _repository.DbContext.Set().Select(x => new Data_Config() { id = x.id, name = x.name, type = x.type, device_ip = x.device_ip, com_ip = x.com_ip - }).OrderBy(x=> x.id).ToList(); + }).OrderBy(x => x.id).ToList(); return list; } + + public Data_Config GetConfigById(int id) { + return _repository.DbContext.Set().FirstOrDefault(e => e.id == id); + } } } diff --git a/vol-net6/VOL.Data/Services/machine/Partial/Data_MachineService.cs b/vol-net6/VOL.Data/Services/machine/Partial/Data_MachineService.cs index f1eec00..4359bad 100644 --- a/vol-net6/VOL.Data/Services/machine/Partial/Data_MachineService.cs +++ b/vol-net6/VOL.Data/Services/machine/Partial/Data_MachineService.cs @@ -43,7 +43,7 @@ namespace VOL.Data.Services _httpContextAccessor = httpContextAccessor; _repository = dbRepository; //多租户会用到这init代码,其他情况可以不用 - //base.Init(dbRepository); + base.Init(dbRepository); } public Dictionary GetMachineData() diff --git a/vol-net6/VOL.Data/Services/modbus/DataProcessing.cs b/vol-net6/VOL.Data/Services/modbus/DataProcessing.cs index 904b6ef..5a79708 100644 --- a/vol-net6/VOL.Data/Services/modbus/DataProcessing.cs +++ b/vol-net6/VOL.Data/Services/modbus/DataProcessing.cs @@ -23,7 +23,6 @@ namespace VOL.Data.Services.modbus // 生产数据 Dictionary map1 = new Dictionary { - { "config_id", 1}, { "com_status",modbus.readData(1, 6430, "int16") }, // 通讯状态 5:通讯正常 15:通讯断线 { "run_time", (int)modbus.readData(1, 6435, "int16") }, // 运行时长 分钟 { "turnout_1",(int)modbus.readData(1, 6436, "int16") }, // 工单1产量 件 @@ -45,18 +44,17 @@ namespace VOL.Data.Services.modbus { // 操作模式 0:JOG 1:AUTO 2:AUTO + TEACHIN 3:JOG + REPOIN 4:JOG + REPOS // 5:MDA 6:MDA + REPOS 7:MDA + REPOS + TEAHIN8:MDA + TEACHIN - { "config_id", 1}, { "com_status", modbus.readData(1, 6430, "int16") }, // 通讯状态 5:通讯正常 15:通讯断线 { "smode", modbus.readData(1, 6099, "int16") }, { "state", modbus.readData(1, 6429, "int16") }, // 运行状态 0:待机 1:故障 2:运行 3:暂停 { "temperature", (decimal)modbus.readData(1, 1201, "single")}, // 电机温度 ℃ { "potential", (decimal)modbus.readData(1, 1203, "single")}, // 母线电压 V { "current", (decimal)modbus.readData(1, 1205, "single")}, // 实际电流 A - { "quantity", (long)modbus.readData(1, 1215, "single")}, // 加工数 次 { "cut_rate", (decimal)modbus.readData(1, 1225, "single")}, // 切削倍率 { "main_rate", (decimal)modbus.readData(1, 1231, "single")}, // 主轴倍率 { "run_program_no", modbus.readData(1, 6689, "string", 26)}, // 加工程序号 length = 52 { "run_time_total", (long)modbus.readData(1, 6435, "int16")}, // 累计运行时长 分钟 + { "quantity_total", (long)modbus.readData(1, 1215, "single")}, // 累计加工数 次 }; // 组装Map返回 @@ -72,7 +70,6 @@ namespace VOL.Data.Services.modbus // 生产数据 Dictionary map1 = new Dictionary { - { "config_id", 2}, // 枚举todo { "program_no", (int)modbus.readData(1, 6429, "int16") }, // 程序编号 { "com_status", modbus.readData(1, 6430, "int16") }, // 通讯状态 5:通讯正常 15:通讯断线 { "run_time", (int)modbus.readData(1, 6435, "int16") }, // 运行时长 分钟 @@ -93,18 +90,17 @@ namespace VOL.Data.Services.modbus // 机床数据 Dictionary map2 = new Dictionary { - { "config_id", 2}, { "com_status", modbus.readData(1, 6430, "int16") }, // 通讯状态 5:通讯正常 15:通讯断线 { "gmode", modbus.readData(1, 6099, "int16") }, // 工作方式 0:编辑 1:自动 2:MDI 3:DNC 4:手动 5:手轮 6:回参考点 { "state", modbus.readData(1, 6100, "int16") }, // 运行状态 0:复位 1:停止 2:运行 3:暂停 - { "quantity", (long)modbus.readData(1, 1199, "int32")}, // 加工数量 次 + { "quantity", (long)modbus.readData(1, 4117, "int32")}, // 当天加工数量 次 { "on_time", (long)modbus.readData(1, 1201, "int32")}, // 开机时间 秒 { "run_time", (long)modbus.readData(1, 1203, "int32")}, // 运行时间 秒 - { "feed_rate", (decimal)modbus.readData(1, 1242, "single")}, // 进给倍率 - { "main_rate", (decimal)modbus.readData(1, 1248, "single")}, // 主轴倍率 + { "feed_rate", (decimal)modbus.readData(1, 1241, "single")}, // 进给倍率 + { "main_rate", (decimal)modbus.readData(1, 1247, "single")}, // 主轴倍率 { "run_program_no", modbus.readData(1, 6299, "string", 4)}, // 运行程序编号 length = 8 { "run_time_total", (long)modbus.readData(1, 4115, "int32")}, // 累计运行时长 分钟 - { "quantity_total", (long)modbus.readData(1, 4117, "int32")} // 累计加工数 次 + { "quantity_total", (long)modbus.readData(1, 1199, "int32")} // 累计加工数 次 }; // 组装Map返回 @@ -114,6 +110,12 @@ namespace VOL.Data.Services.modbus return map; } + // 查询设备信息 + + public Data_Config GetDataConfig(int deviceId) { + return Data_ConfigService.Instance.GetConfigById(deviceId); + } + // 保存机床数据 public bool saveMachineData(Data_Machine machine, out string message) { diff --git a/vol-net6/VOL.Data/Services/produce/Partial/Data_ProduceService.cs b/vol-net6/VOL.Data/Services/produce/Partial/Data_ProduceService.cs index 6d8064c..782b805 100644 --- a/vol-net6/VOL.Data/Services/produce/Partial/Data_ProduceService.cs +++ b/vol-net6/VOL.Data/Services/produce/Partial/Data_ProduceService.cs @@ -37,7 +37,7 @@ namespace VOL.Data.Services _httpContextAccessor = httpContextAccessor; _repository = dbRepository; //多租户会用到这init代码,其他情况可以不用 - //base.Init(dbRepository); + base.Init(dbRepository); } diff --git a/vol-net6/VOL.System/IServices/System/Partial/ISys_DepartmentService.cs b/vol-net6/VOL.System/IServices/System/Partial/ISys_DepartmentService.cs index cdf6107..6831766 100644 --- a/vol-net6/VOL.System/IServices/System/Partial/ISys_DepartmentService.cs +++ b/vol-net6/VOL.System/IServices/System/Partial/ISys_DepartmentService.cs @@ -5,9 +5,12 @@ using VOL.Core.BaseProvider; using VOL.Entity.DomainModels; using VOL.Core.Utilities; using System.Linq.Expressions; +using System.Threading.Tasks; namespace VOL.System.IServices { public partial interface ISys_DepartmentService { + // 获取用户关联根部门 + Task GetUserDepartment(int userId); } } diff --git a/vol-net6/VOL.System/Services/System/Partial/Sys_DepartmentService.cs b/vol-net6/VOL.System/Services/System/Partial/Sys_DepartmentService.cs index 8083de3..a350de3 100644 --- a/vol-net6/VOL.System/Services/System/Partial/Sys_DepartmentService.cs +++ b/vol-net6/VOL.System/Services/System/Partial/Sys_DepartmentService.cs @@ -20,6 +20,8 @@ using VOL.System.IRepositories; using System.Collections.Generic; using VOL.Core.ManageUser; using VOL.Core.UserManager; +using VOL.Core.DBManager; +using System.Threading.Tasks; namespace VOL.System.Services { @@ -96,6 +98,22 @@ namespace VOL.System.Services { return base.Del(keys, delList).Reload(); } + + + public async Task GetUserDepartment(int userId) { + var dapper = DBServerProvider.SqlDapper; + string sql = @"SELECT + d.DepartmentId, + d.DepartmentCode, + d.DepartmentName + FROM + sys_department AS d + LEFT JOIN sys_userdepartment AS ud ON ud.DepartmentId = d.DepartmentId + WHERE + ud.UserId = @userId + AND d.ParentId IS NULL;"; + return await dapper.QueryFirstAsync(sql, new { userId }); ; + } } } diff --git a/vol-net6/VOL.WebApi/Controllers/Data/DataCaptureController.cs b/vol-net6/VOL.WebApi/Controllers/Data/DataCaptureController.cs deleted file mode 100644 index 98671c9..0000000 --- a/vol-net6/VOL.WebApi/Controllers/Data/DataCaptureController.cs +++ /dev/null @@ -1,148 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Authorization; -using System; -using VOL.Core.Filters; -using VOL.Data.IServices.modbus; -using VOL.Data.Services.modbus; -using Microsoft.Extensions.DependencyInjection; -using VOL.WebApi.Utils; -using VOL.Entity.DomainModels; -using System.Collections.Generic; -using Confluent.Kafka; - -namespace VOL.WebApi.Controllers.Data -{ - /// - /// 数据采集API类 - /// - [Route("api/Data_Capture")] - [AllowAnonymous] - public class DataCaptureController : Controller - { - private ModbusTcpService _service; // 静态字段 - - private readonly IHttpContextAccessor _httpContextAccessor; - - private readonly IDataProcessing _dataService; // 业务处理 - - - [ActivatorUtilitiesConstructor] - public DataCaptureController( - IDataProcessing dataService, - IHttpContextAccessor httpContextAccessor - ) - { - _dataService = dataService; - _httpContextAccessor = httpContextAccessor; - } - - - /// - /// 采集西门子设备 - /// - /// IActionResult - [ApiTask] - [HttpGet, HttpPost, Route("gatherSiemens")] - public IActionResult gatherSiemens() - { - try - { - _service = new ModbusTcpService("192.168.1.99", 502); - Console.WriteLine("siemens modbus tcp connected..."); - } - catch (Exception) - { - Console.WriteLine("siemens modbus tcp connect failed!"); - return Content("siemens modbus tcp connect failed!"); - } - if (!_service.isConnected) - { - Console.WriteLine("siemens modbus tcp disconnect!"); - return Content("siemens modbus tcp disconnect!"); - } - string message = ""; - try { - Dictionary> dataMap = _dataService.readSiemensData(_service); - message = saveSourceData(dataMap); - } catch (Exception ex) { - Console.WriteLine(ex.Message); - message = "read data error: " + ex.Message; - } finally { - _service.disConnent(); - } - return Content(message); - } - - - /// - /// 采集广数设备 - /// - /// IActionResult - [ApiTask] - [HttpGet, HttpPost, Route("gatherGSK")] - public IActionResult gatherGSK() - { - try - { - _service = new ModbusTcpService("192.168.1.100", 502); - Console.WriteLine("siemens modbus tcp connected..."); - } - catch (Exception) - { - Console.WriteLine("siemens modbus tcp connect failed!"); - return Content("siemens modbus tcp connect failed!"); - } - if (!_service.isConnected) - { - Console.WriteLine("siemens modbus tcp disconnect!"); - return Content("siemens modbus tcp disconnect!"); - } - string message = ""; - try - { - Dictionary> dataMap = _dataService.readGSKData(_service); - message = saveSourceData(dataMap); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - message = "read data error: " + ex.Message; - } - finally - { - _service.disConnent(); - } - return Content(message); - } - - - [HttpGet, HttpPost, Route("testSave")] - public IActionResult testSave() - { - Dictionary> dataMap = new(); - dataMap.Add("machine", new Dictionary() { { "config_id", 666 } }); - dataMap.Add("produce", new Dictionary() { { "config_id", 666 } }); - string message = saveSourceData(dataMap); - return Content(message); - } - - - private string saveSourceData(Dictionary> dataMap) { - // 获取当前系统时间, 保证插入时间一致 - DateTime now = DateTime.Now; - - Dictionary machineData = dataMap["machine"]; - Data_Machine data_Machine = CommonUtil.ConvertToObject(machineData); - data_Machine.CreateDate = now; - bool result1 = _dataService.saveMachineData(data_Machine, out string message1); - - Dictionary produceData = dataMap["produce"]; - Data_Produce data_Produce = CommonUtil.ConvertToObject(produceData); - data_Produce.CreateDate = now; - bool result2 = _dataService.saveProduceData(data_Produce, out string message2); - - return (result1 && result2) ? "OK" : "save machine: " + message1 + "; save produce" + message2 + ";"; - } - } -} diff --git a/vol-net6/VOL.WebApi/Controllers/Data/NKNCaptureController.cs b/vol-net6/VOL.WebApi/Controllers/Data/NKNCaptureController.cs new file mode 100644 index 0000000..f2b516f --- /dev/null +++ b/vol-net6/VOL.WebApi/Controllers/Data/NKNCaptureController.cs @@ -0,0 +1,244 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; +using System; +using VOL.Core.Filters; +using VOL.Data.IServices.modbus; +using VOL.Data.Services.modbus; +using Microsoft.Extensions.DependencyInjection; +using VOL.WebApi.Utils; +using VOL.Entity.DomainModels; +using System.Collections.Generic; +using Microsoft.Extensions.Primitives; + +/// +// 尼可尼数据采集 +/// +namespace VOL.WebApi.Controllers.Data +{ + /// + /// 数据采集API类 + /// + [Route("api/NKNCapture")] + [AllowAnonymous] + public class NKNCaptureController : Controller + { + private ModbusTcpService _service; // 静态字段 + + private readonly IHttpContextAccessor _httpContextAccessor; + + private readonly IDataProcessing _dataService; // 业务处理 + + + [ActivatorUtilitiesConstructor] + public NKNCaptureController( + IDataProcessing dataService, + IHttpContextAccessor httpContextAccessor + ) + { + _dataService = dataService; + _httpContextAccessor = httpContextAccessor; + } + + + /// + /// 采集西门子设备 + /// + /// IActionResult + [ApiTask] + [HttpGet, HttpPost, Route("gatherSiemens")] + public IActionResult gatherSiemens() + { + var headers = _httpContextAccessor.HttpContext.Request.Headers; + headers.TryGetValue("USER-DEVICE-ID", out StringValues deviceIdStr); + try + { + _service = new ModbusTcpService("192.168.1.99", 502); + Console.WriteLine("siemens modbus tcp connected..."); + } + catch (Exception) + { + Console.WriteLine("siemens modbus tcp connect failed!"); + return Content("siemens modbus tcp connect failed!"); + } + if (!_service.isConnected) + { + Console.WriteLine("siemens modbus tcp disconnect!"); + return Content("siemens modbus tcp disconnect!"); + } + // 切削倍率 17136 1 + //_service.readData(1, 6435, "int16"); // 运行时长 分钟 + //_service.readData(1, 6436, "int16"); // 工单1产量 件 + //_service.readData(1, 6437, "int16"); // 工单2产量 件 + //_service.readData(1, 6438, "int16"); // 工单3产量 件 + //_service.readData(1, 6439, "int16"); // 当班产量 件 + //_service.readData(1, 6440, "int16"); // 运行状态 0:待机 1:运行 2:故障 + //_service.readData(1, 1315, "single"); // 工单1任务进度 % + //_service.readData(1, 1317, "single"); // 工单2任务进度 % + //_service.readData(1, 1319, "single"); // 工单3任务进度 % + //_service.readData(1, 1321, "single"); // 工单1良品率 % 真实值 *= 100 + //_service.readData(1, 1323, "single"); // 工单2良品率 % 真实值 *= 100 + //_service.readData(1, 1325, "single"); // 工单3良品率 % 真实值 *= 100 + //_service.readData(1, 1339, "single"); // 设备综合效率 % 真实值 *= 100 + + //dynamic d1 = _service.readData(1, 1201, "single"); // 电机温度 ℃ + //dynamic d2 = _service.readData(1, 1203, "single"); // 母线电压 V + //dynamic d3 = _service.readData(1, 1205, "single"); // 实际电流 A + //dynamic d4 = _service.readData(1, 1215, "single"); // 累计加工次数 + //dynamic d5 = _service.readData(1, 1225, "single"); // 切削倍率 + //dynamic d6 = _service.readData(1, 1231, "single"); // 主轴倍率 + //dynamic d7 = _service.readData(1, 6689, "string", 50); // 运行程序编号 length = 8 + //dynamic d8 = _service.readData(1, 6435, "int16"); // 累计运行时长 分钟 + string message = ""; + bool success = int.TryParse(deviceIdStr, out int deviceId); + try + { + if (success) + { + Dictionary> dataMap = _dataService.readSiemensData(_service); + message = saveSourceData(dataMap, deviceId); + } + else + { + message = "设备非法或已下线"; + } + + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + message = "read data error: " + ex.Message; + } + finally + { + _service.disConnent(); + } + return Content(message); + } + + + /// + /// 采集广数设备 + /// + /// IActionResult + [ApiTask] + [HttpGet, HttpPost, Route("gatherGSK")] + public IActionResult gatherGSK() + { + var headers = _httpContextAccessor.HttpContext.Request.Headers; + headers.TryGetValue("USER-DEVICE-ID", out StringValues deviceIdStr); + try + { + _service = new ModbusTcpService("192.168.1.100", 502); + Console.WriteLine("GSK modbus tcp connected..."); + } + catch (Exception) + { + Console.WriteLine("GSK modbus tcp connect failed!"); + return Content("GSK modbus tcp connect failed!"); + } + if (!_service.isConnected) + { + Console.WriteLine("GSK modbus tcp disconnect!"); + return Content("GSK modbus tcp disconnect!"); + } + + //_service.readData(1, 6429, "int16"); // 程序编号 + //_service.readData(1, 6435, "int16"); // 通讯状态 5:通讯正常 15:通讯断线 + //_service.readData(1, 6430, "int16"); + //_service.readData(1, 6435, "int16"); // 运行时长 分钟 + //_service.readData(1, 6436, "int16"); // 工单1产量 件 + //_service.readData(1, 6437, "int16"); // 工单2产量 件 + //_service.readData(1, 6438, "int16"); // 工单3产量 件 + //_service.readData(1, 6439, "int16"); // 当班产量 件 + //_service.readData(1, 6440, "int16"); // 运行状态 0:待机 1:运行 2:故障 + //_service.readData(1, 1315, "single"); // 工单1任务进度 % + //_service.readData(1, 1317, "single"); // 工单2任务进度 % + //_service.readData(1, 1319, "single"); // 工单3任务进度 % + //_service.readData(1, 1321, "single"); // 工单1良品率 % 真实值 *= 100 + //_service.readData(1, 1323, "single"); // 工单2良品率 % 真实值 *= 100 + //_service.readData(1, 1325, "single"); // 工单3良品率 % 真实值 *= 100 + //_service.readData(1, 1331, "single"); // 设备综合效率 % 真实值 *= 100 + + //_service.readData(1, 6430, "int16"); // 通讯状态 5:通讯正常 15:通讯断线 + //_service.readData(1, 6099, "int16"); // 工作方式 0:编辑 1:自动 2:MDI 3:DNC 4:手动 5:手轮 6:回参考点 + //_service.readData(1, 6100, "int16"); // 运行状态 0:复位 1:停止 2:运行 3:暂停 + //dynamic d1 = _service.readData(1, 4117, "int32"); // 当天加工数量 次 + //dynamic d2 = _service.readData(1, 1201, "int32"); // 开机时间 秒 + //dynamic d3 = _service.readData(1, 1203, "int32"); // 运行时间 秒 + //dynamic d4 = _service.readData(1, 1241, "single"); // 进给倍率 + //dynamic d5 = _service.readData(1, 1247, "single"); // 主轴倍率 + //dynamic d6 = _service.readData(1, 6299, "string", 8); // 运行程序编号 length = 8 + //dynamic d7 = _service.readData(1, 4115, "int32"); // 累计运行时长 分钟 + //dynamic d8 = _service.readData(1, 1199, "int32"); // 累计加工数 次 + + string message = ""; + bool success = int.TryParse(deviceIdStr, out int deviceId); + try + { + if (success) + { + Dictionary> dataMap = _dataService.readGSKData(_service); + message = saveSourceData(dataMap, deviceId); + } + else + { + message = "设备非法或已下线"; + } + } + catch (Exception ex) + { + Console.WriteLine(ex.StackTrace); + message = "read data error: " + ex.Message; + } + finally + { + _service.disConnent(); + } + return Content(message); + } + + + [HttpGet, HttpPost, Route("testSave")] + public IActionResult testSave() + { + Dictionary> dataMap = new(); + dataMap.Add("machine", new Dictionary() { { "config_id", 666 } }); + dataMap.Add("produce", new Dictionary() { { "config_id", 666 } }); + string message = saveSourceData(dataMap, 1); + return Content(message); + } + + + /// + /// 保存采集数据 + /// + /// IActionResult + private string saveSourceData(Dictionary> dataMap, int deviceId) + { + // 获取当前系统时间, 保证插入时间一致 + DateTime now = DateTime.Now; + // 设备关联的用户信息 + Data_Config dataConfig = _dataService.GetDataConfig(deviceId); + if (dataConfig == null) { + return "设备不存在!"; + } + int userId = dataConfig.CreateID ?? 1; // 默认超管 + Dictionary machineData = dataMap["machine"]; + Data_Machine data_Machine = CommonUtil.ConvertToObject(machineData); + data_Machine.config_id = deviceId; + data_Machine.CreateDate = now; + data_Machine.CreateID = userId; + bool result1 = _dataService.saveMachineData(data_Machine, out string message1); + + Dictionary produceData = dataMap["produce"]; + Data_Produce data_Produce = CommonUtil.ConvertToObject(produceData); + data_Produce.config_id = deviceId; + data_Produce.CreateDate = now; + data_Produce.CreateID = userId; + bool result2 = _dataService.saveProduceData(data_Produce, out string message2); + + return (result1 && result2) ? "OK" : "save machine: " + message1 + "; save produce: " + message2 + ";"; + } + } +} diff --git a/vol-net6/VOL.WebApi/Controllers/System/Partial/Sys_DepartmentController.cs b/vol-net6/VOL.WebApi/Controllers/System/Partial/Sys_DepartmentController.cs index a800825..7848355 100644 --- a/vol-net6/VOL.WebApi/Controllers/System/Partial/Sys_DepartmentController.cs +++ b/vol-net6/VOL.WebApi/Controllers/System/Partial/Sys_DepartmentController.cs @@ -125,6 +125,20 @@ namespace VOL.System.Controllers }).ToListAsync(); return JsonNormal(new { rows }); } + + /// + /// 获取用户根部门 + /// + /// + [HttpGet, Route("getUserDepartment")] + [ApiActionPermission()] + public async Task GetUserDepartment() + { + int useId = UserContext.Current.UserId; + var sysDepartment = await _service.GetUserDepartment(useId); + + return JsonNormal(new { sysDepartment.DepartmentName, sysDepartment.DepartmentId }); + } } } diff --git a/vol-net6/VOL.WebApi/Controllers/System/Partial/Sys_QuartzOptionsController.cs b/vol-net6/VOL.WebApi/Controllers/System/Partial/Sys_QuartzOptionsController.cs index 38f185e..b2aa628 100644 --- a/vol-net6/VOL.WebApi/Controllers/System/Partial/Sys_QuartzOptionsController.cs +++ b/vol-net6/VOL.WebApi/Controllers/System/Partial/Sys_QuartzOptionsController.cs @@ -13,6 +13,7 @@ using VOL.Entity.DomainModels; using VOL.System.IServices; using VOL.Core.Filters; using VOL.Core.Enums; +using Microsoft.Extensions.Primitives; namespace VOL.System.Controllers { @@ -40,6 +41,8 @@ namespace VOL.System.Controllers [HttpGet, HttpPost, Route("test")] public IActionResult Test() { + //var headers = _httpContextAccessor.HttpContext.Request.Headers; + //headers.TryGetValue("USER-DEVICE-ID", out StringValues val); //AuthKey return Content(DateTime.Now.ToString("yyyy-MM-dd HH:mm:sss")); } diff --git a/vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs b/vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs index 2bfb7c9..eb0f2dd 100644 --- a/vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs +++ b/vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs @@ -65,15 +65,16 @@ namespace VOL.WebApi.Utils try { ushort[] temp = new ushort[2]; + for (int i = 0; i < 2; i++) { temp[i] = src[i + start]; } - byte[] bytesTemp = Ushorts2Bytes(temp,false); - Array.Reverse(bytesTemp); + Array.Reverse(temp); // !!!BitConverter默认是小端转换,如果是大端字节顺序数组接收,需要先反序字节顺序 - float res = BitConverter.ToSingle(bytesTemp, 0); - return res; + byte[] bytesTemp = Ushorts2Bytes(temp,false); + float f = BitConverter.ToSingle(bytesTemp, 0); + return float.Parse(f.ToString("F2")); // 保留两位小数 } catch (Exception e) { return 0; @@ -148,7 +149,7 @@ namespace VOL.WebApi.Utils temp[0] = src[start]; temp[1] = src[start + 1]; // 0 100 Array.Reverse(temp); // 100 0 地址低位存储低字节数据(小端) - byte[] bytesTemp = Ushorts2Bytes(temp); + byte[] bytesTemp = Ushorts2Bytes(temp,false); int res = BitConverter.ToInt32(bytesTemp, 0); return res; } catch (Exception e) diff --git a/vol-net6/VOL.WebApi/wwwroot/Upload/Tables/Sys_User/202309270810424470/yz.png b/vol-net6/VOL.WebApi/wwwroot/Upload/Tables/Sys_User/202309270810424470/yz.png new file mode 100644 index 0000000000000000000000000000000000000000..aa891a026207340ff001d1d59f80bfbb53f25347 GIT binary patch literal 12517 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
-
上海尼可尼泵业有限公司
+
{{departName}}