Admin.NET/WCS.Application/Hub/IPlcDeviceHub.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Hub/PlcDeviceHub.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceInput.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceOutput.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Service/WcsDevice/WcsDeviceService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/api/wcs/wcsDevice.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/device/deviceMonitor/component/setting.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/device/deviceMonitor/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/device/deviceMonitor/signalR.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Admin.NET/WCS.Application/Hub/IPlcDeviceHub.cs
New file @@ -0,0 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WCS.Application; public interface IPlcDeviceHub { /// <summary> /// 下发设备信息 /// </summary> /// <param name="context"></param> /// <returns></returns> Task PublicPlcDevice(WcsDeviceOutput context); } Admin.NET/WCS.Application/Hub/PlcDeviceHub.cs
New file @@ -0,0 +1,196 @@ using Admin.NET.Core.Service; using DocumentFormat.OpenXml.Office2010.ExcelAc; using Furion.InstantMessaging; using Microsoft.AspNetCore.SignalR; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WCS.Application; /// <summary> /// 任务日志集线器 /// </summary> [MapHub("/hubs/PlcDevice")] public class PlcDeviceHub : Hub<IPlcDeviceHub> { private static readonly IHubContext<PlcDeviceHub, IPlcDeviceHub> _plcDeviceHubContext = App.GetService<IHubContext<PlcDeviceHub, IPlcDeviceHub>>(); private static readonly SysCacheService _sysCacheService = App.GetRequiredService<SysCacheService>(); private static bool boRunningState = false; private static CancellationTokenSource cts;//取消线程标识 private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId); public PlcDeviceHub() { } /// <summary> /// 连接 /// </summary> /// <returns></returns> public override async Task OnConnectedAsync() { var httpContext = Context.GetHttpContext(); var userId = (httpContext.User.FindFirst(ClaimConst.UserId)?.Value).ToLong(); _sysCacheService.Set("PlcDeviceHub:" + Context.ConnectionId, userId); if (!boRunningState) { //开启读取服务线程 boRunningState = true; cts = new CancellationTokenSource();//取消线程标识 StartRead(); } await base.OnConnectedAsync(); } /// <summary> /// 断开 /// </summary> /// <param name="exception"></param> /// <returns></returns> public override async Task OnDisconnectedAsync(Exception exception) { _sysCacheService.Remove("PlcDeviceHub:" + Context.ConnectionId); //如果没有连接了 就关闭线程不读了 if (_sysCacheService.GetKeysByPrefixKey("PlcDeviceHub").Count == 0) { cts.Cancel(); boRunningState = false; } await base.OnDisconnectedAsync(exception); } /// <summary> /// 开启读取plc线程 /// </summary> public static void StartRead() { Task.Run(() => { // 用于保存每个设备的初始状态 var initialStates = new Dictionary<long, WcsDeviceOutput>(); var listPlc = _db.Queryable<WcsPlc>().Where(s => s.Type == PLCTypeEnum.StackingMachine || s.Type == PLCTypeEnum.ConveyorLine).ToList(); var listPlcId = listPlc.Select(s => s.Id).ToList(); var listPlcDevice = _db.Queryable<WcsDevice>().Where(s => s.DeviceType == DeviceTypeEnum.Business && listPlcId.Contains(s.PlcId)).Select<WcsDeviceOutput>().ToList(); var listPlcDeviceId = listPlcDevice.Select(s => s.Id).ToList(); var listPlcStation = _db.Queryable<WcsPosition>().Where(s => listPlcDeviceId.Contains(s.DeviceId)).ToList(); while (true) { try { //获取跺机的状态 foreach (var modDevice in listPlcDevice) { //取消线程 if (cts.Token.IsCancellationRequested) { throw new OperationCanceledException(); } var modPlc = listPlc.Where(s => s.Id == modDevice.Id).FirstOrDefault(); //读取plc的值 var modConn = PLCTaskAction.listPlcConn.FirstOrDefault(s => s != null && s.PlcId == modDevice.PlcId); if (modConn == null) { modDevice.Status = false; continue; } else { modDevice.Status = modConn.Connected; } if (modConn.Connected) { var listPosition = listPlcStation.Where(s => s.DeviceId == modDevice.Id).ToList(); (var result, var plc) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos); modDevice.Plc = Convert.ToString(plc); (result, var wcs) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos); modDevice.Wcs = Convert.ToString(wcs); //任务号 var modPositionTask = listPosition.FirstOrDefault(s => s.Text == "任务号"); (result, var taskNo) = modConn.GetPlcDBValue(modPositionTask.PosType, modDevice.DbNumber, modPositionTask.PlcPos, modPositionTask.StringLength); modDevice.TaskNo = Convert.ToString(taskNo); //任务类型 var modPositionTaskType = listPosition.FirstOrDefault(s => s.Text == "任务类型"); (result, var taskType) = modConn.GetPlcDBValue(modPositionTaskType.PosType, modDevice.DbNumber, modPositionTaskType.PlcPos); modDevice.TaskType = (TaskTypeEnum)Convert.ToInt32(taskType); //起始工位 var modPositionStartLocatNo = listPosition.FirstOrDefault(s => s.Text == "起始工位"); (result, var startLocatNo) = modConn.GetPlcDBValue(modPositionStartLocatNo.PosType, modDevice.DbNumber, modPositionStartLocatNo.PlcPos); modDevice.StartLocatNo = Convert.ToString(startLocatNo); //目的工位 var modPositionEndLocatNo = listPosition.FirstOrDefault(s => s.Text == "目的工位"); (result, var endLocatNo) = modConn.GetPlcDBValue(modPositionEndLocatNo.PosType, modDevice.DbNumber, modPositionEndLocatNo.PlcPos); modDevice.EndLocatNo = Convert.ToString(endLocatNo); //托盘码 var modPositionPalletNo = listPosition.FirstOrDefault(s => s.Text == "托盘码"); (result, var palletNo) = modConn.GetPlcDBValue(modPositionPalletNo.PosType, modDevice.DbNumber, modPositionPalletNo.PlcPos, modPositionPalletNo.StringLength); modDevice.PalletNo = Convert.ToString(palletNo); if (modPlc.Type == PLCTypeEnum.ConveyorLine) { //放货排 var modPositionReleaseRow = listPosition.FirstOrDefault(s => s.Text == "放货排"); (result, var releaseRow) = modConn.GetPlcDBValue(modPositionReleaseRow.PosType, modDevice.DbNumber, modPositionReleaseRow.PlcPos); modDevice.ReleaseRow = Convert.ToInt32(releaseRow); //放货列 var modPositionReleaseCol = listPosition.FirstOrDefault(s => s.Text == "放货列"); (result, var releaseCol) = modConn.GetPlcDBValue(modPositionReleaseCol.PosType, modDevice.DbNumber, modPositionReleaseCol.PlcPos); modDevice.ReleaseCol = Convert.ToInt32(releaseCol); //放货层 var modPositionReleaseStorey = listPosition.FirstOrDefault(s => s.Text == "放货层"); (result, var releaseStorey) = modConn.GetPlcDBValue(modPositionReleaseStorey.PosType, modDevice.DbNumber, modPositionReleaseStorey.PlcPos); modDevice.ReleaseStorey = Convert.ToInt32(releaseStorey); //取货排 var modPositionPickRow = listPosition.FirstOrDefault(s => s.Text == "取货排"); (result, var pickRow) = modConn.GetPlcDBValue(modPositionPickRow.PosType, modDevice.DbNumber, modPositionPickRow.PlcPos); modDevice.PickRow = Convert.ToInt32(pickRow); //取货列 var modPositionPickCol = listPosition.FirstOrDefault(s => s.Text == "取货列"); (result, var pickCol) = modConn.GetPlcDBValue(modPositionPickCol.PosType, modDevice.DbNumber, modPositionPickCol.PlcPos); modDevice.PickCol = Convert.ToInt32(pickCol); //取货层 var modPositionPickStorey = listPosition.FirstOrDefault(s => s.Text == "取货层"); (result, var pickStorey) = modConn.GetPlcDBValue(modPositionPickStorey.PosType, modDevice.DbNumber, modPositionPickStorey.PlcPos); modDevice.PickStorey = Convert.ToInt32(pickStorey); } } // 比较之前的状态 if (initialStates.TryGetValue(modDevice.Id, out var initialState)) { if (modDevice.Status != initialState.Status || modDevice.Plc != initialState.Plc || modDevice.Wcs != initialState.Wcs || modDevice.TaskNo != initialState.TaskNo || modDevice.TaskType != initialState.TaskType || modDevice.StartLocatNo != initialState.StartLocatNo || modDevice.EndLocatNo != initialState.EndLocatNo || modDevice.PalletNo != initialState.PalletNo || (modPlc.Type == PLCTypeEnum.ConveyorLine && (modDevice.ReleaseRow != initialState.ReleaseRow || modDevice.ReleaseCol != initialState.ReleaseCol || modDevice.ReleaseStorey != initialState.ReleaseStorey || modDevice.PickRow != initialState.PickRow || modDevice.PickCol != initialState.PickCol || modDevice.PickStorey != initialState.PickStorey))) { // 通知用户变更 _plcDeviceHubContext.Clients.All.PublicPlcDevice(modDevice); } } initialStates[modDevice.Id] = modDevice.Adapt<WcsDeviceOutput>(); } Thread.Sleep(2000); } catch (Exception) { throw; } } }, cts.Token); } } Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceInput.cs
@@ -232,4 +232,65 @@ /// </summary> [Required(ErrorMessage = "起始点位不能为空")] public int Pos { get; set; } } /// <summary> /// 写入参数 /// </summary> public class WriteWcsDeviceInput : WcsDeviceBaseInput { /// <summary> /// 主键Id /// </summary> [Required(ErrorMessage = "主键Id不能为空")] public long Id { get; set; } /// <summary> /// 任务号 /// </summary> public string TaskNo { get; set; } /// <summary> /// 任务类型 /// </summary> public TaskTypeEnum? TaskType { get; set; } /// <summary> /// 起始工位 /// </summary> public string StartLocatNo { get; set; } /// <summary> /// 结束工位 /// </summary> public string EndLocatNo { get; set; } /// <summary> /// 托盘码 /// </summary> public string PalletNo { get; set; } public string Plc { get; set; } public string Wcs { get; set; } /// <summary> /// 连接状态 /// </summary> public bool Status { get; set; } = false; /// <summary> /// 放货排 /// </summary> public int ReleaseRow { get; set; } /// <summary> /// 放货列 /// </summary> public int ReleaseCol { get; set; } /// <summary> /// 放货层 /// </summary> public int ReleaseStorey { get; set; } /// <summary> /// 取货排 /// </summary> public int PickRow { get; set; } /// <summary> /// 取货列 /// </summary> public int PickCol { get; set; } /// <summary> /// 取货层 /// </summary> public int PickStorey { get; set; } } Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceOutput.cs
@@ -142,8 +142,30 @@ /// 连接状态 /// </summary> public bool Status { get; set; } = false; /// <summary> /// 放货排 /// </summary> public int ReleaseRow { get; set; } /// <summary> /// 放货列 /// </summary> public int ReleaseCol { get; set; } /// <summary> /// 放货层 /// </summary> public int ReleaseStorey { get; set; } /// <summary> /// 取货排 /// </summary> public int PickRow { get; set; } /// <summary> /// 取货列 /// </summary> public int PickCol { get; set; } /// <summary> /// 取货层 /// </summary> public int PickStorey { get; set; } } Admin.NET/WCS.Application/Service/WcsDevice/WcsDeviceService.cs
@@ -251,6 +251,34 @@ var modPositionPalletNo = listPosition.FirstOrDefault(s => s.Text == "托盘码"); (result, var palletNo) = modConn.GetPlcDBValue(modPositionPalletNo.PosType, modDevice.DbNumber, modPositionPalletNo.PlcPos, modPositionPalletNo.StringLength); modDevice.PalletNo = Convert.ToString(palletNo); if (cachePlc.Type == PLCTypeEnum.ConveyorLine) { //放货排 var modPositionReleaseRow = listPosition.FirstOrDefault(s => s.Text == "放货排"); (result, var releaseRow) = modConn.GetPlcDBValue(modPositionReleaseRow.PosType, modDevice.DbNumber, modPositionReleaseRow.PlcPos); modDevice.ReleaseRow = Convert.ToInt32(releaseRow); //放货列 var modPositionReleaseCol = listPosition.FirstOrDefault(s => s.Text == "放货列"); (result, var releaseCol) = modConn.GetPlcDBValue(modPositionReleaseCol.PosType, modDevice.DbNumber, modPositionReleaseCol.PlcPos); modDevice.ReleaseCol = Convert.ToInt32(releaseCol); //放货层 var modPositionReleaseStorey = listPosition.FirstOrDefault(s => s.Text == "放货层"); (result, var releaseStorey) = modConn.GetPlcDBValue(modPositionReleaseStorey.PosType, modDevice.DbNumber, modPositionReleaseStorey.PlcPos); modDevice.ReleaseStorey = Convert.ToInt32(releaseStorey); //取货排 var modPositionPickRow = listPosition.FirstOrDefault(s => s.Text == "取货排"); (result, var pickRow) = modConn.GetPlcDBValue(modPositionPickRow.PosType, modDevice.DbNumber, modPositionPickRow.PlcPos); modDevice.PickRow = Convert.ToInt32(pickRow); //取货列 var modPositionPickCol = listPosition.FirstOrDefault(s => s.Text == "取货列"); (result, var pickCol) = modConn.GetPlcDBValue(modPositionPickCol.PosType, modDevice.DbNumber, modPositionPickCol.PlcPos); modDevice.PickCol = Convert.ToInt32(pickCol); //取货层 var modPositionPickStorey = listPosition.FirstOrDefault(s => s.Text == "取货层"); (result, var pickStorey) = modConn.GetPlcDBValue(modPositionPickStorey.PosType, modDevice.DbNumber, modPositionPickStorey.PlcPos); modDevice.PickStorey = Convert.ToInt32(pickStorey); } } catch (Exception) { @@ -274,6 +302,69 @@ } return list; } [HttpPost] [ApiDescriptionSettings(Name = "WriteValue")] [DisplayName("写入值")] public async Task WriteValue(WriteWcsDeviceInput modDevice) { var modPlc = await _wcsDeviceRep.Context.Queryable<WcsPlc>().FirstAsync(s => s.Id == modDevice.PlcId); if (modPlc == null) throw Oops.Bah("找不到PLC信息"); PLCUtil modUtil = new PLCUtil(modPlc); var listPosition = await _wcsDeviceRep.Context.Queryable<WcsPosition>().Where(s => s.DeviceId == modDevice.Id).ToListAsync(); //(var result, var plc) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos); //modDevice.Plc = Convert.ToString(plc); //任务号 var modPositionTask = listPosition.FirstOrDefault(s => s.Text == "任务号"); if (modPositionTask != null) modUtil.SetPlcDBValue(modPositionTask.PosType, modPositionTask.PlcPos, modDevice.TaskNo); //任务类型 var modPositionTaskType = listPosition.FirstOrDefault(s => s.Text == "任务类型"); if (modPositionTaskType != null) modUtil.SetPlcDBValue(modPositionTaskType.PosType, modPositionTaskType.PlcPos, modDevice.TaskType.ToString()); //起始工位 var modPositionStartLocatNo = listPosition.FirstOrDefault(s => s.Text == "起始工位"); if (modPositionStartLocatNo != null) modUtil.SetPlcDBValue(modPositionStartLocatNo.PosType, modPositionStartLocatNo.PlcPos, modDevice.StartLocatNo.ToString()); //目的工位 var modPositionEndLocatNo = listPosition.FirstOrDefault(s => s.Text == "目的工位"); if (modPositionEndLocatNo != null) modUtil.SetPlcDBValue(modPositionEndLocatNo.PosType, modPositionEndLocatNo.PlcPos, modDevice.EndLocatNo.ToString()); //托盘码 var modPositionPalletNo = listPosition.FirstOrDefault(s => s.Text == "托盘码"); if (modPositionPalletNo != null) modUtil.SetPlcDBValue(modPositionPalletNo.PosType, modPositionPalletNo.PlcPos, modDevice.PalletNo.ToString()); if (modPlc.Type == PLCTypeEnum.ConveyorLine) { //放货排 var modPositionReleaseRow = listPosition.FirstOrDefault(s => s.Text == "放货排"); if (modPositionReleaseRow != null) modUtil.SetPlcDBValue(modPositionReleaseRow.PosType, modPositionReleaseRow.PlcPos, modDevice.ReleaseRow.ToString()); //放货列 var modPositionReleaseCol = listPosition.FirstOrDefault(s => s.Text == "放货列"); if (modPositionReleaseRow != null) modUtil.SetPlcDBValue(modPositionReleaseCol.PosType, modPositionReleaseCol.PlcPos, modDevice.ReleaseCol.ToString()); //放货层 var modPositionReleaseStorey = listPosition.FirstOrDefault(s => s.Text == "放货层"); if (modPositionReleaseStorey != null) modUtil.SetPlcDBValue(modPositionReleaseStorey.PosType, modPositionReleaseStorey.PlcPos, modDevice.ReleaseStorey.ToString()); //取货排 var modPositionPickRow = listPosition.FirstOrDefault(s => s.Text == "取货排"); if (modPositionPickRow != null) modUtil.SetPlcDBValue(modPositionPickRow.PosType, modPositionPickRow.PlcPos, modDevice.PickRow.ToString()); //取货列 var modPositionPickCol = listPosition.FirstOrDefault(s => s.Text == "取货列"); if (modPositionPickCol != null) modUtil.SetPlcDBValue(modPositionPickCol.PosType, modPositionPickCol.PlcPos, modDevice.PickCol.ToString()); //取货层 var modPositionPickStorey = listPosition.FirstOrDefault(s => s.Text == "取货层"); if (modPositionPickStorey != null) modUtil.SetPlcDBValue(modPositionPickStorey.PosType, modPositionPickStorey.PlcPos, modDevice.PickStorey.ToString()); } modUtil.Close(); } #region 分拣码垛 @@ -304,8 +395,8 @@ [HttpGet] [ApiDescriptionSettings(Name = "WcsPackStationPlcList")] [DisplayName("获取设备对应工位列表")] public async Task<List<WcsDeviceTaskOrderDto>> WcsPackStationPlcList([FromQuery]WcsDeviceBaseInput entry) { public async Task<List<WcsDeviceTaskOrderDto>> WcsPackStationPlcList([FromQuery] WcsDeviceBaseInput entry) { return await _wcsDeviceRep.Context.Queryable<WcsDevice>() .LeftJoin<WcsCheckTask>((device, task) => device.StationNum == task.Port) .Where((device, task) => device.PlcId == entry.PlcId) Web/src/api/wcs/wcsDevice.ts
@@ -8,6 +8,7 @@ GetWcsPlcPlcIdDropdown = '/api/wcsDevice/WcsPlcPlcIdDropdown', GeneratePos = '/api/wcsDevice/GeneratePos', ListWcsDevice = '/api/wcsDevice/list', WriteValue = '/api/wcsdevice/writeValue', GetWcsPackPlcList='/api/wcsDevice/WcsPackPlcList', GetWcsPackStationPlcList='/api/wcsDevice/WcsPackStationPlcList', @@ -101,4 +102,11 @@ url: Api.CloseTaskForPLC, method: 'post', data: params, }); //写入值 export const writeValue = (params?: any) => request({ url: Api.WriteValue, method: 'post', data: params, }); Web/src/views/device/deviceMonitor/component/setting.vue
@@ -10,7 +10,7 @@ <el-card class="box-card" shadow="hover"> <template #header> <div class="card-header"> <div> <span>工位号:</span> <el-select v-model="stationValue" placeholder="请选择" filterable value-key="stationNum" @@ -22,7 +22,8 @@ <el-button style="margin-left: 10px;">自动</el-button> </div> <div> <div :class="['lineStatus', stationValue.status ? 'device-status-0' : 'device-status-1']"></div> <div :class="['lineStatus', stationValue.status ? 'device-status-0' : 'device-status-1']"> </div> </div> </div> </template> @@ -49,41 +50,41 @@ <el-input v-model="stationValue.wcs"></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="取货排"> <el-input ></el-input> <el-input></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="放货排"> <el-input ></el-input> <el-input></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="取货列"> <el-input ></el-input> <el-input></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="放货列"> <el-input ></el-input> <el-input></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="取货层"> <el-input ></el-input> <el-input></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="放货层"> <el-input ></el-input> <el-input></el-input> </el-form-item> </el-col> </el-row> </el-form> <div style="text-align: center;margin: 10px;"> <el-button class="button" size="large">写入数据</el-button> <el-button class="button" size="large" @click="write(stationValue)">写入数据</el-button> </div> </div> <template #footer> @@ -107,6 +108,8 @@ <script lang="ts" setup> import { ref, defineModel } from 'vue'; import { writeValue } from '/@/api/wcs/wcsDevice'; import { ElMessageBox,ElMessage } from 'element-plus'; const listStationsData = defineModel<any>("listStationsData") const stationValue = defineModel<any>("stationValue") @@ -122,7 +125,10 @@ // emit('update:listStationsData', listStationsData.value); // emit('update:stationValue', stationValue); // }; const write = async (row: any) => { await writeValue(row); ElMessage.success('写入成功!'); } const isShowDialog = ref(false); const openDialog = async (row: any) => { @@ -181,18 +187,18 @@ } .lineStatus { right: 0; height: 20px; width: 20px; border-radius: 50%; background-color: #67C23A; right: 0; height: 20px; width: 20px; border-radius: 50%; background-color: #67C23A; } .device-status-0 { background-color: #67C23A; background-color: #67C23A; } .device-status-1 { background-color: red; background-color: red; } </style> Web/src/views/device/deviceMonitor/index.vue
@@ -52,7 +52,6 @@ <div class="lineButtonfix"> <el-form label-position="left" label-width="80px"> <el-form-item> <el-button>写入</el-button> <el-button @click="openDialog">设置</el-button> </el-form-item> </el-form> @@ -85,6 +84,9 @@ <el-form-item label="目的工位"> <el-input v-model="deviceInfo.endLocatNo"></el-input> </el-form-item> <el-form-item label="托盘码"> <el-input v-model="deviceInfo.palletNo"></el-input> </el-form-item> <el-form-item label="PLC"> <el-input v-model="deviceInfo.plc"></el-input> </el-form-item> @@ -99,24 +101,47 @@ <div class="otherButtonfix"> <el-form label-position="left"> <el-form-item> <el-button>写入</el-button> <el-button @click="write(deviceInfo)">写入</el-button> </el-form-item> </el-form> </div> </el-card> </div> </el-main> <setting ref="settingDialogRef" :title="title" v-model:listStationsData="listStationsData" v-model:stationValue="stationValue" /> <setting ref="settingDialogRef" :title="title" v-model:listStationsData="listStationsData" v-model:stationValue="stationValue" /> </el-container> </template> <script lang="ts" setup> import { ref, reactive } from 'vue'; import { listWcsDevice } from '/@/api/wcs/wcsDevice'; import { ref, onMounted } from 'vue'; import { listWcsDevice, writeValue } from '/@/api/wcs/wcsDevice'; import { getDictDataItem as di, getDictDataList as dl } from '/@/utils/dict-utils'; import { listWcsPlc } from '/@/api/wcs/wcsPlc'; import { ElMessageBox, ElMessage } from 'element-plus'; import setting from '/@/views/device/deviceMonitor/component/setting.vue' import { signalR } from './signalR'; //连接signalR 监听变更 onMounted(async () => { signalR.off('PublicPlcDevice'); signalR.on('PublicPlcDevice', (data: any) => { //todo 需要测试 if (data.type == 0) { var index = listStackingMachineData.value.findIndex(s => s.id == data.id); if (index !== -1) { listStackingMachineData.value.splice(index, 1, data); } } else if (data.type == 1) { stations.value.forEach(list => { var index = list.findIndex(s => s.id == data.id); if (index !== -1) { list.splice(index, 1, data); } }); } }); }); const stations = ref<any>([]); const listStationsData = ref<any>([]); @@ -138,6 +163,10 @@ const openDialog = async () => { settingDialogRef.value.openDialog(stationValue); } const write = async (row: any) => { await writeValue(row); ElMessage.success('写入成功!'); } // 查询操作 const handleQuery = async () => { var listplc = await listWcsPlc({ type: 1 }); @@ -153,6 +182,19 @@ listStationsData.value = stations.value[lineValue.value]; stationValue.value = listStationsData.value[0]; } else { listStationsData.value = []; stationValue.value = { stationNum: '', taskNo: '', taskType: '', startLocatNo: '', endLocatNo: '', plc: '', wcs: '', status: false }; } title.value = listStationsData.value[0].text; }; Web/src/views/device/deviceMonitor/signalR.ts
New file @@ -0,0 +1,37 @@ import * as SignalR from '@microsoft/signalr'; import { getToken } from '/@/utils/axios-utils'; // 初始化SignalR对象 const connection = new SignalR.HubConnectionBuilder() .configureLogging(SignalR.LogLevel.Information) .withUrl(`${window.__env__.VITE_API_URL}/hubs/PlcDevice?token=${getToken()}`, { transport: SignalR.HttpTransportType.WebSockets, skipNegotiation: true }) .withAutomaticReconnect({ nextRetryDelayInMilliseconds: () => { return 5000; // 每5秒重连一次 }, }) .build(); connection.keepAliveIntervalInMilliseconds = 15 * 1000; // 心跳检测15s connection.serverTimeoutInMilliseconds = 30 * 60 * 1000; // 超时时间30m // 启动连接 connection.start().then(() => { console.log('启动连接plc'); }); // 断开连接 connection.onclose(async () => { console.log('断开连接plc'); }); // 重连中 connection.onreconnecting(() => { console.log('服务器已断线plc'); }); // 重连成功 connection.onreconnected(() => { console.log('重连成功plc'); }); // connection.on('PublicPlcConn', () => {}); export { connection as signalR };