/// <summary> /// 将文件转换为byte数组 /// </summary> /// <param name="path">文件地址</param> /// <returns>转换后的byte数组</returns> public static byte[] FileToBytes(string path) { if (!System.IO.File.Exists(path)) { return(new byte[0]); } FileInfo fi = new FileInfo(path); byte[] buff = new byte[fi.Length]; FileStream fs = fi.OpenRead(); fs.Read(buff, 0, SafeConverter.SafeToInt(fs.Length)); fs.Close(); return(buff); }
/// <summary> /// 从地址字符串中获取Modbus的信息 /// </summary> /// <param name="address">地址字符串</param> /// <param name="station"></param> /// <param name="function"></param> /// <param name="modAddress"></param> /// <param name="length"></param> public static void GetModbusInfo(string address, ref int station, ref byte function, ref int modAddress, ref int length) { if (address.IndexOf(';') < 0) { modAddress = SafeConverter.SafeToInt(address); // 正常地址 } else { string[] list = address.Split(';'); // 带功能码的地址 for (int i = 0; i < list.Length; i++) { if (string.IsNullOrEmpty(list[i])) { continue; } if (list[i][0] == 's' || list[i][0] == 'S') // 站号信息 { station = SafeConverter.SafeToInt(list[i].Substring(2)); } else if (list[i][0] == 'f' || list[i][0] == 'F') //功能码 { function = (byte)SafeConverter.SafeToInt(list[i].Substring(2)); } else if (list[i][0] == 'd' || list[i][0] == 'D') //数据 { modAddress = SafeConverter.SafeToInt(list[i].Substring(2)); } else if (list[i][0] == 'l' || list[i][0] == 'L') //长度 { length = SafeConverter.SafeToInt(list[i].Substring(2)); } else { if (modAddress == 0) { modAddress = SafeConverter.SafeToInt(list[i]); } } } } }
private List <RsItemMaster> Createm_RsItemMasters(DataTable dt) { m_RsItemMasters = new List <RsItemMaster>(); for (int i = 2; i < dt.Rows.Count; i++) { RsItemMaster m_RsItemMaster = new RsItemMaster(); m_RsItemMaster.PKNO = Guid.NewGuid().ToString("N"); m_RsItemMaster.DRAWING_NO = dt.Rows[i][0].ToString(); m_RsItemMaster.ITEM_NAME = dt.Rows[i][1].ToString(); m_RsItemMaster.ITEM_SPECS = dt.Rows[i][2].ToString(); m_RsItemMaster.ITEM_NORM = dt.Rows[i][3].ToString(); m_RsItemMaster.NORM_CLASS = SafeConverter.SafeToInt(dt.Rows[i][4].ToString()); //m_RsItemMaster.THEORETICAL_WEIGHT =int.Parse( dt.Rows[i][6].ToString()); //m_RsItemMaster.KEY_PART_NORM = dt.Rows[i][5].ToString(); m_RsItemMaster.USE_FLAG = int.Parse(dt.Rows[i][7].ToString()); m_RsItemMaster.REMARK = dt.Rows[i][8].ToString(); m_RsItemMaster.CREATION_DATE = DateTime.Now; m_RsItemMaster.CREATED_BY = CBaseData.LoginName; m_RsItemMaster.LAST_UPDATE_DATE = DateTime.Now; //最后修改日期 m_RsItemMasters.Add(m_RsItemMaster); } return(m_RsItemMasters); }
/// <summary> /// 后台自动升级程序 /// <param name="bFisrtCheck">是否首次检测</param> /// </summary> public static void UpdateAppVersion(bool bFisrtCheck) { try { if (File.Exists(UpgradeBatFile)) { File.Delete(UpgradeBatFile); } //删除升级文件 string updateCmd = ""; int iUpdateIndex = 0; //升级文件的序号 bool bForceUpdate = false; //强制升级 foreach (SysAppInfo appInfo in AllModels) { string error; List <string> value = VersionProcess.GetDBVersionNO(appInfo.MODEL_CODE, out error); //获取服务器的新版本 if (!string.IsNullOrEmpty(error)) //错误 { if (bFisrtCheck) //第一次检验失败 { WPFMessageBox.ShowError(error + "请检查连接!", "系统启动失败"); App.AppExit(5); //系统退出 } continue; } int dbVersion = -1; string newAppPKNO = ""; if (value.Count >= 2) { newAppPKNO = value[0]; dbVersion = SafeConverter.SafeToInt(value[1]); } if (dbVersion < appInfo.MODEL_INNER_VERSION) //服务器版本 < 当前版本 => 上传 { string filename = Environment.CurrentDirectory + "\\" + (String.IsNullOrEmpty(appInfo.APP_RELATIVE_PATH) ? "" : appInfo.APP_RELATIVE_PATH + "\\") + appInfo.APP_NAME; if (!File.Exists(filename)) { continue; } #region 版本 SysAppInfo newApp = new SysAppInfo() { PKNO = CBaseData.NewGuid(), MODEL_CODE = appInfo.MODEL_CODE, MODEL_NAME = appInfo.MODEL_NAME, MODEL_INNER_VERSION = appInfo.MODEL_INNER_VERSION, MODEL_VERSION = appInfo.MODEL_VERSION, APP_NAME = appInfo.APP_NAME, APP_RELATIVE_PATH = appInfo.APP_RELATIVE_PATH, VERSION_INTROD = appInfo.VERSION_INTROD, MODEL_CONTENT = FileHelper.FileToBytes(filename), //上传文档 CREATED_BY = CBaseData.LoginName, CREATION_DATE = DateTime.Now, VERSION_TYPE = appInfo.VERSION_TYPE, REMARK = appInfo.REMARK, }; bool ret = VersionProcess.UploadApp(newApp); //上传到数据库 if (ret) { EventLogger.Log($"上传最新版本 {newApp.MODEL_VERSION} 的程序【{newApp.MODEL_NAME}】到服务器。"); } #endregion } else if (dbVersion > appInfo.MODEL_INNER_VERSION) //服务器版本 > 当前版本 => 升级 { #region 载最新版本 SysAppInfo newApp = VersionProcess.GetNewApp(newAppPKNO); //下载 #endregion if (string.IsNullOrEmpty(newApp?.PKNO)) //下载失败 { continue; } bool updateResult = false; //强制升级 #region 保存到本地,并升级 string newfilename = Environment.CurrentDirectory + "\\Temp\\" + (String.IsNullOrEmpty(newApp.APP_RELATIVE_PATH) ? "" : newApp.APP_RELATIVE_PATH + "\\") + newApp.APP_NAME; string directory = Path.GetDirectoryName(newfilename); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } FileHelper.BytesToFile(newApp.MODEL_CONTENT, newfilename); string oldfilename = Environment.CurrentDirectory + "\\" + (String.IsNullOrEmpty(newApp.APP_RELATIVE_PATH) ? "" : newApp.APP_RELATIVE_PATH + "\\") + newApp.APP_NAME; string filename = (String.IsNullOrEmpty(newApp.APP_RELATIVE_PATH) ? "" : newApp.APP_RELATIVE_PATH + "\\") + newApp.APP_NAME; try { File.Copy(newfilename, oldfilename); updateResult = true; //升级成功 EventLogger.Log($"【{appInfo.MODEL_NAME}】 {appInfo.MODEL_VERSION} 完成自动升级。"); } catch (Exception) //升级失败 { iUpdateIndex++; //索引号 #region 形成升级Bat updateCmd += $"echo {iUpdateIndex}. 正在升级 【{appInfo.MODEL_NAME}】 到 {appInfo.MODEL_VERSION} ..." + Environment.NewLine; //显示提示信息 updateCmd += "ping 127.0.0.1 -n 2 > nul " + Environment.NewLine; //暂停2s updateCmd += "if not exist Temp\\" + filename + " (" + Environment.NewLine; //检验是否已经下载了文件 updateCmd += $" echo 【{appInfo.MODEL_NAME}】 {appInfo.MODEL_VERSION} ... 尚未下载,升级失败!" + Environment.NewLine; // updateCmd += $")" + Environment.NewLine; // updateCmd += "copy /y " + "Temp\\" + filename + " " + filename + Environment.NewLine; //复制 => 升级文件 updateCmd += "if %ERRORLEVEL% == 0 (" + Environment.NewLine; //复制成功 updateCmd += $" echo 【{appInfo.MODEL_NAME}】 {appInfo.MODEL_VERSION} 升级成功。" + Environment.NewLine; // updateCmd += $" echo %DATE% %TIME% 完成【{appInfo.MODEL_NAME}】 {appInfo.MODEL_VERSION} 的升级 >>log\\AutoUpdate.txt" + Environment.NewLine; // updateCmd += ") else (" + Environment.NewLine; //复制失败 updateCmd += " copy /y " + "Temp\\" + filename + " " + filename + Environment.NewLine; //二次复制 => 升级文件 updateCmd += " if %ERRORLEVEL% == 0 (" + Environment.NewLine; //复制成功 updateCmd += $" echo 【{appInfo.MODEL_NAME}】 {appInfo.MODEL_VERSION} 升级成功。" + Environment.NewLine; // updateCmd += $" echo %DATE% %TIME% 完成【{appInfo.MODEL_NAME}】 {appInfo.MODEL_VERSION} 的升级 >>log\\AutoUpdate.txt" + Environment.NewLine; // updateCmd += " ) else (" + Environment.NewLine; updateCmd += $" echo 【{appInfo.MODEL_NAME}】 {appInfo.MODEL_VERSION} 升级失败,请退出系统后,运行【{UpgradeBatFile}】。" + Environment.NewLine; // updateCmd += $" echo %DATE% %TIME% 【{appInfo.MODEL_NAME}】 {appInfo.MODEL_VERSION} 升级失败,错误代码为 %ERRORLEVEL% >>log\\AutoUpdate.txt" + Environment.NewLine; // updateCmd += " pause" + Environment.NewLine; updateCmd += " exit" + Environment.NewLine; updateCmd += " )" + Environment.NewLine; updateCmd += ")" + Environment.NewLine; #endregion updateResult = false; } #endregion if ((!updateResult) && (!bForceUpdate)) //升级失败,检验是否强制升级 { if (bFisrtCheck) { bForceUpdate = true; //强制升级 } else //不是第一次检测,则需要检测是否强制升级 { int updateType = VersionProcess.CheckUpdateVersion(appInfo.MODEL_CODE, appInfo.MODEL_INNER_VERSION.Value); //获取版本升级信息,是否强制升级 #region 强制升级 if (updateType == 2) //强制升级 { bForceUpdate = true; //强制升级 } #endregion } } } } //end foreach if (!string.IsNullOrEmpty(updateCmd)) //有升级 { if (!Directory.Exists("log")) { Directory.CreateDirectory("log"); } updateCmd = "@echo off " + Environment.NewLine + " color fc " + Environment.NewLine + " title ******** 客户端自动升级程序 ******* " + Environment.NewLine + " echo *****************客户端自动升级程序(共" + iUpdateIndex + "个) ************* " + Environment.NewLine + updateCmd; updateCmd += "echo 系统升级成功!" + (bFisrtCheck ? "请重新打开程序。": "") + Environment.NewLine; //升级成功 updateCmd += "del /f /q " + UpgradeBatFile + Environment.NewLine; //删除本身 FileHelper.SaveStrToFile(updateCmd, UpgradeBatFile, true); //保存升级文件 } if (bForceUpdate) //强制升级 { Application.Current.Dispatcher.Invoke(new Action(() => { WPFMessageBox.ShowWarring( $"检测到系统有强制升级的新版本,系统自动升级失败,需要强制升级。" + Environment.NewLine + "***!系统将退出!***", "自动升级程序"); })); App.AppExit(5); } } catch (Exception ex) { NetLog.Error("自动升级程序失败,", ex); Console.WriteLine("自动升级程序失败,错误为:" + ex.Message); } }
public bool FinishProgress() { if (curProcess.PROCESS_STATE == 2) //正在执行,完成该动作 { if (!string.IsNullOrEmpty(startCondition) && !LimitConditions.Contains(startCondition)) //未完成的任务需要增加开始条件 { LimitConditions.Add(startCondition); } #region 完成执行工序 共 3 步 /************ !!!工序完成的条件!!! ************/ string sCurFinishValue = ""; //当前完成的结果 #region 1. 检验当前工序是否完成,未完成,则下一个任务 FmsAssetTagSetting finishTag = jobTaskMode.CopyTags.FirstOrDefault(c => c.PKNO == curAction.FINISH_CONDITION_TAG_PKNO); if (finishTag != null) { string condition = finishTag.PKNO + ".VALUE = " + curAction.FINISH_CONDITION_VALUE; //如果前面的Job存在需要判断该状态,则不执行完成当前 if ((startCondition != condition) && LimitConditions.Contains(condition)) { string sErrorInfo = $"正在执行[{ctrolName}],完成条件[{finishTag?.TAG_NAME}]不足."; if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(s => s.UpdateMesJobOrder(mesJobOrder)); } if (FMSControlService.bStart) { return(true); } } if (finishTag.SAMPLING_MODE == 11) //动作开始后自动开启 => 尚未开启,需要开启 { var tag0 = DeviceMonitor.GetTagSettingById(curAction.FINISH_CONDITION_TAG_PKNO); tag0.SAMPLING_MODE = 10; //尚未开启,需要开启 DeviceMonitor.SetTagSettingValue(tag0, ""); //清空完成条件 if (FMSControlService.bStart) { return(true); } } sCurFinishValue = finishTag.CUR_VALUE; //当前设备的值 string checkValue = sCurFinishValue.Split('|')[0]; //多结果情况,适用于检测 string finishValue = curAction.FINISH_CONDITION_VALUE; string[] finishValues = finishValue.Split('|'); //多个完成条件 if (!finishValues.Contains(checkValue)) //当前值不是工序结束值,不完成 { string sErrorInfo = $"正在执行[{ctrolName}],获取到完成结果为[{checkValue}],判断完成条件为[{finishValue}],生产过程[{ctrolName}]尚未完成."; if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(s => s.UpdateMesJobOrder(mesJobOrder)); } if (!LimitConditions.Contains(condition)) { LimitConditions.Add(condition); //完成条件不满足 } if (FMSControlService.bStart) { return(true); } } //移除完成限制条件 LimitConditions.Remove(condition); //完成条件满足 则移除不满足的条件 if (string.IsNullOrEmpty(startCondition)) { LimitConditions.Remove(startCondition); //移除开始的限制条件 } } else //没有动作完成的检测值,手动完成。 { string sErrorInfo = $"生产过程[{ctrolName}]没有设置过程完成的检测值,请手动完成该过程."; //生产执行信息 if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(s => s.UpdateMesJobOrder(mesJobOrder)); } if (string.IsNullOrEmpty(startCondition)) { LimitConditions.Remove(startCondition); //移除开始的限制条件 } if (FMSControlService.bStart) { return(true); } } #endregion /************ !!!工序已经完成!!! ************/ Console.WriteLine($"收到设备完成指令,完成反馈结果为[{sCurFinishValue}],完成生产过程[{ctrolName}]"); #region 2. 根据工序类型处理 完成当前工序 if (curProcess.PROCESS_ACTION_TYPE == 3) //检测完成 { //合格数量 string[] checkResult = sCurFinishValue.Split('|'); int qualifiedNumber = 1; //合格品数量 if (checkResult.Count() >= 2) { qualifiedNumber = SafeConverter.SafeToInt(checkResult[1], 1); } curProcess.COMPLETE_QTY = qualifiedNumber; //生产数量 - 含不合格的丢弃 curProcess.QUALIFIED_QTY = qualifiedNumber; //合格品数量 mesJobOrder.ONLINE_QTY = mesJobOrder.ONLINE_QTY - firstProcess.PROCESS_QTY + curProcess.QUALIFIED_QTY; //在线数量,更新再制品数量 if (mesJobOrder.ONLINE_QTY < 0) { mesJobOrder.ONLINE_QTY = 0; } } if (productProcess != null) { if (bLastProcess) { productProcess.PRODUCT_STATE = 100; //最后一道工序 正常完成 } string result = DeviceProcessControl.FinishCurBusiness(curProcess); //完成业务 if (result != "OK") { string sErrorInfo = $"业务完成失败,写入数据库错误!"; if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(s => s.UpdateMesJobOrder(mesJobOrder)); } } } #region 已删除 - 之前的方式 if (curProcess.PROCESS_ACTION_TYPE == 1) //加工完成 { //if (productProcess != null) //{ // productProcess.CUR_ITEM_PKNO = curProcess.FINISH_ITEM_PKNO; //生产完成 //} } else if (curProcess.PROCESS_ACTION_TYPE == 2) //搬运完成 { //if (productProcess != null) //{ // productProcess.PRODUCT_POSITION = curProcess.FINISH_POSITION; //目标位置 //} } else if (curProcess.PROCESS_ACTION_TYPE == 3) //检测完成 { //合格数量 string[] result = sCurFinishValue.Split('|'); int qualifiedNumber = 1; //合格品数量 if (result.Count() >= 2) { qualifiedNumber = SafeConverter.SafeToInt(result[1], 1); } curProcess.COMPLETE_QTY = qualifiedNumber; //生产数量 - 含不合格的丢弃 curProcess.QUALIFIED_QTY = qualifiedNumber; //合格品数量 mesJobOrder.ONLINE_QTY = mesJobOrder.ONLINE_QTY - firstProcess.PROCESS_QTY + curProcess.QUALIFIED_QTY; //在线数量,更新再制品数量 if (mesJobOrder.ONLINE_QTY < 0) { mesJobOrder.ONLINE_QTY = 0; } } else if (curProcess.PROCESS_ACTION_TYPE == 11) //出库完成 { //if (productProcess != null) productProcess.PRODUCT_POSITION = curProcess.FINISH_POSITION; //目标位置 //#region 解锁货位地址 - 货位清空 //if (!string.IsNullOrEmpty(curProcess.BEGIN_POSITION)) //{ // WmsAllocationInfo rawAllo = wsWMS.UseService(s => // s.GetWmsAllocationInfoById(curProcess.BEGIN_POSITION)); // if (rawAllo != null) // { // rawAllo.CUR_PALLET_NO = ""; // rawAllo.ALLOCATION_STATE = 0; //空 // wsWMS.UseService(s => s.UpdateWmsAllocationInfo(rawAllo)); // WmsInventory inv = wsWMS.UseService(s => s.GetWmsInventorys($"ALLOCATION_PKNO = '{rawAllo.PKNO}'")) // .FirstOrDefault(); // if (inv != null) wsWMS.UseService(s => s.DelWmsInventory(inv.PKNO)); // } //} //#endregion } else if (curProcess.PROCESS_ACTION_TYPE == 12) //入库完成 { //if (productProcess != null) productProcess.PRODUCT_POSITION = curProcess.FINISH_POSITION; //目标位置 //#region 产品入库处理 - 解锁货位地址、增加产品库存 //if (!string.IsNullOrEmpty(curProcess.FINISH_POSITION)) //{ // WmsAllocationInfo prodAllo = wsWMS.UseService(s => // s.GetWmsAllocationInfoById(curProcess.FINISH_POSITION)); // if (prodAllo != null) //入库货位 // { // prodAllo.ALLOCATION_STATE = 100; //满货位 // WmsInventory inv = new WmsInventory() // { // PKNO = CBaseData.NewGuid(), // COMPANY_CODE = "", // MATERIAL_PKNO = curProcess.FINISH_ITEM_PKNO, // ALLOCATION_PKNO = prodAllo.PKNO, // AREA_PKNO = prodAllo.AREA_PKNO, // BATCH_NO = curProcess.SUB_JOB_ORDER_NO, // INVENTORY_NUM = 1, //curProcess.QUALIFIED_QTY?? 1, // REMARK = "", // }; //库存 // wsWMS.UseService(s => s.UpdateWmsAllocationInfo(prodAllo)); //修改货位 // wsWMS.UseService(s => s.AddWmsInventory(inv)); // } //} //#endregion } else if ((curProcess.PROCESS_ACTION_TYPE >= 40) && (curProcess.PROCESS_ACTION_TYPE < 50)) //换刀 { //40:换刀;41:取刀;42:卸刀;43:装刀;44:放刀 //if (curProcess.PROCESS_ACTION_TYPE == 41) //取刀 //{ // TmsToolsMaster mToolsMaster = wsTMS.UseService(s => // s.GetTmsToolsMasterById(curProcess.BEGIN_ITEM_PKNO)); //装上刀具 // if (mToolsMaster != null) // { // mToolsMaster.TOOLS_POSITION = 10; //出库 // mToolsMaster.TOOLS_POSITION_PKNO = ""; // wsTMS.UseService(s => s.UpdateTmsToolsMaster(mToolsMaster)); // } //} //else if (curProcess.PROCESS_ACTION_TYPE == 42) //卸刀 //{ // TmsDeviceToolsPos mTmsDeviceToolsPos = wsTMS.UseService(s => s.GetTmsDeviceToolsPosById(curProcess.BEGIN_ITEM_PKNO)); //卸下刀具 // if (mTmsDeviceToolsPos != null) // { // mTmsDeviceToolsPos.TOOLS_PKNO = ""; // wsTMS.UseService(s => s.UpdateTmsDeviceToolsPos(mTmsDeviceToolsPos)); //更新 // } // TmsToolsMaster mToolsMaster = wsTMS.UseService(s => // s.GetTmsToolsMasterById(curProcess.FINISH_ITEM_PKNO)); //卸下刀具 // if (mToolsMaster != null) // { // mToolsMaster.TOOLS_POSITION = 10; //已出库 // mToolsMaster.TOOLS_POSITION_PKNO = ""; // wsTMS.UseService(s => s.UpdateTmsToolsMaster(mToolsMaster)); //已出库 // } //} //else if (curProcess.PROCESS_ACTION_TYPE == 43) //装刀 //{ // TmsDeviceToolsPos mTmsDeviceToolsPos = wsTMS.UseService(s => s.GetTmsDeviceToolsPosById(curProcess.BEGIN_ITEM_PKNO)); //装上刀具 // if (mTmsDeviceToolsPos != null) // { // mTmsDeviceToolsPos.TOOLS_PKNO = curProcess.FINISH_ITEM_PKNO; //装上刀具PKNO // wsTMS.UseService(s => s.UpdateTmsDeviceToolsPos(mTmsDeviceToolsPos)); //更新 // } // TmsToolsMaster mToolsMaster = wsTMS.UseService(s => // s.GetTmsToolsMasterById(curProcess.FINISH_ITEM_PKNO)); //装上刀具PKNO // if (mToolsMaster != null) // { // mToolsMaster.TOOLS_POSITION = 2; //在设备 // mToolsMaster.TOOLS_POSITION_PKNO = curProcess.BEGIN_POSITION; //装刀机床PKNO // wsTMS.UseService(s => s.UpdateTmsToolsMaster(mToolsMaster)); //已出库 // } //} //else if (curProcess.PROCESS_ACTION_TYPE == 44) //放刀 //{ // TmsToolsMaster mToolsMaster = wsTMS.UseService(s => // s.GetTmsToolsMasterById(curProcess.BEGIN_ITEM_PKNO)); //卸下刀具 // if (mToolsMaster != null) // { // mToolsMaster.TOOLS_POSITION = 1; // mToolsMaster.TOOLS_POSITION_PKNO = curProcess.FINISH_ITEM_PKNO; //位置信息 // wsTMS.UseService(s => s.UpdateTmsToolsMaster(mToolsMaster)); //已出库 // } //} } #endregion #endregion #region 3. 更新数据 共更新 4 个类 #region 3.1 加工控制 curProcess.PROCESS_END_TIME = DateTime.Now; curProcess.PROCESS_STATE = 10; curProcess.PROCESS_END_TYPE = 1; PServiceEvent?.Invoke(s => s.UpdateMesProcessCtrol(curProcess)); #endregion #region 3.2 Job处理 #region 最后一道工序的处理 mesJobOrder.PROCESS_INFO = "正常"; //生产执行信息 if (bLastProcess) //最后一道工序 { mesJobOrder.COMPLETE_QTY = curProcess.COMPLETE_QTY; mesJobOrder.ONLINE_QTY = 0; //任务完成 mesJobOrder.ACT_FINISH_TIME = DateTime.Now; mesJobOrder.RUN_STATE = 100; //正常完成 mesJobOrder.PROCESS_INFO = $"正常完成,计划数量[{mesJobOrder.TASK_QTY}],完成数量[{mesJobOrder.COMPLETE_QTY}]"; Console.WriteLine($"订单[{mesJobOrder.JOB_ORDER_NO}]生产完成,计划数量[{mesJobOrder.TASK_QTY}],完成数量[{mesJobOrder.COMPLETE_QTY}]"); } #endregion PServiceEvent?.Invoke(s => s.UpdateMesJobOrder(mesJobOrder)); #endregion #region 3.4 清空完成反馈状态,将完成条件置空 var tag = DeviceMonitor.GetTagSettingById(curAction.FINISH_CONDITION_TAG_PKNO); if (tag != null) //将完成结果置为空 { if (tag.SAMPLING_MODE == 10) { tag.SAMPLING_MODE = 11; //按照条件关闭 } DeviceMonitor.SetTagSettingValue(tag, ""); } #endregion #endregion #endregion Thread.Sleep(50); return(true); } return(true); }
public bool StartCurrentProgerss() { if (curProcess.PROCESS_STATE == 1) //准备完成,未开始执行 { if (!string.IsNullOrEmpty(startCondition) && LimitConditions.Contains(startCondition)) //如果前面的Job存在需要判断该状态,则不执行当前的 { string sErrorInfo = $"等待执行"; if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); } return(false); } #region 开始执行工序 共 5 步 string startCustomParam = ""; //开始执行的参数,增加到同步写入数据后面 /************ !!!工序开始的条件!!! ************/ #region 1. 检验当前执行的工序是否可以执行,启动条件 if (startTag != null) //启动条件为空则直接执行 { string checkValue = startTag.CUR_VALUE.Split('|')[0]; //当前执行条件的结果 string startValue = curAction.START_CONDITION_VALUE; //开始条件 string[] startValues = startValue.Split('|'); //多个开启条件 if ((string.IsNullOrEmpty(checkValue)) || (!startValues.Contains(checkValue))) //当前值不是工序开始检测值 { #region 条件不符合的 流程分支情况 if (curProcess.PROCESS_ACTION_TYPE == 4) //流程分支,不启用,直接往下运行 { #region 直接完成当前工序 #region 第一道工序处理 if (bFirstProcess) //第一道工序 { mesJobOrder.RUN_STATE = 20; //正在执行 mesJobOrder.ACT_START_TIME = DateTime.Now; //修改任务开始时间 mesJobOrder.PROCESS_INFO = "正常"; //生产执行信息 PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); } #endregion curProcess.PROCESS_STATE = 10; //直接完成 curProcess.PROCESS_END_TYPE = 1; curProcess.PROCESS_END_TIME = DateTime.Now; curProcess.REMARK = "条件不满足,不启用流程分支,直接执行现有流程。"; PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); return(false); //直接执行重新执行 #endregion } #endregion #region 判断条件不满足 string sErrorInfo = $"生产过程【{ctrolName}】开启条件【{startTag?.TAG_NAME}】不足,当前状态为【{checkValue}】,需要状态【{startValue}】"; if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); } if (!LimitConditions.Contains(startCondition)) { LimitConditions.Add(startCondition); //起始条件不满足,则添加限制条件 } return(false); #endregion } } #endregion /************ !!!工序开始的条件满足,直接执行!!! ************/ Console.WriteLine($"========生产过程【{ctrolName}】开始条件【{startTag?.TAG_NAME}】满足,开始执行======="); #region 2. 启动流程分支 if (curProcess.PROCESS_ACTION_TYPE == 4) //流程分支 { string disableProcesses = curProcess.PROCESS_ACTION_PARAM1_VALUE; //禁用的流程 string enableProcesses = curProcess.PROCESS_ACTION_PARAM2_VALUE; //启用的流程 string stemp = $"触发流程分支.禁用流程[{disableProcesses}], 启用流程[{enableProcesses}]"; mesJobOrder.PROCESS_INFO = stemp; //生产执行信息 Console.WriteLine(stemp); #region 启动流程分支 if (!string.IsNullOrEmpty(disableProcesses)) { foreach (var disableP in disableProcesses.Split(';')) { MesProcessCtrol process = unFinishProcessCtrols.FirstOrDefault(c => c.PROCESS_INDEX == SafeConverter.SafeToInt(disableP, -1)); process.USE_FLAG = 0; //禁用 PServiceEvent?.Invoke(d => d.UpdateMesProcessCtrol(process)); } } if (!string.IsNullOrEmpty(enableProcesses)) { foreach (var enableP in enableProcesses.Split(';')) { MesProcessCtrol process = unFinishProcessCtrols.FirstOrDefault(c => c.PROCESS_INDEX == SafeConverter.SafeToInt(enableP, -1)); process.USE_FLAG = 1; //启用 PServiceEvent?.Invoke(d => d.UpdateMesProcessCtrol(process)); } } #endregion #region 更新数据 #region 加工控制 curProcess.PROCESS_STATE = 10; //直接完成 curProcess.PROCESS_END_TYPE = 1; curProcess.PROCESS_START_TIME = DateTime.Now.AddMilliseconds(-100); curProcess.PROCESS_END_TIME = DateTime.Now; curProcess.REMARK = $"流程分支条件满足,启用流程分支,禁用流程[{disableProcesses}], 启用流程[{enableProcesses}]"; PServiceEvent?.Invoke(d => d.UpdateMesProcessCtrol(curProcess)); #endregion #region Job处理 if (bFirstProcess) //第一道工序 { mesJobOrder.RUN_STATE = 20; //正在执行 mesJobOrder.ACT_START_TIME = DateTime.Now; //修改任务开始时间 } PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); #endregion DeviceMonitor.SetTagSettingValueById(curAction.START_CONDITION_TAG_PKNO, ""); //将检测结果置为空 //产品处理 if (productProcess != null) { productProcess.PRODUCT_STATE = curProcess.PROCESS_ACTION_TYPE; //当前状态 productProcess.LAST_UPDATE_DATE = DateTime.Now; var process = productProcess; PServiceEvent?.Invoke(d => d.UpdateMesProductProcess(process)); } #endregion return(false); //直接开启下一次流程 } //启动流程分支 #endregion //增加限制条件 if (!string.IsNullOrEmpty(startCondition) && !LimitConditions.Contains(startCondition)) //未完成的任务需要增加开始条件 { LimitConditions.Add(startCondition); } #region 3. 获取产品,第一道工序形成产品 if (bFirstProcess || (productProcess == null)) //第一道控制,且没有形成 { string productPKNO = CBaseData.NewGuid(); productProcess = new MesProductProcess() //生成新的产品 { PKNO = productPKNO, COMPANY_CODE = CBaseData.BelongCompPKNO, ITEM_PKNO = curProcess.ITEM_PKNO, JOB_ORDER_PKNO = curProcess.JOB_ORDER_PKNO, JOB_ORDER = curProcess.JOB_ORDER, SUB_JOB_ORDER_NO = curProcess.SUB_JOB_ORDER_NO, PRODUCT_CODE = TableNOHelper.GetNewNO("MesProductProcess.PRODUCT_CODE", "P"), PRODUCT_POSITION = "", //当前位置 CUR_ROCESS_CTROL_PKNO = curProcess.PKNO, //当前过程 RAW_NUMBER = curProcess.PROCESS_QTY, //原料数量 PRODUCT_NUMBER = curProcess.COMPLETE_QTY, //完成数量 QUALIFIED_NUMBER = curProcess.QUALIFIED_QTY, //合格品数量 PALLET_NO = curProcess.PALLET_NO, //托盘号 PRODUCT_STATE = -1, //尚未开始 CREATION_DATE = DateTime.Now, CREATED_BY = CBaseData.LoginNO, LAST_UPDATE_DATE = DateTime.Now, //最后修改日期 USE_FLAG = 1, REMARK = "", //备注 }; //生成新的产品 curProcess.CUR_PRODUCT_CODE_PKNO = productPKNO; //新产品编号 } else { curProcess.CUR_PRODUCT_CODE_PKNO = firstProcess.CUR_PRODUCT_CODE_PKNO; //将所有的产品 } #endregion #region 4. 执行当前工序 => 向设备写入数据 写 3 个值 int ret = 0; string error = ""; string tagPKNO = ""; string sTagValue = ""; bool bWriteSuccess = true; //写入设备成功标志 #region 4.1 写参数1 tagPKNO = curAction.EXECUTE_PARAM1_TAG_PKNO; sTagValue = GetDynamicValue(curProcess.PROCESS_ACTION_PARAM1_VALUE); if ((!string.IsNullOrEmpty(tagPKNO)) && (!string.IsNullOrEmpty(sTagValue))) { #region 多次重写 int iWrite = 0; while (iWrite < ReWriteCount) { ret = DeviceMonitor.WriteTagToDevice(tagPKNO, sTagValue, out error); if (ret == 0) { Thread.Sleep(100); //写入成功后暂停 break; } iWrite++; Thread.Sleep(100); } #endregion if (ret == 10) //写入设备失败 { string sErrorInfo = $"向设备写入参数1失败。错误为:{error}"; //生产执行信息 if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); } Console.WriteLine(sErrorInfo); return(false); } if (ret == 0) { bWriteSuccess = true; //写入成功 } } #endregion #region 4.2 写参数2 tagPKNO = curAction.EXECUTE_PARAM2_TAG_PKNO; sTagValue = GetDynamicValue(curProcess.PROCESS_ACTION_PARAM2_VALUE); if ((!string.IsNullOrEmpty(tagPKNO)) && (!string.IsNullOrEmpty(sTagValue))) { #region 多次重写 int iWrite = 0; while (iWrite < ReWriteCount) { ret = DeviceMonitor.WriteTagToDevice(tagPKNO, sTagValue, out error); if (ret == 0) { Thread.Sleep(100); //写入成功后暂停 break; } iWrite++; Thread.Sleep(100); } #endregion if (ret == 10) //写入设备失败 { string sErrorInfo = $"向设备写入参数2失败。错误为:{error}"; //生产执行信息 if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); } Console.WriteLine(sErrorInfo); return(false); } if (ret == 0) { bWriteSuccess = true; //写入成功 } } #endregion #region 4.3 写执行 tagPKNO = curAction.EXECUTE_TAG_PKNO; sTagValue = GetDynamicValue(curAction.EXECUTE_WRITE_VALUE) + "|" + (string.IsNullOrEmpty(curProcess.PROCESS_ACTION_PARAM1_VALUE) ? "0" : curProcess.PROCESS_ACTION_PARAM1_VALUE) + "|" + (string.IsNullOrEmpty(curProcess.PROCESS_ACTION_PARAM2_VALUE) ? "0" : curProcess.PROCESS_ACTION_PARAM2_VALUE) + "|" + (string.IsNullOrEmpty(startCustomParam) ? "0" : startCustomParam); if ((!string.IsNullOrEmpty(tagPKNO)) && (!string.IsNullOrEmpty(sTagValue.Replace("|", "")))) { #region 多次重写 int iWrite = 0; while (iWrite < ReWriteCount) { ret = DeviceMonitor.WriteTagToDevice(tagPKNO, sTagValue, out error); if (ret == 0) { //Thread.Sleep(100); //写入成功后暂停,最后不需要 break; } iWrite++; Thread.Sleep(100); } #endregion if (ret == 10) //写入设备失败 { string sErrorInfo = $"向设备写入开始动作值失败。错误为:{error}"; //生产执行信息 if (mesJobOrder.PROCESS_INFO != sErrorInfo) { mesJobOrder.PROCESS_INFO = sErrorInfo; //生产执行信息 PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); } Console.WriteLine(sErrorInfo); return(false); } if (ret == 0) { bWriteSuccess = true; //写入成功 } } #endregion if (bWriteSuccess) { Console.WriteLine("给设备发送指令成功.开始进行执行" + (string.IsNullOrEmpty(curProcess.SUB_JOB_ORDER_NO) ? curProcess.JOB_ORDER_PKNO : curProcess.SUB_JOB_ORDER_NO)); //给设备发送动作指令成功 } #endregion #region 5. 更新数据 共更新 4 个模块 #region 5.1 加工控制 curProcess.PROCESS_STATE = 2; //正在执行 curProcess.PROCESS_START_TYPE = 1; //自动开始 curProcess.PROCESS_START_TIME = DateTime.Now; PServiceEvent?.Invoke(d => d.UpdateMesProcessCtrol(curProcess)); #endregion #region 5.2 业务相关处理 if (curProcess.PROCESS_ACTION_TYPE == 11) //开始 出库 { mesJobOrder.ONLINE_QTY = curProcess.PROCESS_QTY; //在线数量 } if (bFirstProcess) //第一道工序,新增产品信息 { PServiceEvent?.Invoke(s => s.AddMesProductProcess(productProcess)); } string sError = ""; string result = DeviceProcessControl.BeginCurBusiness(curProcess, ref sError); //开始当前控制的业务 if (result != "OK") { mesJobOrder.PROCESS_INFO = $"业务开始执行发生错误,写入数据库错误! 具体:{sError}"; } #endregion #region 5.3 Job处理 if (bFirstProcess) //第一道工序 { mesJobOrder.RUN_STATE = 20; //正在执行 mesJobOrder.ACT_START_TIME = DateTime.Now; //修改任务开始时间 } PServiceEvent?.Invoke(d => d.UpdateMesJobOrder(mesJobOrder)); #endregion #region 5.4 将开始和结束条件 置空 DeviceMonitor.SetTagSettingValueById(curAction.START_CONDITION_TAG_PKNO, ""); //将检测结果置为空 FmsAssetTagSetting finishTag = DeviceMonitor.GetTagSettingById(curAction.FINISH_CONDITION_TAG_PKNO); if (finishTag != null) { if (finishTag.SAMPLING_MODE == 11) { finishTag.SAMPLING_MODE = 10; //按照条件开启 } DeviceMonitor.SetTagSettingValue(finishTag, ""); } #endregion #endregion #endregion if (startTag != null) { FMSControlService.iConditionStartAddPause = 500; //按条件启动后增加的延时 } FMSControlService.bStart = true; //本次订单已经启动过了 } return(true); }
//读取Focas的值 private OperateResult <string> ReadFocasData(ushort handle, string dataAddress) { string error = ""; //错误信息 string dataValue = ""; string sValueType = dataAddress.Substring(0, 1); //类型 #region 获取参数值 if ((sValueType == "R") || (sValueType == "Y") || (sValueType == "D") || (sValueType == "E") || (sValueType == "G") || (sValueType == "X")) { #region 获取PMC变量值 short valueType = ValueTypeByStr(sValueType); //内部参数类型 string sAddr = dataAddress.Substring(1); //内部地址 ushort nStarAddr = 0; //起始地址 ushort nEndAddr = 0; int iDataType = 0; //0:字节Byte(CNC中每一个都是一个Byte,如R2000的2000表示一个Byte);1:字型;2:双字型; int iGetPos = -1; //按位进行读时的位。 ushort len = 1; //长度为1 string[] addrsStrings = sAddr.Split(','); if (addrsStrings[0].Contains(".")) //字节 { iDataType = 0; double dAddr = Double.Parse(addrsStrings[0]); nStarAddr = (ushort)dAddr; iGetPos = SafeConverter.SafeToInt(addrsStrings[0].Substring(sAddr.IndexOf('.') + 1)); } else { nStarAddr = Convert.ToUInt16(addrsStrings[0]); if (addrsStrings.Count() > 1) { len = Convert.ToUInt16(addrsStrings[1]); //长度 } if (addrsStrings.Count() > 2) { iDataType = Convert.ToUInt16(addrsStrings[2]); //获取的类型 } } nEndAddr = (ushort)(nStarAddr + (len) * Math.Pow(2, iDataType) - 1); ushort cncLen = (ushort)(8 + (len) * Math.Pow(2, iDataType)); int[] values = new int[len]; short ret = 0; switch (iDataType) { case 0: //Byte Focas1.IODBPMC0 pmcdata0 = new Focas1.IODBPMC0(); // 按照Byte ret = Focas1.pmc_rdpmcrng(handle, valueType, 0, nStarAddr, nEndAddr, cncLen, pmcdata0); if (ret == Focas1.EW_OK) //成功 { for (int i = 0; i < len; i++) { values[i] = pmcdata0.cdata[i]; } } else { error = $"读取失败,错误代码[{ret}]"; } break; case 1: Focas1.IODBPMC1 pmcdata1 = new Focas1.IODBPMC1(); // 按照字型 ret = Focas1.pmc_rdpmcrng(handle, valueType, 0, nStarAddr, nEndAddr, cncLen, pmcdata1); if (ret == Focas1.EW_OK) //成功 { for (int i = 0; i < len; i++) { values[i] = pmcdata1.idata[i]; } } else { error = $"读取失败,错误代码[{ret}]"; } break; case 2: Focas1.IODBPMC2 pmcdata2 = new Focas1.IODBPMC2(); // 按照双字 ret = Focas1.pmc_rdpmcrng(handle, valueType, 0, nStarAddr, nEndAddr, cncLen, pmcdata2); if (ret == Focas1.EW_OK) //成功 { for (int i = 0; i < len; i++) { values[i] = pmcdata2.ldata[i]; } } else { error = $"读取失败,错误代码[{ret}]"; } break; default: return(new OperateResult <string>(error)); } if ((iGetPos >= 0) && (iGetPos <= 7)) //按位读取数据 { string results = Convert.ToString(values[0], 2).PadLeft(8, '0'); if (results.Length < iGetPos) { dataValue = "0"; } else { dataValue = results[7 - iGetPos].ToString(); } } else //正常读取 { dataValue = values[0].ToString(); } #endregion } else if (sValueType == "#") //读取宏变量 { string sAddr = dataAddress.Substring(1); //内部地址 short number = SafeConverter.SafeToShort(sAddr); if (number == 0) { return(new OperateResult <string>("宏变量内部地址错误,地址为:" + sAddr)); } dataValue = GetMacroData(handle, number, out error); if (error != "") { return(new OperateResult <string>($"读取宏变量[{sAddr}],错误为:" + error)); } } else if (dataAddress == "状态") //其他参数,按照参数类型进行读取 { #region 获取状态 dataValue = GetStatus(handle, out error).ToString(); #endregion } else if (dataAddress == "状态2") //其他参数,按照参数类型进行读取 { #region 获取状态 dataValue = GetStatus2(handle, out error).ToString(); #endregion } else if (dataAddress == "程序号") //读正在运行的程序信息 { #region 序号 dataValue = GetProgNum(handle, out error); #endregion } else if (dataAddress == "主程序名称") //其他参数,按照参数类型进行读取 { #region 主程序名称 dataValue = GetProgComment(handle, out error); #endregion } else if (dataAddress == "工件数") //工件数 { #region 工件数 short num = 3901; //num = 3901 工件数 3902 总工件数 dataValue = GetMacro(handle, num, out error).ToString(); #endregion } else if (dataAddress == "工件总数") //工件计数 { #region 工件计数 short num = 3902; //num = 3901 工件数 3902 总工件数 dataValue = GetMacro(handle, num, out error).ToString(); #endregion } else if (dataAddress == "进给倍率") //进给倍率 { #region 进给倍率 dataValue = GetFeedRateOverride(handle, out error).ToString(); #endregion } else if (dataAddress == "进给速度") //进给速度 { #region 进给速度 dataValue = GetFeedRateValue(handle, out error).ToString(); #endregion } else if (dataAddress == "主轴负载") //主轴负载 { #region 主轴负载 dataValue = GetSPLoad(handle, out error).ToString(); #endregion } else if (dataAddress == "主轴转速") //主轴转速 { #region 主轴转速 dataValue = GetSPSpeed(handle, out error).ToString(); #endregion } else if (dataAddress == "报警信息") //主轴转速 { #region 报警信息 dataValue = ReadAlarm(handle, out error).ToString(); #endregion } #endregion if (string.IsNullOrEmpty(error)) { return(OperateResult.CreateSuccessResult <string>(dataValue)); } return(new OperateResult <string>(error)); }
/// <summary> /// 同步写数据,支持按照位写 /// </summary> /// <param name="dataAddress">地址位;R2000</param> /// <param name="dataValues"></param> /// <returns></returns> public OperateResult SyncWriteData(string dataAddress, string dataValues) { if (string.IsNullOrEmpty(dataAddress) || string.IsNullOrEmpty(dataValues)) { return(new OperateResult("传入的参数都不能为空")); } if (dataAddress.Length <= 1) { return(new OperateResult("Tag地址长度不正确")); } string dataValue = dataValues.Split('|')[0]; #region 特殊地址解析 string[] addresses = dataAddress.Split('|'); if ((addresses.Length > 1) && (!string.IsNullOrEmpty(addresses[1]))) { dataValue = string.Format(addresses[1].Replace("#13", "\n"), dataValues.Split('|')); dataAddress = addresses[0]; } #endregion string sInfo = $"写入 Fanuc CNC 设备IP({ServerIP}) 地址({dataAddress}) 值({dataValue}) "; try { string sValueType = dataAddress.Substring(0, 1); //类型 short valueType = 0; //参数类型 string sAddr = dataAddress.Substring(1); //内部地址 string startAddr = sAddr; int iGetPos = -1; //按位进行读时的位。 if (sAddr.Contains('.')) //按位写 { startAddr = sAddr.Substring(0, sAddr.IndexOf('.')); iGetPos = SafeConverter.SafeToInt(sAddr.Substring(sAddr.IndexOf('.') + 1)); } #region 获取类型 valueType = ValueTypeByStr(sValueType); if ((valueType == 0) && (dataAddress != "写入刀补")) //不支持的类型 { string errorType = $"Fanuc CNC 设备 IP({ServerIP}) 地址({dataAddress}) 值({dataValue}),写入失败,不支持的类型."; Console.WriteLine(errorType); return(new OperateResult(errorType)); } #endregion #region Focas 写值 Console.WriteLine($"---Fanuc CNC 设备 IP({ServerIP}) 地址({dataAddress}) 值({dataValue})"); string error = ""; ushort handel = GetFocasHandle(out error); //获取 连接Focas的Handel short ret; if (!string.IsNullOrEmpty(error)) { Console.WriteLine(sInfo + $"失败,连接错误代码({error})"); return(new OperateResult(handel, sInfo + "失败,连接错误代码(" + error + ")")); } ushort nAddr = SafeConverter.SafeToUshort(startAddr); //地址 short nRValue = SafeConverter.SafeToShort(dataValue); //写入值 if (dataAddress == "写入刀补") { #region 写入刀补 ret = DownToolOffset(handel, dataValue, out error); if (ret != Focas1.EW_OK) //失败,两次写入 { FreeFocasHandle(out error); //释放 handel = GetFocasHandle(out error); //重新连接Focas的Handel if (!string.IsNullOrEmpty(error)) { Console.WriteLine(sInfo + $"失败,连接错误代码({error})"); return(new OperateResult(ret, sInfo + "失败,连接错误代码(" + error + ")")); } ret = DownToolOffset(handel, dataValue, out error); } #endregion } else if (sValueType == "#") //写宏变量 { #region 写宏变量 ret = SetMacroData(handel, SafeConverter.SafeToShort(nAddr), SafeConverter.SafeToDouble(dataValue), out error); if (ret != Focas1.EW_OK) //失败,两次写入 { FreeFocasHandle(out error); //释放 handel = GetFocasHandle(out error); //重新连接Focas的Handel if (!string.IsNullOrEmpty(error)) { Console.WriteLine(sInfo + $"失败,连接错误代码({error})"); return(new OperateResult(ret, sInfo + "失败,连接错误代码(" + error + ")")); } ret = SetMacroData(handel, SafeConverter.SafeToShort(nAddr), SafeConverter.SafeToDouble(dataValue), out error); } #endregion } else if (valueType < 100) { #region 写PMC,先读后写 Focas1.IODBPMC0 pmcdata1 = new Focas1.IODBPMC0(); // for 1 Byte ret = Focas1.pmc_rdpmcrng(handel, valueType, 0, nAddr, nAddr, 9, pmcdata1); // D data of 1 Byte if (ret != Focas1.EW_OK) //失败,两次写入 { FreeFocasHandle(out error); //释放 handel = GetFocasHandle(out error); //重新连接Focas的Handel if (!string.IsNullOrEmpty(error)) { Console.WriteLine(sInfo + $"失败,连接错误代码({error})"); return(new OperateResult(ret, sInfo + "失败,连接错误代码(" + error + ")")); } ret = Focas1.pmc_rdpmcrng(handel, valueType, 0, nAddr, nAddr, 9, pmcdata1); // D data of 1 Byte if (ret != Focas1.EW_OK) { Console.WriteLine(sInfo + "失败(读取时),错误代码(" + ret + ")"); return(new OperateResult(ret, sInfo + "失败(读取时),错误代码(" + ret + ")")); } } if ((iGetPos >= 0) && (iGetPos <= 7)) //按位读取数据 { int oldValue = pmcdata1.cdata[0]; byte newValue = (byte)(1 << iGetPos); if (nRValue > 0) //置位 { pmcdata1.cdata[0] = (byte)(oldValue | newValue); //按位或 } else //复位 { pmcdata1.cdata[0] = (byte)(oldValue & (newValue ^ 255)); //按位与 } } else //正常读写 { pmcdata1.cdata[0] = Convert.ToByte(nRValue); } ret = Focas1.pmc_wrpmcrng(handel, nAddr, pmcdata1); #endregion } else { return(new OperateResult(handel, "写Fanuc CNC 数据失败!错误的类型!")); } if (ret != Focas1.EW_OK) { Console.WriteLine(sInfo + "失败(写入时),错误代码(" + ret + ")"); return(new OperateResult(ret, sInfo + "失败(写入时),错误代码(" + ret + ")")); } Console.WriteLine("-----" + sInfo + "成功---"); #endregion return(OperateResult.CreateSuccessResult()); //返回成功 } catch (Exception ex) { string error = sInfo + $"失败,错误为({ex.Message})"; Console.WriteLine(error); return(new OperateResult(error)); } }
/// <summary> /// 异步写数据 /// </summary> /// <param name="dataAddress"></param> /// <param name="dataValue"></param> /// <returns></returns> public OperateResult AsyncWriteData(string dataAddress, string dataValue) { #region 检验 if (string.IsNullOrEmpty(dataAddress) || string.IsNullOrEmpty(dataValue)) { return(new OperateResult("传入的参数都不能为空")); } if (_opcServer == null) { return(new OperateResult("OPCServer未能正确初始化!")); } if (!_opcServer.IsConnected) { return(new OperateResult("OPCServer连接错误!")); } #endregion string groupName = "AsyncWriteData"; OpcGroup group = _opcServer.FindGroupByName(groupName); if (group != null) { _opcServer.RemoveGroup(group); } group = _opcServer.AddGroup(groupName, 1, false); //添加组 string datavalue = dataValue.Split('|')[0]; WriteCompleteEventHandler writeFinishHandler = WriteFinishHandler; IRequest request; #region 添加Item及写入Item if ((dataAddress.Contains(',')) && (OPCServerName == _RSLinxOPC)) //RSLinx 数组的写入 { //地址前缀,类型,起始位置,长度 #region RSLinx 数组及地址串 string[] tags = dataAddress.Split(','); if (tags.Length < 3) { return(new OperateResult("RSLinx 地址错误")); } string mainAddress = tags[0]; //主地址 string type = tags[1]; //类型 int beginIndex = SafeConverter.SafeToInt(tags[2]); //开始索引 int length = SafeConverter.SafeToInt(tags[3]); //长度 string endStr = (tags.Length > 4) ? tags[4] : ""; Guid[] handels = new Guid[length]; string[] address = new string[length]; string[] values = new string[length]; for (int i = 0; i < length; i++) { handels[i] = Guid.NewGuid(); values[i] = datavalue.Length > i ? datavalue[i].ToString() : "0"; //默认为0 if (type.ToLower() == "array") //数组型 { address[i] = mainAddress + "[" + (i + beginIndex).ToString() + "]"; } else //连续地址 { address[i] = mainAddress + type + (i + beginIndex).ToString() + endStr; } } ItemResult[] itemResults = group.AddItems(address, handels); ItemValue[] itemValues = new ItemValue[length]; for (int i = 0; i < length; i++) { itemValues[i] = new ItemValue(itemResults[i]) { Value = values[i] }; } group.AsyncWrite(itemValues, handels, writeFinishHandler, out request); #endregion } else //正常类型 { Guid[] handel = new[] { Guid.NewGuid() }; ItemResult[] itemResults = group.AddItems(new[] { dataAddress }, handel); ItemValue itemValue = new ItemValue(itemResults[0]) { Value = datavalue, }; group.AsyncWrite(new ItemValue[] { itemValue }, handel, writeFinishHandler, out request); } #endregion return(OperateResult.CreateSuccessResult()); }
//测试 private void BtnTest_Click(object sender, RoutedEventArgs e) { TbTestResult.Text = ""; RefreshCalculationText(); Type dynamicCode = null; //获取编译后代码,调用该类用 Dictionary <string, Dictionary <string, string> > FuncAndParamTagPKNO = new Dictionary <string, Dictionary <string, string> >(); //函数和对应参数的Tag的PKNO string className = "C" + Guid.NewGuid().ToString("N"); try { Cursor = Cursors.Wait; #region 形成执行的代码 string execCode = "using System; \r\n" + "using System.Text; \r\n" + "using System.Collections.Generic; \r\n" + "using BFM.Common.Base; \r\n\r\n"; execCode += "public class " + className + "\r\n" + "{ \r\n"; string basicFuc = "AutoCalculation"; int index = 1; FuncAndParamTagPKNO.Clear(); string exp = CalculationText; //表达式 string funcname = basicFuc + index.ToString(); //函数名称 Dictionary <string, string> paramTas = new Dictionary <string, string>(); //参数对应的标签的PKNO, param名称 List <string> funcParam = new List <string>(); //带类型的参数 string code = ""; foreach (var line in exp.Split(new string[] { "\r\n" }, StringSplitOptions.None)) { string ret = line; #region 替换标签值,将标签替换成参数名 string[] expTags = line.Split('{'); for (int i = 0; i < expTags.Length; i++) { string str = expTags[i]; int length = str.IndexOf('}'); if (length < 0) //没有找到 } { continue; } string tagPKNO = str.Substring(0, length); //{ } 内为PKNO string param = "{" + tagPKNO + "}"; if (paramTas.ContainsKey(tagPKNO)) //已经添加了该参数 { param = paramTas[tagPKNO]; } else { FmsAssetTagSetting tag = DeviceTags.FirstOrDefault(s => s.PKNO == tagPKNO); if (tag == null) { continue; } param = "param" + paramTas.Count; paramTas.Add(tagPKNO, param); string paramType = "string"; //string paramType = ((CalculationType == 2) || (tag.VALUE_TYPE > 0 && tag.VALUE_TYPE < 20)) // ? "double" // : "string"; funcParam.Add(paramType + " " + param); } ret = ret.Replace("{" + tagPKNO + "}", param); } #endregion if (string.IsNullOrEmpty(code)) { code = " " + ret; } else { code += Environment.NewLine + " " + ret; } } //C#脚本 //支持C#语法,最后返回值(Double/String) string resultType = "string"; //确定返回结果类型,将code语句转换成C#的语句 if (CalculationType == 1) //逻辑运算 { //(结果为1,0):({标签1}==1)&&({标签2}==1)&&({标签3}==0||{标签4}==0)&&({标签5}==1) code = code.Replace("AND", "&&").Replace("and", "&&").Replace("OR", "||").Replace("or", "||"); resultType = "bool"; } else if (CalculationType == 2) //数值运算 { //{标签1}+3+{标签2}+4 resultType = "double"; } else if (CalculationType == 3) //字符运算 { //{标签1}+"123" } else if (CalculationType == 12) //条件数值运算 { //{标签1}==3:{标签2}+1;{标签1}==4:{标签2}+2;{标签1}==5:{标签2}+3 resultType = "double"; List <string> exps = code.Split(';').ToList(); string temp = ""; foreach (var exp1 in exps) { if (exp1.Split(':').Length < 2) { continue; } temp += " if (" + exp1.Split(':')[0] + ") { return (" + exp1.Split(':')[1] + "); } \r\n"; } temp += " return 0; \r\n"; code = temp; } else if (CalculationType == 13) //条件字符运算 { //{标签1}==3:{标签1}+"123";{标签1}==4:{标签1}+"123" List <string> exps = code.Split(';').ToList(); string temp = ""; foreach (var exp1 in exps) { if (exp1.Split(':').Length < 2) { continue; } temp += " if (" + exp1.Split(':')[0] + ") { return (" + exp1.Split(':')[1] + ").ToString(); } \r\n"; } temp += " return \"\"; \r\n"; code = temp; } else if (CalculationType == 21) { resultType = "string";//{标签1};3 List <string> exps = code.Split(';').ToList(); string temp = ""; if (exps.Count >= 2) { int arrayIndex = SafeConverter.SafeToInt(exps[1].Trim(), 0); temp += " if ( " + exps[0].Trim() + ".Split('|').Length > " + arrayIndex + ") { return " + exps[0].Trim() + ".Split('|')[" + arrayIndex + "]; } \r\n"; } temp += " return \"\"; \r\n"; code = temp; } else if (CalculationType == 100) //C#脚本 { //支持C#语法,最后返回值(Double/String) resultType = "string"; } else //不支持的类型 { code = $" return \"计算类型[{CalculationType}],不支持的类型。\"; \r\n"; } execCode += DynamicCode.BuildExecFunc(funcname, resultType, code, funcParam); FuncAndParamTagPKNO.Add(funcname, paramTas); //添加 execCode += "}\r\n"; #endregion #region 编译代码 CodeDomProvider compiler = new CSharpCodeProvider(); CompilerParameters cp = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true, }; cp.ReferencedAssemblies.Add("BFM.Common.Base.dll"); CompilerResults cr = compiler.CompileAssemblyFromSource(cp, execCode); if (cr.Errors.HasErrors) { WPFMessageBox.ShowError("测试失败,语法错误.\r\n" + execCode, "测试"); return; } dynamicCode = cr.CompiledAssembly.GetType(className); //获取 #endregion #region 获取值 index = 0; string funcName = FuncAndParamTagPKNO.Keys.ToList()[index]; var tagParms = FuncAndParamTagPKNO.Values.ToList()[index]; List <object> paramValues = new List <object>(); //参数值 foreach (var tagpkno in tagParms) //参数 { object value; FmsAssetTagSetting tagParam = DeviceTags.FirstOrDefault(s => s.PKNO == tagpkno.Key); if (tagParam != null) { value = SafeConverter.SafeToStr(tagParam.CUR_VALUE); //if ((CalculationType == 2) || (tagParam.VALUE_TYPE > 0 && tagParam.VALUE_TYPE < 20)) //{ // value = SafeConverter.SafeToDouble(tagParam.CUR_VALUE); //} //else //{ // value = SafeConverter.SafeToStr(tagParam.CUR_VALUE); //} } else { value = ""; } paramValues.Add(value); } object obj = dynamicCode.InvokeMember(funcName, BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, System.Type.DefaultBinder, null, paramValues.ToArray()); string newValue = ""; //新的计算结果 if (CalculationType == 1) //逻辑运算 { newValue = SafeConverter.SafeToBool(obj) ? "1" : "0"; } else { newValue = SafeConverter.SafeToStr(obj); } Console.WriteLine("测试结果:" + newValue); TbTestResult.Text = newValue; #endregion WPFMessageBox.ShowInfo("测试成功. \r\n测试结果为:" + newValue, "测试"); } catch (Exception ex) { Console.WriteLine(ex); WPFMessageBox.ShowError("测试失败,错误为:" + ex.Message, "测试"); } finally { Cursor = Cursors.Arrow; } }
/// <summary> /// 解析地址 /// </summary> /// <param name="address">s=Station;f=读取功能;d=地址;l=长度</param> /// <param name="value">写入值</param> /// <param name="defFuncton">默认的功能</param> /// <param name="spkno">地址的PKNO,默认不需要获取反馈信息</param> private byte[] AnalysisWriteAddress(string address, string value, byte defFuncton, string spkno = "") { byte[] data = null; #region 解析Modbus地址 try { int station = 1; //Station byte function = defFuncton; // int modAddress = 0; //地址 int length = 1; GetModbusInfo(address, ref station, ref function, ref modAddress, ref length); if (length == 1) { value = value.Split('|')[0]; } if (function == WriteOneCoil) //写单个线圈 { data = new byte[6]; data[0] = (byte)station; data[1] = function; data[2] = BitConverter.GetBytes(modAddress)[1]; data[3] = BitConverter.GetBytes(modAddress)[0]; data[4] = (byte)(SafeConverter.SafeToBool(SafeConverter.SafeToInt(value.Split('|')[0])) ? 0xFF : 0x00); data[5] = 0x00; } else if (function == WriteOneRegister) //写单个寄存器 { data = new byte[6]; data[0] = (byte)station; data[1] = function; data[2] = BitConverter.GetBytes(modAddress)[1]; data[3] = BitConverter.GetBytes(modAddress)[0]; data[4] = BitConverter.GetBytes(SafeConverter.SafeToInt(value.Split('|')[0]))[1]; data[5] = BitConverter.GetBytes(SafeConverter.SafeToInt(value.Split('|')[0]))[0]; } else if (function == WriteCoil) //写多个线圈,目前只最多支持16位,注意需要设备支持 ++++++++++++++++需要测试++++++++++++++ { string[] values = value.Split('|'); string result = ""; for (int i = 0; i < length; i++) { if (i < values.Length) { result += SafeConverter.SafeToBool(values[i]) ? "1" : "0"; } else { result += "0"; } } byte innerlength = (byte)(Math.Ceiling(length * 1.0 / 8)); data = new byte[7 + innerlength]; int buf = Convert.ToInt16(result, 2); data[0] = (byte)station; data[1] = function; data[2] = BitConverter.GetBytes(modAddress)[1]; data[3] = BitConverter.GetBytes(modAddress)[0]; data[4] = BitConverter.GetBytes(length)[1]; data[5] = BitConverter.GetBytes(length)[0]; data[6] = innerlength; if (innerlength == 1) { data[7] = BitConverter.GetBytes(buf)[0]; } else if (innerlength == 2) { data[7] = BitConverter.GetBytes(buf)[1]; data[8] = BitConverter.GetBytes(buf)[0]; } } else if (function == WriteRegister) //写多个寄存器 { string[] values = value.Split('|'); byte[] buf = new byte[length * 2]; int index = 0; for (int i = 0; i < length; i++) //按照写入值得长度来确定 { string s = (values.Length > i) ? values[i] : "0"; buf[index++] = BitConverter.GetBytes(SafeConverter.SafeToInt(s))[1]; buf[index++] = BitConverter.GetBytes(SafeConverter.SafeToInt(s))[0]; } data = new byte[7 + buf.Length]; data[0] = (byte)station; data[1] = function; data[2] = BitConverter.GetBytes(modAddress)[1]; data[3] = BitConverter.GetBytes(modAddress)[0]; data[4] = BitConverter.GetBytes(buf.Length / 2)[1]; data[5] = BitConverter.GetBytes(buf.Length / 2)[0]; data[6] = (byte)(buf.Length); buf.CopyTo(data, 7); } } catch { data = null; } #endregion return(PackCommandToTcp(spkno, data)); }
private Action <int, int, string, string, int, string> _showAlloc; //显示界面信息 private void RefreshAllocation() { #region 创建显示信息的函数,提高效率 _showAlloc = (col, lay, allInfo, goodsNO, allocProportion, palletInfo) => { //myShelf.RefreshAlloInfo(col, lay, allInfo, goodsNO, allocProportion, palletInfo); }; #endregion WcfClient <IWMSService> wsWMS = new WcfClient <IWMSService>(); WcfClient <IRSMService> wsRsm1 = new WcfClient <IRSMService>(); while (!CBaseData.AppClosing) { if (!bRefreshAllo) { Thread.Sleep(500); continue; } try { //获取货位及库存状态 List <WmsAllocationInfo> allocations = wsWMS.UseService(s => s.GetWmsAllocationInfos($"USE_FLAG = 1 AND AREA_PKNO = '{areaPKNO}'")); List <WmsInventory> inventories = wsWMS.UseService(s => s.GetWmsInventorys($"AREA_PKNO = '{areaPKNO}'")); //库存信息 for (int col = 1; col <= totalColumn; col++) { for (int lay = 1; lay <= totalLayer; lay++) { WmsAllocationInfo allocation = allocations.FirstOrDefault(c => c.ALLOCATION_COL == col && c.ALLOCATION_LAY == lay); var col1 = col; var lay1 = lay; string allInfo = ""; string goodsNO = ""; int alloproportion = -1; //禁用 string palletInfo = ""; if (allocation != null) { alloproportion = SafeConverter.SafeToInt(allocation.ALLOCATION_STATE); palletInfo = allocation.ALLOCATION_NAME; var inv = inventories.FirstOrDefault(c => c.ALLOCATION_PKNO == allocation.PKNO); if (inv != null) //有库存 { goodsNO = inv.MATERIAL_PKNO; RsItemMaster item = wsRsm1.UseService(s => s.GetRsItemMasterById(inv.MATERIAL_PKNO)); if (item != null) { allInfo = item.ITEM_NAME + " (" + inv.INVENTORY_NUM?.ToString("f0") + ")"; } } } //显示信息 Dispatcher.BeginInvoke(_showAlloc, col1, lay1, allInfo, goodsNO, alloproportion, palletInfo); } } } catch (Exception e) { Console.WriteLine(e); } Thread.Sleep(1000); } }
private Action <DragThumb, FmsAssetTagSetting> _showInfo; //显示界面信息 private void ThreadShowWorkState(object obj) { //状态颜色 0:其他状态=脱机的颜色;1:工作状态颜色;2:故障状态颜色;3:待机状态颜色;4:急停状态颜色 Brush[] StateColors = new Brush[5] { Brushes.Gray, Brushes.Green, Brushes.OrangeRed, Brushes.DarkGoldenrod, Brushes.DarkRed }; #region 创建显示信息的函数,提高效率 _showInfo = (thumb, tag) => { if ((thumb == null) || (tag == null)) { return; } if (tag.STATE_MARK_TYPE == 0) //普通内容 { thumb.Text = tag.TAG_VALUE_NAME + " " + tag.CUR_VALUE + " " + tag.VALUE_UNIT; } else if (tag.STATE_MARK_TYPE == 1) //联机状态 { int state = SafeConverter.SafeToInt(tag.CUR_VALUE, 0); if (state <= 4) //状态 { thumb.Background = StateColors[state]; thumb.BorderBrush = StateColors[state]; } } else if (tag.STATE_MARK_TYPE == 2) //待机状态 { int state = SafeConverter.SafeToInt(tag.CUR_VALUE, 0); if (state == 2) { state = 3; } if (state <= 4) //状态 { thumb.Background = StateColors[state]; thumb.BorderBrush = StateColors[state]; } } else if (tag.STATE_MARK_TYPE == 4) //故障状态 { int state = SafeConverter.SafeToInt(tag.CUR_VALUE, -1); if (state == 1) //故障,整个产线报警 { thumb.Background = StateColors[2]; thumb.BorderBrush = StateColors[2]; } else if (state == 0) //正常 { thumb.Background = StateColors[1]; thumb.BorderBrush = StateColors[1]; } else //离线状态 { thumb.Background = StateColors[0]; thumb.BorderBrush = StateColors[0]; } } else if (tag.STATE_MARK_TYPE == 10) //状态 { int state = SafeConverter.SafeToInt(tag.CUR_VALUE, 0); if ((state < 0) || (state >= StateColors.Length)) { state = 0; } thumb.Background = StateColors[state]; thumb.BorderBrush = StateColors[state]; } }; #endregion #region 后台执行 while (!CBaseData.AppClosing) { if (!bShowInfo) { Thread.Sleep(500); continue; } //显示状态 try { foreach (DragThumb thumb in cvMain.DragThumbs) { if (!bShowInfo) { break; } FmsAssetTagSetting tag = DeviceMonitor.GetTagSettingById(thumb.CtrlName); //查找TagSetting if (tag == null) { continue; } Dispatcher.BeginInvoke(_showInfo, thumb, tag); } } catch (Exception ex) { EventLogger.Log($"!!!!!!实时监控错误,原因:{ex.Message}!!!!!!"); } Thread.Sleep(500); } #endregion }