5567 lines
214 KiB
C#
5567 lines
214 KiB
C#
using CMS_CORE_Library.Models;
|
|
using S7.Net;
|
|
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.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;
|
|
|
|
|
|
namespace CMS_CORE_Library.S7Net
|
|
{
|
|
public class Nc_S7Net : Nc
|
|
{
|
|
// Global Constants
|
|
|
|
private const string NcNotFound = "Missing response";
|
|
private const string NcNotFound2 = "networking error";
|
|
private const string NcNotFound3 = "Nc not Connected";
|
|
#if false
|
|
private const int IDMinPLCMessage = 700000;
|
|
private const int IDMaxPLCMessage = 799999;
|
|
private const int IDMinChannel = 10000;
|
|
private const int IDMaxChannel = 19999;
|
|
#endif
|
|
|
|
#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";
|
|
|
|
#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 static Dictionary<int, string> PlcMessages;
|
|
|
|
#if false
|
|
|
|
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<AxisModel> AxesData = new List<AxisModel>();
|
|
|
|
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;
|
|
#endif
|
|
|
|
private static ushort SelectedProcess = 0;
|
|
|
|
#if false
|
|
private static Dictionary<string, double> MachineAxesPosition = new Dictionary<string, double>();
|
|
private static Dictionary<string, double> ToGoAxesPosition = new Dictionary<string, double>();
|
|
private static Dictionary<string, double> InterpAxesPosition = new Dictionary<string, double>();
|
|
private static Dictionary<string, double> ProgrammedAxisPosition = new Dictionary<string, double>();
|
|
#endif
|
|
|
|
private bool EnableAlarms;
|
|
private bool EnableHeaters;
|
|
private bool EnableModules;
|
|
private bool EnableParameters;
|
|
private bool EnableProd;
|
|
|
|
private bool EnableAxes;
|
|
|
|
private CpuType tipoCpu = CpuType.S71500;
|
|
private short rack = 0;
|
|
private short slot = 1;
|
|
|
|
/// <summary>
|
|
/// Oggetto PLC da ri-utilizzare...
|
|
/// </summary>
|
|
protected Plc currPLC;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#region Contructor & global methods
|
|
|
|
///<summary>
|
|
///Instantiate The NC-S7Net Class
|
|
///</summary>
|
|
///<param name="ConnectionTimeOut">Send/Recieve timeout connection [mS]</param>
|
|
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[] { };
|
|
}
|
|
|
|
/// <summary>
|
|
/// Instantiate The NC-Siemens Class
|
|
/// </summary>
|
|
/// <param name="ConnectionTimeOut">Send/Recieve timeout connection [mS]</param>
|
|
/// <param name="EnableAxes">Enable Axes Svc</param>
|
|
/// <param name="EnableAlarms">Enable Alarms Svc</param>
|
|
/// <param name="EnableHeaters">Enable Heaters Svc</param>
|
|
/// <param name="EnableModules">Enable Modules Svc</param>
|
|
/// <param name="EnableParameters">Enable Parameters Svc</param>
|
|
/// <param name="EnableProd">Enable Prod Svc</param>
|
|
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
|
|
currPLC = new Plc(tipoCpu, this.Ip, this.rack, this.slot);
|
|
currPLC.Open();
|
|
if (currPLC.IsConnected)
|
|
Connected = true;
|
|
|
|
#if false
|
|
// 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" },
|
|
});
|
|
}
|
|
#endif
|
|
|
|
// Setup the alarms (with DB bitmap) --> PlcMessages
|
|
|
|
if (this.EnableAlarms)
|
|
{
|
|
// PlcMessages
|
|
#if false
|
|
SiemensAlarms = new Alarm[] { };
|
|
SiemensAlmSvc = new AlarmSvc(ConvertToSTEPLanguage(SiemensLanguage).ThreeLetterISOLanguageName);
|
|
SiemensAlmSvc.Subscribe(AlarmsChanged);
|
|
Infrastructure.SubscribeLanguageChanged(NcLanguageChanged);
|
|
#endif
|
|
}
|
|
|
|
#if false
|
|
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();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ManageException(ex);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#if false
|
|
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<AxisModel> axesConf = new List<AxisModel>();
|
|
|
|
AXES_RAxesNames(SelectedProcess, ref AxesData);
|
|
|
|
List<Item> axesData = new List<Item>();
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Disconnect Method
|
|
public override CmsError NC_Disconnect()
|
|
{
|
|
// Set Connected to FALSE and close the sessions
|
|
Connected = false;
|
|
currPLC.Close();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#if false
|
|
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<Item> magPosItems = new List<Item>();
|
|
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);
|
|
}
|
|
#endif
|
|
|
|
private void RemoveLifeParamsFromConfig()
|
|
{
|
|
#if false
|
|
SiemensToolFieldsConfig.RemoveAll(x => x.Category == "life");
|
|
SiemensEdgesFieldsConfiguration.EdgeConfiguration.RemoveAll(x => x.Category == "life");
|
|
#endif
|
|
}
|
|
|
|
#if false
|
|
public override CmsError NC_GetTranslatedPlcMessages(string language, ref Dictionary<int, string> messages)
|
|
{
|
|
string filePath;
|
|
try
|
|
{
|
|
messages = new Dictionary<int, string>();
|
|
|
|
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<CultureInfo> 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;
|
|
}
|
|
#endif
|
|
|
|
#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)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_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<byte> lists = new List<byte>();
|
|
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<AlarmModel> 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<PlcAlarmModel> alarms)
|
|
{
|
|
bool[] statusBits;
|
|
int i = 0;
|
|
List<int> readValues = new List<int>();
|
|
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<int> readValues = new List<int>();
|
|
|
|
//// 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<int>();
|
|
|
|
// 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<FunctionalityModel> functions)
|
|
{
|
|
List<int> readValues = new List<int>();
|
|
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<FunctionalityModel>();
|
|
// 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<SoftKeysModel> 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<SoftKeysModel> 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<SoftKeysModel> softKeys)
|
|
{
|
|
softKeys = new List<SoftKeysModel>();
|
|
List<int> readValues = new List<int>();
|
|
|
|
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<HeadDataModel> heads, int number)
|
|
{
|
|
// Check parameters
|
|
if (number > MAX_HEADS_NUMBER)
|
|
return INCORRECT_PARAMETERS_ERROR;
|
|
heads.Clear();
|
|
|
|
List<int> readInts = new List<int>();
|
|
List<byte> readValues = new List<byte>();
|
|
List<uint> readHours = new List<uint>();
|
|
// 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<CounterModel> counters)
|
|
{
|
|
List<uint> val = new List<uint>();
|
|
// 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<M155InputIsNeededModel> 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<byte, string>()
|
|
});
|
|
|
|
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<byte, string> 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<byte, string> 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<M154DataModel> 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<M156InputIsNeededModel> value)
|
|
{
|
|
byte val = 0;
|
|
List<byte> vals = new List<byte>();
|
|
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<ScadaObjectModel> objects)
|
|
{
|
|
try
|
|
{
|
|
List<Item> items = new List<Item>();
|
|
|
|
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<string> 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<AlarmModel> 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<EdgeConfigModel> 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<string, double> axes)
|
|
{
|
|
try
|
|
{
|
|
axes = new Dictionary<string, double>();
|
|
// 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<string, double> axes)
|
|
{
|
|
try
|
|
{
|
|
axes = new Dictionary<string, double>();
|
|
|
|
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<string, double> axes)
|
|
{
|
|
try
|
|
{
|
|
axes = new Dictionary<string, double>();
|
|
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<string, double> axes)
|
|
{
|
|
try
|
|
{
|
|
axes = new Dictionary<string, double>();
|
|
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<string, double> axes)
|
|
{
|
|
try
|
|
{
|
|
axes = new Dictionary<string, double>();
|
|
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<string, double> AXES_RAxesPos(ushort channel, string positionType)
|
|
{
|
|
Dictionary<string, double> axes = new Dictionary<string, double>();
|
|
List<AxisModel> axesConf = new List<AxisModel>();
|
|
|
|
CmsError cmsError = AXES_RAxesNames(channel, ref axesConf);
|
|
|
|
List<Item> items = new List<Item>();
|
|
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<AxisModel> 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<AxisModel> configuredAxes = new List<AxisModel>();
|
|
|
|
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<byte> ids = new List<byte>();
|
|
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<Item> ncAxes = new List<Item>();
|
|
|
|
List<AxisModel> axes = new List<AxisModel>();
|
|
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<byte> ListValue = new List<byte>() { 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<ushort> ListValue = new List<ushort>() { 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<short> ListValue = new List<short>() { 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<uint> ListValue = new List<uint>() { 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<int> ListValue = new List<int>() { 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<uint> Value)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError MEM_RWIntegerList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int Number, ref List<int> Value)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError MEM_RWShortList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int Number, ref List<short> Value)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError MEM_RWWordList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemIndex, int Number, ref List<ushort> 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<byte> 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<byte> Values)
|
|
{
|
|
//Check if the NC is Connected
|
|
CmsError cmsError = CheckConnection();
|
|
if (cmsError.IsError())
|
|
return cmsError;
|
|
|
|
if (MemType != MEMORY_TYPE.Siemens_DB)
|
|
{
|
|
return INCORRECT_PARAMETERS_ERROR;
|
|
}
|
|
|
|
cmsError = null;
|
|
|
|
if (bWrite)
|
|
{
|
|
//Prevent some exceptions
|
|
if (Values.Count == 0)
|
|
return NO_ERROR;
|
|
|
|
currPLC.WriteBytes(DataType.DataBlock, MemTable, MemIndex, Values.ToArray());
|
|
}
|
|
else
|
|
{
|
|
// Prevent some exceptions
|
|
if (Number == 0)
|
|
return NO_ERROR;
|
|
|
|
Values.Clear();
|
|
|
|
var memByteRead = currPLC.ReadBytes(DataType.DataBlock, MemTable, MemIndex, Number);
|
|
Values = memByteRead.ToList();
|
|
#if false
|
|
// ciclo eda ggiungo i bytes...
|
|
foreach (var item in memByteRead)
|
|
{
|
|
Values.Add(item);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
public override CmsError MEM_RWWordList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List<ushort> 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<uint>().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<short> 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<uint>().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<uint> 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<uint>().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<int> 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<uint>().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<PreviewFileModel> 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<Node> 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<Item> itemRead = new List<Item>()
|
|
{
|
|
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<string>(),
|
|
TimeLeft = new DateTime()
|
|
};
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Separate string into list of lines
|
|
List<string> 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<QueueStatusModel> 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<string> 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<int, List<string>>();
|
|
// Remove path and set only names as additionalParams
|
|
foreach (int key in Add_Edges_Param_Config.EdgesConfig.Keys)
|
|
{
|
|
List<string> tmpNames = new List<string>();
|
|
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<MagazineConfigModel>();
|
|
//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<SiemensToolModel> toolTable)
|
|
{
|
|
toolTable = new List<SiemensToolModel>(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<EdgeConfigModel> toolTypeConfig = toolEdgesConfig.EdgesConfig[tool.ToolType];
|
|
Dictionary<string, double> edgeData = toolTypeConfig.ToDictionary(x => x.Name, x => 0.0);
|
|
// Create new edge
|
|
tool.EdgesData = new List<EdgeModel>()
|
|
{
|
|
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<Item> items = new List<Item>()
|
|
{
|
|
// 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<ShankModel> 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<Item> items = new List<Item>()
|
|
{
|
|
// 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<FamilyModel> 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<int> 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<EdgeConfigModel> toolTypeConfig = toolEdgesConfig.EdgesConfig[tool.ToolType];
|
|
DataSvc dataSvc = new DataSvc();
|
|
List<Item> items = new List<Item>();
|
|
|
|
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<ushort> words = new List<ushort>()
|
|
{
|
|
(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<ushort> words = new List<ushort>()
|
|
{
|
|
(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<Item> items = new List<Item> {
|
|
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<EdgeConfigModel> 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<Item>()
|
|
{
|
|
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<PositionModel> 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<MountedToolModel> 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<ShankModel> multiTools, ref List<SiemensToolModel> tools)
|
|
{
|
|
List<int> occupiedIds = new List<int>();
|
|
// 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<NcMagazineConfigModel> 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<NcToolModel> list)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError TOOLS_WUpdateFamilies(List<NcFamilyModel> list)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError TOOLS_WUpdateShanks(List<NcShankModel> list)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError TOOLS_WUpdateMagazinePositions(List<NcMagazinePositionModel> 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<int, byte> updatedStatus, ref Dictionary<int, uint> updatedLives)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError TOOLS_RStoredData(ref List<NcToolModel> tools, ref List<NcFamilyModel> families, ref List<NcShankModel> shanks)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError TOOLS_RMagazineBlock(ref List<int> ids)
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError TOOLS_WFreeMagazines()
|
|
{
|
|
return FUNCTION_NOT_ALLOWED_ERROR;
|
|
}
|
|
|
|
public override CmsError TOOLS_RMagazineStatus(ref Dictionary<int, bool> 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
|
|
|
|
|
|
// Manage the Alarms - Called automatically on changes
|
|
private void AlarmsChanged(Guid guid, Alarm[] alarms)
|
|
{
|
|
#if false
|
|
try
|
|
{
|
|
if (alarms != null)
|
|
SiemensAlarms = alarms.ToArray();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.Message);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
private void NcLanguageChanged(string language)
|
|
{
|
|
#if false
|
|
SiemensAlmSvc.UnSubscribe(AlarmsChanged);
|
|
// SiemensAlmSvc.Dispose();
|
|
SiemensAlmSvc = new AlarmSvc(language);
|
|
SiemensAlmSvc.Subscribe(AlarmsChanged);
|
|
#endif
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if PLC is responding to Ping
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private CmsError CheckS7Ping()
|
|
{
|
|
|
|
// faccio ping...
|
|
if (testPing() != IPStatus.Success)
|
|
return PLC_IP_NOT_FOUND_ERROR;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Ping test to configured Ip address
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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 S7Net exceptions
|
|
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
|
|
{
|
|
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
|
|
{
|
|
#if false
|
|
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;
|
|
#endif
|
|
}
|
|
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<int> ChangeIntListEndianess(List<int> bigEndianvalues)
|
|
{
|
|
List<int> littleEndianValues = new List<int>();
|
|
foreach (int value in bigEndianvalues)
|
|
{
|
|
var a = SwapIntEndianFormat(value);
|
|
littleEndianValues.Add(a);
|
|
}
|
|
|
|
return littleEndianValues;
|
|
}
|
|
|
|
private List<ushort> ChangeUShortListEndianess(List<ushort> bigEndianvalues)
|
|
{
|
|
List<ushort> littleEndianValues = new List<ushort>();
|
|
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<FieldsConfiguration> 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
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
}
|
|
|
|
internal static class MEMORY_ADDRESS
|
|
{
|
|
// aree Parametri
|
|
internal static MEMORY_CELL PARAMETER_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 600, 20, 8000);
|
|
internal static MEMORY_CELL PARAMETER_RT_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 601, 8, 3200);
|
|
|
|
// aree Moduli
|
|
internal static MEMORY_CELL MODULE_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 602, 18, 2304);
|
|
internal static MEMORY_CELL MODULE_RT_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 603, 12, 1536);
|
|
|
|
// riscaldi
|
|
internal static MEMORY_CELL RISC_OCC_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 500, 64, 64);
|
|
internal static MEMORY_CELL RISC_CHP_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 500, 128, 1024);
|
|
internal static MEMORY_CELL RISC_CFI_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 500, 2176, 1024);
|
|
internal static MEMORY_CELL RISC_ICH_MIN_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 500, 3200, 4096);
|
|
internal static MEMORY_CELL RISC_OCS_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 500, 9472, 64);
|
|
internal static MEMORY_CELL RISC_ESP_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 500, 9728, 1024);
|
|
internal static MEMORY_CELL RISC_OVP_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 500, 10752, 1024);
|
|
internal static MEMORY_CELL RISC_ICH_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 500, 11776, 4096);
|
|
|
|
// produzione
|
|
internal static MEMORY_CELL PROCESS_STATUS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 605, 0, 2);
|
|
|
|
// ciclo produzione
|
|
internal const int TABLE = 604;
|
|
|
|
|
|
|
|
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 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);
|
|
}
|
|
} |