Admin.NET/WCS.Application/Hub/IPlcHub.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Hub/PlcHub.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Hub/TaskLogHub.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/device/alarmManage/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/device/alarmManage/signalR.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/device/deviceInfo/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/device/deviceInfo/signalR.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/wcs/wcsTask/signalR.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Admin.NET/WCS.Application/Hub/IPlcHub.cs
@@ -21,5 +21,12 @@ /// <param name="context"></param> /// <returns></returns> //Task PublicStationStatus(List<WcsDevice> context); /// <summary> /// 下发报警信息 /// </summary> /// <param name="context"></param> /// <returns></returns> Task PublicAlarm(WcsAlarmInfoOutput context); } } Admin.NET/WCS.Application/Hub/PlcHub.cs
@@ -4,7 +4,7 @@ namespace WCS.Application; /// <summary> /// 任务日志集线器 /// PLC集线器 /// </summary> [MapHub("/hubs/Plc")] public class PlcHub : Hub<IPlcHub> @@ -20,10 +20,10 @@ /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task PublicPlcConn(WcsPlc context) { await _plcHubContext.Clients.All.PublicPlcConn(context); } //public async Task PublicPlcConn(WcsPlc context) //{ // await _plcHubContext.Clients.All.PublicPlcConn(context); //} /// <summary> /// 下发工位状态 @@ -34,4 +34,14 @@ //{ // await _plcHubContext.Clients.All.PublicStationStatus(context); //} /// <summary> /// 下发报警信息 /// </summary> /// <param name="context"></param> /// <returns></returns> //public async Task PublicAlarm(WcsAlarmInfoOutput context) //{ // await _plcHubContext.Clients.All.PublicAlarm(context); //} } Admin.NET/WCS.Application/Hub/TaskLogHub.cs
@@ -16,41 +16,41 @@ _taskLogHubContext = taskLogHubContext; } /// <summary> /// 连接 /// </summary> /// <returns></returns> public override async Task OnConnectedAsync() { await base.OnConnectedAsync(); } ///// <summary> ///// 连接 ///// </summary> ///// <returns></returns> //public override async Task OnConnectedAsync() //{ // await base.OnConnectedAsync(); //} /// <summary> /// 断开 /// </summary> /// <param name="exception"></param> /// <returns></returns> public override async Task OnDisconnectedAsync(Exception exception) { await base.OnDisconnectedAsync(exception); } ///// <summary> ///// 断开 ///// </summary> ///// <param name="exception"></param> ///// <returns></returns> //public override async Task OnDisconnectedAsync(Exception exception) //{ // await base.OnDisconnectedAsync(exception); //} /// <summary> /// 下发任务 /// </summary> /// <returns></returns> public async Task PublicTask(WcsTaskOutput context) { await _taskLogHubContext.Clients.All.PublicTask(context); } ///// <summary> ///// 下发任务 ///// </summary> ///// <returns></returns> //public async Task PublicTask(WcsTaskOutput context) //{ // await _taskLogHubContext.Clients.All.PublicTask(context); //} /// <summary> /// 下发任务明细 /// </summary> /// <returns></returns> public async Task PublicTaskMonitor(WcsTaskMonitorOutput context) { await _taskLogHubContext.Clients.All.PublicTaskMonitor(context); } ///// <summary> ///// 下发任务明细 ///// </summary> ///// <returns></returns> //public async Task PublicTaskMonitor(WcsTaskMonitorOutput context) //{ // await _taskLogHubContext.Clients.All.PublicTaskMonitor(context); //} } Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -14,7 +14,7 @@ private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId); private static readonly SysCacheService sysCacheService = App.GetRequiredService<SysCacheService>(); private static readonly IHubContext<PlcHub, IPlcHub> _plcHubContext; private static readonly IHubContext<PlcHub, IPlcHub> _plcHubContext = App.GetService<IHubContext<PlcHub, IPlcHub>>(); private static List<WcsPlc> listPlc; private static List<WcsDevice> listPlcDevice; Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs
@@ -1,4 +1,6 @@ namespace WCS.Application; using Microsoft.AspNetCore.SignalR; namespace WCS.Application; /// <summary> /// 报警信息表服务 @@ -7,9 +9,12 @@ public class WcsAlarmInfoService : IDynamicApiController, ITransient { private readonly SqlSugarRepository<WcsAlarmInfo> _wcsAlarmInfoRep; public WcsAlarmInfoService(SqlSugarRepository<WcsAlarmInfo> wcsAlarmInfoRep) private readonly IHubContext<PlcHub, IPlcHub> _plcHubContext; public WcsAlarmInfoService(SqlSugarRepository<WcsAlarmInfo> wcsAlarmInfoRep, IHubContext<PlcHub, IPlcHub> plcHubContext) { _wcsAlarmInfoRep = wcsAlarmInfoRep; _plcHubContext = plcHubContext; } /// <summary> @@ -118,7 +123,10 @@ [DisplayName("复位报警")] public async Task Reset() { throw Oops.Bah("开发中"); //测试推数据用的 await _plcHubContext.Clients.All.PublicAlarm(new WcsAlarmInfoOutput() { Id = new Random().Next(), StationNum = "205", AlarmCode = "MB102", AlarmName = "有物品遮挡", AlarmTime = DateTime.Now }); //throw Oops.Bah("开发中"); } Web/src/views/device/alarmManage/index.vue
@@ -5,13 +5,16 @@ <el-row style="display: flex;text-align: center;justify-content: center;height: 40px;"> <el-button type="warning" style="width: 95%;height: 30px;" @click="reset">报警复位</el-button> </el-row> <el-table :data="tableData" border style="width: 100%" v-loading="loading" <el-table :data="paginatedData" border style="width: 100%" v-loading="loading" :default-sort="{ prop: 'date', order: 'descending' }"> <el-table-column prop="alarmCode" label="变量" align="center"></el-table-column> <el-table-column prop="alarmName" label="描述" align="center"></el-table-column> <el-table-column prop="stationNum" label="位置" align="center"></el-table-column> <el-table-column prop="alarmTime" label="时间" align="center"></el-table-column> </el-table> <el-pagination v-model:currentPage="tableParams.page" v-model:page-size="tableParams.pageSize" :total="tableParams.total" :page-sizes="[10, 20, 50, 100, 200, 500]" size="small" background="" @size-change="handleSizeChange" @current-change="handleCurrentChange" layout="prev, pager, next" /> </el-col> <el-col :span="19"> <div class="card-page"> @@ -48,18 +51,23 @@ </template> <script lang="ts" setup> import { ref, reactive } from 'vue'; import { Splitpanes, Pane } from 'splitpanes'; import { ref, reactive, onMounted, computed } from 'vue'; import 'splitpanes/dist/splitpanes.css'; import { Vue2 } from 'vue-demi'; import { listWcsAlarmInfo, resetWcsAlarmInfo } from '/@/api/wcs/wcsAlarmInfo'; import { signalR } from './signalR'; const tableParams = ref({ page: 1, pageSize: 10, total: 0, }); const loading = ref(false); const tableData = ref<any>([]); const handleQuery = async () => { loading.value = true; var res = await listWcsAlarmInfo({ status: 1 }); tableData.value = res.data.result; tableParams.value.total = tableData.value.length; console.log(tableParams.value.total); loading.value = false; }; handleQuery(); @@ -67,8 +75,41 @@ //复位报警 const reset = async () => { await resetWcsAlarmInfo(); await handleQuery(); } //连接signalR 监听变更 onMounted(async () => { signalR.off('PublicAlarm'); signalR.on('PublicAlarm', (data: any) => { console.log(data) var listAlarm = tableData.value.filter(t => t.id == data.id); if (listAlarm.length == 0) { tableData.value.unshift(data) tableParams.value.total = tableData.value.length; } else { //如果已经存在就更新数据 const index = tableData.value.findIndex(t => t.id == data.id); tableData.value.splice(index, 1, data); } }); }); // 改变页面容量 const handleSizeChange = (val: number) => { tableParams.value.pageSize = val; }; // 改变页码序号 const handleCurrentChange = (val: number) => { tableParams.value.page = val; }; //表格显示数据 const paginatedData = computed(() => { const start = (tableParams.value.page - 1) * tableParams.value.pageSize const end = start + tableParams.value.pageSize return tableData.value.slice(start, end) }) //堆垛机数据 const cellsDataLine = [ Web/src/views/device/alarmManage/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/Plc?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('PublicAlarm', () => {}); export { connection as signalR }; Web/src/views/device/deviceInfo/index.vue
@@ -18,14 +18,14 @@ <el-collapse-item title="堆垛机" name="2"> <div style="overflow-x: auto;white-space: nowrap;"> <el-card v-for="(stacker, index) in stackers" :key="index" class="box-card" shadow="hover"> <el-switch v-model="stacker.isConn" :inactive-text="`${stacker.text}`"></el-switch> <el-switch disabled v-model="stacker.isConn" :inactive-text="`${stacker.text}`"></el-switch> </el-card> </div> </el-collapse-item> <el-collapse-item title="输送线" name="3"> <el-card v-for="(conveyor, index) in conveyors" :key="index" class="box-card" shadow="hover"> <el-switch v-model="conveyor.isConn" :inactive-text="`${conveyor.text}`"></el-switch> <el-switch disabled v-model="conveyor.isConn" :inactive-text="`${conveyor.text}`"></el-switch> </el-card> </el-collapse-item> </el-collapse> @@ -65,9 +65,10 @@ </template> <script lang="ts" setup> import { ref, reactive } from 'vue'; import { Vue2 } from 'vue-demi'; import { ref, reactive, onMounted } from 'vue'; import { listStatus } from '/@/api/wcs/wcsPlc'; import { signalR } from './signalR'; const state = ref<any>({}); const stackers = ref<any>({}); @@ -80,6 +81,28 @@ conveyors.value = res.data.result.listPlc.filter(s => s.type == 1 || s.type == 4); }; handleQuery(); //连接signalR 监听变更 onMounted(async () => { signalR.off('PublicPlcConn'); signalR.on('PublicPlcConn', (data: any) => { console.log(data) if (data.type === 0) { // 替换 stackers 中的相应项 const index = stackers.value.findIndex(item => item.id === data.id); if (index !== -1) { stackers.value[index] = data; } } else if (data.type === 1 || data.type === 4) { // 替换 conveyors 中的相应项 const index = conveyors.value.findIndex(item => item.id === data.id); if (index !== -1) { conveyors.value[index] = data; } } console.log(stackers.value[0].isConn) }); }); const activeName = ['1', '2', '3']; const value1 = ref(false); @@ -1949,12 +1972,16 @@ .grid-container-line { display: grid; grid-template-columns: repeat(51, 1fr); /* 自适应列宽 */ grid-template-rows: 1fr; /* 自适应行高 */ grid-template-columns: repeat(51, 1fr); /* 自适应列宽 */ grid-template-rows: 1fr; /* 自适应行高 */ gap: 0; margin-top: 25px; width: 100%; /* 宽度自适应 */ height: 1fr; /* 高度自适应 */ width: 100%; /* 宽度自适应 */ height: 1fr; /* 高度自适应 */ } .grid-item-line { @@ -2031,9 +2058,12 @@ background-color: #9c9c9c; border: 1px solid #797777; text-align: center; line-height: 1.4vw; /* 行高 */ width: 100%; /* 自适应宽度 */ height: 100%; /* 自适应高度 */ line-height: 1.4vw; /* 行高 */ width: 100%; /* 自适应宽度 */ height: 100%; /* 自适应高度 */ color: #fff; font-size: 0.7vw; } Web/src/views/device/deviceInfo/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/Plc?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 }; Web/src/views/wcs/wcsTask/signalR.ts
@@ -32,6 +32,6 @@ console.log('重连成功task'); }); connection.on('PublicTask', () => {}); // connection.on('PublicTask', () => {}); export { connection as signalR };