hwh
2024-08-30 97dd41eae518db7307b2170a1d986760ef51a53d
报警页面和首页设备实时通讯
8个文件已修改
2个文件已添加
290 ■■■■ 已修改文件
Admin.NET/WCS.Application/Hub/IPlcHub.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Hub/PlcHub.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Hub/TaskLogHub.cs 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/device/alarmManage/index.vue 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/device/alarmManage/signalR.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/device/deviceInfo/index.vue 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/device/deviceInfo/signalR.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/wcs/wcsTask/signalR.ts 2 ●●● 补丁 | 查看 | 原始文档 | 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 };