Admin.NET/WCS.Application/Hub/PlcHub.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/PLC/PLCUtil.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceOutput.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Service/WcsDevice/WcsDeviceService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Service/WcsTask/WcsTaskService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/device/deviceMonitor/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/wcs/wcsTask/component/editDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Admin.NET/WCS.Application/Hub/PlcHub.cs
@@ -42,7 +42,13 @@ { //运行状态 if (context.BoRunningState.HasValue) { PLCTaskAction.boRunningState = context.BoRunningState.Value; if (context.BoRunningState.Value) PLCTaskAction.Init(); else PLCTaskAction.Stop(); } //脱机模式 if (context.BoOffline.HasValue) PLCTaskAction.boOffline = context.BoOffline.Value; Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -21,7 +21,7 @@ private static List<WcsPosition> listPlcStation; private static List<PLCUtil> listPlcUtil = new List<PLCUtil>(); private static CancellationTokenSource cts;//取消线程标识 private static CancellationTokenSource cts = new CancellationTokenSource();//取消线程标识 //对外公布连接状态 public static List<PLCUtil> listPlcConn { @@ -64,6 +64,7 @@ cts = new CancellationTokenSource(); boRunningState = true; StartRead(); ConnectionStatus(); } /// <summary> /// 开启读取plc线程 @@ -82,8 +83,10 @@ { foreach (var modPlcUtil in listPlcUtil) { if (modPlcUtil != null && modPlcUtil.Connected) modPlcUtil.Close(); } break; throw new OperationCanceledException(); } try @@ -94,7 +97,7 @@ modPlcUtil = new PLCUtil(modPlc); listPlcUtil.Add(modPlcUtil); } var listDevice = listPlcDevice.Where(s => s.PlcId == _modplc.Id).ToList(); var listDevice = listPlcDevice.Where(s => s.PlcId == _modplc.Id && s.DeviceType == DeviceTypeEnum.Business).ToList(); //循环读设备 foreach (var modDevice in listDevice.Where(s => s.Level == DeviceLevelEnum.DB)) { @@ -109,9 +112,9 @@ dto.Type = _modplc.Type; dto.PLCUtil = modPlcUtil; dto.listStation = listPlcStation.Where(s => s.DeviceId == modDevice.Id).ToList(); dto.listDevice = listDevice.Where(s => s.StationNum == modDevice.StationNum).ToList(); dto.listDevice = listDevice.Where(s => s.StationNum == modDevice.StationNum && s.Level == DeviceLevelEnum.Station).ToList(); //这里触发值变更事件 DeviceValueChangeEvent?.Invoke(dto, EventArgs.Empty); //DeviceValueChangeEvent?.Invoke(dto, EventArgs.Empty); } else { Admin.NET/WCS.Application/PLC/PLCUtil.cs
@@ -13,7 +13,7 @@ public readonly long PlcId; private SiemensClient _client; private WcsPlc _modPlc; private readonly object OLock = new object(); public PLCUtil(WcsPlc modPlc) { PlcId = modPlc.Id; @@ -41,6 +41,8 @@ /// <param name="Pos">偏移量/地址</param> /// <returns></returns> public (IoTClient.Result, dynamic value) GetPlcDBValue(PLCDataTypeEnum PosType, string DbNumber, string Pos) { lock (OLock) { string address; if (DbNumber.StartsWith("DB")) @@ -89,11 +91,14 @@ } return (result, result.Value); } } /// <summary> /// 批量读取PLC值 /// </summary> /// <returns></returns> public Result<Dictionary<string, object>> GetPlcBatchDBValue(Dictionary<string, PLCDataTypeEnum> listaddress) { lock (OLock) { Dictionary<string, DataTypeEnum> addresses = new Dictionary<string, DataTypeEnum>(); foreach (var address in listaddress) @@ -139,6 +144,7 @@ } return _client.BatchRead(addresses); } } /// <summary> /// 写入PLC值 /// </summary> Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceOutput.cs
@@ -124,12 +124,26 @@ /// 任务类型 /// </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; } public bool Status { get; set; } = false; } Admin.NET/WCS.Application/Service/WcsDevice/WcsDeviceService.cs
@@ -1,5 +1,6 @@ using Admin.NET.Core.Service; using Elastic.Clients.Elasticsearch; namespace WCS.Application; @@ -203,20 +204,69 @@ { var list = await _wcsDeviceRep.AsQueryable() .LeftJoin<WcsPlc>((a, b) => a.PlcId == b.Id) .Where((a, b) => a.DeviceType == DeviceTypeEnum.Business) .Select<WcsDeviceOutput>((a, b) => new WcsDeviceOutput() { Type = b.Type }, true) .ToListAsync(); //获取跺机的状态 foreach (var modDevice in list) { if (_sysCacheService.ExistKey("PlcConn" + modDevice.PlcId)) if (_sysCacheService.ExistKey("PLCCONN" + modDevice.PlcId)) { var cachePlc = _sysCacheService.Get<WcsPlc>("PlcConn" + modDevice.PlcId); var cachePlc = _sysCacheService.Get<WcsPlc>("PLCCONN" + modDevice.PlcId); modDevice.Status = cachePlc.IsConn; if (modDevice.Status) { //读取plc的值 var modConn = PLCTaskAction.listPlcConn.FirstOrDefault(s => s != null && s.PlcId == modDevice.PlcId); if (modConn == null) break; try { 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); (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); 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); modDevice.PalletNo = Convert.ToString(palletNo); } catch (Exception) { } } } else { modDevice.Status = false; } //modDevice.TaskNo = "TK00001"; //modDevice.TaskType = TaskTypeEnum.In; //modDevice.PalletNo = "2024209032"; //modDevice.StartLocatNo = "010101"; //modDevice.EndLocatNo = "020202"; //modDevice.Wcs = new Random().Next(100).ToString(); //modDevice.Plc = new Random().Next(100).ToString(); //modDevice.Status = true; } return list; Admin.NET/WCS.Application/Service/WcsTask/WcsTaskService.cs
@@ -52,7 +52,12 @@ [DisplayName("增加任务表")] public async Task<long> Add(AddWcsTaskInput input) { if(await _wcsTaskRep.AsQueryable().AnyAsync(s => s.TaskNo == input.TaskNo)) { throw Oops.Bah("任务号重复"); } var entity = input.Adapt<WcsTask>(); entity.Origin = "WCS"; await _wcsTaskRep.InsertAsync(entity); return entity.Id; } Web/src/views/device/deviceMonitor/index.vue
@@ -4,43 +4,49 @@ <el-card class="box-card"> <div slot="header" class="linefix"> <span>输送线</span> <div class="lineStatus"></div> <div :class="['lineStatus', { 'device-status-0': stationValue.status === true }, { 'device-status-1': stationValue.status === false }]"> </div> </div> <div class="choosefix"> <el-select v-model="lineValue" placeholder="请选择"> <el-select v-model="lineValue" placeholder="请选择" @change="handleLineChange('item', $event)"> <el-option v-for="item in lineOptions" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> <el-select v-model="stationValue" placeholder="请选择" style="margin-top: 10px;"> <el-option v-for="item in stations" :key="item.id" :label="item.stationNum" :value="item.id"></el-option> <el-select v-model="stationValue" placeholder="请选择" style="margin-top: 10px;" value-key="stationNum"> <el-option v-for="item in listStationsData" :key="item.id" :label="item.stationNum" :value="item"> </el-option> </el-select> </div> <div class="lineValuefix"> <el-form label-position="left" label-width="80px"> <el-form-item label="任务号"> <el-input></el-input> <el-input v-model="stationValue.taskNo"></el-input> </el-form-item> <el-form-item label="任务类型"> <el-input></el-input> <el-select clearable v-model="stationValue.taskType" placeholder="请选择任务类型"> <el-option v-for="(item,index) in dl('TaskTypeEnum')" :key="index" :value="Number(item.value)" :label="`${item.name} [${item.value}]`"></el-option> </el-select> </el-form-item> <el-form-item label="起始工位"> <el-input></el-input> <el-input v-model="stationValue.startLocatNo"></el-input> </el-form-item> <el-form-item label="目的工位"> <el-input></el-input> <el-input v-model="stationValue.endLocatNo"></el-input> </el-form-item> <el-form-item label="托盘码"> <el-input></el-input> <el-input v-model="stationValue.palletNo"></el-input> </el-form-item> <el-form-item label="PLC"> <el-input></el-input> <el-input v-model="stationValue.plc"></el-input> </el-form-item> <el-form-item label="WCS"> <el-input></el-input> <el-input v-model="stationValue.wcs"></el-input> </el-form-item> <el-form-item label="状态"> <el-input></el-input> <el-input :value="stationValue.status ? '在线' : '离线'" readonly></el-input> </el-form-item> </el-form> </div> @@ -71,8 +77,15 @@ <el-form-item label="任务类型"> <el-select clearable="" v-model="deviceInfo.taskType" placeholder="请选择状态"> <el-option v-for="(item, index) in dl('TaskTypeEnum')" :key="index" :value="Number(item.value)" :label="`${item.name} (${item.code}) [${item.value}] `" /> :value="Number(item.value)" :label="`${item.name} [${item.value}] `" /> </el-select> </el-form-item> <el-form-item label="起始工位"> <el-input v-model="deviceInfo.startLocatNo"></el-input> </el-form-item> <el-form-item label="目的工位"> <el-input v-model="deviceInfo.endLocatNo"></el-input> </el-form-item> <el-form-item label="PLC"> <el-input v-model="deviceInfo.plc"></el-input> @@ -106,10 +119,19 @@ import { getDictLabelByVal as dv } from '/@/utils/dict-utils'; const stations = ref<any>([]); const listStationsData = ref<any>([]); const listStackingMachineData = ref<any>([]); const lineValue = ref('1'); const stationValue = ref(); const lineValue = ref(1); const stationValue = ref<any>({ taskNo: '', taskType: '', startLocatNo:'', endLocatNo: '', plc: '', wcs: '', status: false }); // 查询操作 const handleQuery = async () => { @@ -117,47 +139,29 @@ listStackingMachineData.value = res.data.result.filter(s => s.type == 0); const listConveyorLineData = res.data.result.filter(s => s.type == 1 || s.type == 4); stations.value = { '1': listConveyorLineData.filter(s => s.text = '1层托盘输送线'), '2': listConveyorLineData.filter(s => s.text = '2层托盘输送线'), '3': listConveyorLineData.filter(s => s.text = '3层托盘输送线') 1: listConveyorLineData.filter(s => s.text == '1层托盘输送线'), 2: listConveyorLineData.filter(s => s.text == '2层托盘输送线'), 3: listConveyorLineData.filter(s => s.text == '3层托盘输送线') } if (stations.value.length > 0) stationValue.value = stations.value[0][0].id; debugger; if (stations.value[1].length > 0) { listStationsData.value = stations.value[1]; stationValue.value = listStationsData.value[0]; } }; handleQuery(); const handleLineChange = (field: string, value: number) => { listStationsData.value = stations.value[value]; stationValue.value = {}; }; const lineOptions = [ { value: '1', label: '一楼输送线' }, { value: '2', label: '二楼输送线' }, { value: '3', label: '三楼输送线' } { value: 1, label: '一楼输送线' }, { value: 2, label: '二楼输送线' }, { value: 3, label: '三楼输送线' } ]; const deviceList = reactive([ { id: 1, name: '1号码垛机器人', taskNumber: 'T000001', taskType: '', plc: '', wcs: '', status: 0 }, { id: 2, name: '2号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 1 }, { id: 3, name: '3号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 0 }, { id: 4, name: '4号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 1 }, { id: 5, name: '5号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 0 }, { id: 6, name: '6号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 0 }, { id: 7, name: '7号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: '' }, { id: 8, name: '8号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 0 } ]); const deviceTypeText = (taskType: number) => { switch (taskType) { case 0: return '入库任务' case 1: return '出库任务' case 2: return '移库任务' case 3: return 'PLC申请入库' } return '' }; </script> <style scoped> @@ -165,8 +169,8 @@ font-size: 14px; } .item { margin-bottom: 18px; .el-form-item--small { margin-bottom: 10px; } .linefix { Web/src/views/wcs/wcsTask/component/editDialog.vue
@@ -30,13 +30,6 @@ </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="来源" prop="origin"> <el-input v-model="ruleForm.origin" placeholder="请输入来源" maxlength="20" show-word-limit clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="起始位置" prop="startLocate"> <el-input v-model="ruleForm.startLocate" placeholder="请输入起始位置" maxlength="20" show-word-limit clearable /> @@ -67,55 +60,6 @@ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="托盘号" prop="palletNo"> <el-input v-model="ruleForm.palletNo" placeholder="请输入托盘号" maxlength="20" show-word-limit clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="批次号" prop="lotNo"> <el-input v-model="ruleForm.lotNo" placeholder="请输入批次号" maxlength="20" show-word-limit clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="供货批次" prop="supplierLot"> <el-input v-model="ruleForm.supplierLot" placeholder="请输入供货批次" maxlength="20" show-word-limit clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="物料编码" prop="skuNo"> <el-input v-model="ruleForm.skuNo" placeholder="请输入物料编码" maxlength="20" show-word-limit clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="物料名称" prop="skuName"> <el-input v-model="ruleForm.skuName" placeholder="请输入物料名称" maxlength="20" show-word-limit clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="数量" prop="qty"> <el-input-number v-model="ruleForm.qty" placeholder="请输入数量" clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="拆垛数量" prop="completeQty"> <el-input-number v-model="ruleForm.completeQty" placeholder="请输入拆垛数量" clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="拣货方式" prop="unstackingMode"> <el-input v-model="ruleForm.unstackingMode" placeholder="请输入拣货方式" maxlength="10" show-word-limit clearable /> </el-form-item>