using CMS_CORE_Library.Models; using Siemens.Sinumerik.Operate.Services; using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; using System.Xml.Linq; using static CMS_CORE_Library.Models.DataStructures; using static CMS_CORE_Library.Nc; using static CMS_CORE_Library.Siemens.MEMORY_ADDRESS; using static CMS_CORE_Library.ToolConfigurations; using static CMS_CORE_Library.Utils.Nc_Utils; using static Siemens.Sinumerik.Operate.Services.ToolMngmntSvc; namespace CMS_CORE_Library.S7Net { public class Nc_S7Net : Nc { // Global Constants #if false private const string OptionHMINotRunning = "P66"; private const string HMIDllName = "Wrapper.dll"; #endif private const string NcNotFound = "Missing response"; private const string NcNotFound2 = "networking error"; #if false private const string NcNotFound3 = "Nc not Connected"; private const string SinumerikEnvVar = "HMI_INSTALL_DIR"; #endif private const int IDMinPLCMessage = 700000; private const int IDMaxPLCMessage = 799999; private const int IDMinChannel = 10000; private const int IDMaxChannel = 19999; #if false // Siemens Path Constants private const string MAX_CHANNEL_NO_PATH = "/Nck/Configuration/maxnumChannels"; private const string CONF_CHANNEL_NO_PATH = "/Nck/Configuration/numChannels"; private const string NC_TYPE_PATH = "/Nck/Configuration/nckType"; private const string NC_VERSION_PATH = "/Nck/Configuration/nckVersion"; private const string LANGUAGE_PATH = "/Nck/Configuration/anLanguageOnHmi"; private const string SERIAL_NO_PATH = "/Nck/State/hwProductSerialNrL"; private const string NC_TIME_PATH = "/Nck/State/sysTimeBCD"; private const string NC_GENERIC_MODE_PATH = "/Bag/State/opMode"; private const string NC_GENERIC_STATE_PATH = "/Channel/State/chanStatus"; private const string JOG_INCR_PATH = "/Channel/GeometricAxis/actIncrVal"; private const string ADVANCED_JOG_PATH = "/Channel/State/machFunc"; private const string RELATIVE_POS_PATH = "/Channel/GeometricAxis/actToolBasPosEN"; private const string UNIT_OF_MEASURE = "/Nck/Configuration/basicLengthUnit"; private const string ACT_PROG_LINES_PATH = "/Channel/ProgramInfo/actPartProgram"; private const string ACT_PROG_NAME_PATH = "/Channel/ProgramPointer/progName"; private const string MAGAZINE_ACTION_PATH = "DB258.DBB4000"; // TOOLS private const string NC_TOOL_FILE_PATH = "//NC/ACT.DIR/TO.DIR/TO_INI.INI"; private const string LOCALE_TOOL_FILE_PATH = "C:\\CMS\\Active\\TMP\\TO_INI.INI"; #endif // Global Variables private static DateTime Last_Static_Read; private ushort TimeoutConn; private static string Cnc_name; private static string Cnc_SftVersion; private static string Cnc_SeriesNum; private static string Cms_MachNumber; private static uint ConfChannelNo; private static uint MaxChannelNo; private static uint SiemensLanguage; private static string UnitOfMeasure; // Alarms data private AlarmSvc SiemensAlmSvc = null; private Alarm[] SiemensAlarms; #if false // Tool table listeners private static ToolMngmntSvc SiemensToolSvc = null; private static DataSvc MagazinePositionSvc = null; private static DataSvc MagazineActionsSvc = null; private Guid ToolMngmtListGuid = Guid.Empty; // Magazine config parameters private static int MAX_TOOL_NUMER; private static int MAX_EDGES_PER_TOOL; private static int MAX_TOOLS_PER_FAMILY; private static int MAX_MULTITOOLS_NUMBER; private static int MAX_TOOLS_PER_MULTITOOL; private static int MAX_MULTITOOLS_LOCATIONS; private static bool LIFE_OPTION_ACTIVE; private static bool MULTITOOL_OPTION_ACTIVE; private const string PLC_MESSAGES_FILE_PATH = "C:\\Program Files (x86)\\Siemens\\MotionControl\\oem\\sinumerik\\hmi\\lng\\"; private static readonly string AXES_FILE_PATH = AppDomain.CurrentDomain.BaseDirectory + "\\Config\\axesConfig.xml"; // axis data private static List AxesData = new List(); public static uint multitoolsNumber = 0; public static uint MAX_AXES_FOR_PROCESS = 20; // File paths public const string BASE_FILE_PATH = "//NC/"; public const string NC_FILE_PATH = "MPF.DIR"; private static DataSvc AxesSvc; private static DataSvc SelectedProcessSvc; private static ushort SelectedProcess = 0; private static Dictionary MachineAxesPosition = new Dictionary(); private static Dictionary ToGoAxesPosition = new Dictionary(); private static Dictionary InterpAxesPosition = new Dictionary(); private static Dictionary ProgrammedAxisPosition = new Dictionary(); #endif private bool EnableAlarms; private bool EnableHeaters; private bool EnableModules; private bool EnableParameters; private bool EnableProd; private bool EnableAxes; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region Contructor & global methods /// ///Instantiate The NC-S7Net Class /// ///Send/Recieve timeout connection [mS] public Nc_S7Net(ushort ConnectionTimeOut) { //Setup options this.EnableAlarms = true; this.EnableHeaters = true; this.EnableModules = true; this.EnableParameters = true; this.EnableProd = true; this.EnableAxes = false; //Setup timeout TimeoutConn = ConnectionTimeOut; // FIXME: modificare in allarme generico bitmap? SiemensAlarms = new Alarm[] { }; } /// /// Instantiate The NC-Siemens Class /// /// Send/Recieve timeout connection [mS] /// Enable Axes Svc /// Enable Alarms Svc /// Enable Heaters Svc /// Enable Modules Svc /// Enable Parameters Svc /// Enable Prod Svc public Nc_S7Net(ushort ConnectionTimeOut, bool EnableAxes, bool EnableAlarms, bool EnableHeaters, bool EnableModules, bool EnableParameters, bool EnableProd) { //Setup options this.EnableAlarms = EnableAlarms; this.EnableAxes = EnableAxes; this.EnableHeaters = EnableHeaters; this.EnableModules = EnableModules; this.EnableParameters = EnableParameters; this.EnableProd = EnableProd; //Setup timeout TimeoutConn = ConnectionTimeOut; SiemensAlarms = new Alarm[] { }; } public override CmsError NC_Connect() { // Try to get information try { // Check if Siemens Environment is started CmsError cmsError = CheckS7Ping(); if (cmsError.IsError()) return cmsError; // Check connection Item item = new Item("DB258.DBX0.0"); DataSvc svc = new DataSvc(); svc.Read(item); Connected = true; // InitializeSiemens objects if (this.EnableAxes) { if (AxesSvc == null) AxesSvc = new DataSvc(); } if (SelectedProcessSvc == null) { SelectedProcessSvc = new DataSvc(); SelectedProcessSvc.Subscribe(ManageSelectedProcess, new Item[] { new Item() { Path = "DB258.DBX2582.2" }, new Item() { Path = "DB258.DBX2586.2" }, new Item() { Path = "DB258.DBX2590.2" }, new Item() { Path = "DB258.DBX2594.2" }, new Item() { Path = "DB258.DBX2598.2" }, new Item() { Path = "DB258.DBX2602.2" }, }); } //Setup the alarms (Only managed in this way (Siemens Thread) if (this.EnableAlarms) { SiemensAlarms = new Alarm[] { }; SiemensAlmSvc = new AlarmSvc(ConvertToSTEPLanguage(SiemensLanguage).ThreeLetterISOLanguageName); SiemensAlmSvc.Subscribe(AlarmsChanged); Infrastructure.SubscribeLanguageChanged(NcLanguageChanged); } if (this.EnableTools) { // Setup tooltable listeners if (SiemensToolSvc == null) { SiemensToolSvc = new ToolMngmntSvc(1); ToolMngmtListGuid = SiemensToolSvc.Subscribe(ToolMngmtSvcHandler); SetupToolTableData(); } // Setup magazine position listener if (MagazinePositionSvc == null) { MagazinePositionSvc = new DataSvc(); SetupMagazinePositionListener(); } // Setup magazine action if (MagazineActionsSvc == null) { MagazineActionsSvc = new DataSvc(); SetupMagazineActionListener(); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } private void ManageSelectedProcess(Guid guid, Item[] item, DataSvcStatus[] status) { SelectedProcess = 0; // Set selectedProcess for (int i = 0; i < item.Count(); i++) { if (status[i].Ok) { if (Convert.ToBoolean(item[i].Value)) SelectedProcess = (ushort)(i + 1); } } if (this.EnableAxes) { // Clean listener AxesSvc.UnSubscribe(ManageAxes); if (SelectedProcess > 0) { List axesConf = new List(); AXES_RAxesNames(SelectedProcess, ref AxesData); List axesData = new List(); foreach (var conf in AxesData) { // Setup the items to be subscribed // Machine axesData.Add(new Item() { Path = string.Format("/Nck/{0}[u{1},{2}]", "MachineAxis/actToolBasePos", SelectedProcess, conf.Id), SymbolicName = conf.Id.ToString() }); // Programmed axesData.Add(new Item() { Path = string.Format("/Channel/{0}[u{1},{2}]", "GeometricAxis/cmdProgPos", SelectedProcess, conf.Id), SymbolicName = conf.Id.ToString() }); // Interp axesData.Add(new Item() { Path = string.Format("/Channel/{0}[u{1},{2}]", "GeometricAxis/actToolEdgeCenterPos", SelectedProcess, conf.Id), SymbolicName = conf.Id.ToString() }); // Dist to go axesData.Add(new Item() { Path = string.Format("/Channel/{0}[u{1},{2}]", "MachineAxis/toolBaseDistToGo", SelectedProcess, conf.Id), SymbolicName = conf.Id.ToString() }); } if (axesData.Count() > 0) // Subscribe to axis changes AxesSvc.Subscribe(ManageAxes, axesData.ToArray()); } } } private void ManageAxes(Guid guid, Item[] item, DataSvcStatus[] status) { lock (MachineAxesPosition) { lock (ProgrammedAxisPosition) { lock (InterpAxesPosition) { lock (ToGoAxesPosition) { MachineAxesPosition.Clear(); ProgrammedAxisPosition.Clear(); InterpAxesPosition.Clear(); ToGoAxesPosition.Clear(); for (int i = 0; i < AxesData.Count(); i++) { if (status[i * 4].Ok) MachineAxesPosition.Add(item[i * 4].SymbolicName, Convert.ToDouble(item[i * 4].Value)); if (status[i * 4 + 1].Ok) ProgrammedAxisPosition.Add(item[i * 4 + 1].SymbolicName, Convert.ToDouble(item[i * 4 + 1].Value)); if (status[i * 4 + 2].Ok) InterpAxesPosition.Add(item[i * 4 + 2].SymbolicName, Convert.ToDouble(item[i * 4 + 2].Value)); if (status[i * 4 + 3].Ok) ToGoAxesPosition.Add(item[i * 4 + 3].SymbolicName, Convert.ToDouble(item[i * 4 + 3].Value)); } } } } } } // Disconnect Method public override CmsError NC_Disconnect() { // Set Connected to FALSE and close the sessions Connected = false; if (SiemensToolSvc != null) { SiemensToolSvc.UnSubscribe(ToolMngmtSvcHandler); // SiemensToolSvc.Dispose(); } if (MagazinePositionSvc != null) { MagazinePositionSvc.UnSubscribe(MagazinePositionEnabled_OnChange); //MagazinePositionSvc = null; // MagazinePositionSvc.Dispose(); } if (MagazineActionsSvc != null) { MagazineActionsSvc.UnSubscribe(MagazineAction_OnChange); //MagazineActionsSvc = null; // MagazineActionsSvc.Dispose(); } if (this.EnableAxes) { if (AxesSvc != null) AxesSvc.UnSubscribe(ManageAxes); } return NO_ERROR; } private void SetupToolTableData() { DataSvc dataSvc = new DataSvc(); // Read max tool number Item itemToRead = new Item("/NC/_N_NC_TEA_ACX/$MN_MM_NUM_TOOL"); dataSvc.Read(itemToRead); MAX_TOOL_NUMER = (int)itemToRead.Value; // Read max edge per tool number itemToRead = new Item("/NC/_N_NC_TEA_ACX/$MN_MM_MAX_CUTTING_EDGE_PERTOOL"); dataSvc.Read(itemToRead); MAX_EDGES_PER_TOOL = (int)itemToRead.Value; // Read max tools per family itemToRead = new Item("/NC/_N_NC_TEA_ACX/$MN_MAXNUM_REPLACEMENT_TOOLS"); dataSvc.Read(itemToRead); MAX_TOOLS_PER_FAMILY = (int)itemToRead.Value; // Read max multitools number itemToRead = new Item("/NC/_N_NC_TEA_ACX/$MN_MM_NUM_MULTITOOL"); dataSvc.Read(itemToRead); MAX_MULTITOOLS_NUMBER = (int)itemToRead.Value; // Read max tools per multitools itemToRead = new Item("/NC/_N_NC_TEA_ACX/$MN_MAX_TOOLS_PER_MULTITOOL"); dataSvc.Read(itemToRead); MAX_TOOLS_PER_MULTITOOL = (int)itemToRead.Value; // Read file string[] toolsStrings = ReadToolTableFile(); // Read max multitools locations itemToRead = new Item("/NC/_N_NC_TEA_ACX/$MN_MM_NUM_MULTITOOL_LOCATIONS"); dataSvc.Read(itemToRead); MAX_MULTITOOLS_LOCATIONS = (int)itemToRead.Value; // Read Life option //itemToRead = new Item("/NC/_N_NC_TEA_ACX/$MN_MM_TOOL_MANAGEMENT_MASK"); //LIFE_OPTION_ACTIVE = GetBitValue(Convert.ToInt32(itemToRead.Value), 6); // MULTITOOL_OPTION_ACTIVE = GetBitValue(Convert.ToInt32(itemToRead.Value), 10); MULTITOOL_OPTION_ACTIVE = false; // Read Life option itemToRead = new Item("/NC/_N_NC_TEA_ACX/$MNS_ACCESS_WRITE_TM_SUPVIS"); dataSvc.Read(itemToRead); LIFE_OPTION_ACTIVE = Convert.ToInt32(itemToRead.Value) == 7; // If not active remove fields from config if (!LIFE_OPTION_ACTIVE) RemoveLifeParamsFromConfig(); // Read file PopulateToolsTableFromFileStrings(toolsStrings); Array.Clear(toolsStrings, 0, toolsStrings.Count()); //// Subscribe to multitools number //DataSvc d = new DataSvc(); //Item i = new Item() { Path = "/Tool/MTCatalogue/numMultiTools[u1]" }; //d.Subscribe(MultitoolsNumber_OnChange, i); } private void SetupMagazinePositionListener() { // Setup magazine positions listener List magPosItems = new List(); foreach (var position in MagazinePositionsData) { int paramId = ((position.PositionId - 1) * 11) + 5; magPosItems.Add(new Item() { Path = string.Format("/Tool/Magazine/placeData[c{0} , {1}]", position.MagazineId, paramId), SymbolicName = position.MagazineId + "_" + position.PositionId }); } if (magPosItems.Count > 0) // Subscribe MagazinePositionSvc.Subscribe(MagazinePositionEnabled_OnChange, magPosItems.ToArray()); } private void SetupMagazineActionListener() { Item magActionsItem = new Item() { Path = MAGAZINE_ACTION_PATH }; // Setup magazine actions listener MagazineActionsSvc.Subscribe(MagazineAction_OnChange, magActionsItem); } private void RemoveLifeParamsFromConfig() { SiemensToolFieldsConfig.RemoveAll(x => x.Category == "life"); SiemensEdgesFieldsConfiguration.EdgeConfiguration.RemoveAll(x => x.Category == "life"); } public override CmsError NC_GetTranslatedPlcMessages(string language, ref Dictionary messages) { string filePath; try { messages = new Dictionary(); CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture(language); // Setup the path of NC alarms translations file filePath = PLC_MESSAGES_FILE_PATH + "cmsalarm_" + cultureInfo.ThreeLetterISOLanguageName.ToUpper() + ".ts"; if (!File.Exists(filePath)) return INCORRECT_LANGUAGE_ERROR; // Open file reader XDocument xmlTranslationsFile; using (StreamReader oReader = new StreamReader(filePath, Encoding.ASCII)) { xmlTranslationsFile = XDocument.Load(oReader); } // Read file with LINQ var messagesList = xmlTranslationsFile .Root .Descendants("context") .Elements() .Where(x => x.Name == "message") .Select(x => new { Key = Convert.ToInt32(x.Element("source").Value.Split('/').FirstOrDefault()), Value = x.Element("translation").Value }); foreach (var message in messagesList) { // If not contain key if (!messages.Keys.Contains(message.Key)) messages.Add(message.Key, message.Value); } return NO_ERROR; } catch (Exception ex) { return ManageException(ex); } } public override CmsError NC_GetAvailableLanguages(ref ICollection languages) { try { foreach (string file in Directory.GetFiles(PLC_MESSAGES_FILE_PATH)) { if (Path.GetExtension(file) == ".ts") { string fileName = Path.GetFileNameWithoutExtension(file); var splittedFileName = fileName.Split('_'); if (splittedFileName.Count() == 2) { if (splittedFileName[0].ToLower() == "cmsalarm") { // Get lang from threeletter var lang = GetCultureFromThreeLetter(splittedFileName[1]); if (lang != null) languages.Add(lang); } } } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } #endregion Contructor & global methods /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region High level methods // Get the processes-count configurated public override CmsError NC_RProcessesNum(ref ushort ProcNumber) { CmsError cmsError = ReadStaticNCData(); if (cmsError.IsError()) return cmsError; ProcNumber = (ushort)ConfChannelNo; return NO_ERROR; } // Get the NC model Name public override CmsError NC_RModelName(ref string ModelName) { CmsError cmsError = ReadStaticNCData(); if (cmsError.IsError()) return cmsError; ModelName = Cnc_name; return NO_ERROR; } // Get the NC Software Version public override CmsError NC_RSoftwareVersion(ref string SWV) { CmsError cmsError = ReadStaticNCData(); if (cmsError.IsError()) return cmsError; SWV = Cnc_SftVersion; return NO_ERROR; } // Get the NC Language public override CmsError NC_RLanguage(ref CultureInfo Language) { CmsError cmsError = ReadStaticNCData(); if (cmsError.IsError()) return cmsError; Language = ConvertToSTEPLanguage(SiemensLanguage); return NO_ERROR; } // Set the NC Language public override CmsError NC_WLanguage(CultureInfo Language) { //CmsError cmsError = CheckConnection(); //if (cmsError.IsError()) // return cmsError; //// Write write the language //Infrastructure.CurrentLanguage = ConvertToNCLanguage(Language); return NO_ERROR; } // Get the NC Serial number public override CmsError NC_RSerialNumber(ref string serialNumber) { CmsError cmsError = ReadStaticNCData(); if (cmsError.IsError()) return cmsError; serialNumber = Cnc_SeriesNum; return NO_ERROR; } // Get CMS Machine number public override CmsError NC_RMachineNumber(bool hasLetters, ref string MachNumber) { if (!hasLetters) { CmsError cmsError = ReadStaticNCData(); if (cmsError.IsError()) return cmsError; MachNumber = Cms_MachNumber; } else { // New method to read machine number List lists = new List(); CmsError cmsError = MEM_RWByteList(R, 0, NEW_MATR_MACC.MemType, NEW_MATR_MACC.Address, NEW_MATR_MACC.SubAddress, 0, 4, ref lists); if (cmsError.IsError()) return cmsError; lists.Reverse(); MachNumber = Encoding.ASCII.GetString(lists.ToArray()); } return NO_ERROR; } // Get the Date-Time of the NC public override CmsError NC_RDateTime(ref DateTime ActualTime) { // Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Try to get information try { // Setup variables DataSvc Data = LowPriorityDataSvc(); Item itemRead = new Item(NC_TIME_PATH); // Read Data Data.Read(itemRead); // Save Data ActualTime = (DateTime)itemRead.Value; } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } // Check if the NC is in running state public override CmsError NC_RIsRunning(ref bool running) { ushort nProcess = 0; // Get the number of processes CmsError cmsError = NC_RProcessesNum(ref nProcess); if (cmsError.IsError()) return cmsError; ushort i = 1; running = false; do { PROC_STATUS procStatus = PROC_STATUS.IDLE; // Read process status cmsError = PROC_RStatus(i, ref procStatus); if (cmsError.IsError()) return cmsError; if (procStatus == PROC_STATUS.RUN) running = true; i++; } while (!running || i <= nProcess); return NO_ERROR; } // Get NC unit of measure public override CmsError NC_RUnitOfMeasure(ref string unitOfMeasure) { CmsError cmsError = ReadStaticNCData(); if (cmsError.IsError()) return cmsError; unitOfMeasure = UnitOfMeasure; return NO_ERROR; } // Get the Nc Active Alarms public override CmsError NC_RActiveAlarms(ref List alarms) { alarms = SiemensAlarms. Where(x => (x.Id < IDMinPLCMessage || x.Id > IDMaxPLCMessage) && (x.Id < IDMinChannel || x.Id > IDMaxChannel)) .Select(x => { uint id = x.Instance == 1 ? (uint)x.Id : Convert.ToUInt32((x.Id & 0xffff) | (x.Instance << 24)); return new AlarmModel() { Id = id, Message = x.Message, IsWarning = false, Process = 0, DateTime = x.TimeStamp }; }) .GroupBy(x => x.Id).Select(x => x.First()) .ToList(); return NO_ERROR; } // Set the Nc Active Page of the NC public override CmsError NC_SetScreenVisible(SCREEN_PAGE screen) { //Waiting time int SleepMs = 50; int TotalTimes = 2000 / 50; int ActualTimes = 0; string area = ConvertStepToSiemensScreen(screen); if (string.IsNullOrEmpty(area)) return INCORRECT_PARAMETERS_ERROR; if (Infrastructure.CurrentActiveArea != area) { Infrastructure.SwitchToArea(area); while (Infrastructure.CurrentActiveArea != area) { if (ActualTimes == TotalTimes) return HMI_NOT_RESPONDING_ERROR; Thread.Sleep(SleepMs); ActualTimes++; } } return NO_ERROR; } public override CmsError NC_WMDICommand(int processId, string mdiString) { // Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { FileSvc fileSvc = new FileSvc(); var a = fileSvc.ReadMdaBuffer(1); fileSvc.WriteMdaBuffer(processId, mdiString); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } #endregion High level methods /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region PLC High-level data public override CmsError PLC_RWManageWatchdog() { bool plcWatchdog = false; CmsError cmsError = MEM_RWBoolean(R, 0, NC_WATCHDOG.MemType, NC_WATCHDOG.Address, NC_WATCHDOG.SubAddress, 0, ref plcWatchdog); if (cmsError.IsError()) return cmsError; if (plcWatchdog) return PLC_NOT_RUNNING_ERROR; plcWatchdog = true; return MEM_RWBoolean(W, 0, NC_WATCHDOG.MemType, NC_WATCHDOG.Address, NC_WATCHDOG.SubAddress, 0, ref plcWatchdog); } public override CmsError PLC_RActiveMessages(ref List alarms) { bool[] statusBits; int i = 0; List readValues = new List(); CmsError cmsError; try { alarms.Clear(); // Read on data from memory cmsError = MEM_RWIntegerList(R, 0, ALARMS_STATUS.MemType, ALARMS_STATUS.Address, ALARMS_STATUS.SubAddress, (ALARMS_STATUS.Size / 4) + (ALARMS_DATA.Size / 2), // statys_bytes / 4 + data_word / 2 ref readValues); if (cmsError.IsError()) return cmsError; alarms.Clear(); //List readValues = new List(); //// Read on data from memory //CmsError cmsError = MEM_RWIntegerList(R, 0, // ALARMS_STATUS.MemType, // ALARMS_STATUS.Address, // ALARMS_STATUS.SubAddress, // (ALARMS_STATUS.Size + ALARMS_DATA.Size) / 4, // byte / 4 // ref readValues); //if (cmsError.IsError()) // return cmsError; // Convert integer array into bit array statusBits = IntToBits(readValues.ToArray()); for (i = 0; i < ALARMS_STATUS.Size * 8; i++) { // If alarm is active if (statusBits[i]) { // Calculate matching alarm byte info address int dataByteAddress = (i * 16) + ALARMS_NUMBER; var processList = new List(); // Get processes on which alarm is active for (int j = dataByteAddress; j < dataByteAddress + 6; j++) { if (statusBits[j]) processList.Add(j + 1 - dataByteAddress); } // Add alarm info into active alarms list alarms.Add(new PlcAlarmModel() { Id = (uint)i + 1, IsWarning = statusBits[dataByteAddress + 7], RestorationIsActive = statusBits[dataByteAddress + 6], Process = processList }); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError PLC_WRestoreMessage(uint id) { // Check id range if (id > ALARMS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Call restore message CmsError cmsError = PLC_WStrobe(ALARM_ACK, ALARM_RESTORATION_STROBE, id); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_WRefreshMessage(uint id) { // Check id range if (id > ALARMS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Call restore message CmsError cmsError = PLC_WStrobe(ALARM_ACK, ALARM_REFRESH_STROBE, id); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_WRefreshAllMessages() { return PLC_WNcSoftKey(REFRESH_ALL_ALARMS_SFKEY_INDEX); } public override CmsError PLC_RPowerOnData(ref PreAndPostPowerOnModel powerOnModel) { int readValue = 0; // Read pre power on and post power on data from memory CmsError cmsError = MEM_RWInteger(R, 0, PRE_POST_POWER_ON.MemType, PRE_POST_POWER_ON.Address, PRE_POST_POWER_ON.SubAddress, ref readValue); if (cmsError.IsError()) return cmsError; bool[] bits = new bool[32]; // Convert int into to true/false array bits = IntToBits(readValue); // Create adn set pre power on object PrePowerOnModel prePowerOn = new PrePowerOnModel() { PowerOn = new PowerOnDataModel() { Id = 1, Active = bits[0], Clickable = bits[16] }, // id = N, bits = N, Clickable = N + 8 (Second bit) AirPressure = new PowerOnDataModel() { Id = 2, Active = bits[1], Clickable = bits[17] }, ProtectionStatus = new PowerOnDataModel() { Id = 3, Active = bits[2], Clickable = bits[18] }, EmergencyButtons = new PowerOnDataModel() { Id = 4, Active = bits[3], Clickable = bits[19] }, SettingMode = new PowerOnDataModel() { Id = 5, Active = bits[4], Clickable = bits[20] }, StartingKey = new PowerOnDataModel() { Id = 6, Active = bits[5], Clickable = bits[21] } }; // Create and set post power on object PostPowerOnModel postPowerOn = new PostPowerOnModel() { AxisReset = new PowerOnDataModel() { Id = 9, Active = bits[8], Clickable = bits[24] }, // id = N - 8, bits = N, Clickable = N + 8 (Second bit) WaterjetPump = new PowerOnDataModel() { Id = 10, Active = bits[9], Clickable = bits[25] } }; powerOnModel = new PreAndPostPowerOnModel() { PostPowerOn = postPowerOn, PrePowerOn = prePowerOn }; return NO_ERROR; } public override CmsError PLC_WPowerOnData(uint id, bool value) { // Check bit range if (id > 16) return INCORRECT_PARAMETERS_ERROR; // Call restore message CmsError cmsError = PLC_WStrobe(PRE_POST_POWER_ON_ACK, PRE_POST_POWER_ON_CLICKED, id); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_RFunctionAccess(ref List functions) { List readValues = new List(); int numberOfIntegers = FUNCTION_ACCESS.Size / 4; // Read functions access data from memory CmsError cmsError = MEM_RWIntegerList(R, 0, FUNCTION_ACCESS.MemType, FUNCTION_ACCESS.Address, FUNCTION_ACCESS.SubAddress, numberOfIntegers, ref readValues); if (cmsError.IsError()) return cmsError; functions = new List(); // Convert int into to true/false array bool[] bits = IntToBits(readValues.ToArray()); // Convert array into structured data for (int i = 0; i < bits.Count(); i++) { functions.Add(new FunctionalityModel() { Id = (uint)i + 1, IsActive = bits[i] }); } return NO_ERROR; } public override CmsError PLC_RAxesResetData(ref AxisResetDataModel axisResetData) { byte value = 0; // Read byte from memory CmsError cmsError = MEM_RWByte(R, 0, AXIS_RESET_PROCEDURE.MemType, AXIS_RESET_PROCEDURE.Address, AXIS_RESET_PROCEDURE.SubAddress, 0, ref value); if (cmsError.IsError()) return cmsError; // Check last bit if is active if ((value & 128) == 128) { // Set to 0 last bit( isActive bit x - 128 ) // From 0 to 6 bit represents percentage // If higher than 100 then value = 100 byte percentage = value - 128 > 100 ? (byte)100 : (byte)(value - 128); axisResetData = new AxisResetDataModel() { IsActive = true, Percentage = percentage }; } return NO_ERROR; } public override CmsError PLC_RNcSoftKeys(ref List ncSoftKeys) { CmsError cmsError = PLC_RSoftKeys(NC_SOFTKEYS_VALUE, NC_SOFTKEYS_CLICKABLE, ref ncSoftKeys); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_RUserSoftKeys(ref List softKeys) { CmsError cmsError = PLC_RSoftKeys(USER_SOFTKEYS_VALUE, USER_SOFTKEYS_CLICKABLE, ref softKeys); if (cmsError.IsError()) return cmsError; return NO_ERROR; } private CmsError PLC_RSoftKeys(MEMORY_CELL softKeyStatusMemory, MEMORY_CELL softKeysClickableMemory, ref List softKeys) { softKeys = new List(); List readValues = new List(); int memorySizeToRead = (softKeyStatusMemory.Size + softKeysClickableMemory.Size); // Offset between status and clickable data int offset = softKeyStatusMemory.Size * 8; // Read on data from memory CmsError cmsError = MEM_RWIntegerList(R, 0, softKeyStatusMemory.MemType, softKeyStatusMemory.Address, softKeyStatusMemory.SubAddress, memorySizeToRead / 4, ref readValues); if (cmsError.IsError()) return cmsError; // Convert ints into an array of bools bool[] bits = IntToBits(readValues.ToArray()); // Convert array into structured data for (ushort i = 0; i < bits.Count() / 2; i++) { softKeys.Add(new SoftKeysModel() { Id = (uint)i + 1, Value = bits[i], Active = bits[i + offset] }); } return NO_ERROR; } public override CmsError PLC_WNcSoftKey(uint id) { // Check id range if (id > NC_SOFTKEYS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Write strobe into memory CmsError cmsError = PLC_WStrobe(NC_SOFT_KEYS_ACK, NC_SOFT_KEYS_CLICKED, id); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_WUserSoftKey(uint id) { // Check id range if (id > USER_SOFTKEYS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Write strobe into memory CmsError cmsError = PLC_WStrobe(USER_SOFT_KEYS_ACK, USER_SOFT_KEYS_CLICKED, id); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_RHeadsData(List heads, int number) { // Check parameters if (number > MAX_HEADS_NUMBER) return INCORRECT_PARAMETERS_ERROR; heads.Clear(); List readInts = new List(); List readValues = new List(); List readHours = new List(); // Find the size of a single head int headsByte = (HEADS_DATA.Size / MAX_HEADS_NUMBER); double headsInts = Math.Ceiling((double)(headsByte / 4) + 1); // Read data for N heads CmsError cmsError = MEM_RWIntegerList(R, 0, HEADS_DATA.MemType, HEADS_DATA.Address, HEADS_DATA.SubAddress, (int)headsInts * number, ref readInts); if (cmsError.IsError()) return cmsError; // Convert into list of byte readValues = readInts.SelectMany(BitConverter.GetBytes).ToList(); // Read Worked time heads cmsError = MEM_RWDWordList(R, 0, HEADS_WORKED_TIMES.MemType, HEADS_WORKED_TIMES.Address, HEADS_WORKED_TIMES.SubAddress, number, ref readHours); if (cmsError.IsError()) return cmsError; // Parse and format read data for (int i = 0; i < number; i++) { // Head address = posizion * size of single head in memory var headOffset = i * headsByte; short toolId = SwapShortEndianFormat(BitConverter.ToInt16(readValues.ToArray(), headOffset + 4)); double residualLife = 0; // Find tool var tool = ToolTableData.Where(x => x.Id == toolId).FirstOrDefault(); // Check if process is selected if (readValues[headOffset] != 0) { try { // Read selected edge Item activeEdgeId = new Item { Path = "/Channel/State/actDNumber[u" + readValues[headOffset] + ",1]" }; // OffsetId DataSvc dataSvc = new DataSvc(); dataSvc.Read(activeEdgeId); if (Convert.ToInt32(activeEdgeId.Value) != 0) { // Find edge var edge = tool.EdgesData .Where(x => x.Id == Convert.ToInt32(activeEdgeId.Value)) .FirstOrDefault(); // Set residual life if (edge != null) residualLife = edge.ResidualLife; } } catch (Exception ex) { return ManageException(ex); } } heads.Add(new HeadDataModel() { Id = (uint)i + 1, Process = readValues[headOffset], Override = readValues[headOffset + 1], Load_Abrasive = SwapShortEndianFormat(BitConverter.ToInt16(readValues.ToArray(), headOffset + 2)), // Uint 16 = 2byte MountedTool_Vacum = toolId, // Uint 16 = 2byte ActualSpeed_Pressure = SwapIntEndianFormat(BitConverter.ToInt32(readValues.ToArray(), headOffset + 6)), // Int32 = 4byte IsActive = (readValues[headOffset + 10] & 1) != 0, // bit 0 IsSelected = (readValues[headOffset + 10] & 2) != 0, // bit 1 OverrideEditable = (readValues[headOffset + 10] & 4) != 0, // bit 2 Configured = (readValues[headOffset + 10] & 8) != 0, Rotation = (readValues[headOffset + 10] & 16) == 0 ? ROTATION.CLOCKWHISE : ROTATION.COUNTERCLOCKWHISE, WorkedTime = readHours[i], Tool = new ToolInSpindleModel() { ChildId = tool == null ? 0 : tool.ChildId, ToolName = tool == null ? "" : tool.FamilyName, Disabled = tool == null ? false : !tool.IsActive, Measured = tool == null ? false : tool.IsMeasured, Broken = tool == null ? false : tool.IsInhibited, MaxLoad = tool == null ? 0 : tool.Load, MaxSpeed = tool == null ? 0 : tool.MaxSpeed, ResidualLife = residualLife } }); } return NO_ERROR; } public override CmsError PLC_RWorkedTimeHead(int head, ref uint time) { int index = (head - 1) * 4; // Read Worked time CmsError cmsError = MEM_RWDWord(R, 0, HEADS_WORKED_TIMES.MemType, HEADS_WORKED_TIMES.Address, HEADS_WORKED_TIMES.SubAddress + index, ref time); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_WResetWorkedTimeHead(int head) { byte usControlWord = 0; if (head <= 0 || head > MAX_HEADS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Read status CmsError cmsError = MEM_RWByte(R, 0, HEAD_RESET_WORKED_TIME.MemType, HEAD_RESET_WORKED_TIME.Address, HEAD_RESET_WORKED_TIME.SubAddress, 0, ref usControlWord); if (cmsError.IsError()) return cmsError; // Re-Write it status usControlWord = Convert.ToByte((usControlWord & 0xE0) | (head & 0X1F)); cmsError = MEM_RWByte(W, 0, HEAD_RESET_WORKED_TIME.MemType, HEAD_RESET_WORKED_TIME.Address, HEAD_RESET_WORKED_TIME.SubAddress, 0, ref usControlWord); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_RWorkedTimeMachine(ref uint time) { // Read Worked time CmsError cmsError = MEM_RWDWord(R, 0, MACHINE_WORKED_TIME.MemType, MACHINE_WORKED_TIME.Address, MACHINE_WORKED_TIME.SubAddress, ref time); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_WResetWorkedTimeMachine(uint time) { uint actTime = 0; // Read actual Value CmsError cmsError = MEM_RWDWord(R, 0, MACHINE_WORKED_TIME.MemType, MACHINE_WORKED_TIME.Address, MACHINE_WORKED_TIME.SubAddress, ref actTime); if (cmsError.IsError()) return cmsError; // Per richiedere l'azzeramento del timer invio 4 volte il segnale velocemente al PLC // Il PLC resetta il bit e aspetta quello successivo entro 500ms, se no abortisce // Sfrutto così la velocità dei sw, cosa che un "nemico" a mano se provasse a forzare il bit non avrebbe bool bitValue = true; int nTry = 0; for (int i = 0; i <= 4; i++) { //Scrivo il bit bitValue = true; nTry = 0; cmsError = MEM_RWBoolean(W, 0, MACHINE_RESET_WORKED_TIME.MemType, MACHINE_RESET_WORKED_TIME.Address, MACHINE_RESET_WORKED_TIME.SubAddress, 0, ref bitValue); if (cmsError.IsError()) return cmsError; //Aspetto che venga abbassato do { Thread.Sleep(50); nTry += 1; cmsError = MEM_RWBoolean(R, 0, MACHINE_RESET_WORKED_TIME.MemType, MACHINE_RESET_WORKED_TIME.Address, MACHINE_RESET_WORKED_TIME.SubAddress, 0, ref bitValue); if (cmsError.IsError()) return cmsError; } while (bitValue && nTry <= 10); //se il valore è rimasto a 1 il plc non l'ha preso in carico, e abortisco if (bitValue) { bitValue = true; cmsError = MEM_RWBoolean(W, 0, MACHINE_RESET_WORKED_TIME.MemType, MACHINE_RESET_WORKED_TIME.Address, MACHINE_RESET_WORKED_TIME.SubAddress, 0, ref bitValue); if (cmsError.IsError()) return cmsError; return PLC_NOT_RUNNING_ERROR; } else { //Se l'ha abbassato scrivo il nuovo dato cmsError = MEM_RWDWord(W, 0, MACHINE_WORKED_TIME.MemType, MACHINE_WORKED_TIME.Address, MACHINE_WORKED_TIME.SubAddress, ref time); } } return NO_ERROR; } public override CmsError PLC_WHeadOverride(uint id, HEAD_OVERRIDE_SIGN sign) { if (id > MAX_HEADS_NUMBER) return INCORRECT_PARAMETERS_ERROR; MEMORY_CELL currentStrobeCell = sign == HEAD_OVERRIDE_SIGN.PLUS ? HEADS_STROBE_INCREMENT : HEADS_STROBE_DECREMENT; // Write strobe into memory CmsError cmsError = PLC_WStrobe(HEADS_ACK, currentStrobeCell, id); if (cmsError.IsError()) return cmsError; return NO_ERROR; } // MACHINE COUNTERS public override CmsError PLC_RMachineCounters(ref List counters) { List val = new List(); // Read ints CmsError cmsError = MEM_RWDWordList(R, 0, COUNTERS_DATA.MemType, COUNTERS_DATA.Address, COUNTERS_DATA.SubAddress, COUNTERS_DATA.Size / 4, ref val); if (cmsError.IsError()) return cmsError; // Set return value uint i = 0; counters = val.Select(x => new CounterModel() { Id = i++, Value = x }) .ToList(); return NO_ERROR; } public override CmsError PLC_WResetMachineCounters(uint counter) { bool isResettable = false; CmsError cmsError = MEM_RWBoolean(R, 0, COUNTER_IS_RESETTABLE.MemType, COUNTER_IS_RESETTABLE.Address, COUNTER_IS_RESETTABLE.SubAddress, (int)(counter - 1), ref isResettable); if (cmsError.IsError()) return cmsError; if (!isResettable) return FUNCTION_NOT_ALLOWED_ERROR; cmsError = PLC_WStrobe(COUNTER_IS_RESETTABLE_ACK, COUNTER_IS_RESETTABLE_STROBE, counter); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_ROperatorInputIsNeeded(ref List value) { byte val = 0; // Read memory CmsError cmsError = MEM_RWByte(R, 0, M155_INPUT_NEEDED.MemType, M155_INPUT_NEEDED.Address, M155_INPUT_NEEDED.SubAddress, 0, ref val); if (cmsError.IsError()) return cmsError; // Convert byte to an array of bits bool[] bits = ByteToBits(val); uint processId = 1; string[] parameters; string actualLine = ""; foreach (bool bit in bits) { if (bit) { // Read active program line cmsError = PROC_ReadActiveLine(processId, ref actualLine); if (cmsError.IsError()) return cmsError; // Parse line & get parameters parameters = ExtractM155ParametersFromNcCodeLine(actualLine); if (parameters.Count() == 0) { value.Add(new M155InputIsNeededModel() { Process = processId, IsNeeded = bits[processId - 1], Message = "", Type = M155_TYPE.REAL, Buttons = new Dictionary() }); return NO_ERROR; } byte i = 1; if (parameters[0].ToUpper().Trim() == "SHOWVAL") { try { // Skip first parameter because it's the message string // Set button with -> id = 1..5 -> value = parameter value Dictionary buttons = parameters.Skip(2)?.ToDictionary(x => i++, x => x); // Read machine variable DataSvc dataSvc = new DataSvc(); Item item = new Item() { Path = string.Format("/channel/parameter/r[c{0} , 155]", processId), }; dataSvc.Read(item); value.Add(new M155InputIsNeededModel() { Process = processId, IsNeeded = bits[processId - 1], Message = parameters[1] ?? "", Type = M155_TYPE.SHOW_VAL, // if there aren't buttons is a simple request, Value = Convert.ToDouble(item.Value), Buttons = buttons }); } catch (Exception ex) { return ManageException(ex); } } else { // Skip first parameter because it's the message string // Set button with -> id = 1..5 -> value = parameter value Dictionary buttons = parameters.Skip(1)?.ToDictionary(x => i++, x => x); value.Add(new M155InputIsNeededModel() { Process = processId, IsNeeded = bit, Message = parameters[0] ?? "", Type = parameters.Count() > 1 ? M155_TYPE.MULTIPLE_BUTTONS : M155_TYPE.REAL, // if there aren't buttons is a simple request Buttons = buttons }); } } // Next path processId++; } return NO_ERROR; } public override CmsError PLC_WOperatorInputResponse(int process, double responseVal) { try { DataSvc dataSvc = new DataSvc(); Item item = new Item() { Path = string.Format("/channel/parameter/r[c{0} , 155]", process), Value = responseVal }; dataSvc.Write(item); return PLC_WStrobe(M155_INPUT_ACK, M155_INPUT_STROBE, (uint)process); } catch (Exception ex) { return ManageException(ex); } } public override CmsError PLC_RM154Data(ref List data, ref bool MTCOnOff) { MTCOnOff = false; CmsError cmsError = MEM_RWBoolean(R, 0, M154_SWITCH_ONOFF.MemType, M154_SWITCH_ONOFF.Address, M154_SWITCH_ONOFF.SubAddress, 1, ref MTCOnOff); if (cmsError.IsError()) return cmsError; byte val = 0; cmsError = MEM_RWByte(R, 0, M154_STROBE.MemType, M154_STROBE.Address, M154_STROBE.SubAddress, 0, ref val); if (cmsError.IsError()) return cmsError; // Convert a byte to an array of booleans bool[] bits = ByteToBits(val); string[] parameters; string tmpStr = ""; for (uint processId = 1; processId <= MAX_PROCESS_NUMBER; processId++) { if (bits[processId - 1]) { // Read active program line cmsError = PROC_ReadActiveLine(processId, ref tmpStr); if (cmsError.IsError()) return cmsError; // Parse parameters parameters = ExtractM154ParametersFromNcCodeLine(tmpStr); data.Add(new M154DataModel() { Process = processId, IsNeeded = bits[processId - 1], Parameters = parameters }); } } return NO_ERROR; } public override CmsError PLC_W154ManageAck(int processId) { return PLC_ManageActiveAck(M154_STROBE.Address, M154_STROBE.SubAddress, processId - 1, M154_ACK.Address, M154_ACK.SubAddress, processId - 1, M154_STROBE.MemType); } public override CmsError PLC_RM156Data(ref List value) { byte val = 0; List vals = new List(); CmsError cmsError = MEM_RWByte(R, 0, M156_INPUT_NEEDED.MemType, M156_INPUT_NEEDED.Address, M156_INPUT_NEEDED.SubAddress, 0, ref val); if (cmsError.IsError()) return cmsError; cmsError = MEM_RWByteList(R, 0, M156_INPUT_ID_LIST.MemType, M156_INPUT_ID_LIST.Address, 0, M156_INPUT_ID_LIST.Size, ref vals); if (cmsError.IsError()) return cmsError; bool[] bits = ByteToBits(val); for (int processId = 1; processId <= MAX_PROCESS_NUMBER; processId++) { if (bits[processId - 1]) { Item item = new Item() { Path = string.Format("/channel/parameter/r[c{0} , 154]", processId), }; try { DataSvc dataSvc = new DataSvc(); dataSvc.Read(item); } catch (Exception ex) { return ManageException(ex); } // Parse line & get parameters value.Add(new M156InputIsNeededModel() { Process = (uint)processId, Id = vals.ElementAt(processId - 1), Value = Convert.ToDouble(item.Value) }); } } return NO_ERROR; } public override CmsError PLC_WM156Response(int process, double responseVal) { //CmsError cmsError = MEM_RWDouble(W, 0, MEMORY_TYPE.Osai_GD, 900 + (process - 1), ref responseVal); //if (cmsError.IsError()) // return cmsError; return PLC_WStrobe(M156_INPUT_ACK, M156_INPUT_STROBE, (uint)process); } public override CmsError PLC_RScadaValue(string memIndex, SCADA_MEM_TYPE memType, ref object value) { if (memType == SCADA_MEM_TYPE.BOOL) { if (memIndex.ToUpper() == "FALSE") { value = false; return NO_ERROR; } else if (memIndex.ToUpper() == "TRUE") { value = true; return NO_ERROR; } } string[] index = memIndex.Split('.'); CmsError cmsError = NO_ERROR; try { if (index.Count() == 0 || index.Count() == 1) return INCORRECT_PARAMETERS_ERROR; else if (index.Count() == 2) { if (memType == SCADA_MEM_TYPE.INT) { // read INT int val = 0; cmsError = MEM_RWInteger(R, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), ref val); value = val; } else if (memType == SCADA_MEM_TYPE.WORD) { // read WORD short val = 0; cmsError = MEM_RWShort(R, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), ref val); value = val; } else if (memType == SCADA_MEM_TYPE.REAL) { // read DOUBLE double val = 0; cmsError = MEM_RWDouble(R, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), ref val); value = val; } else { // read BYTE byte val = 0; cmsError = MEM_RWByte(R, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), 0, ref val); value = val; } } else if (index.Count() == 3 && memType == SCADA_MEM_TYPE.BOOL) { // read BOOL bool val = false; cmsError = MEM_RWBoolean(R, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), Convert.ToInt32(index[2]), ref val); value = val; } } catch (Exception ex) { return ManageException(ex); } return cmsError; } public override CmsError PLC_RScadaSiemens(ref List objects) { try { List items = new List(); string bit, address; char charType = 'B'; // Cycle through object for (int i = 0; i < objects.Count(); i++) { // Split memory string -> X.Y.Z string[] splittedMem = objects[i].Address.Split('.'); bit = "0"; address = "0"; bool read = true; switch (objects[i].MemType) { case SCADA_MEM_TYPE.BOOL: { // Check if memory contains default value if (splittedMem[0].ToUpper() == "FALSE") { objects[i].Value = false; read = false; break; } else if (splittedMem[0].ToUpper() == "TRUE") { objects[i].Value = true; read = false; break; } bit = splittedMem[2]; address = splittedMem[1]; charType = 'X'; // Siemens memory type character } break; case SCADA_MEM_TYPE.BYTE: { address = splittedMem[1]; charType = 'B'; } break; case SCADA_MEM_TYPE.INT: { address = splittedMem[1]; charType = 'D'; } break; case SCADA_MEM_TYPE.WORD: { address = splittedMem[1]; charType = 'W'; } break; case SCADA_MEM_TYPE.REAL: { address = splittedMem[1]; charType = 'D'; } break; } // If needs to read if (read) { // Convert splitted address into Siemens address ConvertMemToPath(MEMORY_TYPE.Siemens_DB, Convert.ToInt32(splittedMem[0]), Convert.ToInt32(address), Convert.ToInt32(bit), 1, charType, out string item); // Add to the list of items to be readed items.Add(new Item() { Path = item }); } } if (items.Count() > 0) { // Read data DataSvc dataSvc = new DataSvc(); dataSvc.Read(items.ToArray()); int alreadyReaded = 0; for (int i = 0; i < objects.Count(); i++) { // Skip the objects already valorised if (objects[i].Value == null) { switch (objects[i].MemType) { case SCADA_MEM_TYPE.BOOL: { // Valorize data objects[i].Value = Convert.ToBoolean(items[i - alreadyReaded].Value); } break; case SCADA_MEM_TYPE.BYTE: { objects[i].Value = Convert.ToByte(items[i - alreadyReaded].Value); } break; case SCADA_MEM_TYPE.INT: { objects[i].Value = Convert.ToInt32(items[i - alreadyReaded].Value); } break; case SCADA_MEM_TYPE.WORD: { objects[i].Value = Convert.ToInt16(items[i - alreadyReaded].Value); } break; case SCADA_MEM_TYPE.REAL: { // Convert value to double var byteVal = BitConverter.GetBytes((uint)items[i - alreadyReaded].Value); var value = unchecked(Convert.ToDouble(BitConverter.ToSingle(byteVal, 0))); objects[i].Value = Math.Round(value, objects[i].Round); } break; } } else { // Count items already readed alreadyReaded++; } } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError PLC_WScadaValue(string memIndex, SCADA_MEM_TYPE memType, object value) { string[] index = memIndex.Split('.'); CmsError cmsError = NO_ERROR; if (index.Count() == 0) return INCORRECT_PARAMETERS_ERROR; else if (index.Count() == 2) { if (memType == SCADA_MEM_TYPE.INT) { // write INT int val = Convert.ToInt32(value); cmsError = MEM_RWInteger(W, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), ref val); } else if (memType == SCADA_MEM_TYPE.WORD) { // write WORD short val = Convert.ToInt16(value); cmsError = MEM_RWShort(W, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), ref val); } else if (memType == SCADA_MEM_TYPE.REAL) { // write DOUBLE double val = Convert.ToDouble(value); cmsError = MEM_RWDouble(W, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), ref val); } else { // write byte byte val = Convert.ToByte(value); cmsError = MEM_RWByte(W, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), 0, ref val); } } else if (index.Count() == 3 && memType == SCADA_MEM_TYPE.BOOL) { // write BOOL bool val = Convert.ToBoolean(value); cmsError = MEM_RWBoolean(W, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), Convert.ToInt32(index[2]), ref val); } return cmsError; } public override CmsError PLC_WAssistedToolingCmd(ushort toolId, ushort familyId, ushort shankId, ushort magazineId, ushort positionId, ASSISTED_TOOLING_ACTION action) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_RAssistedToolingData(ref AssistedToolingModel data) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_WTerminateAssistedToolingProcedure() { return FUNCTION_NOT_ALLOWED_ERROR; } private CmsError PLC_WStrobe(MEMORY_CELL ackCell, MEMORY_CELL strobeCell, uint id) { CmsError cmsError; bool readValue = false; bool writeValue = true; SetupAckStrobeAddresses(ackCell.SubAddress, strobeCell.SubAddress, id, out int ackByte, out int strobeByte, out int alarmBitId); // Check Strobe cmsError = MEM_RWBoolean(R, 0, strobeCell.MemType, strobeCell.Address, strobeByte, alarmBitId, ref readValue); if (cmsError.IsError()) return cmsError; // If PLC it's performing another request then return if (readValue) return NO_ERROR; // Check ACK cmsError = MEM_RWBoolean(R, 0, ackCell.MemType, ackCell.Address, ackByte, alarmBitId, ref readValue); if (cmsError.IsError()) return cmsError; // If PLC it's performing another request then return if (readValue) return NO_ERROR; // Write strobe into memory cmsError = MEM_RWBoolean(W, 0, strobeCell.MemType, strobeCell.Address, strobeByte, alarmBitId, ref writeValue); if (cmsError.IsError()) return cmsError; // Reset wait ack = 1 and reset the strobe cmsError = ResetStrobe(alarmBitId, strobeByte, ackByte, ackCell.MemType); if (cmsError.IsError()) return cmsError; return NO_ERROR; } private void SetupAckStrobeAddresses(int ackAddress, int strobeAddress, uint id, out int ackByte, out int strobeByte, out int bit) { ackByte = ackAddress + (((int)id - 1) / 8); strobeByte = strobeAddress + (((int)id - 1) / 8); bit = (((int)id - 1) % 8); } private CmsError ResetStrobe(int bitId, int strobeByte, int ackByte, MEMORY_TYPE memType) { int n = 600; bool readValue = false; bool writeValue = false; bool ok = false; CmsError cmsError; do { // Check ACK cmsError = MEM_RWBoolean(R, 0, memType, TABLE, ackByte, bitId, ref readValue); if (cmsError.IsError()) return cmsError; // If true reset strobe if (readValue == true) { // Reset strobe cmsError = MEM_RWBoolean(W, 0, memType, TABLE, strobeByte, bitId, ref writeValue); if (cmsError.IsError()) return cmsError; // Exit from cycle n = 0; ok = true; } else { // Decrement n--; // Wait befor next cycle Thread.Sleep(20); } } while (n > 0); if (!ok) { // Reset strobe cmsError = MEM_RWBoolean(W, 0, memType, TABLE, strobeByte, bitId, ref writeValue); if (cmsError.IsError()) return cmsError; } return cmsError; } private CmsError PLC_ManageActiveAck(int strobeByte, int strobeSubByte, int strobeBit, int ackByte, int ackSubByte, int ackBit, MEMORY_TYPE memType) { int n = 1200; // 30 seconds bool readValue = false; bool writeValue = true; bool ok = false; // Set ack to 1 CmsError cmsError = MEM_RWBoolean(W, 0, memType, ackByte, ackSubByte, ackBit, ref writeValue); if (cmsError.IsError()) return cmsError; do { // Check strobe cmsError = MEM_RWBoolean(R, 0, memType, strobeByte, strobeSubByte, strobeBit, ref readValue); if (cmsError.IsError()) return cmsError; // If true reset acknowledge if (!readValue) { writeValue = false; // Reset acknowledge cmsError = MEM_RWBoolean(W, 0, memType, ackByte, ackSubByte, ackBit, ref writeValue); if (cmsError.IsError()) return cmsError; // Exit from cycle n = 0; ok = true; } else { // Decrement n--; // Wait befor next cycle Thread.Sleep(25); } } while (n > 0); // If loop timeout goes in timeout if (!ok) { // Reset acknowledge writeValue = false; cmsError = MEM_RWBoolean(W, 0, memType, ackByte, ackSubByte, ackBit, ref writeValue); if (cmsError.IsError()) return cmsError; } return cmsError; } public override CmsError PLC_WExpiredCandy(bool value) { bool newVal = false; //Scrivo il dato CmsError cmsError = MEM_RWBoolean(W, 0, EXP_CANDY_MEM.MemType, EXP_CANDY_MEM.Address, EXP_CANDY_MEM.SubAddress, 5, ref value); if (cmsError.IsError()) return cmsError; else { //Leggo il dato cmsError = PLC_RExpiredCandy(ref newVal); if (cmsError.IsError()) return cmsError; //Se i 2 dati coincidono ritorno OK if (value == newVal) return NO_ERROR; else return PLC_NOT_RUNNING_ERROR; } } public override CmsError PLC_RExpiredCandy(ref bool value) { CmsError cmsError = MEM_RWBoolean(R, 0, EXP_CANDY_MEM.MemType, EXP_CANDY_MEM.Address, EXP_CANDY_MEM.SubAddress, 5, ref value); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PLC_WCandy(long value) { // Long is formed by a integer + word // Write Word ushort word = (ushort)((value & 0xFFFF)); CmsError cmsError = MEM_RWWord(W, 0, CANDY_MEM.MemType, CANDY_MEM.Address, CANDY_MEM.SubAddress, ref word); if (cmsError.IsError()) return cmsError; int integer = (int)((value & 0xFFFFFFFF0000) >> 16); // Write Integer (+1 is used because osai uses word) cmsError = MEM_RWInteger(W, 0, CANDY_MEM.MemType, CANDY_MEM.Address, CANDY_MEM.SubAddress + 2, ref integer); if (cmsError.IsError()) return cmsError; // Rieggo il dato long newVal = 0; cmsError = PLC_RCandy(ref newVal); if (cmsError.IsError()) return cmsError; // Se i 2 dati coincidono ritorno OK if (value == newVal) return NO_ERROR; else return PLC_NOT_RUNNING_ERROR; } public override CmsError PLC_RCandy(ref long value) { // Long is formed by a integer + word // Read word ushort word = 0; CmsError cmsError = MEM_RWWord(R, 0, CANDY_MEM.MemType, CANDY_MEM.Address, CANDY_MEM.SubAddress, ref word); if (cmsError.IsError()) return cmsError; // Read first int uint firtInt = 0; cmsError = MEM_RWDWord(R, 0, CANDY_MEM.MemType, CANDY_MEM.Address, CANDY_MEM.SubAddress + 2, ref firtInt); if (cmsError.IsError()) return cmsError; // Build Long value value = ((long)firtInt << 16) + word; return NO_ERROR; } public override CmsError PLC_RActiveClient(ref int clientId) { CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; byte readValues = 0; cmsError = MEM_RWByte(R, 0, ACTIVE_CLIENT.MemType, ACTIVE_CLIENT.Address, ACTIVE_CLIENT.SubAddress, 0, ref readValues); if (cmsError.IsError()) return cmsError; // Convert integer array into bit array bool[] statusBits = ByteToBits(readValues); // check which bit is set for (int i = 0; i < 8; i++) { if (statusBits[i]) clientId = i + 1; } return NO_ERROR; } public override CmsError PLC_RToolMovement(ref MovementBetweenMagazinesModel toolMovement) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_WTerminateMovementProcedure(MOVEMENT_RESPONSE resp) { return FUNCTION_NOT_ALLOWED_ERROR; } #endregion PLC High-level data /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region PROCESS (PATH) High-level data // Get the process Mode public override CmsError PROC_RMode(ushort ProcNumber, ref PROC_MODE Mode) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Try to get information try { // Setup variables DataSvc Data = HighPriorityDataSvc(); Item itemRead = new Item(NC_GENERIC_MODE_PATH + "[u" + ProcNumber + "]"); Item itemReadIncr = new Item(JOG_INCR_PATH + "[u" + ProcNumber + "]"); Item itemReadAdv = new Item(ADVANCED_JOG_PATH + "[u" + ProcNumber + "]"); // Read Data Data.Read(itemRead); Data.Read(itemReadIncr); Data.Read(itemReadAdv); // Save Data Mode = ConvertToSTEPMode((uint)itemRead.Value, (uint)itemReadIncr.Value, (uint)itemReadAdv.Value); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } // Get the process status public override CmsError PROC_RStatus(ushort ProcNumber, ref PROC_STATUS Status) { // Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Try to get information try { // Setup variables DataSvc Data = HighPriorityDataSvc(); Item itemRead = new Item(NC_GENERIC_STATE_PATH + "[u" + ProcNumber + "]"); // Read Data Data.Read(itemRead); // Save Data Status = ConvertToSTEPStatus((uint)itemRead.Value); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } // Get PP Lines public override CmsError PROC_RPPLines(ushort ProcNumber, ref List Lines) { // Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; string[] newLines; // Try to get information try { // Setup variables DataSvc Data = HighPriorityDataSvc(); Item itemRead = new Item(ACT_PROG_LINES_PATH + "[u" + ProcNumber + "]"); // Read Data Data.Read(itemRead); // Save Data newLines = ((string)itemRead.Value).Replace("\r", string.Empty).Split('\n'); // Setup the return values Lines.Clear(); foreach (string Line in newLines) Lines.Add(Line); // Remove the first Line (the previous line) if (Lines.Count > 0) Lines.RemoveAt(0); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } // Get PP Name public override CmsError PROC_RSelectedPPName(ushort ProcNumber, ref string Name) { // Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; string RetString; int LastUnderscore; // Try to get information try { // Setup variables DataSvc Data = HighPriorityDataSvc(); Item itemRead = new Item(ACT_PROG_NAME_PATH + "[u" + ProcNumber + "]"); // Read Data Data.Read(itemRead); // Elaborate String RetString = ((string)itemRead.Value); RetString = RetString.Replace("_N_", ""); LastUnderscore = RetString.LastIndexOf("_"); if (LastUnderscore >= 0) RetString = RetString.Remove(LastUnderscore, 1).Insert(LastUnderscore, "."); // Save Data Name = RetString; } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } // Get the process Active Alarms public override CmsError PROC_RActiveAlarms(ushort procNumber, ref List alarms) { alarms = SiemensAlarms .Where(x => x.Id >= IDMinChannel && x.Id <= IDMaxChannel && x.Parameters[0].Equals(procNumber.ToString())) .Select(x => { uint id = x.Instance == 1 ? (uint)x.Id : Convert.ToUInt32((x.Id & 0xffff) | (x.Instance << 24)); return new AlarmModel() { Id = id, Message = x.Message, IsWarning = false, Process = procNumber, DateTime = x.TimeStamp }; }) .ToList(); return NO_ERROR; } // Get process part program data public override CmsError PROC_RStatusAndData(ushort procNumber, ref ProcessDataModel processData) { processData.Id = procNumber; // Read part program name CmsError cmsError = PROC_RSelectedPPName(procNumber, ref processData.PartProgramName); if (cmsError.IsError()) return cmsError; int readValue = 0; // Read processes status from memory cmsError = MEM_RWInteger(R, 0, PROCESS_STATUS.MemType, PROCESS_STATUS.Address, PROCESS_STATUS.SubAddress + ((procNumber - 1) * 2), ref readValue); if (cmsError.IsError()) return cmsError; byte[] bytes = BitConverter.GetBytes(readValue); // Convert Byte into true/false array BitArray bits = new BitArray(new byte[] { bytes[0] }); // 1st byte -> 0 : Proccess type (AUX-WORK), 1: Process in alarm status, 2: Run, 3: Hold, 4: Read, 5: PartProgramVisible // Get part program info visibility processData.Visible = bits[0]; // Populate response structure processData.Type = bits[1] ? "WORK" : "AUX"; processData.IsSelected = bits[2]; processData.IsInAlarm = bits[3]; processData.CanLoadProgram = bits[4]; // Choose process status if (bytes[1] == 1) processData.Status = "HOLD"; else { if (bytes[1] == 2) processData.Status = "RUN"; else processData.Status = "READY"; } // Get Reps from 3nd-4th byte processData.Reps = BitConverter.ToUInt16(bytes, 2); return NO_ERROR; } public override CmsError PROC_RSelectedProcess(ref ushort procNumber) { if (SelectedProcess == 0) return SELECTED_PROCESS_ERROR; procNumber = SelectedProcess; //CmsError cmsError; //bool readValue = false; //for (int i = 0; i < PROCESS_NUMBER; i++) //{ // // Calculate bit address = ProcessBase + processId * 2 // int memoryAddress = SELECTED_PROCESS.SubAddress + i * (2); // // Read memory from plc // cmsError = MEM_RWBoolean(R, 0, SELECTED_PROCESS.MemType, SELECTED_PROCESS.Address, memoryAddress, 2, ref readValue); // if (cmsError.IsError()) // return cmsError; // if (readValue) // { // procNumber = (ushort)(i + 1); // return NO_ERROR; // } //} return NO_ERROR; } public override CmsError PROC_WSelectProcess(ushort procNumber) { CmsError cmsError; byte processNum = (byte)procNumber; // Check parameter if (processNum > MAX_PROCESS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Write process number cmsError = MEM_RWByte(W, 0, SELECT_PROCESS.MemType, SELECT_PROCESS.Address, SELECT_PROCESS.SubAddress, ref processNum); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError PROC_RSelectedProcessData(int processId, ref SelectedProcessData processData) { if (processId <= 0) return PROC_NOT_FOUND_ERROR; try { Item[] items = new Item[7] { new Item { Path = "/Channel/State/actTNumber[u" + processId + ",1]" }, // ActiveToolId new Item { Path = "/Channel/State/actDNumber[u" + processId + ",1]" }, // OffsetId new Item { Path = "/Channel/State/actFrameIndex[u" + processId + "]" }, // Origin new Item { Path = "DB21.DBB4"}, // Work override new Item { Path = "DB21.DBB5"}, // Rapid override, new Item { Path = "/Channel/State/actFeedRateIpo[u" + processId + ", 1]"}, new Item { Path = "/Nck/Configuration/numCuttEdgeParams[1]"}, // Cutt Edge Params }; // Read data DataSvc dataSvc = new DataSvc(); dataSvc.Read(items); short origin = 0; // Convert SIEMENS enumerable to G(N) format es: G54 if (Convert.ToInt16(items[2].Value) > 0) { if (Convert.ToInt16(items[1].Value) >= 5) origin = (short)(Convert.ToInt16(items[2].Value) + 500); else origin = (short)(Convert.ToInt16(items[2].Value) + 53); } OffsetModel offset = new OffsetModel(); //Read the ID of the Tool & Edge short actualToolId = Convert.ToInt16(items[0].Value); short actualEdgeId = Convert.ToInt16(items[1].Value); short numCuttEdgeParams = Convert.ToInt16(items[6].Value); int offsetEdge = (actualEdgeId - 1) * numCuttEdgeParams; if (actualToolId != 0 && actualEdgeId != 0) { //Setup the items for the tools. Must be read only this value Item[] itemsToolEdge = new Item[4] { new Item { Path = "/Tool/Compensation/edgeData[u1,c"+ actualToolId +","+ (offsetEdge + 3) + "]" }, // $TC_DP3 new Item { Path = "/Tool/Compensation/edgeData[u1,c"+ actualToolId +","+ (offsetEdge + 6) + "]" }, // $TC_DP6 new Item { Path = "/Tool/Compensation/edgeData[u1,c"+ actualToolId +","+ (offsetEdge + 12) + "]" }, // $TC_DP12 new Item { Path = "/Tool/Compensation/edgeData[u1,c"+ actualToolId +","+ (offsetEdge + 15) + "]" } // $TC_DP15 }; dataSvc.Read(itemsToolEdge); offset = new OffsetModel() { Id = actualEdgeId, Length = Convert.ToDouble(itemsToolEdge[0].Value), Radius = Convert.ToDouble(itemsToolEdge[1].Value), WearLength = Convert.ToDouble(itemsToolEdge[2].Value), WearRadius = Convert.ToDouble(itemsToolEdge[3].Value), RealLength = Convert.ToDouble(itemsToolEdge[0].Value) + Convert.ToDouble(itemsToolEdge[2].Value), RealRadius = Convert.ToDouble(itemsToolEdge[1].Value) + Convert.ToDouble(itemsToolEdge[3].Value) }; /* Other Method. Find it in the Database of the Tools... Too SLow? (Nicola Carminati 08/08/19) // Find edge EdgeModel edge = ToolTableData.Where(x => x.Id == Convert.ToInt16(items[0].Value)) .FirstOrDefault() .EdgesData.Where(x => x.Id == Convert.ToInt16(items[1].Value)) .FirstOrDefault(); //Find the Type of the Tool SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration(); List toolTypeConfig = toolEdgesConfig.EdgesConfig[ ToolTableData.Where(x => x.Id == Convert.ToInt16(items[0].Value)).FirstOrDefault().ToolType ]; if(toolTypeConfig != null && toolTypeConfig.Count > 0) { //Read Names of the parameters String lenghtName = toolTypeConfig.Where(x => x.Path == "$TC_DP3[").FirstOrDefault().Name; String radiusName = toolTypeConfig.Where(x => x.Path == "$TC_DP6[").FirstOrDefault().Name; String wearLenghtName = toolTypeConfig.Where(x => x.Path == "$TC_DP12[").FirstOrDefault().Name; String wearRadiusName = toolTypeConfig.Where(x => x.Path == "$TC_DP15[").FirstOrDefault().Name; if(!String.IsNullOrEmpty(wearLenghtName) && !String.IsNullOrEmpty(wearRadiusName) && !String.IsNullOrEmpty(lenghtName) && !String.IsNullOrEmpty(radiusName)) { // Convert edgeModel to offsetModel offset = new OffsetModel() { Id = (short)edge.Id, Length = edge.EdgeAdditionalParams[lenghtName], Radius = edge.EdgeAdditionalParams[radiusName], WearLength = edge.EdgeAdditionalParams[wearLenghtName], WearRadius = edge.EdgeAdditionalParams[wearRadiusName], RealLength = edge.EdgeAdditionalParams[lenghtName] + edge.EdgeAdditionalParams[wearLenghtName], RealRadius = edge.EdgeAdditionalParams[radiusName] + edge.EdgeAdditionalParams[wearRadiusName] }; } }*/ } // Creata return model processData = new SelectedProcessData { ActiveOffsetId = Convert.ToInt16(items[1].Value), Origin = origin, ProcessMessage = "", WorkOverride = Convert.ToByte(items[3].Value), RapidOverride = Convert.ToByte(items[4].Value), OffsetData = offset, FeedOverride = Convert.ToDouble(items[5].Value) }; } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } private CmsError PROC_ReadActiveLine(uint processId, ref string line) { try { Item item = new Item(); if (processId == 0) item.Path = "/Channel/ProgramInfo/actBlock[u1,1]"; // Default else item.Path = "/Channel/ProgramInfo/actBlock[u" + processId + ",1]"; DataSvc dataSvc = new DataSvc(); dataSvc.Read(item); line = item.Value.ToString(); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } #endregion PROCESS (PATH) High-level data /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region PROCESS-AXES (PATH) High-level data public override CmsError AXES_RInterpPosition(ushort channel, ref Dictionary axes) { try { axes = new Dictionary(); // Cycle between axes // The dictionary is written asynchronously so i have to create a copy of the dictionary with .ToList() to avoid exceptions // axes = InterpAxesPosition.ToDictionary(x => x.Key, x => x.Value); This code throws exceptions lock (InterpAxesPosition) { foreach (var axis in InterpAxesPosition.ToList()) { axes.Add(axis.Key, axis.Value); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError AXES_RMachinePosition(ushort channel, ref Dictionary axes) { try { axes = new Dictionary(); lock (MachineAxesPosition) { // Cycle between axes // The dictionary is written asynchronously so i have to create a copy of the dictionary with .ToList() to avoid exceptions foreach (var axis in MachineAxesPosition.ToList()) { axes.Add(axis.Key, axis.Value); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError AXES_RProgrPosition(ushort channel, ref Dictionary axes) { try { axes = new Dictionary(); lock (ProgrammedAxisPosition) { // Cycle between axes // The dictionary is written asynchronously so i have to create a copy of the dictionary with .ToList() to avoid exceptions foreach (var axis in ProgrammedAxisPosition.ToList()) { axes.Add(axis.Key, axis.Value); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError AXES_RFollowingError(ushort channel, ref Dictionary axes) { try { axes = new Dictionary(); lock (InterpAxesPosition) { // Cycle between axes // The dictionary is written asynchronously so i have to create a copy of the dictionary with .ToList() to avoid exceptions foreach (var axis in InterpAxesPosition.ToList()) { axes.Add(axis.Key, axis.Value); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError AXES_RDistanceToGo(ushort channel, ref Dictionary axes) { try { axes = new Dictionary(); lock (ToGoAxesPosition) { // Cycle between axes // The dictionary is written asynchronously so i have to create a copy of the dictionary with .ToList() to avoid exceptions foreach (var axis in ToGoAxesPosition.ToList()) { axes.Add(axis.Key, axis.Value); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } private Dictionary AXES_RAxesPos(ushort channel, string positionType) { Dictionary axes = new Dictionary(); List axesConf = new List(); CmsError cmsError = AXES_RAxesNames(channel, ref axesConf); List items = new List(); foreach (var conf in axesConf) { // Setup the items to be readed items.Add(new Item() { Path = string.Format("/Channel/{0}[u{1},{2}]", positionType, channel, conf.Id) }); } DataSvc dataSvc = new DataSvc(); // Read all the items dataSvc.Read(items.ToArray()); int i = 0; foreach (var conf in axesConf) { axes.Add(conf.Id.ToString(), Convert.ToDouble(items[i].Value)); i++; } return axes; } public override CmsError AXES_RAxesNames(ushort channel, ref List axesData) { if (!File.Exists(AXES_FILE_PATH)) return CmsError.InternalError("File" + AXES_FILE_PATH + " not found", new Exception("File" + AXES_FILE_PATH + " not found")); // Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; List configuredAxes = new List(); Item[] ncAxes = new Item[MAX_AXES_FOR_PROCESS * 3]; try { // Check if the static object is already populated if (AxesData.Count == 0) { XDocument xmlAxesFile = XDocument.Load(AXES_FILE_PATH); // Read data from file configuredAxes = xmlAxesFile .Root .Elements() .Select(x => new AxisModel() { Id = Convert.ToInt32(x.Attribute("id").Value), Name = x.Value, IsSelectable = false }) .Where(x => x.Id != 0) // Parse only active axes .ToList(); } // Object used for reading data from NC DataSvc svcData = new DataSvc(); bool[] axesAreVisible = new bool[MAX_AXES_FOR_PROCESS]; // Read from Nc for (int i = 1; i <= MAX_AXES_FOR_PROCESS; i++) { // Set the path to read on which process is the axis ncAxes[i - 1] = new Item("/Nck/MachineAxis/chanNoAxisIsActive[" + i + "]"); // Set the path in order to find which axes are visible ncAxes[i - 1 + MAX_AXES_FOR_PROCESS] = new Item("/NC/_N_CH_TEA_ACX/$MC_DISPLAY_AXIS[u" + channel + "," + i + "]"); // Set the path of the axes type ncAxes[i - 1 + (MAX_AXES_FOR_PROCESS * 2)] = new Item("/Nck/Configuration/axisType[" + i + "]"); } svcData.Read(ncAxes); for (int i = 0; i < MAX_AXES_FOR_PROCESS; i++) { // Set visible field axesAreVisible[i] = (Convert.ToInt32(ncAxes[i + MAX_AXES_FOR_PROCESS].Value) & 1) == 1; int processAxes = Convert.ToInt32(ncAxes[i].Value); // If axis is visible, add it to the output if (processAxes == channel && axesAreVisible[i]) { // Check if axes is configurated axes var axis = configuredAxes.Where(x => x.Id == (i + 1)).FirstOrDefault(); if (axis != null) { axis.Type = (AXIS_TYPE)Convert.ToInt32(ncAxes[i + (MAX_AXES_FOR_PROCESS * 2)].Value); AxesData.Add(axis); } } } // Get from PLC which axis can be selected List ids = new List(); cmsError = MEM_RWByteList(R, 0, AXES_BUTTON_VISIBLE.MemType, AXES_BUTTON_VISIBLE.Address, AXES_BUTTON_VISIBLE.SubAddress, 0, AXES_BUTTON_VISIBLE.Size, ref ids); if (cmsError.IsError()) return cmsError; // Parse the data readed from PLC foreach (byte id in ids) { if (id != 0) { // If axis exists, set it as selectable var tmpAxis = AxesData.Where(x => x.Id == id).FirstOrDefault(); if (tmpAxis != null) tmpAxis.IsSelectable = true; } } axesData = AxesData; } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError AXES_RSelectedAxis(ref byte axisId) { // Read byte from memory CmsError cmsError = MEM_RWByte(R, 0, SELECTED_AXIS.MemType, SELECTED_AXIS.Address, SELECTED_AXIS.SubAddress, 1, ref axisId); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError AXES_WSelectAxis(byte axisId) { // Write byte from memory CmsError cmsError = MEM_RWByte(W, 0, SELECT_AXIS.MemType, SELECT_AXIS.Address, SELECT_AXIS.SubAddress, 1, ref axisId); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError AXES_ROrigin(int numberOfAxes) { DataSvc dataSvc = new DataSvc(); List ncAxes = new List(); List axes = new List(); CmsError cmsError = AXES_RAxesNames(1, ref axes); for (int i = 1; i <= 4; i++) { foreach (var axis in axes) { var num = axis.Id + (axes.Last().Id * i); ncAxes.Add(new Item() { Path = "/Channel/UserFrame/linShift[u1, " + num + "]" }); } } dataSvc.Read(ncAxes.ToArray()); return NO_ERROR; } #endregion PROCESS-AXES (PATH) High-level data /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region NC Low-level function: single valiable in memory //Read-Write a Boolean-Value inside the NC. public override CmsError MEM_RWBoolean(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int MemBit, ref bool Value) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; //Check if the Bit Number is Correct cmsError = CheckBitRange(MemBit); if (cmsError.IsError()) return cmsError; //Try to get information try { //Setup variables DataSvc Data = HighPriorityDataSvc(); cmsError = ConvertMemToPath(MemType, MemTable, MemIndex, MemBit, 1, 'X', out string itemString); if (cmsError.IsError()) return cmsError; Item item = new Item(itemString); //Read-Write Data if (bWrite) { item.Value = Value; Data.Write(item); } else { Data.Read(item); Value = (bool)item.Value; } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } //Read-Write a Byte-Value-List inside the NC. In writing-mode the field "Number" is not required public override CmsError MEM_RWByte(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int MemByte, ref byte Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError cmsError = MEM_RWByteList(bWrite, Process, MemType, MemTable, MemIndex, MemByte, 1, ref ListValue); if (cmsError.IsError()) return cmsError; Value = ListValue.First(); return NO_ERROR; } //Write a Word-Value inside the NC. In writing-mode the field "Number" is not required public override CmsError MEM_RWWord(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref ushort Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError cmsError = MEM_RWWordList(bWrite, Process, MemType, MemTable, MemIndex, 1, ref ListValue); if (cmsError.IsError()) return cmsError; Value = ListValue.First(); return NO_ERROR; } public override CmsError MEM_RWShort(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref short Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError cmsError = MEM_RWShortList(bWrite, Process, MemType, MemTable, MemIndex, 1, ref ListValue); if (cmsError.IsError()) return cmsError; Value = ListValue.First(); return NO_ERROR; } //Write a Word-Value inside the NC. In writing-mode the field "Number" is not required public override CmsError MEM_RWDWord(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref uint Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError cmsError = MEM_RWDWordList(bWrite, Process, MemType, MemTable, MemIndex, 1, ref ListValue); if (cmsError.IsError()) return cmsError; Value = ListValue.First(); return NO_ERROR; } public override CmsError MEM_RWDouble(bool bWrite, int process, MEMORY_TYPE memType, int memTable, int memIndex, ref double value) { // Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Try to get information try { // Setup variables DataSvc Data = new DataSvc { Timeout = TimeoutConn, PriorityFlag = SlPriority.highPriority }; cmsError = ConvertMemToPath(memType, memTable, memIndex, 0, 1, 'D', out string itemString); if (cmsError.IsError()) return cmsError; Item item = new Item(itemString); byte[] byteVal; // Read-Write Data if (bWrite) { byteVal = BitConverter.GetBytes((Single)value); item.Value = BitConverter.ToUInt32(byteVal, 0); Data.Write(item); } else { Data.Read(item); byteVal = BitConverter.GetBytes((uint)item.Value); value = unchecked(Convert.ToDouble(BitConverter.ToSingle(byteVal, 0))); } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } //Write a Int-Value inside the NC. In writing-mode the field "Number" is not required public override CmsError MEM_RWInteger(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref int Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError cmsError = MEM_RWIntegerList(bWrite, Process, MemType, MemTable, MemIndex, 1, ref ListValue); if (cmsError.IsError()) return cmsError; Value = ListValue.First(); return NO_ERROR; } //-------------------------------------------------------------------------------------------------------------------------- // Other-NC Version of Memory-Access Methods public override CmsError MEM_RWBoolean(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int MemBit, ref bool Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWByte(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int MemByte, ref byte Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWDWord(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, ref uint Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWInteger(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, ref int Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWShort(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, ref short Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWWord(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, ref ushort Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWDouble(bool bWrite, int process, MEMORY_TYPE memType, int memIndex, ref double value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWDWordList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int Number, ref List Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWIntegerList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int Number, ref List Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWShortList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int Number, ref List Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWWordList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int Number, ref List Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError MEM_RWByteList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int MemByteStart, int Number, ref List Value) { return FUNCTION_NOT_ALLOWED_ERROR; } #endregion NC Low-level function: single valiable in memory /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region Low level methods public override CmsError MEM_RWByteList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int MemByteStart, int Number, ref List Value) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; //Try to get/set information try { //Setup variables DataSvc dataSvc = HighPriorityDataSvc(); cmsError = ConvertMemToPath(MemType, MemTable, MemIndex, 0, (bWrite) ? Value.Count : Number, 'B', out string itemString); if (cmsError.IsError()) return cmsError; Item item = new Item(itemString); //Read-Write Data if (bWrite) { item.Value = Value.ToArray(); dataSvc.Write(item); } else { dataSvc.Read(item); if (item.Value.GetType().IsArray) Value = ((object[])item.Value).Cast().ToList(); else { Value.Clear(); Value.Add((byte)(uint)item.Value); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError MEM_RWWordList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Value) { ////Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; //Try to get/set information try { //Setup variables DataSvc Data = HighPriorityDataSvc(); cmsError = ConvertMemToPath(MemType, MemTable, MemIndex, 0, (bWrite) ? Value.Count : Number, 'W', out string itemString); if (cmsError.IsError()) return cmsError; Item item = new Item(itemString); //Read-Write Data if (bWrite) { item.Value = Value.ToArray(); Data.Write(item); } else { Data.Read(item); if (item.Value.GetType().IsArray) Value = Array.ConvertAll(((object[])item.Value).Cast().ToArray(), input => (ushort)input).ToList(); else { Value.Clear(); Value.Add(Convert.ToUInt16((uint)item.Value)); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError MEM_RWShortList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Value) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; //Try to get/set information try { //Setup variables DataSvc Data = HighPriorityDataSvc(); cmsError = ConvertMemToPath(MemType, MemTable, MemIndex, 0, (bWrite) ? Value.Count : Number, 'W', out string itemString); if (cmsError.IsError()) return cmsError; Item item = new Item(itemString); //Read-Write Data if (bWrite) { item.Value = Value.ToArray(); Data.Write(item); } else { Data.Read(item); if (item.Value.GetType().IsArray) Value = Array.ConvertAll(((object[])item.Value).Cast().ToArray(), input => unchecked((short)input)).ToList(); else { Value.Clear(); Value.Add(unchecked((short)(uint)item.Value)); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError MEM_RWDWordList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Value) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; //Try to get/set information try { //Setup variables DataSvc Data = HighPriorityDataSvc(); cmsError = ConvertMemToPath(MemType, MemTable, MemIndex, 0, (bWrite) ? Value.Count : Number, 'D', out string itemString); if (cmsError.IsError()) return cmsError; Item item = new Item(itemString); //Read-Write Data if (bWrite) { item.Value = Value.ToArray(); Data.Write(item); } else { Data.Read(item); if (item.Value.GetType().IsArray) Value = ((object[])item.Value).Cast().ToList(); else { Value.Clear(); Value.Add((uint)item.Value); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError MEM_RWIntegerList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Value) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; //Try to get/set information try { //Setup variables DataSvc Data = HighPriorityDataSvc(); cmsError = ConvertMemToPath(MemType, MemTable, MemIndex, 0, (bWrite) ? Value.Count : Number, 'D', out string itemString); if (cmsError.IsError()) return cmsError; Item item = new Item(itemString); //Read-Write Data if (bWrite) { item.Value = Value.ToArray(); Data.Write(item); } else { Data.Read(item); if (item.Value.GetType().IsArray) Value = Array.ConvertAll(((object[])item.Value).Cast().ToArray(), input => unchecked((int)input)).ToList(); else { Value.Clear(); Value.Add(unchecked((int)(uint)item.Value)); } // Convert BigEndian to LittleEndian Value = ChangeIntListEndianess(Value); } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } #endregion Low level methods /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region NC Low-level function: Parameters public override CmsError NC_RParam(short Index, short Bit, ref bool Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError NC_RParam(short Index, ref byte Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError NC_RParam(short Index, ref short Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError NC_RParam(short Index, ref int Value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError NC_RParam(short Index, ref double Value) { return FUNCTION_NOT_ALLOWED_ERROR; } #endregion NC Low-level function: Parameters /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region File Management public override CmsError FILES_RGetFileList(string path, ref List files) { string[] rootFolders = { "WKS.DIR", "MPF.DIR", "SPF.DIR" }; try { string tmpPath = FormatPath(path); FileSvc fileSvc = new FileSvc(); // Preapare folder node Node folderNode = new Node(BASE_FILE_PATH + tmpPath); // Read files in the folder List nodeArray = fileSvc.List(folderNode).ToList(); // Go through the array of file nodes foreach (Node element in nodeArray) { PreviewFileModel file = new PreviewFileModel(); if (path == "\\\\") { if (rootFolders.Contains(element.Name)) { file = new PreviewFileModel() { Path = path + "\\" + element.Name, IsDirectory = element.IsDirNode, Name = GetStringUntilOrEmpty(element.Name, "."), AbsolutePath = element.LogicalPath }; files.Add(file); } } else { file = new PreviewFileModel() { Path = path + "\\" + element.Name, IsDirectory = element.IsDirNode, Name = element.IsDirNode ? GetStringUntilOrEmpty(element.Name, ".") : element.Name, AbsolutePath = element.LogicalPath }; files.Add(file); } // ACCESS LEVEL CHECK (REMOVED TEMPORARILY) //if (element.AccessRights.List == AccessLevel.KEY_0) //{ // var file = new PreviewFileModel() // { // Path = path + "\\" + element.Name, // IsDirectory = element.IsDirNode, // Name = element.Name, // AbsolutePath = element.LogicalPath // }; // files.Add(file); //} } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError FILES_RGetFileInfo(string path, ref InfoFile fileInfo) { try { FileSvc fileSvc = new FileSvc(); // Preapare folder node Node fileNode = new Node(path); if (fileNode != null) { string filePath = "C://CMS//Active//TMP//" + fileNode.Name; FileStream str = new FileStream(filePath, FileMode.Create); CmsError cmsError = FILES_RProgramToFile(path, str); if (cmsError.IsError()) return cmsError; fileInfo = new InfoFile() { CreationDate = fileNode.Attributes.LastAccess, LastModDate = fileNode.Attributes.LastAccess, Name = fileNode.Name, Content = File.ReadAllLines(filePath).ToList(), // PreviewBase64 = FindImageBase64String(IMAGES_PATH, fileNode.Name), AbsolutePath = fileNode.LogicalPath }; str.Close(); File.Delete(filePath); } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError FILES_WSetActiveProgram(int processId, string filePath, ref ActiveProgramDataModel data) { try { // string ncPath = FormatPath(filePath); FileSvc fileSvc = new FileSvc(); // Preapare folder node Node selectedNode = new Node(filePath); if (!selectedNode.Exists) return FILE_NOT_FOUND_ERROR; // Check if file is stored on NC if (filePath.StartsWith(BASE_FILE_PATH)) fileSvc.Select(selectedNode, processId); else fileSvc.SelectExtern(selectedNode, processId); return FILES_RActiveProgramData(processId, ref data); } catch (Exception ex) { return ManageException(ex); } } public override CmsError FILES_WDeactivateProgram(int processId) { try { string[] piArgs = new string[4]; piArgs[0] = "/NC"; piArgs[1] = (200 + processId).ToString(); piArgs[2] = "/MPF0"; piArgs[3] = "_N_SELECT"; PiSvc pi = new PiSvc(piArgs); pi.Start(); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError FILES_RActiveProgramData(int processId, ref ActiveProgramDataModel programData) { try { //Setup variables DataSvc dataSvc = new DataSvc(); // Read position and tool data List itemRead = new List() { new Item($"/Channel/ProgramInfo/workPandProgName[u{processId}]"), new Item($"/Channel/ProgramInfo/actPartProgram[u{processId}]") }; //Read Data dataSvc.Read(itemRead.ToArray()); // Elaborate String string trimString = ((string)itemRead[0].Value); trimString = trimString.Replace("_N_", ""); int lastUnderscore = trimString.LastIndexOf("_"); if (lastUnderscore >= 0) trimString = trimString.Remove(lastUnderscore, 1).Insert(lastUnderscore, "."); // check if is the NULL Program if (trimString == "/MPF0") { programData = new ActiveProgramDataModel() { Path = "", IsoLines = new List(), TimeLeft = new DateTime() }; return NO_ERROR; } // Separate string into list of lines List isoLines = itemRead[1] .Value .ToString() .Split('\n') // Line separator .Skip(1) // The actPartProgram read starting with the line before the current .ToList(); programData = new ActiveProgramDataModel() { Path = trimString, IsoLines = isoLines, TimeLeft = new DateTime() }; } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError FILES_UploadPartProgram(string localPath, string name, ref string newFilePath) { File.Copy(localPath + name, PART_PRG_PATH + name, true); newFilePath = PART_PRG_PATH + name; return NO_ERROR; } public override CmsError FILES_CopyProgram(string partProgramPath, string newPartProgramPath, bool failIfExist) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { //Setup variables FileSvc FileData = new FileSvc(); Node sourceNode = new Node(partProgramPath); Node destNode = new Node(newPartProgramPath); //Execute Function FileData.Copy(sourceNode, destNode, failIfExist); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError FILES_DeleteProgram(string partProgramPath, string partProgramName) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { // Setup variables FileSvc FileData = new FileSvc(); Node sourceNode = new Node(partProgramPath); //Execute Function FileData.Delete(sourceNode); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError FILES_RProgramToFile(string partProgramPath, FileStream localFile) { // Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { // Setup variables string tmpFile = Path.GetTempFileName(); FileSvc FileData = new FileSvc(); Node sourceNode = new Node(partProgramPath); Node destNode = new Node(tmpFile); // Execute Function FileData.Copy(sourceNode, destNode, true); FileStream tmpFileStream = new FileStream(tmpFile, FileMode.Open); // Write to local file WriteLocalFile(ReadLocalFile(tmpFileStream), ref localFile); tmpFileStream.Close(); // Delete temporary file File.Delete(tmpFile); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError FILES_WProgramFromFile(string partProgramPath, FileStream localFile) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { // Setup variables FileSvc FileData = new FileSvc(); Node sourceNode = new Node(localFile.Name); Node destNode = new Node(partProgramPath); //Execute Function FileData.Copy(sourceNode, destNode, true); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError FILES_RQueueData(ref List statusList) { return NO_ERROR; } public override CmsError FILES_RQueueDataByProcess(ref QueueStatusModel status, int processId) { return NO_ERROR; } public override CmsError FILES_WStartQueue() { return NO_ERROR; } public override CmsError FILES_WStopQueue() { return NO_ERROR; } public override CmsError FILES_WLoadNextPartProgram(string localPath, string ncFileName) { return NO_ERROR; } public override CmsError FILES_WUploadJobFilesAndActivate(int processId, string jobExtractedPath, string fileToActivate) { return NO_ERROR; } public override CmsError FILES_RGetProgramType(ref PROGRAM_TYPE_ENUM programType) { programType = PROGRAM_TYPE_ENUM.PART_PROGRAM; return NO_ERROR; } public override CmsError FILES_WCleanUploadFolder() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WUploadCustomMainProgramAndActivate(int processId, string customPartProgramContent, ref ActiveProgramDataModel activeData) { string customMainName = string.Format(CUSTOM_MAIN_PROGRAM, processId); string newFilePath = ""; CmsError cmsError = FILES_UploadPartProgram(customPartProgramContent, customMainName, ref newFilePath); if (cmsError.IsError()) return cmsError; cmsError = FILES_WSetActiveProgram(processId, newFilePath, ref activeData); if (cmsError.IsError()) return cmsError; return NO_ERROR; } private IEnumerable GetLinesFromString(string text) { string line; using (StringReader reader = new StringReader(text)) { while ((line = reader.ReadLine()) != null) { yield return line; } } } private string FormatPath(string path) { path = path.TrimStart('\\'); path = path.TrimStart('/'); path = path.TrimEnd('\\'); return path.Replace('\\', '/'); } #endregion File Management /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region Siemens Tool Management public override CmsError TOOLS_RConfiguration(ref ToolTableConfiguration config) { // Set limits config.MaxTools = MAX_TOOL_NUMER; config.MaxEdgesPerTools = MAX_EDGES_PER_TOOL; config.MaxToolsPerFamily = MAX_TOOLS_PER_FAMILY; config.MaxMultitools = MAX_MULTITOOLS_NUMBER; config.MaxToolsPerMultitools = MAX_TOOLS_PER_MULTITOOL; // Set options config.MultitoolOptionActive = MULTITOOL_OPTION_ACTIVE; config.FamilyOptionActive = true; config.MagPositionOptionActive = true; config.RadiusMetricType = false; config.LifeOption = true; // Set fields configurations config.ToolsConfiguration = SiemensToolFieldsConfig; config.FamiliesConfiguration = SiemensFamilyFieldsConfig; config.ShanksConfiguration = SiemensShankFieldsConfig; config.MagazinePosConfiguration = SiemensMagazinePosFieldsConfig; config.EdgesConfiguration = SiemensEdgesFieldsConfiguration; config.EdgesConfiguration.EdgesAdditionalParamsConfiguration = new Dictionary>(); // Remove path and set only names as additionalParams foreach (int key in Add_Edges_Param_Config.EdgesConfig.Keys) { List tmpNames = new List(); foreach (var conf in Add_Edges_Param_Config.EdgesConfig[key]) { tmpNames.Add(conf.Name); } // Set config field config.EdgesConfiguration.EdgesAdditionalParamsConfiguration.Add(key, tmpNames); } config.Magazines = MagazineConfig; //config.Magazines = new List(); //foreach (PositionModel pos in MagazinePositionsData) //{ // var tmp = config.Magazines.Where(x => x.Id == pos.MagazineId).FirstOrDefault(); // if (tmp == null) // { // config.Magazines.Add(new MagazineConfigModel() // { // Id = pos.MagazineId, // Type = MAGAZINE_TYPE.CHAIN // }); // } //} return NO_ERROR; } #region Tools functions public override CmsError TOOLS_RToolsData(ref List toolTable) { toolTable = new List(ToolTableData.Select(x => { // Find if is loaded in magazine MountedToolModel tool = MagazineMountedTools.Where(y => y.ToolId == x.Id).FirstOrDefault(); if (tool != null) { x.MagazineId = tool.MagazineId; x.PositionId = tool.PositionId; } else { x.MagazineId = 0; x.PositionId = 0; } // Update multitool id x.MultitoolId = ToolIsInMultitool(x.Id); return x; }) .ToList()); return NO_ERROR; } public override CmsError TOOLS_WAddTool(ref SiemensToolModel tool) { CmsError cmsError = CheckToolData(ref tool); if (cmsError.IsError()) return cmsError; try { //Create Tools string[] piArgs = new string[6]; piArgs[0] = "/NC"; piArgs[1] = "401"; piArgs[2] = tool.FamilyName.Trim().PadRight(32); //Name (32 char) piArgs[3] = "00000"; //Tool ID (00000 > autom) piArgs[4] = "00000"; //Duplo ID (00000 > autom) piArgs[5] = "_N_TMCRTO"; PiSvc pi = new PiSvc(piArgs); pi.Start(); // Get new tool id tool.Id = GetLastToolId(); // Update new tool cmsError = TOOLS_WUpdateTool(ref tool); if (cmsError.IsError()) return cmsError; // Get edge additional data SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration(); List toolTypeConfig = toolEdgesConfig.EdgesConfig[tool.ToolType]; Dictionary edgeData = toolTypeConfig.ToDictionary(x => x.Name, x => 0.0); // Create new edge tool.EdgesData = new List() { new EdgeModel { Id = 1, ResidualLife = 0, PreAlmLife = 0, NominalLife = 0, EdgeAdditionalParams = edgeData } }; } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_WUpdateTool(ref SiemensToolModel tool) { CmsError cmsError = CheckToolData(ref tool); if (cmsError.IsError()) return cmsError; try { // TC_TP2 DataSvc dataSvc = new DataSvc(); // Create status byte from bit array BitArray bitArray = new BitArray(new bool[] { tool.IsActive, tool.IsEnabled, tool.IsInhibited, tool.IsMeasured, tool.PreAlarm, tool.InChangeTool, tool.InFixedPlace, tool.IsInUse }); int[] array = new int[1]; bitArray.CopyTo(array, 0); // Read tool info ( rotation, cooling etc...) Item toolInfo = new Item("/Tool/Compensation/edgeData[c" + tool.Id + ",25]"); dataSvc.Read(toolInfo); int val = Convert.ToInt32(toolInfo.Value); bool clockwhise = false, counterClockwhise = false; // Convert rotation into boolean switch (tool.Rotation) { case ROTATION.CLOCKWHISE: clockwhise = true; counterClockwhise = false; break; case ROTATION.COUNTERCLOCKWHISE: clockwhise = false; counterClockwhise = true; break; } // Set rotation data val = SetBitValue(val, clockwhise, 9); val = SetBitValue(val, counterClockwhise, 10); // Set cooling val = SetBitValue(val, tool.Cooling1, 11); val = SetBitValue(val, tool.Cooling2, 12); toolInfo.Value = val; List items = new List() { // TC_TP2 new Item("/Tool/Data/toolIdent[" + tool.Id + "]") { Value = tool.FamilyName }, // TC_TP3 new Item() { Path = "/Tool/Data/toolsize_left[" + tool.Id + "]", Value = tool.LeftSize }, // TC_TP4 new Item() { Path = "/Tool/Data/toolsize_right[" + tool.Id + "]", Value = tool.RightSize }, // TC_TP7 new Item() { Path = "/Tool/Data/toolplace_spec[" + tool.Id + "]", Value = tool.MagazinePositionType }, // TC_TP8 new Item() { Path = "/Tool/Data/toolStateL[" + tool.Id + "]", Value = array[0] }, // TC_DP1 new Item() { Path = "/Tool/Compensation/edgeData[c" + tool.Id + ",1]", Value = tool.ToolType }, // TC_DP25 { toolInfo }, // Max speed new Item() { Path = "/Tool/Data/toolMaxVelo[" + tool.Id + "]", Value = tool.MaxSpeed }, // Max acceleration // new Item() { Path = "/Tool/Data/toolMaxAcc[" + tool.Id + "]", Value = tool.MaxAcceleration }, // Custom fields new Item() {Path = "/Tool/User/data[c1," + tool.Id + "]", Value = tool.Load}, new Item() {Path = "/Tool/User/data[c2," + tool.Id + "]", Value = tool.Gamma}, new Item() {Path = "/Tool/User/data[c3," + tool.Id + "]", Value = tool.MaxLoadPctAutoload}, new Item() {Path = "/Tool/User/data[c4," + tool.Id + "]", Value = tool.MinLoadPctAutoload}, new Item() {Path = "/Tool/User/data[c5," + tool.Id + "]", Value = tool.ToolTypeCode}, }; if (LIFE_OPTION_ACTIVE) // TC_TP9 items.Add(new Item() { Path = "/Tool/Data/toolMon[" + tool.Id + "]", Value = (int)tool.LifeType }); dataSvc.Write(items.ToArray()); Item childId = new Item() { Path = "/Tool/Data/duploNo[" + tool.Id + "]" }; dataSvc.Read(childId); tool.ChildId = Convert.ToInt32(childId.Value); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_WDeleteTool(int id) { // Find if tool exists var tool = ToolTableData.Where(x => x.Id == id).FirstOrDefault(); if (tool == null) return INCORRECT_PARAMETERS_ERROR; // Check if tool is mounted in magazine bool isMounted = MagazineMountedTools.Exists(x => x.ToolId == tool.Id); if (isMounted) return TOOL_IS_MOUNTED_ERROR; try { // Create string parameters string[] piArgs = new string[4]; piArgs[0] = "/NC"; piArgs[1] = "401"; piArgs[2] = id.ToString().PadLeft(5, '0'); // Tool ID (> 00000) piArgs[3] = "_N_DELETO"; // Start NC delete command PiSvc pi = new PiSvc(piArgs); pi.Start(); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } private CmsError CheckToolData(ref SiemensToolModel tool) { int toolId = tool.Id; //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Check if it can be added a tool if (ToolTableData.Count == MAX_TOOL_NUMER) return MAX_TOOL_REACHED_ERROR; // Check if family has reached max tool number string family = tool.FamilyName; int toolsWithSameFamily = ToolTableData.Where(x => x.FamilyName == family && x.Id != toolId).Count(); if (toolsWithSameFamily >= MAX_TOOLS_PER_FAMILY) return MAX_FAMILY_REACHED_ERROR; if (tool.FamilyName.Count() > 32) tool.FamilyName = tool.FamilyName.Substring(0, 32); return NO_ERROR; } #endregion Tools functions #region Shanks functions public override CmsError TOOLS_RShanksData(ref List shanksData) { return NO_ERROR; // *SHANK FIX* shanksData = MultitoolsData; foreach (ShankModel shank in shanksData) { // Get magazine and position id MountedToolModel mountedTool = MagazineMountedTools.Where(y => y.ToolId == shank.Id).FirstOrDefault(); if (mountedTool != null) { shank.MagazineId = mountedTool.MagazineId; shank.PositionId = mountedTool.PositionId; } else { shank.MagazineId = 0; shank.PositionId = 0; } // Populate childs foreach (ShankChildModel child in shank.ChildsTools) { // Find tool by id SiemensToolModel tool = ToolTableData.Where(x => x.Id == child.Id).FirstOrDefault(); if (tool != null) { child.FamilyName = tool.FamilyName; child.ToolType = tool.ToolType; } } } return NO_ERROR; } public override CmsError TOOLS_WAddShank(ref ShankModel shank) { return NO_ERROR; // Check if you can add a multitool if (MultitoolsData.Count >= MAX_MULTITOOLS_NUMBER) return MAX_MULTITOOL_REACHED_ERROR; // Check data CmsError cmsError = CheckMultitoolData(ref shank, false); if (cmsError.IsError()) return cmsError; try { //Create Shank with NC Pi service string[] piArgs = new string[8]; piArgs[0] = "/NC"; piArgs[1] = "401"; piArgs[2] = shank.Name.Trim().PadRight(32); piArgs[3] = "-0001"; // Reserved piArgs[4] = "00000"; // "00000" or “-0001” -> Nc choice / “00001” not allowed piArgs[5] = MAX_TOOLS_PER_MULTITOOL.ToString().PadLeft(3, '0');// shank.MaxChilds.ToString().PadLeft(3, '0'); // From "002" to "$MN_MAX_TOOLS_PER_MULTITOOL" // 001 not allowed piArgs[6] = "1"; // “1”..”3” tipo di riconoscimento distanza tra utensili nel multitool piArgs[7] = "_N_TMCRMT"; // PI create command PiSvc pi = new PiSvc(piArgs); pi.Start(); // Find new tool id shank.Id = GetLastMultitoolId(); DataSvc dataSvc = new DataSvc(); // WriteMultitool position type = 0 in order to load tools for (int i = 0; i < MAX_TOOLS_PER_MULTITOOL; i++) { int paramId = (i * 6) + 3; Item item = new Item() { Path = string.Format("/Tool/MTPlace/mtPlaceData[c{0},{1}]", shank.Id, paramId), Value = 0 }; dataSvc.Write(item); } // Update data cmsError = TOOLS_WUpdateShank(ref shank); if (cmsError.IsError()) return cmsError; } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_WUpdateShank(ref ShankModel shank) { return NO_ERROR; CmsError cmsError = CheckMultitoolData(ref shank, true); if (cmsError.IsError()) return cmsError; try { DataSvc dataSvc = new DataSvc(); // Set status byte BitArray bitArray = new BitArray(new bool[] { false, shank.IsEnabled, shank.IsInhibited, false, false, shank.InChangeTool, shank.InFixedPlace, shank.InUse }); int[] array = new int[1]; bitArray.CopyTo(array, 0); List items = new List() { // TC_MTP2 new Item("/Tool/MT/multitoolIdent[" + shank.Id + "]") { Value = shank.Name }, // TC_MTP3 new Item() { Path = "/Tool/MT/multitoolsize_left[" + shank.Id + "]", Value = shank.LeftSize <= 0 ? 1 : shank.LeftSize }, // TC_MTP4 new Item() { Path = "/Tool/MT/multitoolsize_right[" + shank.Id + "]", Value = shank.RightSize <= 0 ? 1 : shank.RightSize }, // TC_TMP7 new Item() { Path = "/Tool/MT/multitoolplace_spec[" + shank.Id + "]", Value = shank.MagazinePositionType <= 0 ? 1 : shank.MagazinePositionType }, // TC_MTP8 new Item() { Path = "/Tool/MT/multitoolStateL[" + shank.Id + "]", Value = array[0] } }; dataSvc.Write(items.ToArray()); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_WDeleteShank(int id) { return NO_ERROR; //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Find if exists var multitool = MultitoolsData.Where(x => x.Id == id).FirstOrDefault(); if (multitool == null) return INCORRECT_PARAMETERS_ERROR; // Check if multitool is mounted in magazine bool isMounted = MagazineMountedTools.Exists(x => x.ToolId == multitool.Id); if (isMounted) return TOOL_IS_MOUNTED_ERROR; try { // Create string parameters string[] piArgs = new string[7]; piArgs[0] = "/NC"; piArgs[1] = "401"; piArgs[2] = "".PadRight(32); piArgs[3] = "00000"; piArgs[4] = id.ToString().PadLeft(5, '0'); // Tool ID (> 00000) piArgs[5] = "1"; // 0 No delete childs, 1 delete childs piArgs[6] = "_N_TMDLMT"; // Start NC delete command PiSvc pi = new PiSvc(piArgs); pi.Start(); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } #endregion Shanks functions #region Families functions public override CmsError TOOLS_RFamilyData(ref List families) { families = FamiliesData; foreach (FamilyModel family in families) { // Get family childs tools family.ChildTools = ToolTableData .Where(x => x.FamilyName == family.Name) .Select(x => new FamilyChildModel() { Id = x.Id, ChildId = x.ChildId, ToolType = x.ToolType }) .ToList(); // Set current family child tools family.ChildTools .Sort((p, q) => p.ChildId.CompareTo(q.ChildId)); } return NO_ERROR; } public override CmsError TOOLS_WAddFamily(ref FamilyModel family) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateFamilyData(string oldName, string newName) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WDeleteFamily(string name) { return FUNCTION_NOT_ALLOWED_ERROR; } #endregion Families functions #region Edges functions public override CmsError TOOLS_WAddEdge(int toolId, ref EdgeModel edge) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; var tool = ToolTableData.Where(x => x.Id == toolId).FirstOrDefault(); if (tool == null) return INCORRECT_PARAMETERS_ERROR; if (tool.EdgesData.Count >= MAX_EDGES_PER_TOOL) return MAX_EDGES_PER_TOOL_REACHED_ERROR; List ids = Enumerable.Range(1, MAX_EDGES_PER_TOOL).ToList(); foreach (var edgeVal in tool.EdgesData) { ids.Remove(edgeVal.Id); } // Get next edge id int nextEdgeId = ids[0]; try { // Create strings parameters string[] piArgs = new string[5]; piArgs[0] = "/NC"; piArgs[1] = "401"; piArgs[2] = toolId.ToString().PadLeft(5, '0'); //Tool ID piArgs[3] = "00000"; //Cutt. edge ID (00000 > autom) piArgs[4] = "_N_CRCEDN"; // Start NC add command PiSvc pi = new PiSvc(piArgs); pi.Start(); edge.Id = nextEdgeId; cmsError = TOOLS_WUpdateEdge(toolId, ref edge); if (cmsError.IsError()) return cmsError; } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_WUpdateEdge(int toolId, ref EdgeModel edge) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; SiemensToolModel tool = ToolTableData.Where(x => x.Id == toolId).FirstOrDefault(); if (tool == null) return INCORRECT_PARAMETERS_ERROR; if (tool.ToolType == 9999) return INCORRECT_PARAMETERS_ERROR; try { // Initialize edges configuration SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration(); // Get config for current tool type List toolTypeConfig = toolEdgesConfig.EdgesConfig[tool.ToolType]; DataSvc dataSvc = new DataSvc(); List items = new List(); int edgeLifeOffset = (edge.Id - 1) * 9; if (LIFE_OPTION_ACTIVE) // Check if life option is active { switch (tool.LifeType) { // Add item choosing based on life case SIEMENS_LIFE_TYPE.TIME: { items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 1), Value = edge.PreAlmLife }); items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 2), Value = edge.NominalLife }); items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 5), Value = edge.ResidualLife }); } break; case SIEMENS_LIFE_TYPE.COUNT: { items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 3), Value = edge.PreAlmLife }); items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 6), Value = edge.NominalLife }); items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 4), Value = edge.ResidualLife }); } break; case SIEMENS_LIFE_TYPE.WEAR: { items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 7), Value = edge.PreAlmLife }); items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 9), Value = edge.NominalLife }); items.Add(new Item() { Path = string.Format("/Tool/Supervision/data[c{0}, {1}]", tool.Id, edgeLifeOffset + 8), Value = edge.ResidualLife }); } break; } } // Edge params int edgeParamsIndex = ((edge.Id - 1) * 35); // Set edge id type items.Add(new Item() { Path = string.Format("/Tool/Compensation/edgeData[c{0},{1}]", tool.Id, edgeParamsIndex + 1), Value = tool.ToolType }); // Update edge type to 9 items.Add(new Item() { Path = string.Format("/Tool/Compensation/edgeData[c{0}, {1}]", tool.Id, edgeParamsIndex + 2), Value = 9 }); // Set edge additional params, read by configuration foreach (EdgeConfigModel conf in toolTypeConfig) { if (edge.EdgeAdditionalParams.ContainsKey(conf.Name)) { items.Add(new Item() { Path = string.Format("/Tool/Compensation/edgeData[c{0}, {1}]", tool.Id, edgeParamsIndex + conf.Number), Value = edge.EdgeAdditionalParams[conf.Name] }); } } dataSvc.Write(items.ToArray()); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_WDeleteEdge(int toolId, int edgeId) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Find tool var tool = ToolTableData.Where(x => x.Id == toolId).FirstOrDefault(); // If tool not exists, return if (tool == null) return INCORRECT_PARAMETERS_ERROR; // if edge not exists, return if (tool.EdgesData.Where(x => x.Id == edgeId).FirstOrDefault() == null) return INCORRECT_PARAMETERS_ERROR; // If there is only 1 edge, return with error if (tool.EdgesData.Count == 1) return INCORRECT_PARAMETERS_ERROR; try { // Create strings parameters string[] piArgs = new string[5]; piArgs[0] = "/NC"; piArgs[1] = "401"; piArgs[2] = toolId.ToString().PadLeft(5, '0'); //Tool ID (> 00000) piArgs[3] = edgeId.ToString().PadLeft(5, '0'); //Cutt. edge ID (> 00000) piArgs[4] = "_N_DELECE"; // Start NC delete command PiSvc pi = new PiSvc(piArgs); pi.Start(); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } #endregion Edges functions #region Load/Unload functions public override CmsError TOOLS_WLoadToolInMagazine(int magazineId, NewToolInMagazineModel newMagazineTool, ref MountedToolModel newMountedTool) { // Check if magazine is occupied if (MagazineAction.Action != MAGAZINE_ACTIONS.READY) return MAGAZINE_BUSY_ERROR; // Get mag config SiemensMagazineConfigModel magConfig = MagazineConfig.Where(x => x.Id == magazineId).FirstOrDefault(); if (magConfig == null || !magConfig.LoadingIsActive) return INCORRECT_PARAMETERS_ERROR; // Get magazine position type PositionModel position = MagazinePositionsData.Where(x => x.PositionId == newMagazineTool.PositionId && x.MagazineId == magazineId).FirstOrDefault(); if (position == null || position.Disabled) return INCORRECT_PARAMETERS_ERROR; if (position.Occupied) return MAGAZINE_POSITION_OCCUPIED_ERROR; // Get tool data var tool = GetToolOrMultitool(newMagazineTool.ToolId); if (tool == null) return INCORRECT_PARAMETERS_ERROR; // Check if magazine position is occupied MountedToolModel magPos = MagazineMountedTools .Where(x => x.MagazineId == magazineId && x.PositionId == newMagazineTool.PositionId) .FirstOrDefault(); if (magPos != null) return MAGAZINE_POSITION_OCCUPIED_ERROR; // Get position type int newToolPositionType = tool is SiemensToolModel ? (tool as SiemensToolModel).MagazinePositionType : (tool as ShankModel).MagazinePositionType; // Check type if (newToolPositionType != position.Type) return TOOL_AND_POSITION_NOT_MATCHING_ERROR; // Check if tool can fit in the position considering disabled positions if (magConfig.Type != SIEMENS_MAGAZINE_TYPE.BOX_MAGAZINE) { foreach (var pos in MagazinePositionsData) { if (pos.Disabled && pos.MagazineId == magazineId) { // If magazine is circular, move position before ( for left case ) or after ( right case ) the location you want to mount the tool var right = pos.PositionId < newMagazineTool.PositionId ? pos.PositionId + magConfig.MaxPositions : pos.PositionId; var left = pos.PositionId > newMagazineTool.PositionId ? pos.PositionId - magConfig.MaxPositions : pos.PositionId; // Calculate right space needed double rightToBeMount = newMagazineTool.PositionId + ((tool as SiemensToolModel).RightSize / 2.0); if (right < rightToBeMount) return MAGAZINE_POSITION_OCCUPIED_ERROR; // Left check // Calculate left space needed double leftToBeMounted = newMagazineTool.PositionId - ((tool as SiemensToolModel).LeftSize / 2.0); if (left > leftToBeMounted) return MAGAZINE_POSITION_OCCUPIED_ERROR; } } } else { // Check if near positions are disabled var posizionDisabled = MagazinePositionsData.Where( x => x.MagazineId == magazineId && x.Disabled == true && ((x.PositionId > newMagazineTool.PositionId && x.PositionId <= newMagazineTool.PositionId + (tool as SiemensToolModel).RightSize / 2.0) || (x.PositionId < newMagazineTool.PositionId && x.PositionId >= newMagazineTool.PositionId - (tool as SiemensToolModel).LeftSize / 2.0))) .ToList(); if (posizionDisabled.Count() > 0) return MAGAZINE_POSITION_OCCUPIED_ERROR; } // Check if tool can fit in the position considering other tools foreach (var mountedTool in MagazineMountedTools) { // Check if is not the same position && if is different check if the position is on the same magazine if (mountedTool.PositionId != newMagazineTool.PositionId && mountedTool.MagazineId == magazineId) { // Get mounted tool data int toolIndex = ToolTableData.FindIndex(x => x.Id == mountedTool.ToolId); if (toolIndex > -1) { int decPosition, incPosition; decPosition = incPosition = mountedTool.PositionId; // If the magazine is a circular magazine move position before ( for left case ) or after ( right case ) the location you want to mount the tool if (magConfig.Type != SIEMENS_MAGAZINE_TYPE.BOX_MAGAZINE) { // If magazine is circular, move position before ( for left case ) or after ( right case ) the location you want to mount the tool decPosition = decPosition < newMagazineTool.PositionId ? decPosition + magConfig.MaxPositions : decPosition; incPosition = incPosition > newMagazineTool.PositionId ? incPosition - magConfig.MaxPositions : incPosition; // Right check // Calculate left space occupied double leftMounted = decPosition - (ToolTableData[toolIndex].LeftSize / 2.0); // Calculate right space needed double rightToBeMount = newMagazineTool.PositionId + ((tool as SiemensToolModel).RightSize / 2.0); if (leftMounted < rightToBeMount) return MAGAZINE_POSITION_OCCUPIED_ERROR; // Left check // Calculate right space occupied double rightMounted = incPosition + (ToolTableData[toolIndex].RightSize / 2.0); // Calculate left space needed double leftToBeMounted = newMagazineTool.PositionId - ((tool as SiemensToolModel).LeftSize / 2.0); if (rightMounted > leftToBeMounted) return MAGAZINE_POSITION_OCCUPIED_ERROR; } else { // Right check if (newMagazineTool.PositionId < mountedTool.PositionId) { // Calculate left space occupied double leftMounted = mountedTool.PositionId - (ToolTableData[toolIndex].LeftSize / 2.0); // Calculate right space needed double rightToBeMount = newMagazineTool.PositionId + ((tool as SiemensToolModel).RightSize / 2.0); if (leftMounted < rightToBeMount) return MAGAZINE_POSITION_OCCUPIED_ERROR; } // Left check // Calculate right space occupied if (newMagazineTool.PositionId > mountedTool.PositionId) { double rightMounted = mountedTool.PositionId + (ToolTableData[toolIndex].RightSize / 2.0); // Calculate left space needed double leftToBeMounted = newMagazineTool.PositionId - ((tool as SiemensToolModel).LeftSize / 2.0); if (rightMounted > leftToBeMounted) return MAGAZINE_POSITION_OCCUPIED_ERROR; } } } } } //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { //Load tool in magazine string[] piArgs = new string[8]; piArgs[0] = "/NC"; piArgs[1] = "401"; piArgs[2] = newMagazineTool.ToolId.ToString().PadLeft(5, '0'); //Tool ID (> 00000) piArgs[3] = magConfig.LoadPosition.ToString().PadLeft(5, '0'); ; // Manina carico (valore fisso) piArgs[4] = "09999"; // Magazzino di carico (valore fisso) piArgs[5] = newMagazineTool.PositionId.ToString().PadLeft(5, '0'); // Manina di destinazione (dove caricare l'utensile) piArgs[6] = magazineId.ToString().PadLeft(5, '0'); // Magazzino di destinazione (dove caricare l'utensile) piArgs[7] = "_N_TMMVTL"; // Start NC load command PiSvc pi = new PiSvc(piArgs); pi.Start(); } catch (Exception ex) { return ManageException(ex); } // Mount temporarily till the Siemens notification arrives MoveToolInMagazineList(newMagazineTool.ToolId, magazineId, newMagazineTool.PositionId); newMountedTool = new MountedToolModel() { MagazineId = magazineId, PositionId = newMagazineTool.PositionId, ToolId = newMagazineTool.ToolId, ChildTool = tool as SiemensToolModel, ChildShank = null // Todo when multitools work }; return NO_ERROR; } public override CmsError TOOLS_WUnloadToolFromMagazine(int magazineId, int positionId) { if (MagazineAction.Action != MAGAZINE_ACTIONS.READY) return MAGAZINE_BUSY_ERROR; // Get mag config SiemensMagazineConfigModel magConfig = MagazineConfig.Where(x => x.Id == magazineId).FirstOrDefault(); if (magConfig == null || !magConfig.LoadingIsActive) return INCORRECT_PARAMETERS_ERROR; //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { //UnLoad tool in magazine string[] piArgs = new string[8]; piArgs[0] = "/NC"; piArgs[1] = "401"; piArgs[2] = "-0001"; // Tool ID (Fixed, no ID) piArgs[3] = positionId.ToString().PadLeft(5, '0'); // Manina carico (valore fisso) piArgs[4] = magazineId.ToString().PadLeft(5, '0'); // Magazzino di carico (valore fisso) piArgs[5] = magConfig.LoadPosition.ToString().PadLeft(5, '0'); //Manina carico (valore fisso) piArgs[6] = "09999"; // Magazzino da cui scaricare l'utensile piArgs[7] = "_N_TMMVTL"; // Start NC load command PiSvc pi = new PiSvc(piArgs); pi.Start(); } catch (Exception ex) { return ManageException(ex); } //// Smount temporarily till the Siemens notification arrives int magPosIndex = MagazineMountedTools.FindIndex(x => x.MagazineId == magazineId && x.PositionId == positionId); if (magPosIndex >= 0) MagazineMountedTools.Remove(MagazineMountedTools[magPosIndex]); return NO_ERROR; } public override CmsError TOOLS_WLoadToolIntoShank(int shankId, int positionId, int toolId) { return NO_ERROR; // Check if mt exists ShankModel shank = MultitoolsData.Where(x => x.Id == shankId).FirstOrDefault(); if (shank == null) return INCORRECT_PARAMETERS_ERROR; // Check if tool can be loaded if (shank.ChildsTools.Count >= MAX_TOOLS_PER_MULTITOOL) return MAX_TOOLS_PER_MULTITOOL_REACHED_ERROR; //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { DataSvc dataSvc = new DataSvc(); int paramId = ((positionId - 1) * 6) + 5; // Write parameter into multitool parameters Item item = new Item() { Path = string.Format("/Tool/MTPlace/mtPlaceData[c{0},{1}]", shankId, paramId), Value = toolId }; dataSvc.Write(item); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_WUnloadToolFromShank(int shankId, int positionId) { return NO_ERROR; //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { DataSvc dataSvc = new DataSvc(); int paramId = ((positionId - 1) * 6) + 5; // TC_MTP2 Item item = new Item() { Path = string.Format("/Tool/MTPlace/mtPlaceData[c{0},{1}]", shankId, paramId), Value = 0 }; dataSvc.Write(item); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_WStartTDILoading(ushort magazineId, ushort positionId) { List words = new List() { (ushort)(((int)SIEMENS_TDI_ACTION.LOAD << 8) + positionId), magazineId }; CmsError cmsError = MEM_RWWordList(W, 1, BALLUF_ACTION_DATA.MemType, BALLUF_ACTION_DATA.Address, BALLUF_ACTION_DATA.SubAddress, 2, ref words); if (cmsError.IsError()) return cmsError; return PLC_WStrobe(BALLUF_ACTION_ACK, BALLUF_ACTION_STROBE, 1); } public override CmsError TOOLS_WStartTDIUnloading(ushort magazineId, ushort positionId, ushort toolId) { var mountedTool = MagazineMountedTools.Where(x => x.ToolId == toolId).FirstOrDefault(); if (mountedTool == null || (mountedTool.ToolId != toolId && mountedTool.PositionId != positionId)) return INCORRECT_PARAMETERS_ERROR; List words = new List() { (ushort)(((int)SIEMENS_TDI_ACTION.UNLOAD << 8) + positionId), magazineId, toolId }; CmsError cmsError = MEM_RWWordList(W, 1, BALLUF_ACTION_DATA.MemType, BALLUF_ACTION_DATA.Address, BALLUF_ACTION_DATA.SubAddress, 2, ref words); if (cmsError.IsError()) return cmsError; return PLC_WStrobe(BALLUF_ACTION_ACK, BALLUF_ACTION_STROBE, 1); } public override CmsError TOOLS_WEmptyBallufTablet(SiemensToolModel tool) { CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Setup status byte BitArray bitArray = new BitArray(new bool[] { tool.IsActive, tool.IsEnabled, tool.IsInhibited, tool.IsMeasured, tool.PreAlarm, tool.InChangeTool, tool.InFixedPlace, tool.IsInUse }); int[] statusArray = new int[1]; bitArray.CopyTo(statusArray, 0); // Setup dimensions byte ( byte is formed by nibble => left_size right_size 0001 0001 ) ushort dimensions = (ushort)((((tool.LeftSize << 4) + tool.RightSize) << 8) + 17); // 17 = 0001 0001 -> DataSvc dataSvc = new DataSvc(); // Main data byte[] familyName = Encoding.ASCII.GetBytes(tool.FamilyName); List items = new List { new Item(){ Path = string.Format("DB{0}.DBB0", BALLUF_EMPTY_TABLE.Address), Value = tool.ChildId }, new Item(){ Path = string.Format("DB{0}.DBB2[" + familyName.Length +"]", BALLUF_EMPTY_TABLE.Address), Value = familyName }, new Item(){ Path = string.Format("DB{0}.DBW34", BALLUF_EMPTY_TABLE.Address), Value = dimensions }, new Item(){ Path = string.Format("DB{0}.DBW36", BALLUF_EMPTY_TABLE.Address), Value = tool.MagazinePositionType }, new Item(){ Path = string.Format("DB{0}.DBW38", BALLUF_EMPTY_TABLE.Address), Value = statusArray[0] }, new Item(){ Path = string.Format("DB{0}.DBW40", BALLUF_EMPTY_TABLE.Address), Value = (int)tool.LifeType }, new Item(){ Path = string.Format("DB{0}.DBD42", BALLUF_EMPTY_TABLE.Address), Value = tool.MaxSpeed }, new Item(){ Path = string.Format("DB{0}.DBD46", BALLUF_EMPTY_TABLE.Address), Value = tool.Load }, new Item(){ Path = string.Format("DB{0}.DBD50", BALLUF_EMPTY_TABLE.Address), Value = tool.Gamma }, new Item(){ Path = string.Format("DB{0}.DBD54", BALLUF_EMPTY_TABLE.Address), Value = tool.MaxLoadPctAutoload }, new Item(){ Path = string.Format("DB{0}.DBD58", BALLUF_EMPTY_TABLE.Address), Value = tool.MinLoadPctAutoload }, new Item(){ Path = string.Format("DB{0}.DBD62", BALLUF_EMPTY_TABLE.Address), Value = tool.ToolTypeCode }, //new Item(){ Path = string.Format("DB{0}.DBB64:STRING", BALLUF_EMPTY_TABLE.Address), Value = tool.FamilyName }, new Item(){ Path = string.Format("DB{0}.DBW70", BALLUF_EMPTY_TABLE.Address), Value = 1 }, // Edge data new Item(){ Path = string.Format("DB{0}.DBW86", BALLUF_EMPTY_TABLE.Address), Value = tool.ToolType }, new Item(){ Path = string.Format("DB{0}.DBW88", BALLUF_EMPTY_TABLE.Address), Value = 9 }, }; EdgeModel edge = tool.EdgesData[0]; SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration(); // Get config for current tool type List toolTypeConfig = toolEdgesConfig.EdgesConfig[tool.ToolType]; // Set edge additional params, read by configuration foreach (EdgeConfigModel conf in toolTypeConfig) { if (edge.EdgeAdditionalParams.ContainsKey(conf.Name) && toolEdgesConfig.TDIEdgeFields.ContainsKey(conf.Path)) { items.Add(new Item() { Path = string.Format(toolEdgesConfig.TDIEdgeFields[conf.Path], BALLUF_EMPTY_TABLE.Address), Value = edge.EdgeAdditionalParams[conf.Name] }); } } // Life Parameters switch (tool.LifeType) { case SIEMENS_LIFE_TYPE.TIME: { items.AddRange(new List() { new Item() { Path = string.Format("DB{0}.DBD186", BALLUF_EMPTY_TABLE.Address), Value = edge.ResidualLife }, // MOP2 new Item() { Path = string.Format("DB{0}.DBD194", BALLUF_EMPTY_TABLE.Address), Value = edge.NominalLife }, // MOP11 new Item() { Path = string.Format("DB{0}.DBD182", BALLUF_EMPTY_TABLE.Address), Value = edge.PreAlmLife } // MOP1 }); } break; case SIEMENS_LIFE_TYPE.COUNT: { items.Add(new Item() { Path = string.Format("DB{0}.DBW192", BALLUF_EMPTY_TABLE.Address), Value = edge.ResidualLife }); // MOP4 items.Add(new Item() { Path = string.Format("DB{0}.DBW198", BALLUF_EMPTY_TABLE.Address), Value = edge.NominalLife }); // MOP13 items.Add(new Item() { Path = string.Format("DB{0}.DBW190", BALLUF_EMPTY_TABLE.Address), Value = edge.PreAlmLife }); // MOP3 } break; case SIEMENS_LIFE_TYPE.WEAR: { items.Add(new Item() { Path = string.Format("DB{0}.DBD204", BALLUF_EMPTY_TABLE.Address), Value = edge.ResidualLife }); // MOP6 items.Add(new Item() { Path = string.Format("DB{0}.DBD208", BALLUF_EMPTY_TABLE.Address), Value = edge.NominalLife }); // MOP15 items.Add(new Item() { Path = string.Format("DB{0}.DBD200", BALLUF_EMPTY_TABLE.Address), Value = edge.PreAlmLife }); // MOP5 } break; } try { dataSvc.Write(items.ToArray()); } catch (Exception ex) { return ManageException(ex); } return WBallufAction(SIEMENS_TDI_ACTION.ABORT); } public override CmsError TOOLS_WAbortBallufTablet() { return WBallufAction(SIEMENS_TDI_ACTION.ABORT); } private CmsError WBallufAction(SIEMENS_TDI_ACTION action) { byte act = (byte)action; CmsError cmsError = MEM_RWByte(W, 1, BALLUF_ACTION_DATA.MemType, BALLUF_ACTION_DATA.Address, BALLUF_ACTION_DATA.SubAddress, 0, ref act); if (cmsError.IsError()) return cmsError; return PLC_WStrobe(BALLUF_ACTION_ACK, BALLUF_ACTION_STROBE, 1); } #endregion Load/Unload functions public override CmsError TOOLS_RMagazinePositions(ref List positions) { positions = MagazinePositionsData; return NO_ERROR; } public override CmsError TOOLS_WUpdatePosition(PositionModel position) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; try { DataSvc dataSvc = new DataSvc(); int paramId = ((position.PositionId - 1) * 11) + 5; // TC_MTP2 Item item = new Item() { Path = string.Format("/Tool/Magazine/placeData[c{0} , {1}]", position.MagazineId, paramId) }; dataSvc.Read(item); item.Value = SetBitValue(Convert.ToInt32(item.Value), position.Disabled, 1); dataSvc.Write(item); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError TOOLS_RMountedTools(int magazineId, ref List magazinePos) { if (magazineId <= 0) return INCORRECT_PARAMETERS_ERROR; // Filter by magazine id magazinePos = MagazineMountedTools .Where(x => x.MagazineId == magazineId) .ToList(); foreach (var pos in magazinePos) { var tool = GetToolOrMultitool(pos.ToolId); if (tool is SiemensToolModel) pos.ChildTool = tool as SiemensToolModel; else if (tool is ShankModel) pos.ChildShank = tool as ShankModel; } return NO_ERROR; } public override CmsError TOOLS_RAvailableTools(ref List multiTools, ref List tools) { List occupiedIds = new List(); // Find ids of tools mounted in the magazines foreach (var mounted in MagazineMountedTools) { var tmp = mounted as MountedToolModel; var tool = GetToolOrMultitool(tmp.ToolId); //if (tool is ShankModel) // If multitool //{ // occupiedIds.Add((tool as ShankModel).Id); // Add multitool id //} else if (tool is SiemensToolModel) // If tool { occupiedIds.Add((tool as SiemensToolModel).Id); } } //// Add tools mounted in multitools //foreach (var multi in MultitoolsData) //{ // if (multi.ChildsTools.Count > 0) // mountedIds.AddRange(multi.ChildsTools.Select(x => x.Id).ToList()); //} // Filter tools tools = ToolTableData .Where(x => !occupiedIds.Contains(x.Id)) .ToList(); //// Filter multitools //multiTools = MultitoolsData // .Where(x => !mountedIds.Contains(x.Id)) // .ToList(); return NO_ERROR; } private object GetToolOrMultitool(int toolId) { int toolIndex = ToolTableData.FindIndex(x => x.Id == toolId); if (toolIndex >= 0) { return ToolTableData[toolIndex]; } //else //{ // int multiIndex = MultitoolsData.FindIndex(x => x.Id == toolId); // if (multiIndex >= 0) // return MultitoolsData[multiIndex]; //} return null; } public override CmsError TOOLS_RMagazineAction(ref MagazineActionModel magazineAction) { magazineAction = MagazineAction; return NO_ERROR; } #endregion Siemens Tool Management /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region Nc Tool Manager public override CmsError TOOLS_RMagazineConfig(ref List config) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WOptions(ToolManagerOptionsModel options) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_ROffset(short offsetId, ref OffsetModel offset) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WOffset(short offsetId, ref OffsetModel offset) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStartEditData() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStopEditData() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateTools(List list) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateFamilies(List list) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateShanks(List list) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateMagazinePositions(List list) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStartEditTooling(int magazineId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStopEditTooling(int magazineId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WRestoreBackup() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RUpdatedToolsData(ref Dictionary updatedStatus, ref Dictionary updatedLives) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RStoredData(ref List tools, ref List families, ref List shanks) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RMagazineBlock(ref List ids) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WFreeMagazines() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RMagazineStatus(ref Dictionary magazineStatus) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RAdatpivePathStep(ref Byte step) { // Check ACK CmsError cmsError = MEM_RWByte(R, 0, SELF_ADAPTIVE_PATH.MemType, SELF_ADAPTIVE_PATH.Address, SELF_ADAPTIVE_PATH.SubAddress, 0, ref step); if (cmsError.IsError()) return cmsError; return NO_ERROR; } public override CmsError TOOLS_WAdatpivePathStep(Byte step) { // Check ACK CmsError cmsError = MEM_RWByte(W, 0, SELF_ADAPTIVE_PATH.MemType, SELF_ADAPTIVE_PATH.Address, SELF_ADAPTIVE_PATH.SubAddress, 0, ref step); if (cmsError.IsError()) return cmsError; return NO_ERROR; } #endregion Nc Tool Manager /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region Subordinate Private Functions private DataSvc HighPriorityDataSvc() { return new DataSvc() { PriorityFlag = SlPriority.highPriority, Timeout = TimeoutConn }; } private DataSvc DefaultPriorityDataSvc() { return new DataSvc() { PriorityFlag = SlPriority.defaultPriority, Timeout = TimeoutConn }; } private DataSvc LowPriorityDataSvc() { return new DataSvc() { PriorityFlag = SlPriority.lowPriority, Timeout = TimeoutConn }; } // Manage the Alarms - Called automatically on changes private void AlarmsChanged(Guid guid, Alarm[] alarms) { try { if (alarms != null) SiemensAlarms = alarms.ToArray(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } private void NcLanguageChanged(string language) { SiemensAlmSvc.UnSubscribe(AlarmsChanged); // SiemensAlmSvc.Dispose(); SiemensAlmSvc = new AlarmSvc(language); SiemensAlmSvc.Subscribe(AlarmsChanged); } private int SetBitValue(int intVal, bool val, int bitIndex) { if (val) return intVal | (1 << (bitIndex - 1)); else return intVal & ~(1 << (bitIndex - 1)); } //Manage the Mode private PROC_MODE ConvertToSTEPMode(uint mode, uint JogMode, uint AdvMode) { if (mode == 0) { if (AdvMode == 0) return (JogMode < 6) ? PROC_MODE.JOGINC : PROC_MODE.JOG; else if (AdvMode == 1) return PROC_MODE.RETPROF; else if (AdvMode == 2) return PROC_MODE.TEACH; else if (AdvMode == 3) return PROC_MODE.REF; } else if (mode == 1) return PROC_MODE.MDI; else if (mode == 2) return PROC_MODE.AUTO; return PROC_MODE.ERROR; } //Manage the Status private PROC_STATUS ConvertToSTEPStatus(uint status) { switch (status) { case 0: return PROC_STATUS.IDLE; case 1: return PROC_STATUS.RUN; case 2: return PROC_STATUS.HOLD; } return PROC_STATUS.ERROR; } //Check Bit In Range private CmsError CheckBitRange(int bitnum) { if (bitnum < 0 || bitnum > 7) return BIT_NOT_IN_RANGE_ERROR; return NO_ERROR; } // Check if Memory Area is corrected private CmsError ConvertMemToPath(MEMORY_TYPE MemoryType, int Address, int SubAddress, int SubBit, int Qty, char MemAccess, out string item) { char[] allowedAccess = { 'X', 'B', 'W', 'D' }; //Check if is the right area and allowed type if (!MemoryType.ToString().StartsWith(SIEMENS_MEMTYPE) || !allowedAccess.Contains(MemAccess) || Qty < 1) { item = ""; return INCORRECT_PARAMETERS_ERROR; } else { //If is Bit Access change access type if (MemAccess == 'X') item = "DB" + Address + ".DB" + MemAccess + SubAddress + "." + SubBit; else item = "DB" + Address + ".DB" + MemAccess + SubAddress + "[" + Qty + "]"; return NO_ERROR; } } // Check if NC is connected private CmsError CheckConnection() { if (!NC_IsConnected()) return NOT_CONNECTED_ERROR; return NO_ERROR; } /// /// Check if PLC is responding to Ping /// /// private CmsError CheckS7Ping() { // faccio ping... if(testPing() != IPStatus.Success) return PLC_IP_NOT_FOUND_ERROR; return NO_ERROR; } /// /// Ping test to configured Ip address /// /// private IPStatus testPing() { IPStatus answ = IPStatus.Unknown; ; IPAddress address; PingReply reply; Ping pingSender = new Ping(); address = IPAddress.Loopback; IPAddress.TryParse(this.Ip, out address); reply = pingSender.Send(address, 100); answ = reply.Status; return answ; } //Manage the Exception Launch private CmsError ManageException(Exception ex) { //Catch the Siemens exceptions if (ex is OperateMissingOptionException && ex.Message.Contains(OptionHMINotRunning) || ex.Message.Contains("CORBA")) { Connected = false; return SIEMENS_HMI_NOT_RUNNING_ERROR; } else if (ex is FileNotFoundException && ex.Message.Contains(HMIDllName)) { return SIEMENS_ENVIRONMENT_NOT_FOUND_ERROR; } else if (ex.Message.Contains(NcNotFound) || ex.Message.Contains(NcNotFound2) || ex.Message.Contains(NcNotFound3) || ex.Message.Contains("Read() failed:")) { Connected = false; return NOT_CONNECTED_ERROR; } else if (ex.Message.Contains("m_pSlToolMngmntSvc")) { return SIEMENS_TOOL_TABLE_ERROR; } else { return CmsError.InternalError(ex.Message, ex); } } // Create and return CmsError object private CmsError GetError(string message) { return CmsError.NcError(message); } //Read Static Data private CmsError ReadStaticNCData() { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; //Read oly one time every X seconds if (DateTime.Now - Last_Static_Read > new TimeSpan(NC_MIN_SEC_READ_STATIC_DATA * TimeSpan.TicksPerSecond)) { //Try to get information try { DataSvc ReadStaticData = DefaultPriorityDataSvc(); Item ItemNcType = new Item(NC_TYPE_PATH); Item ItemNcVersion = new Item(NC_VERSION_PATH); Item ItemMaxChannelNo = new Item(MAX_CHANNEL_NO_PATH); Item ItemConfChannelNo = new Item(CONF_CHANNEL_NO_PATH); Item ItemLanguage = new Item(LANGUAGE_PATH); Item ItemSerialNumber = new Item(SERIAL_NO_PATH); Item ItemUnitOfMeasure = new Item(UNIT_OF_MEASURE); cmsError = ConvertMemToPath(MATR_MACCH_SIEMENS.MemType, MATR_MACCH_SIEMENS.Address, MATR_MACCH_SIEMENS.SubAddress, 0, 1, 'W', out string itemString); if (cmsError.IsError()) return cmsError; Item ItemMachineNumber = new Item(itemString); //Read All Data ReadStaticData.Read(ItemNcType); ReadStaticData.Read(ItemNcVersion); ReadStaticData.Read(ItemMaxChannelNo); ReadStaticData.Read(ItemConfChannelNo); ReadStaticData.Read(ItemLanguage); ReadStaticData.Read(ItemSerialNumber); ReadStaticData.Read(ItemMachineNumber); ReadStaticData.Read(ItemUnitOfMeasure); //Setup variables Cnc_name = GetName((uint)ItemNcType.Value); Cnc_SftVersion = Regex.Replace(((double)ItemNcVersion.Value).ToString(), ".{2}", "$0.").TrimEnd('.'); ; Cnc_SeriesNum = ((string)ItemSerialNumber.Value); MaxChannelNo = (uint)ItemMaxChannelNo.Value; ConfChannelNo = (uint)ItemConfChannelNo.Value; SiemensLanguage = (uint)ItemLanguage.Value; Cms_MachNumber = ((uint)ItemMachineNumber.Value).ToString(); UnitOfMeasure = (uint)ItemUnitOfMeasure.Value == 0 ? MILLIMETERS : INCHES; //Save NOW Last_Static_Read = DateTime.Now; } catch (Exception ex) { return ManageException(ex); } } return NO_ERROR; } // Convert the internal Name var in Readable STEP Name private string GetName(uint value) { string name = "Siemens "; switch (value) { case 0: name += "840D pl"; break; case 1000: name += "FM-NC"; break; case 2000: name += "810D pl"; break; case 3000: name += "802S"; break; case 4000: name += "802D pl"; break; case 5000: name += "840Di pl"; break; case 6000: name += "SOLUTIONLINE"; break; case 10700: name += "840D sl"; break; case 14000: name += "802D sl T/M - N/G - C/U"; break; case 15000: name += "840Di sl"; break; } return name; } //Convert to Step Language private CultureInfo ConvertToSTEPLanguage(uint language) { switch (language) { case 1: return new CultureInfo("de"); case 2: return new CultureInfo("fr"); case 3: return new CultureInfo("en"); case 4: return new CultureInfo("es"); case 6: return new CultureInfo("it"); case 7: return new CultureInfo("nl"); case 8: return new CultureInfo("zh-CHS"); case 9: return new CultureInfo("sv"); case 18: return new CultureInfo("hu"); case 19: return new CultureInfo("fi"); case 26: return new CultureInfo("el"); case 28: return new CultureInfo("cs"); case 50: return new CultureInfo("pt-BR"); case 53: return new CultureInfo("pl"); case 55: return new CultureInfo("da"); case 57: return new CultureInfo("ru"); case 65: return new CultureInfo("hr-HR"); case 68: return new CultureInfo("sk"); case 69: return new CultureInfo("sl"); case 72: return new CultureInfo("ro"); case 75: return new CultureInfo("bg"); case 80: return new CultureInfo("zh-CHT"); case 85: return new CultureInfo("ko"); case 87: return new CultureInfo("ja"); case 89: return new CultureInfo("tr"); case 122: return new CultureInfo("id"); case 212: return new CultureInfo("th"); case 213: return new CultureInfo("vi"); case 230: return new CultureInfo("ms"); default: return new CultureInfo("en"); } } //Convert to Step Language private string ConvertToNCLanguage(CultureInfo language) { return language.ThreeLetterISOLanguageName; } private int SwapIntEndianFormat(int value) { var b1 = (value >> 0) & 0xff; var b2 = (value >> 8) & 0xff; var b3 = (value >> 16) & 0xff; var b4 = (value >> 24) & 0xff; return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0; } private short SwapShortEndianFormat(short value) { var b1 = (value >> 0) & 0xff; var b2 = (value >> 8) & 0xff; return (short)(b1 << 8 | b2 << 0); } private ushort SwapShortEndianFormat(ushort value) { var b1 = (value >> 0) & 0xff; var b2 = (value >> 8) & 0xff; return (ushort)(b1 << 8 | b2 << 0); } private List ChangeIntListEndianess(List bigEndianvalues) { List littleEndianValues = new List(); foreach (int value in bigEndianvalues) { var a = SwapIntEndianFormat(value); littleEndianValues.Add(a); } return littleEndianValues; } private List ChangeUShortListEndianess(List bigEndianvalues) { List littleEndianValues = new List(); foreach (ushort value in bigEndianvalues) { var a = SwapShortEndianFormat(value); littleEndianValues.Add(a); } return littleEndianValues; } private bool PositionContainsTool(MountedToolModel mounted, int toolId) { if (mounted.ToolId == toolId) return true; //else //{ // // Check if tool is a multitool child // foreach (var multi in MultitoolsData) // { // // Check childs id // int index = multi.ChildsTools.FindIndex(x => x.Id == toolId); // if (index >= 0) // return true; // } //} return false; } //private void CheckData(object obj, List config) //{ // foreach(PropertyInfo prop in obj.GetType().GetProperties()) // { // bool val = config.Where(x => x.Name == prop.Name).Select(x => x.); // } //} private string ConvertStepToSiemensScreen(SCREEN_PAGE page) { switch (page) { case SCREEN_PAGE.Siemens_Machine: return "AreaMachine"; case SCREEN_PAGE.Siemens_Parameter: return "AreaParameter"; case SCREEN_PAGE.Siemens_Program: return "AreaProgramEdit"; case SCREEN_PAGE.Siemens_ProgramManager: return "AreaProgramManager"; case SCREEN_PAGE.Siemens_Setup: return "AreaStartup"; case SCREEN_PAGE.Siemens_Diagnostics: return "AreaDiagnosis"; default: return ""; } } #endregion Subordinate Private Functions /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region Siemens Tool private functions private string[] ReadToolTableFile() { // Create a configuration file FileStream f = new FileStream(LOCALE_TOOL_FILE_PATH, FileMode.Create); // Read siemens configuration file CmsError cmsError = FILES_RProgramToFile(NC_TOOL_FILE_PATH, f); f.Close(); return File.ReadAllLines(LOCALE_TOOL_FILE_PATH); } private void MagazinePositionEnabled_OnChange(Guid guid, Item[] items, DataSvcStatus[] status) { int i = 0; // Parse each new item foreach (Item item in items) { if (status[i].Ok) { // Get Ids string[] ids = item.SymbolicName.Split('_'); int magazineId = Convert.ToInt32(ids[0]); int positionId = Convert.ToInt32(ids[1]); foreach (PositionModel pos in MagazinePositionsData) { // Find position if (pos.PositionId == positionId && pos.MagazineId == magazineId) { // Set Value pos.Disabled = GetBitValue(Convert.ToInt32(item.Value), 0); } } } i++; } } private void MagazineAction_OnChange(Guid guid, Item item, DataSvcStatus status) { CmsError cmsError = NO_ERROR; if (Connected == false) NC_Connect(); List wordList = new List(); cmsError = MEM_RWWordList(R, 0, MAGAZINE_ACTION.MemType, MAGAZINE_ACTION.Address, MAGAZINE_ACTION.SubAddress + 2, 6, ref wordList); if (cmsError.IsError()) { MagazineAction = new MagazineActionModel() { Action = MAGAZINE_ACTIONS.NOT_READY, Tool = null, SecondTool = null, OriginMagazine = 0, OriginPosition = 0, DestinationMagazine = 0, DestinationPosition = 0 }; } else { MagazineActionToolModel tool = null; MagazineActionToolModel secondTool = null; // Get the first tool if exists ushort toolId = wordList[0]; if (toolId != 0) tool = ToolTableData .Where(x => x.Id == toolId) .Select(x => new MagazineActionToolModel() { Id = x.Id, IsMultitool = false, Name = x.FamilyName, ToolType = x.ToolType }).FirstOrDefault(); // Get the second tool if exists toolId = wordList[1]; if (toolId != 0) secondTool = ToolTableData .Where(x => x.Id == toolId) .Select(x => new MagazineActionToolModel() { Id = x.Id, IsMultitool = false, Name = x.FamilyName, ToolType = x.ToolType }).FirstOrDefault(); // Populate model with new data MagazineAction = new MagazineActionModel() { Action = (MAGAZINE_ACTIONS)Convert.ToInt32(item.Value), Tool = tool, SecondTool = secondTool, OriginMagazine = wordList[4], OriginPosition = wordList[5], DestinationMagazine = wordList[2], DestinationPosition = wordList[3] }; } } private void PopulateToolsTableFromFileStrings(string[] toolsStrings) { SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration(); int lastFirstId = 0; int lastSecondId = 0; int toolIndex = 0; int edgeIndex = 0; // int multitoolIndex = 0; // Foreach string for (int i = 0; i < toolsStrings.Count(); i++) { string actualString = toolsStrings[i]; // Get actual string data GetIdsFromSiemensToolString(actualString, out int firstId, out int secondId); // find ids from current string if (firstId != 0) { // If tool is changed, change current index tool if (lastFirstId != firstId) { toolIndex = ToolTableData.FindIndex(x => x.Id == firstId); // multitoolIndex = MultitoolsData.FindIndex(x => x.Id == firstId); } // Check if the key string has only 1 id if (secondId == 0) { switch (GetStringUntilOrEmpty(actualString)) // Cut string until [ character { case "$TC_TP1": { ToolTableData.Add(new SiemensToolModel() { Id = firstId, ChildId = Convert.ToInt32(actualString.Split('=').LastOrDefault()) }); // Update Index toolIndex = ToolTableData.Count - 1; } break; case "$TC_TP2": { string familyName = actualString.Split('=').LastOrDefault().Replace("\"", ""); ToolTableData[toolIndex].FamilyName = familyName; // Add new family with new tool AddOrUpdateFamilyChild(familyName); } break; case "$TC_TP3": ToolTableData[toolIndex].LeftSize = Convert.ToByte(actualString.Split('=').LastOrDefault()); break; case "$TC_TP4": ToolTableData[toolIndex].RightSize = Convert.ToByte(actualString.Split('=').LastOrDefault()); break; case "$TC_TP7": ToolTableData[toolIndex].MagazinePositionType = Convert.ToInt32(actualString.Split('=').LastOrDefault()); break; case "$TC_TP8": { // Get tool status and read each bit int toolStatus = Convert.ToInt32(actualString.Split('=').LastOrDefault()); ToolTableData[toolIndex].IsActive = GetBitValue(toolStatus, 0); ToolTableData[toolIndex].IsEnabled = GetBitValue(toolStatus, 1); ToolTableData[toolIndex].IsInhibited = GetBitValue(toolStatus, 2); ToolTableData[toolIndex].IsMeasured = GetBitValue(toolStatus, 3); ToolTableData[toolIndex].PreAlarm = GetBitValue(toolStatus, 4); ToolTableData[toolIndex].InChangeTool = GetBitValue(toolStatus, 5); ToolTableData[toolIndex].InFixedPlace = GetBitValue(toolStatus, 6); ToolTableData[toolIndex].IsInUse = GetBitValue(toolStatus, 7); } break; case "$TC_TP9": ToolTableData[toolIndex].LifeType = (SIEMENS_LIFE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault()); break; case "$TC_TP_MAX_VELO": ToolTableData[toolIndex].MaxSpeed = Convert.ToDouble(actualString.Split('=').LastOrDefault(), numberFormat); break; //case "$TC_TP_MAX_ACC": // ToolTableData[toolIndex].MaxAcceleration = Convert.ToDouble(actualString.Split('=').LastOrDefault(), numberFormat); // break; // Custom CMS fields case "$TC_TPC1": ToolTableData[toolIndex].Load = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; case "$TC_TPC2": ToolTableData[toolIndex].Gamma = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; case "$TC_TPC3": ToolTableData[toolIndex].MaxLoadPctAutoload = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; case "$TC_TPC4": ToolTableData[toolIndex].MinLoadPctAutoload = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; case "$TC_TPC5": ToolTableData[toolIndex].ToolTypeCode = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; //*SHANK FIX*case "$TC_MTPN": // { // // Insert new multitool // MultitoolsData.Add(new ShankModel() // { // Id = firstId, // MaxChilds = Convert.ToInt32(actualString.Split('=').LastOrDefault()) // }); // // Update Index // multitoolIndex = MultitoolsData.Count - 1; // } // break; //case "$TC_MTP2": // MultitoolsData[multitoolIndex].Name = actualString.Split('=').LastOrDefault().Replace("\"", ""); // break; //case "$TC_MTP3": // MultitoolsData[multitoolIndex].LeftSize = Convert.ToInt32(actualString.Split('=').LastOrDefault()); // break; //case "$TC_MTP4": // MultitoolsData[multitoolIndex].RightSize = Convert.ToInt32(actualString.Split('=').LastOrDefault()); // break; //case "$TC_MTP7": // MultitoolsData[multitoolIndex].MagazinePositionType = Convert.ToInt32(actualString.Split('=').LastOrDefault()); // break; //case "$TC_MTP8": // { // // Get tool status // byte toolStatus = Convert.ToByte(actualString.Split('=').LastOrDefault()); // MultitoolsData[multitoolIndex].IsEnabled = GetBitValue(toolStatus, 1); // MultitoolsData[multitoolIndex].IsInhibited = GetBitValue(toolStatus, 2); // MultitoolsData[multitoolIndex].InChangeTool = GetBitValue(toolStatus, 3); // MultitoolsData[multitoolIndex].InFixedPlace = GetBitValue(toolStatus, 4); // MultitoolsData[multitoolIndex].InUse = GetBitValue(toolStatus, 7); // } // break; case "$TC_MAP1": { // Magazine type SiemensMagazineConfigModel mag = MagazineConfig.Where(x => x.Id == firstId).FirstOrDefault(); if (mag == null) { bool active = true; SIEMENS_MAGAZINE_TYPE type = (SIEMENS_MAGAZINE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault()); if (type == SIEMENS_MAGAZINE_TYPE.MAGAZINE_LOADING_STATION || type == SIEMENS_MAGAZINE_TYPE.MAGAZINE_TOOL_BUFFER) active = false; MagazineConfig.Add(new SiemensMagazineConfigModel() { Id = (short)firstId, Type = (SIEMENS_MAGAZINE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault()), LoadingIsActive = active }); } else mag.Type = (SIEMENS_MAGAZINE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault()); } break; case "$TC_MAP2": { // Magazine Name SiemensMagazineConfigModel mag = MagazineConfig.Where(x => x.Id == firstId).FirstOrDefault(); if (mag != null) mag.Name = actualString.Split('=').LastOrDefault().Replace("\"", ""); } break; case "$TC_MAP7": { // Add max number of magazine positions SiemensMagazineConfigModel mag = MagazineConfig.Where(x => x.Id == firstId).FirstOrDefault(); if (mag != null) mag.MaxPositions = Convert.ToInt32(actualString.Split('=').LastOrDefault()); } break; } } else // If the key string has 2 ids ex: $TC_DP1[1,3] { // If secondId is changed, change current edge id if (lastSecondId != secondId && toolIndex >= 0) edgeIndex = ToolTableData[toolIndex].EdgesData.FindIndex(x => x.Id == secondId); switch (GetStringUntilOrEmpty(actualString)) { case "$TC_DP1": { if (secondId == 1) // Read tool type from first edge type ToolTableData[toolIndex].ToolType = Convert.ToInt32(actualString.Split('=').LastOrDefault()); // Add new edge ToolTableData[toolIndex].EdgesData.Add(new EdgeModel() { Id = secondId }); edgeIndex = ToolTableData[toolIndex].EdgesData.Count - 1; // Update Index } break; case "$TC_MOP1": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.TIME) { tool .EdgesData[edgeIndex] .PreAlmLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP2": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.TIME) { ToolTableData[toolIndex] .EdgesData[edgeIndex] .ResidualLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP11": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.TIME) { ToolTableData[toolIndex] .EdgesData[edgeIndex] .NominalLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP3": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.COUNT) { ToolTableData[toolIndex] .EdgesData[edgeIndex] .PreAlmLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP4": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.COUNT) { ToolTableData[toolIndex] .EdgesData[edgeIndex] .ResidualLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP13": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.COUNT) { ToolTableData[toolIndex] .EdgesData[edgeIndex] .NominalLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP6": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.WEAR) { tool .EdgesData[edgeIndex] .ResidualLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP15": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.WEAR) { ToolTableData[toolIndex] .EdgesData[edgeIndex] .NominalLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP5": { SiemensToolModel tool = ToolTableData[toolIndex]; if (tool.LifeType == SIEMENS_LIFE_TYPE.WEAR) { ToolTableData[toolIndex] .EdgesData[edgeIndex] .PreAlmLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; //case "$TC_DP2": case "$TC_DP3": case "$TC_DP4": case "$TC_DP5": case "$TC_DP6": case "$TC_DP7": case "$TC_DP8": case "$TC_DP9": case "$TC_DP10": case "$TC_DP11": case "$TC_DP12": case "$TC_DP13": case "$TC_DP14": case "$TC_DP15": case "$TC_DP16": case "$TC_DP17": case "$TC_DP21": case "$TC_DP22": case "$TC_DP23": case "$TC_DP24": case "$TC_DPV": case "$TC_DPV3": case "$TC_DPV4": case "$TC_DPV5": case "$TC_DPNT": { SiemensToolModel tool = ToolTableData[toolIndex]; //// Clear tool //tool // .EdgesData[edgeIndex] // .EdgeAdditionalParams // .Clear(); // Get tool type additional parameters if (toolEdgesConfig.EdgesConfig.ContainsKey(tool.ToolType)) { // Find if actual param exist for the tool type List toolTypeConfig = toolEdgesConfig.EdgesConfig[tool.ToolType]; EdgeConfigModel paramConfig = toolTypeConfig .Where(x => x.Path == (GetStringUntilOrEmpty(actualString) + "[")) .FirstOrDefault(); // If Exist if (paramConfig != null) { // Add additional param tool .EdgesData[edgeIndex] .EdgeAdditionalParams .Add(paramConfig.Name, Convert.ToDouble(actualString.Split('=').LastOrDefault(), numberFormat)); } } } break; case "$TC_DP25": { SiemensToolModel tool = ToolTableData[toolIndex]; // Sets tool value only with the first edge value if (tool.EdgesData[edgeIndex].Id == 1) { // Get tool general information var toolInfo = Convert.ToInt32(actualString.Split('=').LastOrDefault()); // Convert rotation data ROTATION rotation = ROTATION.NONE; if (GetBitValue(toolInfo, 8)) rotation = ROTATION.CLOCKWHISE; else if (GetBitValue(toolInfo, 9)) rotation = ROTATION.COUNTERCLOCKWHISE; // Set new data tool.Cooling1 = GetBitValue(toolInfo, 10); tool.Cooling2 = GetBitValue(toolInfo, 11); tool.Rotation = rotation; } } break; case "$TC_MPP1": { MagazinePositionsData.Add(new PositionModel() { PositionId = secondId, MagazineId = firstId, PhysicalType = (POSITION_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault()) }); } break; case "$TC_MPP2": { int index = MagazinePositionsData.FindIndex(x => x.PositionId == secondId && x.MagazineId == firstId); if (index >= 0) MagazinePositionsData[index].Type = Convert.ToInt32(actualString.Split('=').LastOrDefault()); //*SHANK FIX*MagazinePositionsData.Add(new PositionModel() //{ // PositionId = secondId, // MagazineId = firstId, // Type = Convert.ToInt32(actualString.Split('=').LastOrDefault()) //}); } break; case "$TC_MPP4": { int index = MagazinePositionsData.FindIndex(x => x.PositionId == secondId && x.MagazineId == firstId); if (index >= 0) { MagazinePositionsData[index].Disabled = GetBitValue(Convert.ToInt32(actualString.Split('=').LastOrDefault()), 0); MagazinePositionsData[index].Occupied = GetBitValue(Convert.ToInt32(actualString.Split('=').LastOrDefault()), 2); } } break; case "$TC_MPP6": { int toolId = Convert.ToInt32(actualString.Split('=').LastOrDefault()); if (toolId != 0) { MoveToolInMagazineList(toolId, firstId, secondId); } } break; //*SHANK FIX*case "$TC_MTPP6": // { // // Find tool by id // int toolId = Convert.ToInt32(actualString.Split('=').LastOrDefault()); // if (toolId != 0) // { // // Add new multitool child // MultitoolsData[multitoolIndex].ChildsTools.Add(new ShankChildModel() // { // Id = toolId, // MultitoolId = secondId // }); // } // } // break; case "$TC_MDP1": { // Add max number of magazine positions SiemensMagazineConfigModel mag = MagazineConfig.Where(x => x.Id == firstId).FirstOrDefault(); if (mag != null) mag.LoadPosition = secondId; } break; } } } } } private SiemensToolModel CreateToolFromId(int toolIdToGet, string[] toolsStrings) { SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration(); SiemensToolModel outputTool = new SiemensToolModel(); int lastSecondId = 0; int edgeIndex = 0; // Foreach string for (int i = 0; i < toolsStrings.Count(); i++) { string actualString = toolsStrings[i]; // Get actual string data GetIdsFromSiemensToolString(actualString, out int firstId, out int secondId); // find ids from current string if (firstId != 0 && firstId == toolIdToGet) { if (secondId == 0) { switch (GetStringUntilOrEmpty(actualString)) // Cut string until [ character { case "$TC_TP1": { outputTool = new SiemensToolModel() { Id = firstId, ChildId = Convert.ToInt32(actualString.Split('=').LastOrDefault()) }; } break; case "$TC_TP2": { string familyName = actualString.Split('=').LastOrDefault().Replace("\"", ""); outputTool.FamilyName = familyName; // Add new family with new tool AddOrUpdateFamilyChild(familyName); } break; case "$TC_TP3": outputTool.LeftSize = Convert.ToByte(actualString.Split('=').LastOrDefault()); break; case "$TC_TP4": outputTool.RightSize = Convert.ToByte(actualString.Split('=').LastOrDefault()); break; case "$TC_TP7": outputTool.MagazinePositionType = Convert.ToInt32(actualString.Split('=').LastOrDefault()); break; case "$TC_TP8": { // Get tool status and read each bit int toolStatus = Convert.ToInt32(actualString.Split('=').LastOrDefault()); outputTool.IsActive = GetBitValue(toolStatus, 0); outputTool.IsEnabled = GetBitValue(toolStatus, 1); outputTool.IsInhibited = GetBitValue(toolStatus, 2); outputTool.IsMeasured = GetBitValue(toolStatus, 3); outputTool.PreAlarm = GetBitValue(toolStatus, 4); outputTool.InChangeTool = GetBitValue(toolStatus, 5); outputTool.InFixedPlace = GetBitValue(toolStatus, 6); outputTool.IsInUse = GetBitValue(toolStatus, 7); } break; case "$TC_TP9": outputTool.LifeType = (SIEMENS_LIFE_TYPE)Convert.ToInt32(actualString.Split('=').LastOrDefault()); break; case "$TC_TP_MAX_VELO": outputTool.MaxSpeed = Convert.ToDouble(actualString.Split('=').LastOrDefault(), numberFormat); break; //case "$TC_TP_MAX_ACC": // outputTool.MaxAcceleration = Convert.ToDouble(actualString.Split('=').LastOrDefault(), numberFormat); // break; // Custom CMS fields case "$TC_TPC1": outputTool.Load = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; case "$TC_TPC2": outputTool.Gamma = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; case "$TC_TPC3": outputTool.MaxLoadPctAutoload = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; case "$TC_TPC4": outputTool.MinLoadPctAutoload = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; case "$TC_TPC5": outputTool.ToolTypeCode = Convert.ToInt32(actualString.Split('=').LastOrDefault(), numberFormat); break; } } else { // If secondId is changed, change current edge id if (lastSecondId != secondId) edgeIndex = outputTool.EdgesData.FindIndex(x => x.Id == secondId); switch (GetStringUntilOrEmpty(actualString)) { case "$TC_DP1": { if (secondId == 1) // Read tool type from first edge type outputTool.ToolType = Convert.ToInt32(actualString.Split('=').LastOrDefault()); // Add new edge outputTool.EdgesData.Add(new EdgeModel() { Id = secondId }); edgeIndex = outputTool.EdgesData.Count - 1; // Update Index } break; case "$TC_MOP1": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.TIME) { outputTool .EdgesData[edgeIndex] .PreAlmLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP2": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.TIME) { outputTool .EdgesData[edgeIndex] .ResidualLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP11": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.TIME) { outputTool .EdgesData[edgeIndex] .NominalLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP3": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.COUNT) { outputTool .EdgesData[edgeIndex] .PreAlmLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP4": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.COUNT) { outputTool .EdgesData[edgeIndex] .ResidualLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP13": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.COUNT) { outputTool .EdgesData[edgeIndex] .NominalLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP6": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.WEAR) { outputTool .EdgesData[edgeIndex] .ResidualLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP15": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.WEAR) { outputTool .EdgesData[edgeIndex] .NominalLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; case "$TC_MOP5": { if (outputTool.LifeType == SIEMENS_LIFE_TYPE.WEAR) { outputTool .EdgesData[edgeIndex] .PreAlmLife = Convert.ToDouble(actualString.Split('=').LastOrDefault()); } } break; //case "$TC_DP2": case "$TC_DP3": case "$TC_DP4": case "$TC_DP5": case "$TC_DP6": case "$TC_DP7": case "$TC_DP8": case "$TC_DP9": case "$TC_DP10": case "$TC_DP11": case "$TC_DP12": case "$TC_DP13": case "$TC_DP14": case "$TC_DP15": case "$TC_DP16": case "$TC_DP17": case "$TC_DP21": case "$TC_DP22": case "$TC_DP23": case "$TC_DP24": case "$TC_DPV": case "$TC_DPV3": case "$TC_DPV4": case "$TC_DPV5": case "$TC_DPNT": { //// Clear tool //outputTool // .EdgesData[edgeIndex] // .EdgeAdditionalParams // .Clear(); // Get tool type additional parameters if (toolEdgesConfig.EdgesConfig.ContainsKey(outputTool.ToolType)) { // Find if actual param exist for the tool type List toolTypeConfig = toolEdgesConfig.EdgesConfig[outputTool.ToolType]; EdgeConfigModel paramConfig = toolTypeConfig .Where(x => x.Path == (GetStringUntilOrEmpty(actualString) + "[")) .FirstOrDefault(); // If Exist if (paramConfig != null) { // Add additional param outputTool .EdgesData[edgeIndex] .EdgeAdditionalParams .Add(paramConfig.Name, Convert.ToDouble(actualString.Split('=').LastOrDefault(), numberFormat)); } } } break; case "$TC_DP25": { // Sets tool values with first edge value if (outputTool.EdgesData[edgeIndex].Id == 1) { // Get tool general information var toolInfo = Convert.ToInt32(actualString.Split('=').LastOrDefault()); // Convert rotation data ROTATION rotation = ROTATION.NONE; if (GetBitValue(toolInfo, 8)) rotation = ROTATION.CLOCKWHISE; else if (GetBitValue(toolInfo, 9)) rotation = ROTATION.COUNTERCLOCKWHISE; // Set new data outputTool.Cooling1 = GetBitValue(toolInfo, 10); outputTool.Cooling2 = GetBitValue(toolInfo, 11); outputTool.Rotation = rotation; } } break; } } } } return outputTool; } private EdgeModel SetUpEdgeData(string[] toolsString, SIEMENS_LIFE_TYPE lifeType, int toolId, int edgeId) { EdgeModel edgeData = new EdgeModel { Id = edgeId }; switch (lifeType) { case SIEMENS_LIFE_TYPE.TIME: { edgeData.ResidualLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP2[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); edgeData.NominalLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP11[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); edgeData.PreAlmLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP1[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); } break; case SIEMENS_LIFE_TYPE.COUNT: { edgeData.ResidualLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP4[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); edgeData.NominalLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP13[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); edgeData.PreAlmLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP3[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); } break; case SIEMENS_LIFE_TYPE.WEAR: { // TODO: Check params edgeData.ResidualLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP6[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); edgeData.NominalLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP15[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); edgeData.PreAlmLife = Convert.ToDouble(toolsString.FirstOrDefault(X => X.StartsWith("$TC_MOP5[" + toolId + "," + edgeId)).Split('=').LastOrDefault(), numberFormat); } break; } return edgeData; } private void ToolMngmtSvcHandler(Guid guid, ToolInfo[] toolInfos) { for (int i = 0; i < toolInfos.Count(); i++) { // Choose behavior based on the actions5 ActionsHandler(toolInfos[i]); } } private void ActionsHandler(ToolInfo toolInfo) { switch (toolInfo.action) { case ToolAction.TOOL_DELETED: { // Find tool SiemensToolModel tool = ToolTableData.FirstOrDefault(t => t.Id == toolInfo.tNo); if (tool != null) { // Delete Families SiemensToolModel sameFamilyTool = ToolTableData.FirstOrDefault(x => x.FamilyName == tool.FamilyName && x.Id != tool.Id); if (sameFamilyTool == null) { FamiliesData.RemoveAll(x => x.Name == tool.FamilyName); } // Dismount tool if is mounted in magazine if (MagazineMountedTools.FirstOrDefault(x => x.ToolId == tool.Id) != null) MoveToolInMagazineList(tool.Id, 0, 0); // Remove ToolTableData.Remove(tool); } //*SHANK FIX* else if (MULTITOOL_OPTION_ACTIVE) // { // // if tool not exist, find into shanks // ShankModel shank = MultitoolsData.FirstOrDefault(t => t.Id == toolInfo.tNo); // if (shank != null) // try // { // Item item = new Item(string.Format("/Tool/MT/multitoolMyPlace[u1, {0}]", toolInfo.tNo)); // DataSvc dataSvc = new DataSvc(); // dataSvc.Read(item); // } // catch (Exception ex) // { // MultitoolsData.Remove(shank); // } // } } break; case ToolAction.TOOL_CREATED: { string[] toolsStrings = ReadToolTableFile(); SiemensToolModel newTool = CreateToolFromId((int)toolInfo.tNo, toolsStrings); if (newTool != null) { ToolTableData.Add(newTool); AddOrUpdateFamilyChild(newTool.FamilyName); // Read magazine id and position id from NC DataSvc dataSvc = new DataSvc(); Item[] item = new Item[] { new Item(){ Path = string.Format("/Tool/Data/toolInMag[{0}]", (int)toolInfo.tNo) }, new Item(){ Path = string.Format("/Tool/Data/toolInPlace[{0}]", toolInfo.tNo) } }; dataSvc.Read(item); int magazineId = Convert.ToInt32(item[0].Value); int positionId = Convert.ToInt32(item[1].Value); if (magazineId != 0 && positionId != 0) MoveToolInMagazineList(newTool.Id, magazineId, positionId); } //*SHANK FIX*else if (MULTITOOL_OPTION_ACTIVE) //{ // ShankModel newMultitool = CreateMultitoolFromId((int)toolInfo.tNo, toolsStrings); // MultitoolsData.Add(newMultitool); //} } break; case ToolAction.TOOL_DATA_CHANGED: { string[] toolsStrings = ReadToolTableFile(); // Find edited toolIndex int toolIndex = ToolTableData.FindIndex(t => t.Id == toolInfo.tNo); // If the id belongs to a tool if (toolIndex != -1) { // Get tool new data SiemensToolModel newTool = CreateToolFromId((int)toolInfo.tNo, toolsStrings); // *ASSISTED TOOLING FIX* // After one reset in an assisted tooling procedure siemens send a "tool_data_changed" message // Check if tool is not mounted and remove from magazine // Read magazine id and position id from NC DataSvc dataSvc = new DataSvc(); Item[] item = new Item[] { new Item(){ Path = string.Format("/Tool/Data/toolInMag[{0}]", (int)toolInfo.tNo) }, new Item(){ Path = string.Format("/Tool/Data/toolInPlace[{0}]", toolInfo.tNo) } }; dataSvc.Read(item); int magazineId = Convert.ToInt32(item[0].Value); int positionId = Convert.ToInt32(item[1].Value); MoveToolInMagazineList(newTool.Id, magazineId, positionId); // Replace the element if (newTool != null) ToolTableData[toolIndex] = newTool; } //*SHANK FIX*else if (MULTITOOL_OPTION_ACTIVE) //{ // // Find if its a multitool // int multitoolIndex = MultitoolsData.FindIndex(t => t.Id == toolInfo.tNo); // if (multitoolIndex != -1) // { // // Create model with new data // ShankModel newShank = CreateMultitoolFromId((int)toolInfo.tNo, toolsStrings); // // Replace element // if (newShank != null) // MultitoolsData[multitoolIndex] = newShank; // } // else // { // ShankModel newMultitool = CreateMultitoolFromId((int)toolInfo.tNo, toolsStrings); // MultitoolsData.Add(newMultitool); // } //} Array.Clear(toolsStrings, 0, toolsStrings.Count()); } break; case ToolAction.TOOL_MOVED: { int magazineId = 0; int positionId = 0; var tool = GetToolOrMultitool(Convert.ToInt32(toolInfo.tNo)); if (tool is SiemensToolModel) { try { // Read magazine id and position id from NC DataSvc dataSvc = new DataSvc(); Item[] item = new Item[] { new Item(){ Path = string.Format("/Tool/Data/toolInMag[{0}]", (int)toolInfo.tNo) }, new Item(){ Path = string.Format("/Tool/Data/toolInPlace[{0}]", toolInfo.tNo) } }; dataSvc.Read(item); magazineId = Convert.ToInt32(item[0].Value); positionId = Convert.ToInt32(item[1].Value); } catch (Exception ex) { magazineId = 0; positionId = 0; } } MoveToolInMagazineList((int)toolInfo.tNo, magazineId, positionId); // moved MULTITOOL handler, add when Siemens Library bugs have been fixed //*SHANK FIX*catch (Exception ex) //{ // int shankIdx = MultitoolsData.FindIndex(x => x.Id == toolInfo.tNo); // if (shankIdx < 0) // { // // Check that the move is inside a multitool // item = new Item() { Path = string.Format("/Tool/Data/toolInMultitool[{0}]", toolInfo.tNo) }; // dataSvc.Read(item); // // Check if readed multitool id exists // int mtIndex = MultitoolsData.FindIndex(x => x.Id == Convert.ToInt32(item.Value)); // if (mtIndex >= 0) // { // int childIndex = MultitoolsData[mtIndex].ChildsTools.FindIndex(x => x.Id == toolInfo.tNo); // if (childIndex < 0) // { // MultitoolsData[mtIndex].ChildsTools.Add(new ShankChildModel() // { // Id = Convert.ToInt32(toolInfo.tNo), // MultitoolId = MultitoolsData[mtIndex].ChildsTools.Count + 1 // TODO ADD TOOL DATA OR REMOVE // }); // } // } // } //} } break; } } private void MoveToolInMagazineList(int toolId, int magazineId, int positionId) { // If load magazine != 0, add new tool if (magazineId != 0 && positionId != 0) { // Find tool by id var tool = GetToolOrMultitool(toolId); if (tool != null) { if (magazineId == 9998) { // Get old tool position MountedToolModel toolMounted = MagazineMountedTools .Where(x => x.ToolId == toolId) .FirstOrDefault(); if (toolMounted != null) { // Set magazine position as occupied var position = MagazinePositionsData.Where(x => x.MagazineId == toolMounted.MagazineId && x.PositionId == toolMounted.PositionId) .FirstOrDefault(); if (position != null) position.Occupied = true; } } else { // Free a position var position = MagazinePositionsData.Where(x => x.MagazineId == magazineId && x.PositionId == positionId).FirstOrDefault(); if (position != null) position.Occupied = false; } // Remove tool from list MagazineMountedTools.RemoveAll(mountTool => PositionContainsTool(mountTool, toolId)); // Find if position exist MountedToolModel mounted = MagazineMountedTools .Where(x => x.MagazineId == magazineId && x.PositionId == positionId) .FirstOrDefault(); if (mounted != null) return; // Add tool to list MagazineMountedTools.Add(new MountedToolModel() { MagazineId = magazineId, PositionId = positionId, ToolId = toolId }); } } else { // Remove tool from list MagazineMountedTools.RemoveAll(mountTool => PositionContainsTool(mountTool, toolId)); } } private int GetLastToolId() { Item item = new Item() { Path = "/Tool/Catalogue/TnumWZV" }; DataSvc dataSvc = new DataSvc(); dataSvc.Read(item); return Convert.ToInt32(item.Value); // First implementation before the path was found //Get tool ids //List toolIds = ToolTableData.Select(x => x.Id).ToList(); //// Sort tools ids array //toolIds.Sort((x, y) => x.CompareTo(y)); //if (toolIds.Count == 0) // return 1; //for (int i = 0; i < toolIds.Count - 1; i++) //{ // // If next id is different than previus + 1, there is an empty space in the array of numbers // if (toolIds[i] + 1 != toolIds[i + 1]) // { // // Check if the empty space is a multitool // ShankModel shank = MultitoolsData.Where(x => x.Id == (toolIds[i] + 1)).FirstOrDefault(); // if (shank == null) // { // // return new id // return toolIds[i] + 1; // } // } //} //// If there isn't an empty space return max id + 1 //return toolIds[toolIds.Count - 1] + 1; } private int GetLastMultitoolId() { Item item = new Item() { Path = "/Tool/MTCatalogue/MTnumWZV" }; DataSvc dataSvc = new DataSvc(); dataSvc.Read(item); return Convert.ToInt32(item.Value); } private int GetLastEdgeId(int toolId) { // Get edgeIds ids List edgeIds = ToolTableData.Where(x => x.Id == toolId).FirstOrDefault()?.EdgesData.Select(x => x.Id).ToList(); // Sort tools ids array edgeIds.Sort((x, y) => x.CompareTo(y)); if (edgeIds.Count == 0) return 1; for (int i = 0; i < edgeIds.Count - 1; i++) { // If next id is different than previus + 1, there is an empty space in the array of numbers if (edgeIds[i] + 1 != edgeIds[i + 1]) { // return new id return edgeIds[i] + 1; } } // If there isn't an empty space return max id + 1 return edgeIds[edgeIds.Count - 1] + 1; } private void AddOrUpdateFamilyChild(string familyName) { // Find family int familyIndex = FamiliesData.FindIndex(x => x.Name == familyName); if (familyIndex < 0) { // Create family and add child FamiliesData.Add(new FamilyModel() { Name = familyName }); } } private static void GetIdsFromSiemensToolString(string text, out int toolId, out int edgeId) { toolId = 0; edgeId = 0; if (!string.IsNullOrWhiteSpace(text)) { // Get indexes from string int startingData = text.IndexOf("[", StringComparison.Ordinal) + 1; int secondData = text.IndexOf(",", StringComparison.Ordinal) + 1; int endingData = text.IndexOf("]", StringComparison.Ordinal); // If the string is matching with the pattern STRING[N]=N or STRING[N,M]=N if (startingData > 0 && endingData > 0) // STRING[N,M]=N case if (secondData > 0) { toolId = Convert.ToInt32(text.Substring(startingData, secondData - (startingData + 1))); edgeId = Convert.ToInt32(text.Substring(secondData, endingData - (secondData))); } else // STRING[N]=N case { toolId = Convert.ToInt32(text.Substring(startingData, endingData - (startingData))); edgeId = 0; } } } #endregion Siemens Tool private functions #region Multitool Private region private void MultitoolsNumber_OnChange(Guid guid, Item item, DataSvcStatus status) { // Check if an element has been deleted if ((uint)item.Value < multitoolsNumber) { // for each saved multitool for (int i = 0; i < MultitoolsData.Count; i++) { try { // Check if exists Item toolData = new Item(string.Format("/Tool/MT/multitoolMyPlace[u1, {0}]", MultitoolsData[i].Id)); DataSvc dataSvc = new DataSvc(); dataSvc.Read(toolData); } catch (Exception) { // Remove from list MultitoolsData.RemoveAt(i); } } } // Update multitool counter multitoolsNumber = (uint)item.Value; } private int ToolIsInMultitool(int toolId) { // Loop through multitools //foreach (ShankModel multi in MultitoolsData) //{ // if (multi.ChildsTools.Count() > 0) // { // // Find tool id in multitool childs // int childIndex = multi.ChildsTools.FindIndex(x => x.Id == toolId); // if (childIndex >= 0) // return multi.Id; // } //} return 0; } private CmsError CheckMultitoolData(ref ShankModel shank, bool isUpdate) { //Check if the NC is Connected CmsError cmsError = CheckConnection(); if (cmsError.IsError()) return cmsError; // Truncate name if (shank.Name.Count() > 32) shank.Name = shank.Name.Substring(0, 32); int totalNumberOfChilds = 0; foreach (ShankModel multi in MultitoolsData) { if (shank.Name == multi.Name && shank.Id != multi.Id) return INCORRECT_PARAMETERS_ERROR; // Calculate max number of childs totalNumberOfChilds += multi.MaxChilds; } // Check if there are enough locations if (!isUpdate && totalNumberOfChilds + MAX_TOOLS_PER_MULTITOOL > MAX_MULTITOOLS_LOCATIONS) return MAX_MULTITOOL_LOCATION_REACHED_ERROR; return NO_ERROR; } private ShankModel CreateMultitoolFromId(int multitoolId, string[] toolsStrings) { SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration(); // Find tool status status var toolStatusByte = toolsStrings.FirstOrDefault(X => X.StartsWith("$TC_MTP8[" + multitoolId)); if (toolStatusByte == null) return null; int toolStatus = Convert.ToInt32(toolStatusByte.Split('=').LastOrDefault()); // Find shank, in order to get childs ShankModel oldShank = MultitoolsData.Where(x => x.Id == multitoolId).FirstOrDefault(); // Create shank model ShankModel shank = new ShankModel() { Id = multitoolId, Name = toolsStrings.FirstOrDefault(x => x.Contains("$TC_MTP2[" + multitoolId)).Split('=').LastOrDefault().Replace("\"", ""), LeftSize = Convert.ToByte(toolsStrings.FirstOrDefault(X => X.StartsWith("$TC_MTP3[" + multitoolId)).Split('=').LastOrDefault()), RightSize = Convert.ToByte(toolsStrings.FirstOrDefault(X => X.StartsWith("$TC_MTP4[" + multitoolId)).Split('=').LastOrDefault()), MagazinePositionType = Convert.ToByte(toolsStrings.FirstOrDefault(x => x.StartsWith("$TC_MTP7[" + multitoolId)).Split('=').LastOrDefault()), MaxChilds = Convert.ToInt32(toolsStrings.FirstOrDefault(x => x.StartsWith("$TC_MTPN[" + multitoolId)).Split('=').LastOrDefault()), IsEnabled = GetBitValue(toolStatus, 1), IsInhibited = GetBitValue(toolStatus, 2), InChangeTool = GetBitValue(toolStatus, 5), InFixedPlace = GetBitValue(toolStatus, 6), InUse = GetBitValue(toolStatus, 7), ChildsTools = new List() }; // Populate shank childs for (int i = 1; i <= MAX_TOOLS_PER_MULTITOOL; i++) { // Find if position exists var multitoolPos = toolsStrings.FirstOrDefault(x => x.Contains("$TC_MTPP6[" + multitoolId + "," + i)); if (multitoolPos != null) { // If not empty int toolId = Convert.ToInt32(multitoolPos.Split('=').LastOrDefault()); if (toolId != 0) { shank.ChildsTools.Add(new ShankChildModel() { Id = toolId, MultitoolId = i }); } } } // Check position in magazine // Read magazine id from memory DataSvc dataSvc = new DataSvc(); Item item = new Item() { Path = string.Format("/Tool/MT/multitoolInMag[{0}]", multitoolId) }; // Read magazine position dataSvc.Read(item); int magazineId = Convert.ToInt32(item.Value); item = new Item() { Path = string.Format("/Tool/MT/multitoolInPlace[{0}]", multitoolId) }; dataSvc.Read(item); int positionId = Convert.ToInt32(item.Value); MoveToolInMagazineList(multitoolId, magazineId, positionId); return shank; } #endregion Multitool Private region } internal static class MEMORY_ADDRESS { // aree Parametri // aree Moduli // riscaldi superiori // riscaldi inferiori // produzione // ciclo produzione internal const int TABLE = 258; internal static MEMORY_CELL NC_WATCHDOG = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 1); internal static MEMORY_CELL ACTIVE_WATCHDOG = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2, 1); internal static MEMORY_CELL ACTIVE_CLIENT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 4, 1); internal static MEMORY_CELL FUNCTION_ACCESS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6, 8); internal static MEMORY_CELL PRE_POST_POWER_ON = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2574, 2); internal static MEMORY_CELL PRE_POST_POWER_ON_CLICKABLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2576, 2); internal static MEMORY_CELL PRE_POST_POWER_ON_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2578, 2); internal static MEMORY_CELL PRE_POST_POWER_ON_CLICKED = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2580, 2); internal static MEMORY_CELL AXIS_RESET_PROCEDURE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2608, 1); internal static MEMORY_CELL PROCESS_STATUS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2582, 24); internal static MEMORY_CELL SELECTED_PROCESS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2582, 24); internal static MEMORY_CELL SELECT_PROCESS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2606, 1); internal static MEMORY_CELL COUNTERS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 40); internal static MEMORY_CELL SELECTED_AXIS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2626, 1); internal static MEMORY_CELL SELECT_AXIS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2627, 1); internal static MEMORY_CELL NC_SOFTKEYS_VALUE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2610, 4); internal static MEMORY_CELL NC_SOFTKEYS_CLICKABLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2614, 4); internal static MEMORY_CELL NC_SOFT_KEYS_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2618, 4); internal static MEMORY_CELL NC_SOFT_KEYS_CLICKED = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2622, 4); internal static MEMORY_CELL USER_SOFTKEYS_VALUE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2628, 16); internal static MEMORY_CELL USER_SOFTKEYS_CLICKABLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2644, 16); internal static MEMORY_CELL USER_SOFT_KEYS_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2660, 16); internal static MEMORY_CELL USER_SOFT_KEYS_CLICKED = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2676, 16); internal static MEMORY_CELL ALARMS_STATUS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 14, 128); internal static MEMORY_CELL ALARMS_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 142, 1024); internal static MEMORY_CELL ALARM_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2190, 128); internal static MEMORY_CELL ALARM_RESTORATION_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2318, 128); internal static MEMORY_CELL ALARM_REFRESH_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2446, 128); internal static MEMORY_CELL HEADS_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2692, 240); internal static MEMORY_CELL HEADS_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2932, 4); internal static MEMORY_CELL HEADS_STROBE_INCREMENT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2936, 4); internal static MEMORY_CELL HEADS_STROBE_DECREMENT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2940, 4); internal static MEMORY_CELL COUNTERS_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2944, 64); internal static MEMORY_CELL COUNTER_IS_RESETTABLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3008, 2); internal static MEMORY_CELL COUNTER_IS_RESETTABLE_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3010, 2); internal static MEMORY_CELL COUNTER_IS_RESETTABLE_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3012, 2); internal static MEMORY_CELL M155_INPUT_NEEDED = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3014, 1); internal static MEMORY_CELL M155_INPUT_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3015, 1); internal static MEMORY_CELL M155_INPUT_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3016, 1); internal static MEMORY_CELL M156_INPUT_NEEDED = new MEMORY_CELL(MEMORY_TYPE.Osai_MW, 4333, 1); internal static MEMORY_CELL M156_INPUT_ACK = new MEMORY_CELL(MEMORY_TYPE.Osai_MW, 4335, 1); internal static MEMORY_CELL M156_INPUT_STROBE = new MEMORY_CELL(MEMORY_TYPE.Osai_MW, 4337, 1); internal static MEMORY_CELL M156_INPUT_ID_LIST = new MEMORY_CELL(MEMORY_TYPE.Osai_MW, 4339, 8); internal static MEMORY_CELL M154_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3042, 1); internal static MEMORY_CELL M154_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3043, 1); internal static MEMORY_CELL M154_SWITCH_ONOFF = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 2); internal static MEMORY_CELL AXES_BUTTON_VISIBLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3044, 16); internal static MEMORY_CELL MAGAZINE_ACTION = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 4000, 16); internal static MEMORY_CELL BALLUF_ACTION_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 4014, 1); internal static MEMORY_CELL BALLUF_ACTION_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 4015, 1); internal static MEMORY_CELL BALLUF_ACTION_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 4016, 1); //old CMS-Control variables internal static MEMORY_CELL HEADS_WORKED_TIMES = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 254, 60, 4); internal static MEMORY_CELL HEAD_RESET_WORKED_TIME = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 92, 4); internal static MEMORY_CELL MACHINE_WORKED_TIME = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 94, 4); internal static MEMORY_CELL MACHINE_RESET_WORKED_TIME = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 98, 4); internal static MEMORY_CELL CANDY_MEM = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 130, 1); internal static MEMORY_CELL EXP_CANDY_MEM = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 92, 1); internal static MEMORY_CELL SELF_ADAPTIVE_PATH = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 253, 16, 4); internal static MEMORY_CELL BALLUF_EMPTY_TABLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 111, 0, 486); // Machine number internal static MEMORY_CELL MATR_MACCH_SIEMENS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 0, 1); internal static MEMORY_CELL NEW_MATR_MACC = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 258, 3060, 4); } }