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.ServiceModel.Channels; using System.Text; using System.Threading; using static CMS_CORE_Library.Models.DataStructures; using static CMS_CORE_Library.Nc; using static CMS_CORE_Library.S7Net.MEMORY_ADDRESS; using static CMS_CORE_Library.Utils.Nc_Utils; namespace CMS_CORE_Library.S7Net { internal static class MEMORY_ADDRESS { // A) THERMO SPECIAL MEMORY #region Internal Fields // Main DB Table internal const int TABLE = 604; // B) GEN memory (NOT Thermo) internal static MEMORY_CELL ACTIVE_CLIENT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 4, 1); internal static MEMORY_CELL ALARM_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2190, 128); internal static MEMORY_CELL ALARM_REFRESH_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2318, 128); internal static MEMORY_CELL ALARM_RESTORATION_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2318, 128); internal static MEMORY_CELL ALARMS_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 142, 1024); internal static MEMORY_CELL ALARMS_STATUS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 14, 128); // assi internal static MEMORY_CELL AXES_BUTTON_VISIBLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 3044, 16); internal static MEMORY_CELL AXES_COMMAND = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 616, 512, 512); internal static MEMORY_CELL AXES_GEN_CONTROL = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 616, 1026, 2); internal static MEMORY_CELL AXES_GEN_STATUS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 616, 1024, 2); internal static MEMORY_CELL AXES_INFO = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 616, 0, 512); internal static MEMORY_CELL AXES_RTDATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 615, 0, 768); internal static MEMORY_CELL AXIS_RESET_PROCEDURE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2608, 1); internal static MEMORY_CELL CANDY_MEM = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 130, 1); 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 COUNTERS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 40); internal static MEMORY_CELL COUNTERS_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2944, 64); internal static MEMORY_CELL EXP_CANDY_MEM = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 92, 1); internal static MEMORY_CELL FIRMWARE_PLC = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 604, 6764, 4); internal static MEMORY_CELL FUNCTION_ACCESS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6, 8); internal static MEMORY_CELL HEAD_RESET_WORKED_TIME = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 92, 4); //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 IO_AI_VAL_ACT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 132, 64); internal static MEMORY_CELL IO_AI_VISIB = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 388, 4); internal static MEMORY_CELL IO_AO_FORCE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 524, 4); internal static MEMORY_CELL IO_AO_VAL_ACT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 196, 64); internal static MEMORY_CELL IO_AO_VAL_FOR = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 528, 64); internal static MEMORY_CELL IO_AO_VISIB = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 392, 4); internal static MEMORY_CELL IO_COMMW_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 2, 2); internal static MEMORY_CELL IO_DI_VAL_ACT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 4, 64); internal static MEMORY_CELL IO_DI_VISIB = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 260, 64); internal static MEMORY_CELL IO_DO_FORCE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 396, 64); internal static MEMORY_CELL IO_DO_VAL_ACT = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 68, 64); internal static MEMORY_CELL IO_DO_VAL_FOR = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 460, 64); internal static MEMORY_CELL IO_DO_VISIB = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 324, 64); // gestione canali IO internal static MEMORY_CELL IO_STATW_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 628, 0, 2); internal static MEMORY_CELL KEYBOARD_STAR_MEMORY = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6780, 2); internal static MEMORY_CELL LOG_CYCLE_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 617, 12, 1000); 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 M156_INPUT_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6770, 1); internal static MEMORY_CELL M156_INPUT_ID_LIST = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6774, 2); internal static MEMORY_CELL M156_INPUT_NEEDED = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6768, 1); //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 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_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6772, 1); //internal static MEMORY_CELL HEADS_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2692, 240); internal static MEMORY_CELL M156_RESPONSE_MEMORY = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6776, 4); // generic machine gauge data internal static MEMORY_CELL MACHINE_GAUGE_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 605, 6, 16); internal static MEMORY_CELL MACHINE_RESET_WORKED_TIME = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 98, 4); internal static MEMORY_CELL MACHINE_WORKED_TIME = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 255, 94, 4); internal static MEMORY_CELL MAGAZINE_ACTION = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 4000, 16); // 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); 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 NC_SOFTKEYS_CLICKABLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2614, 4); internal static MEMORY_CELL NC_SOFTKEYS_VALUE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2610, 4); // watchdog internal static MEMORY_CELL NC_WATCHDOG = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 1); internal static MEMORY_CELL NEW_MATR_MACC = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 604, 6720, 4); // aree Parametri internal static MEMORY_CELL PARAMETER_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 600, 20, 8000); // recipe edit confirmation/cancel strobe/ack internal static MEMORY_CELL PARAMETER_EDIT_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 2); internal static MEMORY_CELL PARAMETER_EDIT_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2, 2); internal static MEMORY_CELL PARAMETER_RT_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 601, 8, 3200); internal static MEMORY_CELL PRE_POST_POWER_ON = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6542, 4); // C) STD MEM (need check!) FIXME TODO 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 PROCESS_PROD_CYCLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 605, 0, 22); // produzione internal static MEMORY_CELL PROCESS_PROD_INFO = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 606, 0, 52); internal static MEMORY_CELL PROCESS_STATUS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 605, 0, 2); // Prod strobe/ack internal static MEMORY_CELL PROD_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 2); internal static MEMORY_CELL PROD_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2, 2); internal static MEMORY_CELL REQ_CONF_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2, 2); // strobe received from PLC internal static MEMORY_CELL REQ_CONF_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 2); // Mode request strobe/ack internal static MEMORY_CELL REQ_MODE_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 2); internal static MEMORY_CELL REQ_MODE_STROBE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2, 2); internal static MEMORY_CELL RISC_CFI_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 2176, 1024); // riscaldi internal static MEMORY_CELL RISC_CHP_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 614, 0, 1024); internal static MEMORY_CELL RISC_ESP_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 9728, 1024); internal static MEMORY_CELL RISC_ICH_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 11776, 4096); internal static MEMORY_CELL RISC_ICH_MIN_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 3200, 4096); internal static MEMORY_CELL RISC_OCC_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 64, 64); internal static MEMORY_CELL RISC_OCS_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 9472, 64); internal static MEMORY_CELL RISC_OVP_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 10752, 1024); internal static MEMORY_CELL RISC_PLC_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 627, 0, 1024); internal static MEMORY_CELL RISC_VU_MIN = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 513, 0, 2); internal static MEMORY_CELL SELECT_AXIS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2627, 1); internal static MEMORY_CELL SELECT_PROCESS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2606, 1); internal static MEMORY_CELL SELECTED_AXIS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2626, 1); internal static MEMORY_CELL SELECTED_PROCESS = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2582, 24); internal static MEMORY_CELL SER_NUM_PLC = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 604, 6746, 22); // Machine data internal static MEMORY_CELL STATIC_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 604, 6720, 48); // status/command data internal static MEMORY_CELL STATUS_CMD_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 0, 4); internal static MEMORY_CELL TCAM_CH_ENAB_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 626, 4, 128); internal static MEMORY_CELL TCAM_COMMW_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 626, 2, 2); //internal static MEMORY_CELL RISC_PLC_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 514, 128, 1024); //valore PRE thermoCam // ThermoCamera internal static MEMORY_CELL TCAM_STATW_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 626, 0, 2); internal static MEMORY_CELL TCAM_TEMP_ACT_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 625, 0, 2048); internal static MEMORY_CELL TCAM_TEMP_REQ_DATA = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 624, 0, 2048); internal static MEMORY_CELL USER_SOFT_KEYS_ACK = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6584, 16); internal static MEMORY_CELL USER_SOFT_KEYS_CLICKED = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6600, 16); internal static MEMORY_CELL USER_SOFTKEYS_CLICKABLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6568, 16); internal static MEMORY_CELL USER_SOFTKEYS_VALUE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 6552, 16); internal static MEMORY_CELL VERS_SW_PLC = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, 604, 6724, 22); #endregion Internal Fields //internal static MEMORY_CELL PRE_POST_POWER_ON_CLICKABLE = new MEMORY_CELL(MEMORY_TYPE.Siemens_DB, TABLE, 2576, 2); } public class Nc_S7Net : NcThermo { // Global Constants #region Private Fields private const string NcNotFound = "Missing response"; private const string NcNotFound2 = "networking error"; private const string NcNotFound3 = "Nc not Connected"; private const string THERMO_DICT_PATH = @"Dict\"; /// /// Lock per connessione PLC /// private readonly static object connectLock = new object(); private static string Cms_MachNumber; private static string Cnc_name; private static string Cnc_SeriesNum; private static string Cnc_SftVersion; private static uint ConfChannelNo; // Global Variables private static DateTime Last_Static_Read; private static string PlcFirmware_SerialNum; // Alarms data private static Dictionary PlcMessages = new Dictionary(); private static ushort SelectedProcess = 1; private static ThermoModels.ThermoCam ThermoCamData = new ThermoModels.ThermoCam(); private static ThermoModels.ChanIOFor ThermoIOFor = new ThermoModels.ChanIOFor(); private static ThermoModels.ChanIOVal ThermoIOVal = new ThermoModels.ChanIOVal(); private static ThermoModels.ChanIOValFor ThermoIOValFor = new ThermoModels.ChanIOValFor(); private static ThermoModels.ChanIOVis ThermoIOVis = new ThermoModels.ChanIOVis(); private static Dictionary ThermoModuleList = new Dictionary(); // Dizionario parametri specifici per THERMO private static Dictionary ThermoParamList = new Dictionary(); private static ThermoModels.ProdCycleModel ThermoProdCycle = new ThermoModels.ProdCycleModel(); private static ThermoModels.ProdInfoModel ThermoProdInfo = new ThermoModels.ProdInfoModel(); private static Dictionary ThermoWarmChannels = new Dictionary(); private static string UnitOfMeasure; private bool EnableAlarms; private bool EnableAxes; private bool EnableHeaters; private bool EnableModules; private bool EnableParameters; private bool EnableProd; private short rack = 0; private byte S7Language; private short slot = 1; // connessione S7 private CpuType tipoCpu = CpuType.S71500; #endregion Private Fields #region Protected Fields /// /// Oggetto PLC da ri-utilizzare... /// protected Plc currPLC; #endregion Protected Fields /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region Public Constructors /// ///Instantiate The NC-S7Net Class /// /// Remote Ip-Address of the Nc /// Remote Port of the Nc ///Send/Recieve timeout connection [mS] public Nc_S7Net(string IpAddress, ushort RemotePort, ushort ConnectionTimeOut) { initObjects(IpAddress, RemotePort, false, true, true, true, true, true); } /// /// Instantiate The NC-Siemens Class /// /// Remote Ip-Address of the Nc /// Remote Port of the Nc /// Send/Recieve timeout connection [mS] /// Enable Axes Svc /// Enable Alarms Svc /// Enable Heaters Svc /// Enable Modules Svc /// Enable Parameters Svc /// Enable Prod Svc public Nc_S7Net(string IpAddress, ushort RemotePort, ushort ConnectionTimeOut, bool EnableAxes, bool EnableAlarms, bool EnableHeaters, bool EnableModules, bool EnableParameters, bool EnableProd) { initObjects(IpAddress, RemotePort, EnableAxes, EnableAlarms, EnableHeaters, EnableModules, EnableParameters, EnableProd); } #endregion Public Constructors #region Private Methods private Dictionary AXES_RAxesPos(ushort channel, string positionType) { Dictionary axes = new Dictionary(); return axes; } private List ChangeIntListEndianess(List bigEndianvalues) { List littleEndianValues = new List(); foreach (int value in bigEndianvalues) { var a = SwapIntEndianFormat(value); littleEndianValues.Add(a); } return littleEndianValues; } private List ChangeUShortListEndianess(List bigEndianvalues) { List littleEndianValues = new List(); foreach (ushort value in bigEndianvalues) { var a = SwapShortEndianFormat(value); littleEndianValues.Add(a); } return littleEndianValues; } //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 NC is connected private CmsError CheckConnection() { if (!NC_IsConnected()) return NOT_CONNECTED_ERROR; return NO_ERROR; } /// /// Check if PLC is responding to Ping /// /// private CmsError CheckS7Ping() { // faccio ping... if (testPing() != IPStatus.Success) return PLC_IP_NOT_FOUND_ERROR; return NO_ERROR; } // 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; } } 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 ""; } } //Convert to Step Language private string ConvertToNCLanguage(CultureInfo language) { return language.ThreeLetterISOLanguageName; } //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"); } } //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; } private string FormatPath(string path) { path = path.TrimStart('\\'); path = path.TrimStart('/'); path = path.TrimEnd('\\'); return path.Replace('\\', '/'); } // Create and return CmsError object private CmsError GetError(string message) { return CmsError.NcError(message); } private IEnumerable GetLinesFromString(string text) { string line; using (StringReader reader = new StringReader(text)) { while ((line = reader.ReadLine()) != null) { yield return line; } } } // 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; } /// /// /Inizializzazione effettiva parametri classe /// /// /// /// /// /// /// /// /// private void initObjects(string IpAddress, ushort RemotePort, 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 parametri Ip = IpAddress; Port = RemotePort; // mesasggi generici PLC PlcMessages = new Dictionary(); // Init dati specifici Thermo } //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); } } private void NcLanguageChanged(string language) { } private CmsError PLC_ManageActiveAck(int strobeByte, int strobeSubByte, int strobeBit, int ackByte, int ackSubByte, int ackBit, MEMORY_TYPE memType, bool fixEndian) { int n = 1200; // 30 seconds bool readValue = false; bool writeValue = true; bool ok = false; // Set ack to 1 CmsError libraryError = MEM_RWBoolean(W, fixEndian, 0, memType, ackByte, ackSubByte, ackBit, ref writeValue); if (libraryError.IsError()) return libraryError; do { // Check strobe libraryError = MEM_RWBoolean(R, fixEndian, 0, memType, strobeByte, strobeSubByte, strobeBit, ref readValue); if (libraryError.IsError()) return libraryError; // If true reset acknowledge if (!readValue) { writeValue = false; // Reset acknowledge libraryError = MEM_RWBoolean(W, fixEndian, 0, memType, ackByte, ackSubByte, ackBit, ref writeValue); if (libraryError.IsError()) return libraryError; // 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; libraryError = MEM_RWBoolean(W, fixEndian, 0, memType, ackByte, ackSubByte, ackBit, ref writeValue); if (libraryError.IsError()) return libraryError; } return libraryError; } private CmsError PLC_RSoftKeys(MEMORY_CELL softKeyStatusMemory, MEMORY_CELL softKeysClickableMemory, ref List softKeys) { softKeys = new List(); List readValues = new List(); int memorySizeToRead = (softKeyStatusMemory.Size + softKeysClickableMemory.Size); // Offset between status and clickable data int offset = softKeyStatusMemory.Size * 8; // Read on data from memory CmsError libraryError = MEM_RWIntegerList(R, 0, softKeyStatusMemory.MemType, softKeyStatusMemory.Address, softKeyStatusMemory.SubAddress, memorySizeToRead / 4, ref readValues); if (libraryError.IsError()) return libraryError; // need byte swap! List fixValues = new List(); foreach (var item in readValues) { fixValues.Add(SwapBytes(item)); } // Convert ints into an array of bools bool[] bits = IntToBits(fixValues.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; } /// /// Write ack for strobe received from PLC /// /// Apply endianness swap (word=yes, bitArray=no) /// /// /// /// private CmsError PLC_WAck(bool fixEndian, MEMORY_CELL ackCell, MEMORY_CELL strobeCell, uint id) { CmsError libraryError; bool readValue = false; bool writeValue = true; SetupAckStrobeAddresses(ackCell.SubAddress, strobeCell.SubAddress, id, out int ackByte, out int strobeByte, out int alarmBitId); // Check Strobe libraryError = MEM_RWBoolean(R, fixEndian, 0, strobeCell.MemType, strobeCell.Address, strobeByte, alarmBitId, ref readValue); if (libraryError.IsError()) return libraryError; // if there's a strobe --> give ack!!! if (readValue) { // abbasso ack se fosse su... libraryError = MEM_RWBoolean(W, fixEndian, 0, ackCell.MemType, ackCell.Address, ackByte, alarmBitId, ref writeValue); if (libraryError.IsError()) return libraryError; // attendo 50ms... Thread.Sleep(50); // Reset wait ack = 1 and reset the strobe libraryError = ResetAck(alarmBitId, strobeByte, ackByte, ackCell.MemType, ackCell.Address, fixEndian); if (libraryError.IsError()) return libraryError; // exit and next round will continue... return NO_ERROR; } return NO_ERROR; } /// /// Write strobe and manage ack from PLC /// /// Apply endianness swap (word=yes, bitArray=no) /// /// /// /// private CmsError PLC_WStrobe(bool fixEndian, MEMORY_CELL ackCell, MEMORY_CELL strobeCell, uint id) { CmsError libraryError; bool readValue = false; bool writeValue = true; SetupAckStrobeAddresses(ackCell.SubAddress, strobeCell.SubAddress, id, out int ackByte, out int strobeByte, out int alarmBitId); // Check Strobe libraryError = MEM_RWBoolean(R, fixEndian, 0, strobeCell.MemType, strobeCell.Address, strobeByte, alarmBitId, ref readValue); if (libraryError.IsError()) return libraryError; // se è true int n = 200; do { // Check Strobe libraryError = MEM_RWBoolean(R, fixEndian, 0, strobeCell.MemType, strobeCell.Address, strobeByte, alarmBitId, ref readValue); Thread.Sleep(20); n--; } while (n > 0 && readValue); // If PLC is true --> reset if (readValue) { bool forceVal = false; libraryError = MEM_RWBoolean(W, fixEndian, 0, strobeCell.MemType, strobeCell.Address, strobeByte, alarmBitId, ref forceVal); } // Check ACK libraryError = MEM_RWBoolean(R, fixEndian, 0, ackCell.MemType, ackCell.Address, ackByte, alarmBitId, ref readValue); if (libraryError.IsError()) return libraryError; // If PLC it's performing another request then return if (readValue) return NO_ERROR; // Write strobe into memory libraryError = MEM_RWBoolean(W, fixEndian, 0, strobeCell.MemType, strobeCell.Address, strobeByte, alarmBitId, ref writeValue); if (libraryError.IsError()) return libraryError; // Reset wait ack = 1 and reset the strobe libraryError = ResetStrobe(alarmBitId, strobeByte, ackByte, ackCell.MemType, ackCell.Address, fixEndian); if (libraryError.IsError()) return libraryError; return NO_ERROR; } 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 CmsError PROC_ReadActiveLine(uint processId, ref string line) { return FUNCTION_NOT_ALLOWED_ERROR; } //Read Static Data private CmsError ReadStaticNCData() { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; #if false // prendo 2° valore(num max valori) numByte = memByteRead[1]; // poi prendo la stringa... string outVal = ""; for (int i = 2; i < numByte + 2; i++) { outVal += Char.ConvertFromUtf32(memByteRead[i]); } #endif // 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 { List currMem = new List(); libraryError = MEM_RWByteList(R, 0, STATIC_DATA.MemType, STATIC_DATA.Address, STATIC_DATA.SubAddress, 0, STATIC_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; if (currMem.Count > 0) { // completare nuove variabili (matricola macchina, seriale PLC, firmware PLC) S7Language = 0; ConfChannelNo = 1; Last_Static_Read = DateTime.Now; Cnc_name = $"{currPLC.CPU}"; // decodifico info! byte[] memByteRead = currMem.Skip(0).Take(4).ToArray(); int numByte = 0; string outVal = ""; for (int i = 0; i < 4; i++) { outVal += Char.ConvertFromUtf32(memByteRead[i]); } Cms_MachNumber = outVal; // matricola macchina, DB604.DBB6720..6723 memByteRead = currMem.Skip(4).Take(22).ToArray(); outVal = ""; numByte = memByteRead[1]; for (int i = 2; i < numByte + 2; i++) { outVal += Char.ConvertFromUtf32(memByteRead[i]); } Cnc_SftVersion = outVal; // versione SW del firmware PLC/CNC | DB604.DBB6724..6745 memByteRead = currMem.Skip(26).Take(18).ToArray(); outVal = ""; numByte = memByteRead[1]; for (int i = 2; i < numByte + 2; i++) { outVal += Char.ConvertFromUtf32(memByteRead[i]); } Cnc_SeriesNum = outVal; // seriale PLC/CNC | DB604.DBB6746..6763 memByteRead = currMem.Skip(44).Take(4).ToArray(); outVal = ""; outVal += Char.ConvertFromUtf32(memByteRead[0]); for (int i = 1; i < 4; i++) { outVal += $"{memByteRead[i]}"; } PlcFirmware_SerialNum = outVal; // seriale PLC/CNC | DB604.DBB6764..6767 UnitOfMeasure = MILLIMETERS; } } catch (Exception ex) { return ManageException(ex); } } return NO_ERROR; } /// /// Refresh Canali Riscaldi: actual current PLC /// private void refreshRiscActCurr() { // leggo DB514 x area Ich List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, RISC_ICH_DATA.MemType, RISC_ICH_DATA.Address, RISC_ICH_DATA.SubAddress, 0, RISC_ICH_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); double currVal = 0; for (int i = 0; i < RISC_ICH_DATA.Size / 4; i++) { currVal = S7.Net.Types.Double.FromByteArray(memArray.Skip(4 * i).Take(4).ToArray()); // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { ThermoWarmChannels[i + 1].CurrAct = currVal; } else { try { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, CurrAct = currVal }); } catch { } } } } } /// /// Refresh Canali Riscaldi: Percentuale lavoro Attuale /// private void refreshRiscPerc() { // leggo DB514 x area OVp List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, RISC_OVP_DATA.MemType, RISC_OVP_DATA.Address, RISC_OVP_DATA.SubAddress, 0, RISC_OVP_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < RISC_OVP_DATA.Size; i++) { // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { ThermoWarmChannels[i + 1].PercAct = memArray[i]; } else { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, PercAct = memArray[i] }); } } } } /// /// Refresh Canali Riscaldi: SetPoint HMI /// private void refreshRiscSetpointHMI() { // leggo DB614 x area Ich List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, RISC_CHP_DATA.MemType, RISC_CHP_DATA.Address, RISC_CHP_DATA.SubAddress, 0, RISC_CHP_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < RISC_CHP_DATA.Size; i++) { // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { try { ThermoWarmChannels[i + 1].SetpointHMI = memArray[i]; } catch { } } else { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, SetpointHMI = memArray[i] }); } } } else { libraryError = S7_PLC_EMPTY_READ; } } /// /// Refresh Canali Riscaldi: SetPoint PLC (% lavoro applicata ATTUALE dal PLC) /// private void refreshRiscSetpointPLC() { // leggo area DB627 (era DB514) x area CHp List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, RISC_PLC_DATA.MemType, RISC_PLC_DATA.Address, RISC_PLC_DATA.SubAddress, 0, RISC_PLC_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < RISC_PLC_DATA.Size; i++) { // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { ThermoWarmChannels[i + 1].SetpointPLC = memArray[i]; } else { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, SetpointPLC = memArray[i] }); } } } } /// /// Refresh Canali Riscaldi: Status /// private void refreshRiscStatus() { // leggo DB514 x area ESP List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, RISC_ESP_DATA.MemType, RISC_ESP_DATA.Address, RISC_ESP_DATA.SubAddress, 0, RISC_ESP_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < RISC_ESP_DATA.Size; i++) { // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { ThermoWarmChannels[i + 1].ChStatus = memArray[i]; } else { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, ChStatus = memArray[i] }); } } } } /// /// Refresh dati ThermoCamera dal PLC x area command/status /// private void refreshRiscTermoCamCommStatus() { #if false // leggo DB614 x area Ich List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, RISC_CHP_DATA.MemType, RISC_CHP_DATA.Address, RISC_CHP_DATA.SubAddress, 0, RISC_CHP_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < RISC_CHP_DATA.Size; i++) { // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { try { ThermoWarmChannels[i + 1].SetpointHMI = memArray[i]; } catch { } } else { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, SetpointHMI = memArray[i] }); } } } else { libraryError = S7_PLC_EMPTY_READ; } #endif } /// /// Refresh dati ThermoCamera dal PLC x area command/status /// private void refreshRiscTermoCamEnab() { // leggo DB664 x abilitazione ch alla termocamera List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, TCAM_CH_ENAB_DATA.MemType, TCAM_CH_ENAB_DATA.Address, TCAM_CH_ENAB_DATA.SubAddress, 0, TCAM_CH_ENAB_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { bool[] bits = new bool[TCAM_CH_ENAB_DATA.Size * 8]; // Convert int into to true/false array var bArray = new BitArray(currMem.ToArray()); bArray.CopyTo(bits, 0); for (int i = 0; i < TCAM_CH_ENAB_DATA.Size * 8; i++) { // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { try { ThermoWarmChannels[i + 1].TCamActive = bits[i]; } catch { } } else { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, TCamActive = bits[i] }); } } } else { libraryError = S7_PLC_EMPTY_READ; } } /// /// Refresh dati ThermoCamera dal PLC: ultima temp letta /// private void refreshRiscTermoCamTempAct() { // leggo DB625 x Temp attuale List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWShortList(R, 0, TCAM_TEMP_ACT_DATA.MemType, TCAM_TEMP_ACT_DATA.Address, TCAM_TEMP_ACT_DATA.SubAddress, TCAM_TEMP_ACT_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { for (int i = 0; i < TCAM_TEMP_ACT_DATA.Size / 2; i++) { // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { try { ThermoWarmChannels[i + 1].TCamTempActual = currMem[i]; } catch { } } else { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, TCamTempActual = currMem[i] }); } } } else { libraryError = S7_PLC_EMPTY_READ; } } /// /// Refresh dati ThermoCamera dal PLC: temperatura impostata come riferimento /// private void refreshRiscTermoCamTempSet() { // leggo DB624 x Setpoint Temp richiesti List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWShortList(R, 0, TCAM_TEMP_REQ_DATA.MemType, TCAM_TEMP_REQ_DATA.Address, TCAM_TEMP_REQ_DATA.SubAddress, TCAM_TEMP_REQ_DATA.Size, ref currMem); // copio! controllo SE ho dati... if (currMem.Count > 0) { for (int i = 0; i < TCAM_TEMP_REQ_DATA.Size / 2; i++) { // cerco id + 1 (su memoria è base 0) if (ThermoWarmChannels.ContainsKey(i + 1)) { try { ThermoWarmChannels[i + 1].TCamTempSet = currMem[i]; } catch { } } else { ThermoWarmChannels.Add(i + 1, new ThermoModels.WarmerChannel() { IdChannel = i + 1, TCamTempSet = currMem[i] }); } } } else { libraryError = S7_PLC_EMPTY_READ; } } private CmsError ResetAck(int bitId, int strobeByte, int ackByte, MEMORY_TYPE memType, int address, bool fixEndian) { int n = 600; bool readValue = false; bool writeValue = false; bool ok = false; // aspetto 100ms Thread.Sleep(100); CmsError libraryError; do { // Check Strobe libraryError = MEM_RWBoolean(R, fixEndian, 0, memType, address, strobeByte, bitId, ref readValue); if (libraryError.IsError()) return libraryError; // If false reset ACK if (readValue == false) { // Reset strobe libraryError = MEM_RWBoolean(W, fixEndian, 0, memType, address, ackByte, bitId, ref writeValue); if (libraryError.IsError()) return libraryError; // Exit from cycle n = 0; ok = true; } else { // Decrement n--; // Wait befor next cycle Thread.Sleep(20); } } while (n > 0); if (!ok) { // Reset ack (forced) writeValue = false; libraryError = MEM_RWBoolean(W, fixEndian, 0, memType, address, ackByte, bitId, ref writeValue); if (libraryError.IsError()) return libraryError; } return libraryError; } private CmsError ResetStrobe(int bitId, int strobeByte, int ackByte, MEMORY_TYPE memType, int address, bool fixEndian) { int n = 200; bool readValue = false; bool writeValue = false; bool ok = false; CmsError libraryError; do { // Check ACK libraryError = MEM_RWBoolean(R, fixEndian, 0, memType, address, ackByte, bitId, ref readValue); if (libraryError.IsError()) return libraryError; // If true reset strobe if (readValue == true) { // Reset strobe libraryError = MEM_RWBoolean(W, fixEndian, 0, memType, address, strobeByte, bitId, ref writeValue); if (libraryError.IsError()) return libraryError; // Exit from cycle n = 0; ok = true; } else { // Decrement n--; // Wait befor next cycle Thread.Sleep(20); } } while (n > 0); if (!ok) { writeValue = false; // Reset strobe libraryError = MEM_RWBoolean(W, fixEndian, 0, memType, address, strobeByte, bitId, ref writeValue); if (libraryError.IsError()) return libraryError; } return libraryError; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private int SetBitValue(int intVal, bool val, int bitIndex) { if (val) return intVal | (1 << (bitIndex - 1)); else return intVal & ~(1 << (bitIndex - 1)); } /// /// Setup memory for ack/strobe processing /// /// base addr for ack zone /// base addr for strobe zone /// parameters to set (id 1...n) /// ack byte to use (OUT) /// strobe byte to use (out) /// bit 1..8 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 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); } /// /// Ping test to configured Ip address /// /// private IPStatus testPing() { IPStatus answ = IPStatus.Unknown; ; IPAddress address; PingReply reply; Ping pingSender = new Ping(); address = IPAddress.Loopback; IPAddress.TryParse(this.Ip, out address); reply = pingSender.Send(address, 100); answ = reply.Status; return answ; } #endregion Private Methods #region Protected Methods /// /// Refresh recipe parameters /// protected CmsError refreshChIOForced() { CmsError libraryError = NO_ERROR; List readValuesDO = new List(); List readValuesAO = new List(); // leggo da PLC a array di byte di appoggio x visibilità DO... libraryError = MEM_RWWordList(R, 0, IO_DO_FORCE.MemType, IO_DO_FORCE.Address, IO_DO_FORCE.SubAddress, IO_DO_FORCE.Size, ref readValuesDO); if (libraryError.IsError()) return libraryError; // leggo da PLC a array di byte di appoggio x visibilità AO... libraryError = MEM_RWWordList(R, 0, IO_AO_FORCE.MemType, IO_AO_FORCE.Address, IO_AO_FORCE.SubAddress, IO_AO_FORCE.Size, ref readValuesAO); if (libraryError.IsError()) return libraryError; ThermoIOFor.DO = convToDictIntBol(readValuesDO); ThermoIOFor.AO = convToDictIntBol(readValuesAO); return libraryError; } /// /// Refresh recipe parameters /// protected CmsError refreshChIOForcedVal() { CmsError libraryError = NO_ERROR; List readValuesDO = new List(); List readValuesAO = new List(); // leggo da PLC valori DO... libraryError = MEM_RWWordList(R, 0, IO_DO_VAL_FOR.MemType, IO_DO_VAL_FOR.Address, IO_DO_VAL_FOR.SubAddress, IO_DO_VAL_FOR.Size, ref readValuesDO); if (libraryError.IsError()) return libraryError; // leggo da PLC valori AO... libraryError = MEM_RWShortList(R, 0, IO_AO_VAL_FOR.MemType, IO_AO_VAL_FOR.Address, IO_AO_VAL_FOR.SubAddress, IO_AO_VAL_FOR.Size, ref readValuesAO); if (libraryError.IsError()) return libraryError; ThermoIOValFor.DO = convToDictIntBol(readValuesDO); ThermoIOValFor.AO = convToDictIntInt(readValuesAO); return libraryError; } /// /// Refresh IO channels actual value /// /// protected CmsError refreshChIOVal() { CmsError libraryError = NO_ERROR; List readValuesDI = new List(); List readValuesDO = new List(); List readValuesAI = new List(); List readValuesAO = new List(); // leggo da PLC a array di byte di appoggio x visibilità DI... libraryError = MEM_RWWordList(R, 0, IO_DI_VAL_ACT.MemType, IO_DI_VAL_ACT.Address, IO_DI_VAL_ACT.SubAddress, IO_DI_VAL_ACT.Size, ref readValuesDI); if (libraryError.IsError()) return libraryError; // leggo da PLC a array di byte di appoggio x visibilità DO... libraryError = MEM_RWWordList(R, 0, IO_DO_VAL_ACT.MemType, IO_DO_VAL_ACT.Address, IO_DO_VAL_ACT.SubAddress, IO_DO_VAL_ACT.Size, ref readValuesDO); if (libraryError.IsError()) return libraryError; // leggo da PLC a array di byte di appoggio x visibilità AI... libraryError = MEM_RWShortList(R, 0, IO_AI_VAL_ACT.MemType, IO_AI_VAL_ACT.Address, IO_AI_VAL_ACT.SubAddress, IO_AI_VAL_ACT.Size, ref readValuesAI); if (libraryError.IsError()) return libraryError; // leggo da PLC a array di byte di appoggio x visibilità AO... libraryError = MEM_RWShortList(R, 0, IO_AO_VAL_ACT.MemType, IO_AO_VAL_ACT.Address, IO_AO_VAL_ACT.SubAddress, IO_AO_VAL_ACT.Size, ref readValuesAO); if (libraryError.IsError()) return libraryError; ThermoIOVal.DI = convToDictIntBol(readValuesDI); ThermoIOVal.DO = convToDictIntBol(readValuesDO); ThermoIOVal.AI = convToDictIntInt(readValuesAI); ThermoIOVal.AO = convToDictIntInt(readValuesAO); return libraryError; } /// /// Refresh recipe parameters /// protected CmsError refreshChIOVisib() { CmsError libraryError = NO_ERROR; List readValuesDI = new List(); List readValuesDO = new List(); List readValuesAI = new List(); List readValuesAO = new List(); // leggo da PLC a array di byte di appoggio x visibilità DI... libraryError = MEM_RWWordList(R, 0, IO_DI_VISIB.MemType, IO_DI_VISIB.Address, IO_DI_VISIB.SubAddress, IO_DI_VISIB.Size, ref readValuesDI); if (libraryError.IsError()) return libraryError; // leggo da PLC a array di byte di appoggio x visibilità DO... libraryError = MEM_RWWordList(R, 0, IO_DO_VISIB.MemType, IO_DO_VISIB.Address, IO_DO_VISIB.SubAddress, IO_DO_VISIB.Size, ref readValuesDO); if (libraryError.IsError()) return libraryError; // leggo da PLC a array di byte di appoggio x visibilità AI... libraryError = MEM_RWWordList(R, 0, IO_AI_VISIB.MemType, IO_AI_VISIB.Address, IO_AI_VISIB.SubAddress, IO_AI_VISIB.Size, ref readValuesAI); if (libraryError.IsError()) return libraryError; // leggo da PLC a array di byte di appoggio x visibilità AO... libraryError = MEM_RWWordList(R, 0, IO_AO_VISIB.MemType, IO_AO_VISIB.Address, IO_AO_VISIB.SubAddress, IO_AO_VISIB.Size, ref readValuesAO); if (libraryError.IsError()) return libraryError; ThermoIOVis.DI = convToDictIntBol(readValuesDI); ThermoIOVis.DO = convToDictIntBol(readValuesDO); ThermoIOVis.AI = convToDictIntBol(readValuesAI); ThermoIOVis.AO = convToDictIntBol(readValuesAO); return libraryError; } /// /// Refresh ModuleBlock /// protected void refreshMemModBlockParameter() { List currMem = new List(); int packSize = 18; // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, MODULE_DATA.MemType, MODULE_DATA.Address, MODULE_DATA.SubAddress, 0, MODULE_DATA.Size, ref currMem); // controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < MODULE_DATA.Size / packSize; i++) { PlcModBlock currModBlock = new PlcModBlock(memArray.Skip(i * packSize).Take(packSize).ToArray()); // calcolo lista PrecId List PrecId = new List(); PrecId.Add(currModBlock.PrevId_01); PrecId.Add(currModBlock.PrevId_02); PrecId.Add(currModBlock.PrevId_03); // solo se ID > 0... if (currModBlock.Id > 0) { // update oggetto thermoParamList... if (ThermoModuleList.ContainsKey(currModBlock.Id)) { ThermoModuleList[currModBlock.Id].EstimatedDelay = currModBlock.EstimDelay; ThermoModuleList[currModBlock.Id].EstimatedDuration = currModBlock.EstimDuration; ThermoModuleList[currModBlock.Id].PrecedingId = PrecId; } else { ThermoModuleList.Add(currModBlock.Id, new ThermoModels.ModuleBlock() { Id = currModBlock.Id, EstimatedDelay = currModBlock.EstimDelay, EstimatedDuration = currModBlock.EstimDuration, PrecedingId = PrecId }); } } else { libraryError = S7_PLC_WRONG_DATA; } } } else { libraryError = S7_PLC_EMPTY_READ; } } /// /// Refresh ModuleBlock RT /// protected void refreshMemModBlockParameterRT() { List currMem = new List(); int packSize = 12; // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWByteList(R, 0, MODULE_RT_DATA.MemType, MODULE_RT_DATA.Address, MODULE_RT_DATA.SubAddress, 0, MODULE_RT_DATA.Size, ref currMem); // controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < MODULE_RT_DATA.Size / packSize; i++) { PlcModBlockRT currModBlock = new PlcModBlockRT(memArray.Skip(i * packSize).Take(packSize).ToArray()); // solo se ID > 0... if (currModBlock.Id > 0) { // update oggetto thermoParamList... if (ThermoModuleList.ContainsKey(currModBlock.Id)) { try { ThermoModuleList[currModBlock.Id].Visible = currModBlock.Visible; ThermoModuleList[currModBlock.Id].Running = currModBlock.Running; ThermoModuleList[currModBlock.Id].HasError = currModBlock.HasError; ThermoModuleList[currModBlock.Id].Terminated = currModBlock.Terminated; ThermoModuleList[currModBlock.Id].ActualDuration = currModBlock.ActualDuration; ThermoModuleList[currModBlock.Id].ActualDelay = currModBlock.ActualDelay; } catch { } } else { try { ThermoModuleList.Add(currModBlock.Id, new ThermoModels.ModuleBlock() { Id = currModBlock.Id, ActualDuration = currModBlock.ActualDuration, ActualDelay = currModBlock.ActualDelay, Visible = currModBlock.Visible, Running = currModBlock.Running, HasError = currModBlock.HasError, Terminated = currModBlock.Terminated }); } catch { } } } else { libraryError = S7_PLC_WRONG_DATA; } } } else { libraryError = S7_PLC_EMPTY_READ; } } /// /// Refresh recipe parameters /// protected CmsError refreshMemRecipeParameter() { CmsError libraryError = NO_ERROR; List currMem = new List(); int packSize = 20; // leggo da PLC a array di byte di appoggio... libraryError = MEM_RWByteList(R, 0, PARAMETER_DATA.MemType, PARAMETER_DATA.Address, PARAMETER_DATA.SubAddress, 0, PARAMETER_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; // controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < PARAMETER_DATA.Size / packSize; i++) { PlcParam currParam = new PlcParam(memArray.Skip(i * packSize).Take(packSize).ToArray()); // solo se ID > 0... if (currParam.Id > 0) { // update oggetto thermoParamList... if (ThermoParamList.ContainsKey(currParam.Id)) { try { ThermoParamList[currParam.Id].SetpointHMI = currParam.SetpointHMI; ThermoParamList[currParam.Id].SetpointPLC = currParam.SetpointPLC; ThermoParamList[currParam.Id].ValMax = currParam.ValMax; ThermoParamList[currParam.Id].ValMin = currParam.ValMin; ThermoParamList[currParam.Id].UnitMeasure = currParam.UnitMeasure; } catch { } } else { try { ThermoParamList.Add(currParam.Id, new ThermoModels.RecipeParam() { Id = currParam.Id, SetpointHMI = currParam.SetpointHMI, SetpointPLC = currParam.SetpointPLC, ValMax = currParam.ValMax, ValMin = currParam.ValMin, UnitMeasure = currParam.UnitMeasure }); } catch { } } } else { libraryError = S7_PLC_WRONG_DATA; } } } else { libraryError = S7_PLC_EMPTY_READ; } return libraryError; } /// /// Refresh recipE parameters RT /// protected CmsError refreshMemRecipeParameterRT() { CmsError libraryError = NO_ERROR; List currMem = new List(); int packSize = 8; // leggo da PLC a array di byte di appoggio... libraryError = MEM_RWByteList(R, 0, PARAMETER_RT_DATA.MemType, PARAMETER_RT_DATA.Address, PARAMETER_RT_DATA.SubAddress, 0, PARAMETER_RT_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; // controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di 8 byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < PARAMETER_RT_DATA.Size / packSize; i++) { PlcParamRT currParam = new PlcParamRT(memArray.Skip(i * packSize).Take(packSize).ToArray()); // solo se ID > 0... if (currParam.Id > 0) { // update oggetto thermoParamList... if (ThermoParamList.ContainsKey(currParam.Id)) { try { ThermoParamList[currParam.Id].Enabled = currParam.Enabled; ThermoParamList[currParam.Id].HasError = currParam.HasError; ThermoParamList[currParam.Id].Visible = currParam.Visible; ThermoParamList[currParam.Id].ValueAct = currParam.ValueAct; } catch { } } else { try { ThermoParamList.Add(currParam.Id, new ThermoModels.RecipeParam() { Id = currParam.Id, Enabled = currParam.Enabled, HasError = currParam.HasError, Visible = currParam.Visible, ValueAct = currParam.ValueAct }); } catch { } } } } } return libraryError; } #endregion Protected Methods #region Public Methods public static byte[] boolsToByteArray(bool[] bits) { // pack (in this case, using the first bool as the lsb - if you want // the first bool as the msb, reverse things ;-p) int bytes = bits.Length / 8; if ((bits.Length % 8) != 0) bytes++; byte[] answ = new byte[bytes]; int bitIndex = 0, byteIndex = 0; for (int i = 0; i < bits.Length; i++) { if (bits[i]) { answ[byteIndex] |= (byte)(((byte)1) << bitIndex); } bitIndex++; if (bitIndex == 8) { bitIndex = 0; byteIndex++; } } return answ; } public override CmsError AXES_RAxesNames(ushort channel, ref List axesData) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError AXES_RDistanceToGo(ushort channel, ref Dictionary axes) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError AXES_RFollowingError(ushort channel, ref Dictionary axes) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError AXES_RInterpPosition(ushort channel, ref Dictionary axes) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError AXES_RMachinePosition(ushort channel, ref Dictionary axes) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError AXES_ROrigin(int numberOfAxes) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError AXES_RProgrPosition(ushort channel, ref Dictionary axes) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError AXES_RSelectedAxis(ref byte axisId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError AXES_WSelectAxis(byte axisId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_CopyProgram(string partProgramPath, string newPartProgramPath, bool failIfExist) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_DeleteProgram(string partProgramPath, string partProgramName) { return FUNCTION_NOT_ALLOWED_ERROR; } /// /// Load selected recipe, convert and save to PLC memory area /// /// /// /// public CmsError FILES_LoadRecipe(string path, string name) { return NO_ERROR; } public override CmsError FILES_RActiveProgramData(int processId, ref ActiveProgramDataModel programData) { return FUNCTION_NOT_ALLOWED_ERROR; } /// /// Get list of recipe (from local PC area) /// /// /// /// public CmsError FILES_RecipeList(string path, ref List file) { return NO_ERROR; } public override CmsError FILES_RGetFileInfo(string path, ref InfoFile fileInfo) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_RGetFileList(string path, ref List files) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_RGetProgramType(ref PROGRAM_TYPE_ENUM programType) { programType = PROGRAM_TYPE_ENUM.PART_PROGRAM; return NO_ERROR; } public override CmsError FILES_RProgramToFile(string partProgramPath, FileStream localFile) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_RQueueData(ref List statusList) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_RQueueDataByProcess(ref QueueStatusModel status, int processId) { return FUNCTION_NOT_ALLOWED_ERROR; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Save current recipe from PLC memory area to file /// /// /// /// public CmsError FILES_SaveRecipe(string path, string name) { return NO_ERROR; } public override CmsError FILES_UploadPartProgram(string localPath, string name, ref string newFilePath) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WCleanUploadFolder() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WDeactivateProgram(int processId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WLoadNextPartProgram(string localPath, string ncFileName) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WProgramFromFile(string partProgramPath, FileStream localFile) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WSetActiveProgram(int processId, string filePath, ref ActiveProgramDataModel data) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WStartQueue() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WStopQueue() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WUploadCustomMainProgramAndActivate(int processId, string customPartProgramContent, ref ActiveProgramDataModel activeData) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError FILES_WUploadJobFilesAndActivate(int processId, string jobExtractedPath, string fileToActivate) { return FUNCTION_NOT_ALLOWED_ERROR; } //Read-Write a Boolean-Value inside the NC. public override CmsError MEM_RWBoolean(bool bWrite, bool fixEndian, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int MemBit, ref bool Value) { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; //Check if the Bit Number is Correct libraryError = CheckBitRange(MemBit); if (libraryError.IsError()) return libraryError; byte bValue = 0; ushort pow = (ushort)Math.Pow(2, MemBit); //Read the Byte where is the bit libraryError = MEM_RWByte(R, fixEndian, Process, MemType, MemTable, MemIndex, 0, ref bValue); if (libraryError.IsError()) return libraryError; //If i have to Write -> Write the Bit if (bWrite) { if (Value) bValue = (byte)(bValue | (1 << MemBit)); else bValue = (byte)(bValue & ~(1 << MemBit)); libraryError = MEM_RWByte(W, fixEndian, Process, MemType, MemTable, MemIndex, 0, ref bValue); if (libraryError.IsError()) return libraryError; } //If i have to read -> Read the Bit else { Value = (bValue & pow) == pow; } return NO_ERROR; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Read-Write a SINGLE Byte inside the NC. In writing-mode the field "Number" is not required /// /// R/W mode /// fix endianness /// /// /// /// /// /// /// public override CmsError MEM_RWByte(bool bWrite, bool fixEndian, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int MemByte, ref byte Value) { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; if (MemType != MEMORY_TYPE.Siemens_DB) { return INCORRECT_PARAMETERS_ERROR; } libraryError = null; // attenzione endianness! inverte byte se richiesto... int fixIndex = MemIndex; if (fixEndian) { fixIndex = MemIndex % 2 == 0 ? MemIndex + 1 : MemIndex - 1; } // vere operazioni R/W if (bWrite) { // try/catch try { byte[] DB_Byte = new byte[1]; DB_Byte[0] = Value; currPLC.WriteBytes(DataType.DataBlock, MemTable, fixIndex, DB_Byte); } catch { return S7_PLC_WRITE_ERROR_BYTE; } } else { try { var memByteRead = currPLC.ReadBytes(DataType.DataBlock, MemTable, fixIndex, 1); Value = memByteRead[0]; } catch { return S7_PLC_READ_ERROR_BYTE; } } return NO_ERROR; } public override CmsError MEM_RWByteList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int MemByteStart, int Number, ref List Values) { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; if (MemType != MEMORY_TYPE.Siemens_DB) { return INCORRECT_PARAMETERS_ERROR; } libraryError = null; if (bWrite) { //Prevent some exceptions if (Values.Count == 0) return NO_ERROR; // try/catch try { currPLC.WriteBytes(DataType.DataBlock, MemTable, MemIndex, Values.ToArray()); } catch { return S7_PLC_WRITE_ERROR_LST_BYTE; } } else { // Prevent some exceptions if (Number == 0) return NO_ERROR; Values.Clear(); try { byte[] memByteRead = currPLC.ReadBytes(DataType.DataBlock, MemTable, MemIndex, Number); Values = memByteRead.ToList(); } catch { return S7_PLC_READ_ERROR_LST_BYTE; } } return NO_ERROR; } public override CmsError MEM_RWDouble(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref double Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError libraryError = MEM_RWDoubleList(bWrite, Process, MemType, MemTable, MemIndex, 4, ref ListValue); if (libraryError.IsError()) return libraryError; Value = ListValue.First(); return NO_ERROR; } public override CmsError MEM_RWDoubleList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Values) { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; if (MemType != MEMORY_TYPE.Siemens_DB) { return INCORRECT_PARAMETERS_ERROR; } libraryError = null; if (bWrite) { //Prevent some exceptions if (Values.Count == 0) return NO_ERROR; byte[] singleItem = new byte[4]; List memByteList = new List(); foreach (var Item in Values) { singleItem = S7.Net.Types.Double.ToByteArray(Item); memByteList.AddRange(singleItem); } try { currPLC.WriteBytes(DataType.DataBlock, MemTable, MemIndex, memByteList.ToArray()); } catch { return S7_PLC_WRITE_ERROR_LST_DOUBLE; } } else { // Prevent some exceptions if (Number == 0) return NO_ERROR; Values.Clear(); try { byte[] memByteRead = currPLC.ReadBytes(DataType.DataBlock, MemTable, MemIndex, Number); // converto a word! double shortVal = 0; for (int i = 0; i < memByteRead.Length / 4; i++) { shortVal = S7.Net.Types.Double.FromByteArray(memByteRead.Skip(4 * i).Take(4).ToArray()); Values.Add(shortVal); } } catch { return S7_PLC_READ_ERROR_LST_DOUBLE; } } return NO_ERROR; } //Write a Word-Value inside the NC. In writing-mode the field "Number" is not required public override CmsError MEM_RWDWord(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref uint Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError libraryError = MEM_RWDWordList(bWrite, Process, MemType, MemTable, MemIndex, 1, ref ListValue); if (libraryError.IsError()) return libraryError; Value = ListValue.First(); return NO_ERROR; } public override CmsError MEM_RWDWordList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Values) { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; if (MemType != MEMORY_TYPE.Siemens_DB) { return INCORRECT_PARAMETERS_ERROR; } libraryError = null; if (bWrite) { //Prevent some exceptions if (Values.Count == 0) return NO_ERROR; byte[] singleItem = new byte[4]; List memByteList = new List(); foreach (var Item in Values) { singleItem = S7.Net.Types.DWord.ToByteArray(Item); memByteList.AddRange(singleItem); } try { currPLC.WriteBytes(DataType.DataBlock, MemTable, MemIndex, memByteList.ToArray()); } catch { return S7_PLC_WRITE_ERROR_LST_DWORD; } } else { // Prevent some exceptions if (Number == 0) return NO_ERROR; Values.Clear(); try { byte[] memByteRead = currPLC.ReadBytes(DataType.DataBlock, MemTable, MemIndex, Number); // converto a word! uint shortVal = 0; for (int i = 0; i < memByteRead.Length / 4; i++) { shortVal = S7.Net.Types.DWord.FromByteArray(memByteRead.Skip(4 * i).Take(4).ToArray()); Values.Add(shortVal); } } catch { return S7_PLC_READ_ERROR_LST_DWORD; } } return NO_ERROR; } //Write a Int-Value inside the NC. In writing-mode the field "Number" is not required public override CmsError MEM_RWInteger(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref int Value) { List ListValue = new List() { Value }; // uses the List method with one-element list, reading int32 (4byte) data... CmsError libraryError = MEM_RWIntegerList(bWrite, Process, MemType, MemTable, MemIndex, 1, ref ListValue); if (libraryError.IsError()) return libraryError; if (ListValue.Count > 0) { Value = ListValue.First(); } return NO_ERROR; } /// /// Lettura lista di interi /// /// /// /// /// /// /// numero di INT 32 da leggere (byte/4) /// /// public override CmsError MEM_RWIntegerList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Values) { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; if (MemType != MEMORY_TYPE.Siemens_DB) { return INCORRECT_PARAMETERS_ERROR; } libraryError = null; if (bWrite) { //Prevent some exceptions if (Values.Count == 0) return NO_ERROR; byte[] singleItem = new byte[4]; List memByteList = new List(); foreach (var Item in Values) { singleItem = S7.Net.Types.DInt.ToByteArray(Item); memByteList.AddRange(singleItem); } try { currPLC.WriteBytes(DataType.DataBlock, MemTable, MemIndex, memByteList.ToArray()); } catch { return S7_PLC_WRITE_ERROR_LST_INT; } } else { // Prevent some exceptions if (Number == 0) return NO_ERROR; Values.Clear(); byte[] memByteRead = null; try { memByteRead = currPLC.ReadBytes(DataType.DataBlock, MemTable, MemIndex, Number * 4); // converto a word! int intVal = 0; for (int i = 0; i < memByteRead.Length / 4; i++) { intVal = S7.Net.Types.DInt.FromByteArray(memByteRead.Skip(4 * i).Take(4).ToArray()); Values.Add(intVal); } } catch { return S7_PLC_READ_ERROR_LST_INT; } } if (Values.Count == 0) { return NOT_CONNECTED_ERROR; } return NO_ERROR; } public override CmsError MEM_RWShort(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref short Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError libraryError = MEM_RWShortList(bWrite, Process, MemType, MemTable, MemIndex, 1, ref ListValue); if (libraryError.IsError()) return libraryError; Value = ListValue.First(); return NO_ERROR; } public override CmsError MEM_RWShortList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Values) { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; if (MemType != MEMORY_TYPE.Siemens_DB) { return INCORRECT_PARAMETERS_ERROR; } libraryError = null; if (bWrite) { //Prevent some exceptions if (Values.Count == 0) return NO_ERROR; byte[] singleItem = new byte[2]; List memByteList = new List(); foreach (var Item in Values) { singleItem = S7.Net.Types.Int.ToByteArray(Item); memByteList.AddRange(singleItem); } try { currPLC.WriteBytes(DataType.DataBlock, MemTable, MemIndex, memByteList.ToArray()); } catch { return S7_PLC_WRITE_ERROR_LST_SHORT; } } else { // Prevent some exceptions if (Number == 0) return NO_ERROR; Values.Clear(); try { byte[] memByteRead = currPLC.ReadBytes(DataType.DataBlock, MemTable, MemIndex, Number); // converto a word! short shortVal = 0; for (int i = 0; i < memByteRead.Length / 2; i++) { shortVal = S7.Net.Types.Int.FromByteArray(memByteRead.Skip(2 * i).Take(2).ToArray()); Values.Add(shortVal); } } catch { return S7_PLC_READ_ERROR_LST_SHORT; } } return NO_ERROR; } //Write a Word-Value inside the NC. In writing-mode the field "Number" is not required public override CmsError MEM_RWWord(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, ref ushort Value) { List ListValue = new List() { Value }; //uses the List method with one-element list CmsError libraryError = MEM_RWWordList(bWrite, Process, MemType, MemTable, MemIndex, 2, ref ListValue); if (libraryError.IsError()) return libraryError; if (ListValue.Count > 0) Value = ListValue.First(); return NO_ERROR; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override CmsError MEM_RWWordList(bool bWrite, int Process, MEMORY_TYPE MemType, int MemTable, int MemIndex, int Number, ref List Values) { ////Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; if (MemType != MEMORY_TYPE.Siemens_DB) { return INCORRECT_PARAMETERS_ERROR; } libraryError = null; if (bWrite) { //Prevent some exceptions if (Values.Count == 0) return NO_ERROR; byte[] singleItem = new byte[2]; List memByteList = new List(); foreach (var Item in Values) { singleItem = S7.Net.Types.Word.ToByteArray(Item); memByteList.AddRange(singleItem); } try { currPLC.WriteBytes(DataType.DataBlock, MemTable, MemIndex, memByteList.ToArray()); } catch { return S7_PLC_WRITE_ERROR_LST_WORD; } } else { // Prevent some exceptions if (Number == 0) return NO_ERROR; Values.Clear(); byte[] memByteRead; try { memByteRead = currPLC.ReadBytes(DataType.DataBlock, MemTable, MemIndex, Number); // converto a word! ushort shortVal = 0; for (int i = 0; i < memByteRead.Length / 2; i++) { shortVal = S7.Net.Types.Word.FromByteArray(memByteRead.Skip(2 * i).Take(2).ToArray()); Values.Add(shortVal); } } catch { return S7_PLC_READ_ERROR_LST_WORD; } } return NO_ERROR; } /// /// Connessione al PLC /// /// public override CmsError NC_Connect() { lock (connectLock) { // Try to get information try { // Check if Siemens Environment is started CmsError libraryError = CheckS7Ping(); if (libraryError.IsError()) return libraryError; // Check connection currPLC = new Plc(tipoCpu, this.Ip, this.rack, this.slot); currPLC.Open(); if (currPLC.IsConnected) Connected = true; // FARE TODO FIXME // 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 } } catch (Exception ex) { return ManageException(ex); } } return NO_ERROR; } /// /// Disconnect Method /// /// public override CmsError NC_Disconnect() { // Set Connected to FALSE and close the sessions Connected = false; if (currPLC != null) { try { currPLC.Close(); } catch { } } return NO_ERROR; } /// /// Elenco lingue disponibili /// /// /// public override CmsError NC_GetAvailableLanguages(ref ICollection languages) { // FIXME TODO #if false 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); } #endif var lang = GetCultureFromThreeLetter("eng"); if (lang != null) languages.Add(lang); lang = GetCultureFromThreeLetter("ita"); if (lang != null) languages.Add(lang); return NO_ERROR; } /// /// Compilazione dizionario allarmi x lingua /// /// /// /// public override CmsError NC_GetTranslatedPlcMessages(string language, ref Dictionary messages) { string filePath; try { PlcMessages = new Dictionary(); CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture(language); string langName = ""; if (cultureInfo.IsNeutralCulture) langName = cultureInfo.EnglishName; else langName = cultureInfo.Parent.EnglishName; //Setup the Path filePath = THERMO_DICT_PATH + @"Messaggi_" + langName + @".txt"; //Read From Files messages = File.ReadAllLines(filePath, Encoding.Default) .Select(line => line.Split(',')) .Where(line => line.Count() == 2) .ToDictionary(line => Convert.ToInt32(line[0]), line => line[1].Trim()); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } /// /// Compilazione dizionario traduzioni THermo /// /// /// /// public override CmsError NC_GetTranslatedThermoLabels(string language, ref Dictionary messages) { string filePath; Dictionary dict01 = new Dictionary(); Dictionary dict02 = new Dictionary(); try { CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture(language); string langName = ""; if (cultureInfo.IsNeutralCulture) langName = cultureInfo.EnglishName; else langName = cultureInfo.Parent.EnglishName; // Setup the Path for enums filePath = THERMO_DICT_PATH + @"Enums_" + langName + @".txt"; // Read From File... dict01 = File.ReadAllLines(filePath, Encoding.Default) .Select(line => line.Split(',')) .Where(line => line.Count() == 2) .ToDictionary(line => line[0].Trim(), line => line[1].Trim()); // Setup the Path for labels filePath = THERMO_DICT_PATH + @"Labels_" + langName + @".txt"; // Read From File... dict02 = File.ReadAllLines(filePath, Encoding.Default) .Select(line => line.Split(',')) .Where(line => line.Count() == 2) .ToDictionary(line => line[0].Trim(), line => line[1].Trim()); // combine 2 dictionary... messages = dict01.Union(dict02).ToDictionary(d => d.Key, d => d.Value); } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Get the Nc Active Alarms /// /// /// public override CmsError NC_RActiveAlarms(ref List alarms) { return NO_ERROR; } /// /// Get the Date-Time of the NC /// /// /// public override CmsError NC_RDateTime(ref DateTime ActualTime) { ActualTime = DateTime.Now; 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 libraryError = NC_RProcessesNum(ref nProcess); if (libraryError.IsError()) return libraryError; ushort i = 1; running = false; do { PROC_STATUS procStatus = PROC_STATUS.IDLE; // Read process status libraryError = PROC_RStatus(i, ref procStatus); if (libraryError.IsError()) return libraryError; if (procStatus == PROC_STATUS.RUN) running = true; i++; } while (!running || i <= nProcess); return NO_ERROR; } /// /// Get the NC Language /// /// /// public override CmsError NC_RLanguage(ref CultureInfo Language) { // Read static data CmsError libraryError = ReadStaticNCData(); if (libraryError.IsError()) return libraryError; Language = ConvertToSTEPLanguage(S7Language); return NO_ERROR; } /// /// Get CMS Machine number /// /// /// /// public override CmsError NC_RMachineNumber(bool hasLetters, ref string MachNumber) { if (!hasLetters) { CmsError libraryError = ReadStaticNCData(); if (libraryError.IsError()) return libraryError; MachNumber = Cms_MachNumber; } else { // New method to read machine number List lists = new List(); CmsError libraryError = MEM_RWByteList(R, 0, NEW_MATR_MACC.MemType, NEW_MATR_MACC.Address, NEW_MATR_MACC.SubAddress, 0, 4, ref lists); if (libraryError.IsError()) return libraryError; lists.Reverse(); MachNumber = Encoding.ASCII.GetString(lists.ToArray().Reverse().ToArray()); } return NO_ERROR; } /// /// Get the NC model Name /// /// /// public override CmsError NC_RModelName(ref string ModelName) { CmsError libraryError = ReadStaticNCData(); if (libraryError.IsError()) return libraryError; ModelName = Cnc_name; return NO_ERROR; } 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; } /// /// Get the processes-count configurated /// /// /// public override CmsError NC_RProcessesNum(ref ushort ProcNumber) { CmsError libraryError = ReadStaticNCData(); if (libraryError.IsError()) return libraryError; ProcNumber = (ushort)ConfChannelNo; return NO_ERROR; } /// /// Get the NC Serial number /// /// /// public override CmsError NC_RSerialNumber(ref string serialNumber) { CmsError libraryError = ReadStaticNCData(); if (libraryError.IsError()) return libraryError; serialNumber = Cnc_SeriesNum; return NO_ERROR; } /// /// Get the NC Software Version /// /// /// public override CmsError NC_RSoftwareVersion(ref string SWV) { CmsError libraryError = ReadStaticNCData(); if (libraryError.IsError()) return libraryError; SWV = Cnc_SftVersion; return NO_ERROR; } /// /// Get NC unit of measure /// /// /// public override CmsError NC_RUnitOfMeasure(ref string unitOfMeasure) { CmsError libraryError = ReadStaticNCData(); if (libraryError.IsError()) return libraryError; unitOfMeasure = UnitOfMeasure; return NO_ERROR; } /// /// Set the Nc Active Page of the NC /// /// /// public override CmsError NC_SetScreenVisible(SCREEN_PAGE screen) { return FUNCTION_NOT_ALLOWED_ERROR; } /// /// Set the NC Language /// /// /// public override CmsError NC_WLanguage(CultureInfo Language) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError NC_WMDICommand(int processId, string mdiString) { return FUNCTION_NOT_ALLOWED_ERROR; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override CmsError PLC_RActiveClient(ref int clientId) { CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; byte readValues = 0; libraryError = MEM_RWByte(R, true, 0, ACTIVE_CLIENT.MemType, ACTIVE_CLIENT.Address, ACTIVE_CLIENT.SubAddress, 0, ref readValues); if (libraryError.IsError()) return libraryError; // 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; } /// /// Active message list /// /// /// public override CmsError PLC_RActiveMessages(ref List alarms) { // FIXME TODO controllare bool[] statusBits; int i = 0; List readValues = new List(); List currMem = new List(); CmsError libraryError; try { alarms.Clear(); // Read on data from memory libraryError = MEM_RWIntegerList(R, 0, ALARMS_STATUS.MemType, ALARMS_STATUS.Address, ALARMS_STATUS.SubAddress, (ALARMS_STATUS.Size / 4) + (ALARMS_DATA.Size / 2), // status_bytes / 4 + data_word / 2 ref readValues); if (libraryError.IsError()) return libraryError; // leggo a BYTE libraryError = MEM_RWByteList(R, 0, ALARMS_STATUS.MemType, ALARMS_STATUS.Address, ALARMS_STATUS.SubAddress, 0, (ALARMS_STATUS.Size), // status_bytes ref currMem); if (libraryError.IsError()) return libraryError; alarms.Clear(); // Convert integer array into bit array statusBits = IntToBits(readValues.ToArray()); BitArray bArray = new BitArray(currMem.ToArray()); for (i = 0; i < ALARMS_STATUS.Size * 8; i++) { // If alarm is active if (bArray[i]) { // Calculate matching alarm byte info address int dataByteAddress = (i * 16) + ALARMS_NUMBER; var processList = new List(); // Get processes on which alarm is active for (int j = dataByteAddress; j < dataByteAddress + 6; j++) { if (statusBits[j]) processList.Add(j + 1 - dataByteAddress); } // Add alarm info into active alarms list alarms.Add(new PlcAlarmModel() { Id = (uint)i + 1, IsWarning = statusBits[dataByteAddress + 7], RestorationIsActive = statusBits[dataByteAddress + 6], Process = processList }); } } } catch (Exception ex) { return ManageException(ex); } return NO_ERROR; } public override CmsError PLC_RAssistedToolingData(ref AssistedToolingModel data) { return FUNCTION_NOT_ALLOWED_ERROR; } /// /// Get current Production Info data /// /// /// public override CmsError PLC_RAxesMov(ref ThermoModels.AxisRT currProdInfo) { List currMem = new List(); CmsError libraryError = MEM_RWByteList(R, 0, PROCESS_PROD_INFO.MemType, PROCESS_PROD_INFO.Address, PROCESS_PROD_INFO.SubAddress, 0, PROCESS_PROD_INFO.Size, ref currMem); if (libraryError.IsError()) return libraryError; #if false // converto! currProdInfo = new ThermoModels.ProdInfoModel() { NumTarget = S7.Net.Types.Int.FromByteArray(currMem.Skip(0).Take(2).ToArray()), NumDone = S7.Net.Types.Int.FromByteArray(currMem.Skip(2).Take(2).ToArray()), // cicli preriscaldo? FIXME TODO TimeWarm = S7.Net.Types.DInt.FromByteArray(currMem.Skip(6).Take(4).ToArray()), TimeVent = S7.Net.Types.DInt.FromByteArray(currMem.Skip(10).Take(4).ToArray()), TimeVacuum = S7.Net.Types.DInt.FromByteArray(currMem.Skip(14).Take(4).ToArray()), TimeCycleGross = S7.Net.Types.DInt.FromByteArray(currMem.Skip(18).Take(4).ToArray()), TimeCycleNet = S7.Net.Types.DInt.FromByteArray(currMem.Skip(22).Take(4).ToArray()), MaterialTempEndWarm = S7.Net.Types.Double.FromByteArray(currMem.Skip(26).Take(4).ToArray()), MaterialTempEndVent = S7.Net.Types.Double.FromByteArray(currMem.Skip(30).Take(4).ToArray()), MoldTemp = S7.Net.Types.Double.FromByteArray(currMem.Skip(34).Take(4).ToArray()), VacuumReadVal = S7.Net.Types.Double.FromByteArray(currMem.Skip(38).Take(4).ToArray()), MouldEnergyOUT = S7.Net.Types.Double.FromByteArray(currMem.Skip(42).Take(4).ToArray()), MouldEnergyIN = S7.Net.Types.Double.FromByteArray(currMem.Skip(46).Take(4).ToArray()) }; #endif return NO_ERROR; } public override CmsError PLC_RAxesResetData(ref AxisResetDataModel axisResetData) { byte value = 0; // Read byte from memory CmsError libraryError = MEM_RWByte(R, true, 0, AXIS_RESET_PROCEDURE.MemType, AXIS_RESET_PROCEDURE.Address, AXIS_RESET_PROCEDURE.SubAddress, 0, ref value); if (libraryError.IsError()) return libraryError; // 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; } /// /// Get current Axis Info data /// /// /// public override CmsError PLC_RAxisInfoList(ref Dictionary currAxisInfo) { CmsError libraryError = NO_ERROR; List currMem = new List(); int packSize = 8; // leggo da PLC a array di byte di appoggio... libraryError = MEM_RWByteList(R, 0, AXES_INFO.MemType, AXES_INFO.Address, AXES_INFO.SubAddress, 0, AXES_INFO.Size, ref currMem); if (libraryError.IsError()) return libraryError; // controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < AXES_INFO.Size / packSize; i++) { ThermoModels.AxisInfo currData = new ThermoModels.AxisInfo(i + 1, memArray.Skip(i * packSize).Take(packSize).ToArray()); // solo se ID > 0... if (currData.Id > 0) { // update oggetto thermoParamList... if (currAxisInfo.ContainsKey(currData.Id)) { try { currAxisInfo[currData.Id].ErrorCode = currData.ErrorCode; currAxisInfo[currData.Id].MovPhase = currData.MovPhase; currAxisInfo[currData.Id].StatusWord = currData.StatusWord; } catch { } } else { try { currAxisInfo.Add(currData.Id, currData); } catch { } } } } } return libraryError; } /// /// Get current LOG Cycle data /// /// /// public override CmsError PLC_RLogCycleData(out List currLogCycle) { CmsError libraryError = NO_ERROR; List currMem = new List(); int packSize = 10; currLogCycle = new List(); // leggo da PLC a array di byte di appoggio... libraryError = MEM_RWByteList(R, 0, LOG_CYCLE_DATA.MemType, LOG_CYCLE_DATA.Address, LOG_CYCLE_DATA.SubAddress, 0, LOG_CYCLE_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; // controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < LOG_CYCLE_DATA.Size / packSize; i++) { ThermoModels.LogCycleData currData = new ThermoModels.LogCycleData(memArray.Skip(i * packSize).Take(packSize).ToArray()); // se il valore ricevuto di evento è > 0... if (currData.Code > 0) { try { currLogCycle.Add(currData); } catch { } } } } return libraryError; } /// /// Get current Axis RT data /// /// /// public override CmsError PLC_RAxisRTList(ref Dictionary currAxisRT) { CmsError libraryError = NO_ERROR; List currMem = new List(); int packSize = 12; // leggo da PLC a array di byte di appoggio... libraryError = MEM_RWByteList(R, 0, AXES_RTDATA.MemType, AXES_RTDATA.Address, AXES_RTDATA.SubAddress, 0, AXES_RTDATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; // controllo SE ho dati... if (currMem.Count > 0) { // converto a blocchi di byte... byte[] memArray = currMem.ToArray(); for (int i = 0; i < AXES_RTDATA.Size / packSize; i++) { ThermoModels.AxisRT currData = new ThermoModels.AxisRT(i + 1, memArray.Skip(i * packSize).Take(packSize).ToArray()); // solo se ID > 0... if (currData.Id > 0) { // update oggetto thermoParamList... if (currAxisRT.ContainsKey(currData.Id)) { try { currAxisRT[currData.Id].Position = currData.Position; currAxisRT[currData.Id].Speed = currData.Speed; currAxisRT[currData.Id].Load = currData.Load; } catch { } } else { try { currAxisRT.Add(currData.Id, currData); } catch { } } } } } return libraryError; } public override CmsError PLC_RCandy(ref long value) { // Long is formed by a integer + word // Read word ushort word = 0; CmsError libraryError = MEM_RWWord(R, 0, CANDY_MEM.MemType, CANDY_MEM.Address, CANDY_MEM.SubAddress, ref word); if (libraryError.IsError()) return libraryError; // Read first int uint firtInt = 0; libraryError = MEM_RWDWord(R, 0, CANDY_MEM.MemType, CANDY_MEM.Address, CANDY_MEM.SubAddress + 2, ref firtInt); if (libraryError.IsError()) return libraryError; // Build Long value value = ((long)firtInt << 16) + word; return NO_ERROR; } public override CmsError PLC_RExpiredCandy(ref bool value) { CmsError libraryError = MEM_RWBoolean(R, true, 0, EXP_CANDY_MEM.MemType, EXP_CANDY_MEM.Address, EXP_CANDY_MEM.SubAddress, 5, ref value); if (libraryError.IsError()) return libraryError; return NO_ERROR; } public override CmsError PLC_RFunctionAccess(ref List functions) { List readValues = new List(); int numberOfIntegers = FUNCTION_ACCESS.Size / 4; // Read functions access data from memory CmsError libraryError = MEM_RWIntegerList(R, 0, FUNCTION_ACCESS.MemType, FUNCTION_ACCESS.Address, FUNCTION_ACCESS.SubAddress, numberOfIntegers, ref readValues); if (libraryError.IsError()) return libraryError; functions = new List(); // Convert int into to true/false array bool[] bits = IntToBits(readValues.ToArray()); // Convert array into structured data for (int i = 0; i < bits.Count(); i++) { functions.Add(new FunctionalityModel() { Id = (uint)i + 1, // forzo a true perché non gestita dal PLC IsActive = true //bits[i] }); } return NO_ERROR; } /// /// Get gauge data /// /// /// public override CmsError PLC_RGaugeData(ref ThermoModels.LiveProdDataModel gaugeData) { List Values = new List(); CmsError libraryError = MEM_RWIntegerList(R, 1, MACHINE_GAUGE_DATA.MemType, MACHINE_GAUGE_DATA.Address, MACHINE_GAUGE_DATA.SubAddress, MACHINE_GAUGE_DATA.Size / 4, ref Values); if (libraryError.IsError()) return libraryError; gaugeData = new ThermoModels.LiveProdDataModel() { TimeAdv = Convert.ToUInt32(Values[0]), Power = Values[1], Vacuum = Values[2], Air = Values[3], }; return NO_ERROR; } public override CmsError PLC_RHeadsData(List heads, int number) { return FUNCTION_NOT_ALLOWED_ERROR; } /// /// Read PLC current IO Channels visibility (conf) /// /// Visibility status for all channels /// public override CmsError PLC_RIOChannelsConf(ref ThermoModels.ChanIOVis currThermoIOVis) { CmsError currError = NO_ERROR; // refresh dati refreshChIOVisib(); // copio liste in output... currThermoIOVis = ThermoIOVis; // esco return currError; } /// /// Read PLC current IO Channels VALUES (actual + forced) /// /// Values for channels /// Indicates if values are forced by UI /// Values forced by UI /// public override CmsError PLC_RIOChannelsVal(ref ThermoModels.ChanIOVal currThermoIOVal, ref ThermoModels.ChanIOFor currThermoIOFor, ref ThermoModels.ChanIOValFor currThermoIOValFor) { CmsError currError = NO_ERROR; // refresh dati veloci (valori) refreshChIOVal(); refreshChIOForced(); refreshChIOForcedVal(); // copio liste in output... currThermoIOVal = ThermoIOVal; currThermoIOFor = ThermoIOFor; currThermoIOValFor = ThermoIOValFor; // esco return currError; } public override CmsError PLC_RM154Data(ref List data, ref bool MTCOnOff) { // FIXME TODO - levare? inserito anche endiannes MTCOnOff = false; CmsError libraryError = MEM_RWBoolean(R, true, 0, M154_SWITCH_ONOFF.MemType, M154_SWITCH_ONOFF.Address, M154_SWITCH_ONOFF.SubAddress, 1, ref MTCOnOff); if (libraryError.IsError()) return libraryError; byte val = 0; libraryError = MEM_RWByte(R, true, 0, M154_STROBE.MemType, M154_STROBE.Address, M154_STROBE.SubAddress, 0, ref val); if (libraryError.IsError()) return libraryError; // 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 libraryError = PROC_ReadActiveLine(processId, ref tmpStr); if (libraryError.IsError()) return libraryError; // Parse parameters parameters = ExtractM154ParametersFromNcCodeLine(tmpStr); data.Add(new M154DataModel() { Process = processId, IsNeeded = bits[processId - 1], Parameters = parameters }); } } return NO_ERROR; } public override CmsError PLC_RM156Data(ref List value) { // NB: da verificare se sia corretto o meno come BIT ARRAY... byte val = 0; List vals = new List(); CmsError libraryError = MEM_RWByte(R, false, 0, M156_INPUT_NEEDED.MemType, M156_INPUT_NEEDED.Address, M156_INPUT_NEEDED.SubAddress, 0, ref val); if (libraryError.IsError()) return libraryError; libraryError = MEM_RWByteList(R, 0, M156_INPUT_ID_LIST.MemType, M156_INPUT_ID_LIST.Address, M156_INPUT_ID_LIST.SubAddress, 0, M156_INPUT_ID_LIST.Size, ref vals); if (libraryError.IsError()) return libraryError; bool[] bits = ByteToBits(val); // FORZO: 1 solo processo //for (int processId = 1; processId <= MAX_PROCESS_NUMBER; processId++) for (int processId = 1; processId <= 1; processId++) { if (bits[processId - 1]) { // leggo x compatibilità la risposta standard double responseVal = 0; // Read machine variable libraryError = MEM_RWDouble(R, 0, M156_RESPONSE_MEMORY.MemType, M156_RESPONSE_MEMORY.Address, M156_RESPONSE_MEMORY.SubAddress + (int)processId - 1, ref responseVal); if (libraryError.IsError()) return libraryError; // Parse line & get parameters value.Add(new M156InputIsNeededModel() { Process = (uint)processId, Id = vals.ElementAt(processId - 1), Value = responseVal }); } } return NO_ERROR; } // MACHINE COUNTERS public override CmsError PLC_RMachineCounters(ref List counters) { List val = new List(); // Read ints CmsError libraryError = MEM_RWDWordList(R, 0, COUNTERS_DATA.MemType, COUNTERS_DATA.Address, COUNTERS_DATA.SubAddress, COUNTERS_DATA.Size / 4, ref val); if (libraryError.IsError()) return libraryError; // Set return value uint i = 0; counters = val.Select(x => new CounterModel() { Id = i++, Value = x }) .ToList(); return NO_ERROR; } /// /// Get current Modules Block list /// /// updates only RT parameters (false = update all) /// /// public override CmsError PLC_RModulesBlockList(bool onlyRT, ref Dictionary currModulesBlockList) { // se richiesto NON SOLO RT faccio refresh anche dati "lenti" if (!onlyRT) { refreshMemModBlockParameter(); } // refresh dati veloci / RT refreshMemModBlockParameterRT(); // copio lista act in output... currModulesBlockList = ThermoModuleList; return NO_ERROR; } public override CmsError PLC_ROperatorInputIsNeeded(ref List value) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_RPowerOnData(ref PreAndPostPowerOnModel powerOnModel) { //int readValue = 0; //// Read pre power on and post power on data from memory //CmsError libraryError = MEM_RWInteger(R, 0, PRE_POST_POWER_ON.MemType, PRE_POST_POWER_ON.Address, PRE_POST_POWER_ON.SubAddress, ref readValue); CmsError libraryError = NO_ERROR; List currMem = new List(); libraryError = MEM_RWByteList(R, 0, PRE_POST_POWER_ON.MemType, PRE_POST_POWER_ON.Address, PRE_POST_POWER_ON.SubAddress, 0, 4, ref currMem); if (libraryError.IsError()) return libraryError; bool[] bits = new bool[32]; // Convert int into to true/false array //bits = IntToBits(readValue); var bArray = new BitArray(currMem.ToArray()); bArray.CopyTo(bits, 0); // 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] }, BarriersNotOk = new PowerOnDataModel() { Id = 7, Active = bits[6], Clickable = bits[22] } }; // 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; } /// /// Get current Production Cycle data /// /// /// public override CmsError PLC_RProdCycle(ref ThermoModels.ProdCycleModel currProdCycle) { List currMem = new List(); CmsError libraryError = MEM_RWByteList(R, 0, PROCESS_PROD_CYCLE.MemType, PROCESS_PROD_CYCLE.Address, PROCESS_PROD_CYCLE.SubAddress, 0, PROCESS_PROD_CYCLE.Size, ref currMem); if (libraryError.IsError()) return libraryError; // converto! currProdCycle = new ThermoModels.ProdCycleModel() { Status = S7.Net.Types.Word.FromByteArray(currMem.Skip(0).Take(2).ToArray()), MessageId = S7.Net.Types.Word.FromByteArray(currMem.Skip(2).Take(2).ToArray()), Mode = S7.Net.Types.Byte.FromByteArray(currMem.Skip(4).Take(1).ToArray()), Submode = S7.Net.Types.Byte.FromByteArray(currMem.Skip(5).Take(1).ToArray()), TimeAdv = S7.Net.Types.DWord.FromByteArray(currMem.Skip(6).Take(4).ToArray()) }; return NO_ERROR; } /// /// Get current Production Info data /// /// /// /// public override CmsError PLC_RProdInfo(ref ThermoModels.ProdInfoModel currProdInfo) { List currMem = new List(); CmsError libraryError = MEM_RWByteList(R, 0, PROCESS_PROD_INFO.MemType, PROCESS_PROD_INFO.Address, PROCESS_PROD_INFO.SubAddress, 0, PROCESS_PROD_INFO.Size, ref currMem); if (libraryError.IsError()) return libraryError; // converto! currProdInfo = new ThermoModels.ProdInfoModel() { NumTarget = S7.Net.Types.Int.FromByteArray(currMem.Skip(0).Take(2).ToArray()), NumDone = S7.Net.Types.Int.FromByteArray(currMem.Skip(2).Take(2).ToArray()), TimeWarm = S7.Net.Types.DInt.FromByteArray(currMem.Skip(6).Take(4).ToArray()), TimeVent = S7.Net.Types.DInt.FromByteArray(currMem.Skip(10).Take(4).ToArray()), TimeVacuum = S7.Net.Types.DInt.FromByteArray(currMem.Skip(14).Take(4).ToArray()), TimeCycleGross = S7.Net.Types.DInt.FromByteArray(currMem.Skip(18).Take(4).ToArray()), TimeCycleNet = S7.Net.Types.DInt.FromByteArray(currMem.Skip(22).Take(4).ToArray()), MaterialTempEndWarm = S7.Net.Types.Real.FromByteArray(currMem.Skip(26).Take(4).ToArray()), MaterialTempEndVent = S7.Net.Types.Real.FromByteArray(currMem.Skip(30).Take(4).ToArray()), MoldTemp = S7.Net.Types.Real.FromByteArray(currMem.Skip(34).Take(4).ToArray()), VacuumReadVal = S7.Net.Types.Real.FromByteArray(currMem.Skip(38).Take(4).ToArray()), MouldEnergyOUT = S7.Net.Types.Real.FromByteArray(currMem.Skip(42).Take(4).ToArray()), MouldEnergyIN = S7.Net.Types.Real.FromByteArray(currMem.Skip(46).Take(4).ToArray()), NumPreHot = S7.Net.Types.Int.FromByteArray(currMem.Skip(50).Take(2).ToArray()) }; return NO_ERROR; } /// /// read current recipe parameter list /// /// updates only RT parameters (false = update all) /// /// public override CmsError PLC_RRecipeParamList(bool onlyRT, ref Dictionary currParamList) { CmsError currError = NO_ERROR; // refresh dati veloci / RT refreshMemRecipeParameterRT(); // se richiesto NON SOLO RT faccio refresh anche dati "lenti" if (!onlyRT) { refreshMemRecipeParameter(); } // copio lista act in output... currParamList = ThermoParamList; return currError; } public override CmsError PLC_RScadaSiemens(ref List objects) { return FUNCTION_NOT_ALLOWED_ERROR; } 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 libraryError = 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; libraryError = 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; libraryError = 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; libraryError = MEM_RWDouble(R, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), ref val); value = val; } else { // FIXME TODO verificare endianness (qui true) // read BYTE byte val = 0; libraryError = MEM_RWByte(R, true, 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) { // FIXME TODO verificare endianness, qui false // read BOOL bool val = false; libraryError = MEM_RWBoolean(R, false, 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 libraryError; } /// /// Read Status/command words /// /// public override CmsError PLC_RStatusCommand(ref List statusCmd) { CmsError libraryError = NO_ERROR; // leggo intera area DWORD e di conseguenza processo... statusCmd = new List(); libraryError = MEM_RWWordList(R, 0, STATUS_CMD_DATA.MemType, STATUS_CMD_DATA.Address, STATUS_CMD_DATA.SubAddress, STATUS_CMD_DATA.Size, ref statusCmd); if (libraryError.IsError()) return libraryError; return libraryError; } public override CmsError PLC_RToolMovement(ref MovementBetweenMagazinesModel toolMovement) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_RUserSoftKeys(ref List softKeys) { CmsError libraryError = PLC_RSoftKeys(USER_SOFTKEYS_VALUE, USER_SOFTKEYS_CLICKABLE, ref softKeys); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Get current Warmers Channels list /// /// updates only READ parameters (false = update all data) /// /// public override CmsError PLC_RWarmerChannelList(bool useCache, ref Dictionary currWarmerChannelList) { // refresh stato canale ESP[i] refreshRiscStatus(); // refresh % lavoro attuale OVp[i] refreshRiscPerc(); // refresh corrente attuale Ich[i] refreshRiscActCurr(); // refresh setpoint PLC % (era 514 --> 627) refreshRiscSetpointPLC(); // refresh dati status/comando termocamera refreshRiscTermoCamCommStatus(); // refresh setpoint HMI canale % | Write refreshRiscSetpointHMI(); if (!useCache) { // refresh abilitazione canale x thermoCam | Write refreshRiscTermoCamEnab(); // refresh ultima temp canale letta da thermoCam | Write refreshRiscTermoCamTempAct(); // refresh temp canale impostata x thermoCam | Write refreshRiscTermoCamTempSet(); } // copio lista act in output currWarmerChannelList = ThermoWarmChannels; return NO_ERROR; } /// /// Get current Warmers VUMin data /// /// /// public override CmsError PLC_RWarmerConfVUMin(ref ushort VUmin) { // leggo da 513.0 --> default 210 VUmin = 230; List currMem = new List(); // read actual data on memory... CmsError libraryError = MEM_RWWord(R, 0, RISC_VU_MIN.MemType, RISC_VU_MIN.Address, RISC_VU_MIN.SubAddress, ref VUmin); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Get current Warmers ThermoCam Data /// /// /// public override CmsError PLC_RWarmerTCamData(out ThermoModels.ThermoCam currTCamData) { // init... bool currValue = false; currTCamData = new ThermoModels.ThermoCam(); // leggo da PLC singoli bit... CmsError libraryError = MEM_RWBoolean(R, true, 0, TCAM_STATW_DATA.MemType, TCAM_STATW_DATA.Address, TCAM_STATW_DATA.SubAddress, 0, ref currValue); if (libraryError.IsError()) return libraryError; ThermoCamData.ThermoOptionActive = currValue; libraryError = MEM_RWBoolean(R, true, 0, TCAM_COMMW_DATA.MemType, TCAM_COMMW_DATA.Address, TCAM_COMMW_DATA.SubAddress, 0, ref currValue); if (libraryError.IsError()) return libraryError; ThermoCamData.ThermoCamMode = currValue; libraryError = MEM_RWBoolean(R, true, 0, TCAM_COMMW_DATA.MemType, TCAM_COMMW_DATA.Address, TCAM_COMMW_DATA.SubAddress, 1, ref currValue); if (libraryError.IsError()) return libraryError; ThermoCamData.ThermoCamOnOff = currValue; // restituisce status dei parametri termocamera (in cache...) currTCamData = ThermoCamData; return libraryError; } public override CmsError PLC_RWManageWatchdog() { // watchdog in memoria WORD --> true x endianness! bool plcWatchdog = false; CmsError libraryError = MEM_RWBoolean(R, true, 0, NC_WATCHDOG.MemType, NC_WATCHDOG.Address, NC_WATCHDOG.SubAddress, 0, ref plcWatchdog); if (libraryError.IsError()) return libraryError; if (plcWatchdog) return PLC_NOT_RUNNING_ERROR; // tira su il bit... plcWatchdog = true; return MEM_RWBoolean(W, true, 0, NC_WATCHDOG.MemType, NC_WATCHDOG.Address, NC_WATCHDOG.SubAddress, 0, ref plcWatchdog); } public override CmsError PLC_RWorkedTimeHead(int head, ref uint time) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_RWorkedTimeMachine(ref uint time) { // Read Worked time CmsError libraryError = MEM_RWDWord(R, 0, MACHINE_WORKED_TIME.MemType, MACHINE_WORKED_TIME.Address, MACHINE_WORKED_TIME.SubAddress, ref time); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Write MULTIPLE Digital Out FORCED Status (bitmap) /// /// Oggetto valori da aggiornare (from HMI) /// num max parametri da scrivere singolarmente /// delay in scriottura multi parametri singoli /// public override CmsError PLC_W_IO_AO_Reset(Dictionary newValues) { CmsError libraryError = NO_ERROR; List rwValuesAO = new List(); // leggo da PLC a array di byte di appoggio x visibilità AO... libraryError = MEM_RWWordList(R, 0, IO_AO_FORCE.MemType, IO_AO_FORCE.Address, IO_AO_FORCE.SubAddress, IO_AO_FORCE.Size, ref rwValuesAO); if (libraryError.IsError()) return libraryError; int bank = 0; int pos = 0; int size = 16; // imposto i valori NUOVI... cerco il BANK da 16 bit... foreach (var item in newValues) { bank = item.Key / size; pos = item.Key % size; // aggiorno if (item.Value) { rwValuesAO[bank] = (ushort)(((int)rwValuesAO[bank]).SetBitOne(pos)); } else { rwValuesAO[bank] = (ushort)(((int)rwValuesAO[bank]).SetBitZero(pos)); } } // scrivo! libraryError = MEM_RWWordList(W, 0, IO_AO_FORCE.MemType, IO_AO_FORCE.Address, IO_AO_FORCE.SubAddress, IO_AO_FORCE.Size, ref rwValuesAO); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Write MULTIPLE Analog Out values (+ force) /// /// Oggetto valori da aggiornare (from HMI) /// num max parametri da scrivere singolarmente /// delay in scriottura multi parametri singoli /// public override CmsError PLC_W_IO_AO_Val(Dictionary newValues) { CmsError libraryError = NO_ERROR; List rwValuesAO = new List(); Dictionary newForced = new Dictionary(); // leggo da PLC valori AO... libraryError = MEM_RWShortList(R, 0, IO_AO_VAL_FOR.MemType, IO_AO_VAL_FOR.Address, IO_AO_VAL_FOR.SubAddress, IO_AO_VAL_FOR.Size, ref rwValuesAO); if (libraryError.IsError()) return libraryError; // aggiorno valori ricevuti// imposto i valori NUOVI... cerco il BANK da 16 bit... foreach (var item in newValues) { rwValuesAO[item.Key] = (short)item.Value; newForced.Add(item.Key, true); } // scrivo valori libraryError = MEM_RWShortList(W, 0, IO_AO_VAL_FOR.MemType, IO_AO_VAL_FOR.Address, IO_AO_VAL_FOR.SubAddress, IO_AO_VAL_FOR.Size, ref rwValuesAO); if (libraryError.IsError()) return libraryError; // scrivo forced PLC_W_IO_AO_Reset(newForced); return libraryError; } /// /// Write MULTIPLE Digital Out FORCED Status (bitmap) /// /// Oggetto valori da aggiornare (from HMI) /// num max parametri da scrivere singolarmente /// delay in scriottura multi parametri singoli /// public override CmsError PLC_W_IO_DO_Reset(Dictionary newValues) { CmsError libraryError = NO_ERROR; List rwValuesDO = new List(); // leggo da PLC a array di byte di appoggio x visibilità DO... libraryError = MEM_RWWordList(R, 0, IO_DO_FORCE.MemType, IO_DO_FORCE.Address, IO_DO_FORCE.SubAddress, IO_DO_FORCE.Size, ref rwValuesDO); if (libraryError.IsError()) return libraryError; int bank = 0; int pos = 0; int size = 16; // imposto i valori NUOVI... cerco il BANK da 16 bit... foreach (var item in newValues) { bank = item.Key / size; pos = item.Key % size; // aggiorno if (item.Value) { rwValuesDO[bank] = (ushort)(((int)rwValuesDO[bank]).SetBitOne(pos)); } else { rwValuesDO[bank] = (ushort)(((int)rwValuesDO[bank]).SetBitZero(pos)); } } // scrivo! libraryError = MEM_RWWordList(W, 0, IO_DO_FORCE.MemType, IO_DO_FORCE.Address, IO_DO_FORCE.SubAddress, IO_DO_FORCE.Size, ref rwValuesDO); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Write MULTIPLE Digital Out values (+ force) /// /// Oggetto valori da aggiornare (from HMI) /// num max parametri da scrivere singolarmente /// delay in scriottura multi parametri singoli /// public override CmsError PLC_W_IO_DO_Val(Dictionary newValues) { CmsError libraryError = NO_ERROR; List rwValuesDO = new List(); Dictionary newForced = new Dictionary(); // leggo da PLC valori DO... libraryError = MEM_RWWordList(R, 0, IO_DO_VAL_FOR.MemType, IO_DO_VAL_FOR.Address, IO_DO_VAL_FOR.SubAddress, IO_DO_VAL_FOR.Size, ref rwValuesDO); if (libraryError.IsError()) return libraryError; int bank = 0; int pos = 0; int size = 16; // imposto i valori NUOVI... cerco il BANK da 16 bit... foreach (var item in newValues) { bank = item.Key / size; pos = item.Key % size; // aggiorno if (item.Value) { rwValuesDO[bank] = (ushort)(((int)rwValuesDO[bank]).SetBitOne(pos)); } else { rwValuesDO[bank] = (ushort)(((int)rwValuesDO[bank]).SetBitZero(pos)); } newForced.Add(item.Key, true); } // scrivo! libraryError = MEM_RWWordList(W, 0, IO_DO_VAL_FOR.MemType, IO_DO_VAL_FOR.Address, IO_DO_VAL_FOR.SubAddress, IO_DO_VAL_FOR.Size, ref rwValuesDO); if (libraryError.IsError()) return libraryError; // scrivo forced PLC_W_IO_DO_Reset(newForced); return libraryError; } /// /// Reset ALL DO / AO forced bitmap /// /// public override CmsError PLC_W_IO_ResetAll() { CmsError libraryError = NO_ERROR; List writeValuesDO = new List(); List writeValuesAO = new List(); // imposto a zero... for (int i = 0; i < IO_DO_FORCE.Size; i++) { writeValuesDO.Add(0); } for (int i = 0; i < IO_AO_FORCE.Size; i++) { writeValuesAO.Add(0); } // scrivo su PLC libraryError = MEM_RWWordList(W, 0, IO_DO_FORCE.MemType, IO_DO_FORCE.Address, IO_DO_FORCE.SubAddress, IO_DO_FORCE.Size, ref writeValuesDO); if (libraryError.IsError()) return libraryError; // scrivo su PLC libraryError = MEM_RWWordList(W, 0, IO_AO_FORCE.MemType, IO_AO_FORCE.Address, IO_AO_FORCE.SubAddress, IO_AO_FORCE.Size, ref writeValuesAO); if (libraryError.IsError()) return libraryError; return libraryError; } 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, true); } /// /// Process conf request /// /// public override CmsError PLC_WAckConfRecipeRequest() { CmsError libraryError = NO_ERROR; // Call ack for config request RECIPE libraryError = PLC_WAck(true, REQ_CONF_ACK, REQ_CONF_STROBE, 9); if (libraryError.IsError()) return libraryError; return libraryError; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Process conf request for RISK data /// /// public override CmsError PLC_WAckConfRiskRequest() { CmsError libraryError = NO_ERROR; // Call ack for config request RISK libraryError = PLC_WAck(true, REQ_CONF_ACK, REQ_CONF_STROBE, 8); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Process conf request for FLIR picture request /// /// public override CmsError PLC_WAckFlirRequest() { CmsError libraryError = NO_ERROR; // Call ack for config request RISK libraryError = PLC_WAck(true, REQ_CONF_ACK, REQ_CONF_STROBE, 13); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Process production info update /// /// public override CmsError PLC_WAckProdUpdate() { CmsError libraryError = NO_ERROR; // Call ack for prod update libraryError = PLC_WAck(true, REQ_CONF_ACK, REQ_CONF_STROBE, 4); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Process end prod ack /// /// public override CmsError PLC_WAckPzProdEnd() { CmsError libraryError = NO_ERROR; // Call ack for prod update libraryError = PLC_WAck(true, REQ_CONF_ACK, REQ_CONF_STROBE, 12); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Process start prod ack /// /// public override CmsError PLC_WAckPzProdStart() { CmsError libraryError = NO_ERROR; // Call ack for prod update libraryError = PLC_WAck(true, REQ_CONF_ACK, REQ_CONF_STROBE, 11); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Process setpointHMI invalidated with ack /// /// public override CmsError PLC_WAckSetpointInvalidated() { CmsError libraryError = NO_ERROR; // Call ack for prod update libraryError = PLC_WAck(true, REQ_CONF_ACK, REQ_CONF_STROBE, 15); if (libraryError.IsError()) return libraryError; return libraryError; } 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_WCandy(long value) { // Long is formed by a integer + word // Write Word ushort word = (ushort)((value & 0xFFFF)); CmsError libraryError = MEM_RWWord(W, 0, CANDY_MEM.MemType, CANDY_MEM.Address, CANDY_MEM.SubAddress, ref word); if (libraryError.IsError()) return libraryError; int integer = (int)((value & 0xFFFFFFFF0000) >> 16); // Write Integer (+1 is used because osai uses word) libraryError = MEM_RWInteger(W, 0, CANDY_MEM.MemType, CANDY_MEM.Address, CANDY_MEM.SubAddress + 2, ref integer); if (libraryError.IsError()) return libraryError; // Rieggo il dato long newVal = 0; libraryError = PLC_RCandy(ref newVal); if (libraryError.IsError()) return libraryError; // Se i 2 dati coincidono ritorno OK if (value == newVal) return NO_ERROR; else return PLC_NOT_RUNNING_ERROR; } public override CmsError PLC_WExpiredCandy(bool value) { bool newVal = false; //Scrivo il dato CmsError libraryError = MEM_RWBoolean(W, true, 0, EXP_CANDY_MEM.MemType, EXP_CANDY_MEM.Address, EXP_CANDY_MEM.SubAddress, 5, ref value); if (libraryError.IsError()) return libraryError; else { //Leggo il dato libraryError = PLC_RExpiredCandy(ref newVal); if (libraryError.IsError()) return libraryError; //Se i 2 dati coincidono ritorno OK if (value == newVal) return NO_ERROR; else return PLC_NOT_RUNNING_ERROR; } } public override CmsError PLC_WHeadOverride(uint id, HEAD_OVERRIDE_SIGN sign) { return FUNCTION_NOT_ALLOWED_ERROR; } /// /// Set Keyboard softkey ID /// /// Softkey ID of the first button /// Softkey ID of the second button /// public override CmsError PLC_WKeyboardSoftkey(ushort idKey1, ushort idKey2) { List currMem = new List(); currMem.Add(idKey1); currMem.Add(idKey2); CmsError libraryError = MEM_RWWordList(W, 0, KEYBOARD_STAR_MEMORY.MemType, KEYBOARD_STAR_MEMORY.Address, KEYBOARD_STAR_MEMORY.SubAddress, KEYBOARD_STAR_MEMORY.Size, ref currMem); if (libraryError.IsError()) return libraryError; return NO_ERROR; } public override CmsError PLC_WM156Response(int process, double responseVal) { // forzo process a 1... process = 1; CmsError libraryError = MEM_RWDouble(W, 0, M156_RESPONSE_MEMORY.MemType, M156_RESPONSE_MEMORY.Address, M156_RESPONSE_MEMORY.SubAddress + (int)process - 1, ref responseVal); if (libraryError.IsError()) return libraryError; // FIXME TODO verifica se endianness vada gestita o meno (qui FALSE) return PLC_WStrobe(false, M156_INPUT_ACK, M156_INPUT_STROBE, (uint)process); } /// /// Request for mode selection via strobe /// /// 1: MAN, 2: AUTO, 3: SETUP /// public override CmsError PLC_WModeSel(int mode) { // se update --> scrivo strobe comando update... if (mode == 1) { // Call confirm update CmsError libraryError = PLC_WStrobe(true, REQ_MODE_ACK, REQ_MODE_STROBE, 6); if (libraryError.IsError()) return libraryError; } else if (mode == 2) { // Call confirm update CmsError libraryError = PLC_WStrobe(true, REQ_MODE_ACK, REQ_MODE_STROBE, 5); if (libraryError.IsError()) return libraryError; } else if (mode == 3) { // Call confirm update CmsError libraryError = PLC_WStrobe(true, REQ_MODE_ACK, REQ_MODE_STROBE, 7); if (libraryError.IsError()) return libraryError; } return NO_ERROR; } public override CmsError PLC_WOperatorInputResponse(int process, double responseVal) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_WPowerOnData(uint id, bool value) { // Check bit range if (id > 16) return INCORRECT_PARAMETERS_ERROR; // Call restore message CmsError libraryError = PLC_WStrobe(false, PRE_POST_POWER_ON_ACK, PRE_POST_POWER_ON_CLICKED, id); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Set ProdInfo data /// /// Qty requested (target) /// Reset counter (actual counter) /// Number of pre-warm cycle requested /// public override CmsError PLC_WProdInfo(short numTarget, bool doReset, short preWarmCycle) { List currMem = new List(); CmsError libraryError = MEM_RWByteList(R, 0, PROCESS_PROD_INFO.MemType, PROCESS_PROD_INFO.Address, PROCESS_PROD_INFO.SubAddress, 0, PROCESS_PROD_INFO.Size, ref currMem); if (libraryError.IsError()) return libraryError; // converto! var currProdInfo = new ThermoModels.ProdInfoModel() { NumTarget = S7.Net.Types.Int.FromByteArray(currMem.Skip(0).Take(2).ToArray()), NumDone = S7.Net.Types.Int.FromByteArray(currMem.Skip(2).Take(2).ToArray()), PreWarmCycle = S7.Net.Types.Int.FromByteArray(currMem.Skip(4).Take(2).ToArray()), TimeWarm = S7.Net.Types.DInt.FromByteArray(currMem.Skip(6).Take(4).ToArray()), TimeVent = S7.Net.Types.DInt.FromByteArray(currMem.Skip(10).Take(4).ToArray()), TimeVacuum = S7.Net.Types.DInt.FromByteArray(currMem.Skip(14).Take(4).ToArray()), TimeCycleGross = S7.Net.Types.DInt.FromByteArray(currMem.Skip(18).Take(4).ToArray()), TimeCycleNet = S7.Net.Types.DInt.FromByteArray(currMem.Skip(22).Take(4).ToArray()), MaterialTempEndWarm = S7.Net.Types.Real.FromByteArray(currMem.Skip(26).Take(4).ToArray()), MaterialTempEndVent = S7.Net.Types.Real.FromByteArray(currMem.Skip(30).Take(4).ToArray()), MoldTemp = S7.Net.Types.Real.FromByteArray(currMem.Skip(34).Take(4).ToArray()), VacuumReadVal = S7.Net.Types.Real.FromByteArray(currMem.Skip(38).Take(4).ToArray()), MouldEnergyOUT = S7.Net.Types.Real.FromByteArray(currMem.Skip(42).Take(4).ToArray()), MouldEnergyIN = S7.Net.Types.Real.FromByteArray(currMem.Skip(46).Take(4).ToArray()), NumPreHot = S7.Net.Types.Int.FromByteArray(currMem.Skip(50).Take(2).ToArray()) }; // aggiorno... currProdInfo.NumTarget = numTarget; currProdInfo.PreWarmCycle = preWarmCycle; // converto a byte... List newMem = currProdInfo.convertToByte().ToList(); // riscrivo!!!! libraryError = MEM_RWByteList(W, 0, PROCESS_PROD_INFO.MemType, PROCESS_PROD_INFO.Address, PROCESS_PROD_INFO.SubAddress, 0, PROCESS_PROD_INFO.Size, ref newMem); if (libraryError.IsError()) return libraryError; if (doReset) { // send strobe of NEW WorkOrder / reset QTY libraryError = PLC_WStrobe(true, PROD_ACK, PROD_STROBE, 10); if (libraryError.IsError()) return libraryError; } return NO_ERROR; } /// /// Confirm/Cancel recipe modifications /// /// true: HMI --> PLC, false: PLC --> HMI /// public override CmsError PLC_WRecipeEdit(bool confirmUpdate) { CmsError libraryError = NO_ERROR; // se update --> scrivo strobe comando update... if (confirmUpdate) { // Call confirm update libraryError = PLC_WStrobe(true, PARAMETER_EDIT_ACK, PARAMETER_EDIT_STROBE, 2); if (libraryError.IsError()) return libraryError; } // altrimenti mando strobe comando cancel... else { // Call cancel update libraryError = PLC_WStrobe(true, PARAMETER_EDIT_ACK, PARAMETER_EDIT_STROBE, 3); if (libraryError.IsError()) return libraryError; } return libraryError; } /// /// Write recipe updated MULTIPLE parameter /// /// Oggetto parametri da aggiornare (from HMI) /// num max parametri da scrivere singolarmente, default = 10 /// delay in scriottura multi parametri singoli, default = 20ms /// public override CmsError PLC_WRecipeParameters(Dictionary newParameters, int nMaxParamWrite = 10, int delayParamWrite = 20) { // init variabili accessorie CmsError libraryError = NO_ERROR; List currMem = new List(); int memIndex = 0; int packSize = 20; // 2020.09.03: ricevuto da chiamata, dovrebbe essere 5 parametri x scrivere tutto (era 30 prima di 2008.08.07) bool writeSingle = newParameters.Count < nMaxParamWrite; // leggo da PLC a array di byte di appoggio... libraryError = MEM_RWByteList(R, 0, PARAMETER_DATA.MemType, PARAMETER_DATA.Address, PARAMETER_DATA.SubAddress, 0, PARAMETER_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; PlcParam currParam; List newMem = new List(); // controllo SE ho dati... if (currMem.Count > 0) { // converto in array di byte... byte[] memArray = currMem.ToArray(); // ciclo x ogni parametro x aggiornare il valore... foreach (var item in newParameters) { memIndex = (item.Key - 1) * packSize; // recupero oggetto parametri currParam = new PlcParam(memArray.Skip(memIndex).Take(packSize).ToArray()); if (currParam.Id > 0) { // se servisse resetto... if (currParam.Id != (short)item.Key) currParam.Id = (short)item.Key; currParam.SetpointHMI = (int)item.Value; // scrivo 1:1 se pochi dati SOLO i singoli valori HMI if (writeSingle) { newMem = S7.Net.Types.DInt.ToByteArray(currParam.SetpointHMI).ToList();// currParam.convertToByte().ToList(); libraryError = MEM_RWByteList(W, 0, PARAMETER_DATA.MemType, PARAMETER_DATA.Address, PARAMETER_DATA.SubAddress + packSize * (currParam.Id - 1) + 2, 0, 4, ref newMem); if (libraryError.IsError()) return libraryError; // attendo x sicurezza... Thread.Sleep(delayParamWrite); } else { // accodo su memoria generale Buffer.BlockCopy(currParam.convertToByte(), 0, memArray, memIndex, packSize); } } } // converto nuova memoria newMem = memArray.ToList(); memIndex = 0; if (!writeSingle) { // SCRIVO in blocco! libraryError = MEM_RWByteList(W, 0, PARAMETER_DATA.MemType, PARAMETER_DATA.Address, PARAMETER_DATA.SubAddress, 0, PARAMETER_DATA.Size, ref newMem); if (libraryError.IsError()) return libraryError; } } return NO_ERROR; } /// /// Send axis command /// /// ID asse /// Comando (0..15) /// Indica se scrivere la TargetPos /// Posizione target /// public override CmsError PLC_WAxisCommand(int AxisNum, uint CommandBit, bool WritePos, double TargetPos) { CmsError libraryError = NO_ERROR; if (WritePos) { MEMORY_CELL caTgtPos = new MEMORY_CELL(AXES_COMMAND.MemType, AXES_COMMAND.Address, AXES_COMMAND.SubAddress + ((AxisNum - 1) * 8) + 4, 2); // in primis scrivo la TargetPos nei 4 byte DWord... libraryError = MEM_RWDouble(W, 0, caTgtPos.MemType, caTgtPos.Address, caTgtPos.SubAddress, ref TargetPos); if (libraryError.IsError()) return libraryError; } // ...è permesso solo 0..7 if (CommandBit >= 1 && CommandBit < 8) { // posizione: è da array assi 0..n-1, 8byte ogni asse MEMORY_CELL currAxAck = new MEMORY_CELL(AXES_COMMAND.MemType, AXES_COMMAND.Address, AXES_COMMAND.SubAddress + ((AxisNum - 1) * 8), 2); MEMORY_CELL currAxStr = new MEMORY_CELL(AXES_COMMAND.MemType, AXES_COMMAND.Address, AXES_COMMAND.SubAddress + ((AxisNum - 1) * 8 + 2), 2); // Call confirm update libraryError = PLC_WStrobe(true, currAxAck, currAxStr, CommandBit); if (libraryError.IsError()) return libraryError; } return libraryError; } /// /// Send Axes Gen Control /// /// Boolean for advanced mode /// public override CmsError PLC_WAxisGeneralControl(bool AdvMode) { CmsError libraryError = NO_ERROR; // preparo la word ushort controlData = 0; if (AdvMode) { controlData = 1; } MEMORY_CELL caTgtPos = new MEMORY_CELL(AXES_GEN_CONTROL.MemType, AXES_GEN_CONTROL.Address, AXES_GEN_CONTROL.SubAddress, 2); // in primis scrivo la TargetPos nei 4 byte DWord... libraryError = MEM_RWWord(W, 0, caTgtPos.MemType, caTgtPos.Address, caTgtPos.SubAddress, ref controlData); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Read Axes Gen Control /// /// Boolean for advanced mode /// public override CmsError PLC_RAxisGeneralStatus(ref bool AdvMode) { CmsError libraryError = NO_ERROR; // preparo la word ushort controlData = 0; MEMORY_CELL caTgtPos = new MEMORY_CELL(AXES_GEN_STATUS.MemType, AXES_GEN_STATUS.Address, AXES_GEN_STATUS.SubAddress, 2); // in primis scrivo la TargetPos nei 4 byte DWord... libraryError = MEM_RWWord(R, 0, caTgtPos.MemType, caTgtPos.Address, caTgtPos.SubAddress, ref controlData); if (libraryError.IsError()) return libraryError; AdvMode = (controlData == 1); return libraryError; } public override CmsError PLC_WRefreshAllMessages() { // imposto come UserSoftKey return PLC_WUserSoftKey(REFRESH_ALL_ALARMS_SFKEY_INDEX); } public override CmsError PLC_WRefreshMessage(uint id) { // Check id range if (id > ALARMS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Call restore message: is a BIT ARRAY --> false! CmsError libraryError = PLC_WStrobe(false, ALARM_ACK, ALARM_REFRESH_STROBE, id); if (libraryError.IsError()) return libraryError; return NO_ERROR; } public override CmsError PLC_WResetMachineCounters(uint counter) { // FIXME TODO verifica se endianness vada gestita o meno (qui FALSE) bool isResettable = false; CmsError libraryError = MEM_RWBoolean(R, false, 0, COUNTER_IS_RESETTABLE.MemType, COUNTER_IS_RESETTABLE.Address, COUNTER_IS_RESETTABLE.SubAddress, (int)(counter - 1), ref isResettable); if (libraryError.IsError()) return libraryError; if (!isResettable) return FUNCTION_NOT_ALLOWED_ERROR; libraryError = PLC_WStrobe(false, COUNTER_IS_RESETTABLE_ACK, COUNTER_IS_RESETTABLE_STROBE, counter); if (libraryError.IsError()) return libraryError; return NO_ERROR; } public override CmsError PLC_WResetWorkedTimeHead(int head) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_WResetWorkedTimeMachine(uint time) { //FIXME TODO verificare endianness aree memoria uint actTime = 0; // Read actual Value CmsError libraryError = MEM_RWDWord(R, 0, MACHINE_WORKED_TIME.MemType, MACHINE_WORKED_TIME.Address, MACHINE_WORKED_TIME.SubAddress, ref actTime); if (libraryError.IsError()) return libraryError; // 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; libraryError = MEM_RWBoolean(W, true, 0, MACHINE_RESET_WORKED_TIME.MemType, MACHINE_RESET_WORKED_TIME.Address, MACHINE_RESET_WORKED_TIME.SubAddress, 0, ref bitValue); if (libraryError.IsError()) return libraryError; //Aspetto che venga abbassato do { Thread.Sleep(50); nTry += 1; libraryError = MEM_RWBoolean(R, true, 0, MACHINE_RESET_WORKED_TIME.MemType, MACHINE_RESET_WORKED_TIME.Address, MACHINE_RESET_WORKED_TIME.SubAddress, 0, ref bitValue); if (libraryError.IsError()) return libraryError; } while (bitValue && nTry <= 10); //se il valore è rimasto a 1 il plc non l'ha preso in carico, e abortisco if (bitValue) { bitValue = true; libraryError = MEM_RWBoolean(W, true, 0, MACHINE_RESET_WORKED_TIME.MemType, MACHINE_RESET_WORKED_TIME.Address, MACHINE_RESET_WORKED_TIME.SubAddress, 0, ref bitValue); if (libraryError.IsError()) return libraryError; return PLC_NOT_RUNNING_ERROR; } else { //Se l'ha abbassato scrivo il nuovo dato libraryError = 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_WRestoreMessage(uint id) { // Check id range if (id > ALARMS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Call restore message: is a BIT ARRAY --> true! CmsError libraryError = PLC_WStrobe(true, ALARM_ACK, ALARM_RESTORATION_STROBE, id); if (libraryError.IsError()) return libraryError; return NO_ERROR; } public override CmsError PLC_WScadaValue(string memIndex, SCADA_MEM_TYPE memType, object value) { string[] index = memIndex.Split('.'); CmsError libraryError = 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); libraryError = 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); libraryError = 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); libraryError = 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); libraryError = MEM_RWByte(W, true, 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); libraryError = MEM_RWBoolean(W, false, 0, MEMORY_TYPE.Siemens_DB, Convert.ToInt32(index[0]), Convert.ToInt32(index[1]), Convert.ToInt32(index[2]), ref val); } return libraryError; } /// /// Confirm FLIR image acquired and copied to PLC (STR from server) /// /// public override CmsError PLC_WStrFlirAcquired() { // Call confirm update CmsError libraryError = PLC_WStrobe(true, PARAMETER_EDIT_ACK, PARAMETER_EDIT_STROBE, 14); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Set ThermoCamera functionality active (HMI) /// /// /// public override CmsError PLC_WTCamActiv(bool enableTCam) { CmsError libraryError = MEM_RWBoolean(W, true, 0, TCAM_COMMW_DATA.MemType, TCAM_COMMW_DATA.Address, TCAM_COMMW_DATA.SubAddress, 1, ref enableTCam); return libraryError; } /// /// Set ThermoCamera mode /// /// /// public override CmsError PLC_WTCamMode(bool enableTCam) { CmsError libraryError = MEM_RWBoolean(W, true, 0, TCAM_COMMW_DATA.MemType, TCAM_COMMW_DATA.Address, TCAM_COMMW_DATA.SubAddress, 0, ref enableTCam); return libraryError; } public override CmsError PLC_WTerminateAssistedToolingProcedure() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_WTerminateMovementProcedure(MOVEMENT_RESPONSE resp) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PLC_WUserSoftKey(uint id) { // Check id range if (id > USER_SOFTKEYS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Write strobe into memory --> false because is bitArray CmsError libraryError = PLC_WStrobe(false, USER_SOFT_KEYS_ACK, USER_SOFT_KEYS_CLICKED, id); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Write Warmers channels load data /// /// /// public override CmsError PLC_WWarmerChSetpHmi(Dictionary newData) { // memory area byte[] newMem = new byte[newData.Count]; List currMem = new List(); // read actual data on memory... CmsError libraryError = MEM_RWByteList(R, 0, RISC_CHP_DATA.MemType, RISC_CHP_DATA.Address, RISC_CHP_DATA.SubAddress, 0, RISC_CHP_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; newMem = currMem.ToArray(); // update only given data... foreach (var item in newData) { newMem[item.Key - 1] = (byte)item.Value; } // return as list... currMem = newMem.ToList(); // scrivo sul PLC array di byte... libraryError = MEM_RWByteList(W, 0, RISC_CHP_DATA.MemType, RISC_CHP_DATA.Address, RISC_CHP_DATA.SubAddress, 0, RISC_CHP_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Set current Warmers Channels as enabled/disabled for working with thermo camera data /// /// /// public override CmsError PLC_WWarmerChTCamEnab(Dictionary newData) { // leggo DB664 x abilitazione ch alla termocamera bool[] newMem = new bool[TCAM_CH_ENAB_DATA.Size * 8]; List currMem = new List(); // read actual data on memory... CmsError libraryError = MEM_RWByteList(R, 0, TCAM_CH_ENAB_DATA.MemType, TCAM_CH_ENAB_DATA.Address, TCAM_CH_ENAB_DATA.SubAddress, 0, TCAM_CH_ENAB_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; // Convert int into to true/false array BitArray bArray = new BitArray(currMem.ToArray()); bArray.CopyTo(newMem, 0); // update only given data... foreach (var item in newData) { newMem[item.Key - 1] = item.Value; } // return as list... currMem = boolsToByteArray(newMem).ToList(); // scrivo sul PLC array di byte... libraryError = MEM_RWByteList(W, 0, TCAM_CH_ENAB_DATA.MemType, TCAM_CH_ENAB_DATA.Address, TCAM_CH_ENAB_DATA.SubAddress, 0, TCAM_CH_ENAB_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; return libraryError; } /// /// Set current Warmers Channels Thermocam read (actual) value (°C) /// /// /// public override CmsError PLC_WWarmerChTCamTempAct(Dictionary newData) { // valori in 1/10 di °C int dataScale = 10; // memory area short[] newMem = new short[newData.Count]; // leggo DB625 x val Temp attuali List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWShortList(R, 0, TCAM_TEMP_ACT_DATA.MemType, TCAM_TEMP_ACT_DATA.Address, TCAM_TEMP_ACT_DATA.SubAddress, TCAM_TEMP_ACT_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; newMem = currMem.ToArray(); // update only given data... foreach (var item in newData) { // attenzione: effettua scalatura dati! newMem[item.Key - 1] = (short)(dataScale * item.Value); } // return as list... currMem = newMem.ToList(); // scrivo sul PLC array di byte... libraryError = MEM_RWShortList(W, 0, TCAM_TEMP_ACT_DATA.MemType, TCAM_TEMP_ACT_DATA.Address, TCAM_TEMP_ACT_DATA.SubAddress, TCAM_TEMP_ACT_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Set current Warmers Channels Temp REF Setpoints (1/10 °C) /// /// /// public override CmsError PLC_WWarmerChTCamTempSet(Dictionary newData) { // valori in 1/10 di °C int dataScale = 10; // memory area short[] newMem = new short[newData.Count]; // leggo DB624 x Setpoint Temp richiesti List currMem = new List(); // leggo da PLC a array di byte di appoggio... CmsError libraryError = MEM_RWShortList(R, 0, TCAM_TEMP_REQ_DATA.MemType, TCAM_TEMP_REQ_DATA.Address, TCAM_TEMP_REQ_DATA.SubAddress, TCAM_TEMP_REQ_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; newMem = currMem.ToArray(); // update only given data... foreach (var item in newData) { // attenzione: effettua scalatura dati! newMem[item.Key - 1] = (short)(dataScale * item.Value); } // return as list... currMem = newMem.ToList(); // scrivo sul PLC array di byte... libraryError = MEM_RWShortList(W, 0, TCAM_TEMP_REQ_DATA.MemType, TCAM_TEMP_REQ_DATA.Address, TCAM_TEMP_REQ_DATA.SubAddress, TCAM_TEMP_REQ_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Set current Warmers Channels reflector's data /// /// /// public override CmsError PLC_WWarmerConfBoardEnabl(Dictionary newData) { // memory area byte[] newMem = new byte[newData.Count]; List currMem = new List(); // read actual data on memory... CmsError libraryError = MEM_RWByteList(R, 0, RISC_OCC_DATA.MemType, RISC_OCC_DATA.Address, RISC_OCC_DATA.SubAddress, 0, RISC_OCC_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; newMem = currMem.ToArray(); // update only given data... foreach (var item in newData) { newMem[item.Key] = (byte)item.Value; } // return as list... currMem = newMem.ToList(); // scrivo sul PLC array di byte... libraryError = MEM_RWByteList(W, 0, RISC_OCC_DATA.MemType, RISC_OCC_DATA.Address, RISC_OCC_DATA.SubAddress, 0, RISC_OCC_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Set current Warmers Channels min current data /// /// /// public override CmsError PLC_WWarmerConfMinCurr(Dictionary newData) { // memory area List ListValue = new List(); // read actual data on memory... CmsError libraryError = MEM_RWDoubleList(R, 0, RISC_ICH_MIN_DATA.MemType, RISC_ICH_MIN_DATA.Address, RISC_ICH_MIN_DATA.SubAddress, RISC_ICH_MIN_DATA.Size, ref ListValue); if (libraryError.IsError()) return libraryError; var newMem = ListValue.ToArray(); // update only given data... foreach (var item in newData) { // 2020.07.21 fix perché channes 1 based, memory 0 based newMem[item.Key - 1] = item.Value; } // return as list... ListValue = newMem.ToList(); // scrivo sul PLC array di byte... libraryError = MEM_RWDoubleList(W, 0, RISC_ICH_MIN_DATA.MemType, RISC_ICH_MIN_DATA.Address, RISC_ICH_MIN_DATA.SubAddress, RISC_ICH_MIN_DATA.Size, ref ListValue); if (libraryError.IsError()) return libraryError; return NO_ERROR; } /// /// Set current Warmers Channels reflector's data /// /// /// public override CmsError PLC_WWarmerConfRefl(Dictionary newData) { // memory area byte[] newMem = new byte[newData.Count]; List currMem = new List(); // read actual data on memory... CmsError libraryError = MEM_RWByteList(R, 0, RISC_CFI_DATA.MemType, RISC_CFI_DATA.Address, RISC_CFI_DATA.SubAddress, 0, RISC_CFI_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; newMem = currMem.ToArray(); // update only given data... foreach (var item in newData) { // algoritmo: valore = (val + 1) % 8, ovvero riflettore 0, 8, 16 --> 1, riflettore 1, 9, 17 --> 2 newMem[item.Key - 1] = (byte)((item.Value + 1) % 8); } // return as list... currMem = newMem.ToList(); // scrivo sul PLC array di byte... libraryError = MEM_RWByteList(W, 0, RISC_CFI_DATA.MemType, RISC_CFI_DATA.Address, RISC_CFI_DATA.SubAddress, 0, RISC_CFI_DATA.Size, ref currMem); if (libraryError.IsError()) return libraryError; return NO_ERROR; } // Get the process Active Alarms public override CmsError PROC_RActiveAlarms(ushort procNumber, ref List alarms) { // FIXME TODO - fare guardando bitmap allarmi attivi #if false 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(); #endif return NO_ERROR; } // Get the process Mode public override CmsError PROC_RMode(ushort ProcNumber, ref PROC_MODE Mode) { //Check if the NC is Connected CmsError libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; // FIXME TODO - fare guardando mappatura memoria stsato processo #if false // 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); } #endif return NO_ERROR; } // Get PP Lines public override CmsError PROC_RPPLines(ushort ProcNumber, ref List Lines) { return FUNCTION_NOT_ALLOWED_ERROR; } // Get PP Name public override CmsError PROC_RSelectedPPName(ushort ProcNumber, ref string Name) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError PROC_RSelectedProcess(ref ushort procNumber) { if (SelectedProcess == 0) return SELECTED_PROCESS_ERROR; procNumber = SelectedProcess; //CmsError libraryError; //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 // libraryError = MEM_RWBoolean(R, 0, SELECTED_PROCESS.MemType, SELECTED_PROCESS.Address, memoryAddress, 2, ref readValue); // if (libraryError.IsError()) // return libraryError; // if (readValue) // { // procNumber = (ushort)(i + 1); // return NO_ERROR; // } //} return NO_ERROR; } public override CmsError PROC_RSelectedProcessData(int processId, ref SelectedProcessData processData) { if (processId <= 0) return PROC_NOT_FOUND_ERROR; // FIXME TODO - ha senso? #if false try { Item[] items = new Item[7] { new Item { Path = "/Channel/State/actTNumber[u" + processId + ",1]" }, // ActiveToolId new Item { Path = "/Channel/State/actDNumber[u" + processId + ",1]" }, // OffsetId new Item { Path = "/Channel/State/actFrameIndex[u" + processId + "]" }, // Origin new Item { Path = "DB21.DBB4"}, // Work override new Item { Path = "DB21.DBB5"}, // Rapid override, new Item { Path = "/Channel/State/actFeedRateIpo[u" + processId + ", 1]"}, new Item { Path = "/Nck/Configuration/numCuttEdgeParams[1]"}, // Cutt Edge Params }; // Read data DataSvc dataSvc = new DataSvc(); dataSvc.Read(items); short origin = 0; // Convert SIEMENS enumerable to G(N) format es: G54 if (Convert.ToInt16(items[2].Value) > 0) { if (Convert.ToInt16(items[1].Value) >= 5) origin = (short)(Convert.ToInt16(items[2].Value) + 500); else origin = (short)(Convert.ToInt16(items[2].Value) + 53); } OffsetModel offset = new OffsetModel(); //Read the ID of the Tool & Edge short actualToolId = Convert.ToInt16(items[0].Value); short actualEdgeId = Convert.ToInt16(items[1].Value); short numCuttEdgeParams = Convert.ToInt16(items[6].Value); int offsetEdge = (actualEdgeId - 1) * numCuttEdgeParams; if (actualToolId != 0 && actualEdgeId != 0) { //Setup the items for the tools. Must be read only this value Item[] itemsToolEdge = new Item[4] { new Item { Path = "/Tool/Compensation/edgeData[u1,c"+ actualToolId +","+ (offsetEdge + 3) + "]" }, // $TC_DP3 new Item { Path = "/Tool/Compensation/edgeData[u1,c"+ actualToolId +","+ (offsetEdge + 6) + "]" }, // $TC_DP6 new Item { Path = "/Tool/Compensation/edgeData[u1,c"+ actualToolId +","+ (offsetEdge + 12) + "]" }, // $TC_DP12 new Item { Path = "/Tool/Compensation/edgeData[u1,c"+ actualToolId +","+ (offsetEdge + 15) + "]" } // $TC_DP15 }; dataSvc.Read(itemsToolEdge); offset = new OffsetModel() { Id = actualEdgeId, Length = Convert.ToDouble(itemsToolEdge[0].Value), Radius = Convert.ToDouble(itemsToolEdge[1].Value), WearLength = Convert.ToDouble(itemsToolEdge[2].Value), WearRadius = Convert.ToDouble(itemsToolEdge[3].Value), RealLength = Convert.ToDouble(itemsToolEdge[0].Value) + Convert.ToDouble(itemsToolEdge[2].Value), RealRadius = Convert.ToDouble(itemsToolEdge[1].Value) + Convert.ToDouble(itemsToolEdge[3].Value) }; /* Other Method. Find it in the Database of the Tools... Too SLow? (Nicola Carminati 08/08/19) // Find edge EdgeModel edge = ToolTableData.Where(x => x.Id == Convert.ToInt16(items[0].Value)) .FirstOrDefault() .EdgesData.Where(x => x.Id == Convert.ToInt16(items[1].Value)) .FirstOrDefault(); //Find the Type of the Tool SiemensEdgesConfiguration toolEdgesConfig = new SiemensEdgesConfiguration(); List toolTypeConfig = toolEdgesConfig.EdgesConfig[ ToolTableData.Where(x => x.Id == Convert.ToInt16(items[0].Value)).FirstOrDefault().ToolType ]; if(toolTypeConfig != null && toolTypeConfig.Count > 0) { //Read Names of the parameters String lenghtName = toolTypeConfig.Where(x => x.Path == "$TC_DP3[").FirstOrDefault().Name; String radiusName = toolTypeConfig.Where(x => x.Path == "$TC_DP6[").FirstOrDefault().Name; String wearLenghtName = toolTypeConfig.Where(x => x.Path == "$TC_DP12[").FirstOrDefault().Name; String wearRadiusName = toolTypeConfig.Where(x => x.Path == "$TC_DP15[").FirstOrDefault().Name; if(!String.IsNullOrEmpty(wearLenghtName) && !String.IsNullOrEmpty(wearRadiusName) && !String.IsNullOrEmpty(lenghtName) && !String.IsNullOrEmpty(radiusName)) { // Convert edgeModel to offsetModel offset = new OffsetModel() { Id = (short)edge.Id, Length = edge.EdgeAdditionalParams[lenghtName], Radius = edge.EdgeAdditionalParams[radiusName], WearLength = edge.EdgeAdditionalParams[wearLenghtName], WearRadius = edge.EdgeAdditionalParams[wearRadiusName], RealLength = edge.EdgeAdditionalParams[lenghtName] + edge.EdgeAdditionalParams[wearLenghtName], RealRadius = edge.EdgeAdditionalParams[radiusName] + edge.EdgeAdditionalParams[wearRadiusName] }; } }*/ } // Creata return model processData = new SelectedProcessData { ActiveOffsetId = Convert.ToInt16(items[1].Value), Origin = origin, ProcessMessage = "", WorkOverride = Convert.ToByte(items[3].Value), RapidOverride = Convert.ToByte(items[4].Value), OffsetData = offset, FeedOverride = Convert.ToDouble(items[5].Value) }; } catch (Exception ex) { return ManageException(ex); } #endif 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 libraryError = CheckConnection(); if (libraryError.IsError()) return libraryError; // FIXME TODO - fare guardando mappatura variabili status #if false // 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); } #endif return NO_ERROR; } // Get process part program data public override CmsError PROC_RStatusAndData(ushort procNumber, ref ProcessDataModel processData) { processData.Id = procNumber; CmsError libraryError = NO_ERROR; #if false // Read part program name libraryError = PROC_RSelectedPPName(procNumber, ref processData.PartProgramName); if (libraryError.IsError()) return libraryError; #endif // FIXME TODO --> forzato tutto a true... eventualmente rivedere in futuro x processo caricatore vs processo principale bool forceValues = true; if (forceValues) { processData.Visible = true; processData.Type = "WORK"; processData.IsSelected = true; processData.IsInAlarm = false; processData.CanLoadProgram = true; processData.Status = "RUN"; processData.Reps = 0; } else { int readValue = 0; // Read processes status from memory libraryError = MEM_RWInteger(R, 0, PROCESS_STATUS.MemType, PROCESS_STATUS.Address, PROCESS_STATUS.SubAddress + ((procNumber - 1) * 2), ref readValue); if (libraryError.IsError()) return libraryError; 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_WSelectProcess(ushort procNumber) { CmsError libraryError; byte processNum = (byte)procNumber; // Check parameter if (processNum > MAX_PROCESS_NUMBER) return INCORRECT_PARAMETERS_ERROR; // Write process number libraryError = MEM_RWByte(W, true, 0, SELECT_PROCESS.MemType, SELECT_PROCESS.Address, SELECT_PROCESS.SubAddress, 0, ref processNum); if (libraryError.IsError()) return libraryError; return NO_ERROR; } public override CmsError TOOLS_RAdatpivePathStep(ref Byte step) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RAvailableTools(ref List multiTools, ref List tools) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RConfiguration(ref ToolTableConfiguration config) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RFamilyData(ref List families) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RMagazineAction(ref MagazineActionModel magazineAction) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RMagazineBlock(ref List ids) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RMagazineConfig(ref List config) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RMagazinePositions(ref List positions) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RMagazineStatus(ref Dictionary magazineStatus) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RMountedTools(int magazineId, ref List magazinePos) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_ROffset(short offsetId, ref OffsetModel offset) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RShanksData(ref List shanksData) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RStoredData(ref List tools, ref List families, ref List shanks) { return FUNCTION_NOT_ALLOWED_ERROR; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override CmsError TOOLS_RToolsData(ref List toolTable) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_RUpdatedToolsData(ref Dictionary updatedStatus, ref Dictionary updatedLives, ref Dictionary updatedPresetting, ref Dictionary updatedDressing) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WAbortBallufTablet() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WAdatpivePathStep(Byte step) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WAddEdge(int toolId, ref EdgeModel edge) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WAddFamily(ref FamilyModel family) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WAddShank(ref ShankModel shank) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WAddTool(ref SiemensToolModel tool) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WDeleteEdge(int toolId, int edgeId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WDeleteFamily(string name) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WDeleteShank(int id) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WDeleteTool(int id) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WEmptyBallufTablet(SiemensToolModel tool) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WEmptyBallufTabletAdditionalData(SiemensToolModel tool) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WFreeMagazines() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WLoadToolInMagazine(int magazine, NewToolInMagazineModel newMagazineTool, ref MountedToolModel newMountedTool) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WLoadToolIntoShank(int shankId, int positionId, int toolId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WOffset(short offsetId, ref OffsetModel offset) { return FUNCTION_NOT_ALLOWED_ERROR; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override CmsError TOOLS_WOptions(ToolManagerOptionsModel options) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WRestoreBackup() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStartEditData() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStartEditTooling(int magazineId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStartTDILoading(ushort magazineId, ushort positionId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStartTDIUnloading(ushort magazineId, ushort positionId, ushort toolId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStopEditData() { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WStopEditTooling(int magazineId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUnloadToolFromMagazine(int magazineId, int positionId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUnloadToolFromShank(int shankId, int positionId) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateEdge(int toolId, ref EdgeModel newEdge) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateFamilies(List list) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateFamilyData(string oldName, string newName) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateMagazinePositions(List list) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdatePosition(PositionModel position) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateShank(ref ShankModel shank) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateShanks(List list) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateTool(ref SiemensToolModel tool) { return FUNCTION_NOT_ALLOWED_ERROR; } public override CmsError TOOLS_WUpdateTools(List list) { return FUNCTION_NOT_ALLOWED_ERROR; } #endregion Public Methods #region Protected Classes /// /// Oggetto Modulo Blocco da PLC /// protected class PlcModBlock { #region Public Constructors /// /// Deserializzazione da byte ad oggetto Param /// /// public PlcModBlock(byte[] rawData) { // converto i dati da byte grezzi ai 3 componenti... Id = S7.Net.Types.Int.FromByteArray(rawData.Skip(0).Take(2).ToArray()); EstimDuration = S7.Net.Types.DInt.FromByteArray(rawData.Skip(2).Take(4).ToArray()); EstimDelay = S7.Net.Types.DInt.FromByteArray(rawData.Skip(6).Take(4).ToArray()); PrevId_01 = S7.Net.Types.Int.FromByteArray(rawData.Skip(12).Take(2).ToArray()); PrevId_02 = S7.Net.Types.Int.FromByteArray(rawData.Skip(14).Take(2).ToArray()); PrevId_03 = S7.Net.Types.Int.FromByteArray(rawData.Skip(16).Take(2).ToArray()); } #endregion Public Constructors #region Public Properties public int EstimDelay { get; set; } = 0; public int EstimDuration { get; set; } = 0; public short Id { get; set; } = 0; public short PrevId_01 { get; set; } = 0; public short PrevId_02 { get; set; } = 0; public short PrevId_03 { get; set; } = 0; #endregion Public Properties #region Public Methods /// /// Converte un singolo item in un array di byte per scrittura su PLC S7 /// /// public byte[] convertToByte() { byte[] answ = new byte[18]; Buffer.BlockCopy(S7.Net.Types.Int.ToByteArray(Id), 0, answ, 0, 2); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(EstimDuration), 0, answ, 2, 4); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(EstimDelay), 0, answ, 6, 4); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(PrevId_01), 0, answ, 12, 2); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(PrevId_02), 0, answ, 14, 2); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(PrevId_03), 0, answ, 16, 2); return answ; } #endregion Public Methods } /// /// Oggetto Modulo Blocco RT da PLC /// protected class PlcModBlockRT { #region Public Constructors /// /// Deserializzazione da byte ad oggetto ParamRT /// /// public PlcModBlockRT(byte[] rawData) { // converto i dati da byte grezzi ai 3 componenti... Id = S7.Net.Types.Int.FromByteArray(rawData.Skip(0).Take(2).ToArray()); ActualDuration = S7.Net.Types.DInt.FromByteArray(rawData.Skip(2).Take(4).ToArray()); ActualDelay = S7.Net.Types.DInt.FromByteArray(rawData.Skip(6).Take(4).ToArray()); // sono in realtà BIT STRUC --> reverse! Stato = S7.Net.Types.Word.FromByteArray(rawData.Skip(10).Take(2).Reverse().ToArray()); // calcolo bit... Visible = (Stato & 1) == 1; Running = (Stato & 2) == 2; HasError = (Stato & 4) == 4; Terminated = (Stato & 8) == 8; } #endregion Public Constructors #region Private Properties private ushort Stato { get; set; } = 0; #endregion Private Properties #region Public Properties public int ActualDelay { get; set; } = 0; public int ActualDuration { get; set; } = 0; public bool HasError { get; set; } public short Id { get; set; } = 0; public bool Running { get; set; } public bool Terminated { get; set; } = false; public bool Visible { get; set; } #endregion Public Properties #region Public Methods /// /// Converte un singolo item in un array di byte per scrittura su PLC S7 /// /// public byte[] convertToByte() { // convero stato dai bit... Stato = 0; Stato += (ushort)(Visible ? 1 : 0); Stato += (ushort)(Running ? 2 : 0); Stato += (ushort)(HasError ? 4 : 0); Stato += (ushort)(Terminated ? 8 : 0); byte[] answ = new byte[12]; Buffer.BlockCopy(S7.Net.Types.Int.ToByteArray(Id), 0, answ, 0, 2); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(ActualDuration), 0, answ, 2, 4); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(ActualDelay), 0, answ, 6, 4); Buffer.BlockCopy(S7.Net.Types.Word.ToByteArray(Stato), 0, answ, 10, 1); return answ; } #endregion Public Methods } /// /// Oggetto Parametro da PLC /// protected class PlcParam { #region Public Constructors /// /// Deserializzazione da byte ad oggetto Param /// /// public PlcParam(byte[] rawData) { // converto i dati da byte grezzi ai 3 componenti... Id = S7.Net.Types.Int.FromByteArray(rawData.Skip(0).Take(2).ToArray()); SetpointHMI = S7.Net.Types.DInt.FromByteArray(rawData.Skip(2).Take(4).ToArray()); SetpointPLC = S7.Net.Types.DInt.FromByteArray(rawData.Skip(6).Take(4).ToArray()); ValMax = S7.Net.Types.DInt.FromByteArray(rawData.Skip(10).Take(4).ToArray()); ValMin = S7.Net.Types.DInt.FromByteArray(rawData.Skip(14).Take(4).ToArray()); UnitMeasure = S7.Net.Types.Word.FromByteArray(rawData.Skip(18).Take(2).ToArray()); } #endregion Public Constructors #region Public Properties public short Id { get; set; } = 0; public int SetpointHMI { get; set; } = 0; public int SetpointPLC { get; set; } = 0; public ushort UnitMeasure { get; set; } = 0; public int ValMax { get; set; } = 0; public int ValMin { get; set; } = 0; #endregion Public Properties #region Public Methods /// /// Converte un singolo item in un array di byte per scrittura su PLC S7 /// /// public byte[] convertToByte() { byte[] answ = new byte[20]; Buffer.BlockCopy(S7.Net.Types.Int.ToByteArray(Id), 0, answ, 0, 2); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(SetpointHMI), 0, answ, 2, 4); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(SetpointPLC), 0, answ, 6, 4); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(ValMax), 0, answ, 10, 4); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(ValMin), 0, answ, 14, 4); Buffer.BlockCopy(S7.Net.Types.Word.ToByteArray(UnitMeasure), 0, answ, 18, 2); return answ; } #endregion Public Methods } /// /// Oggetto Parametro RT da PLC /// protected class PlcParamRT { #region Public Constructors /// /// Deserializzazione da byte ad oggetto ParamRT /// /// public PlcParamRT(byte[] rawData) { // converto i dati da byte grezzi ai 3 componenti... Id = S7.Net.Types.Int.FromByteArray(rawData.Skip(0).Take(2).ToArray()); ValueAct = S7.Net.Types.DInt.FromByteArray(rawData.Skip(4).Take(4).ToArray()); Visible = S7.Net.Types.Boolean.GetValue(rawData[2], 0); Enabled = S7.Net.Types.Boolean.GetValue(rawData[2], 1); HasError = S7.Net.Types.Boolean.GetValue(rawData[2], 2); #if false // calcolo bit... Stato = S7.Net.Types.Word.FromByteArray(rawData.Skip(2).Take(2).Reverse().ToArray()); Visible = (Stato & 1) == 1; Enabled = (Stato & 2) == 2; HasError = (Stato & 4) == 4; #endif } #endregion Public Constructors #region Private Properties private byte Stato { get; set; } = 0; #endregion Private Properties #region Public Properties public bool Enabled { get; set; } public bool HasError { get; set; } public short Id { get; set; } = 0; public int ValueAct { get; set; } = 0; public bool Visible { get; set; } #endregion Public Properties #region Public Methods /// /// Converte un singolo item in un array di byte per scrittura su PLC S7 /// /// public byte[] convertToByte() { // convero stato dai bit... Stato = 0; Stato += (byte)(Visible ? 1 : 0); Stato += (byte)(Enabled ? 2 : 0); Stato += (byte)(HasError ? 4 : 0); byte[] answ = new byte[8]; Buffer.BlockCopy(S7.Net.Types.Int.ToByteArray(Id), 0, answ, 0, 2); Buffer.BlockCopy(S7.Net.Types.Byte.ToByteArray(Stato), 0, answ, 2, 1); Buffer.BlockCopy(S7.Net.Types.DInt.ToByteArray(ValueAct), 0, answ, 4, 4); return answ; } #endregion Public Methods } #endregion Protected Classes //private void CheckData(object obj, List config) //{ // foreach(PropertyInfo prop in obj.GetType().GetProperties()) // { // bool val = config.Where(x => x.Name == prop.Name).Select(x => x.); // } //} } }