diff --git a/IOB-UT-NEXT/Enums.cs b/IOB-UT-NEXT/Enums.cs index 8e65d7e8..faa39363 100644 --- a/IOB-UT-NEXT/Enums.cs +++ b/IOB-UT-NEXT/Enums.cs @@ -362,6 +362,11 @@ namespace IOB_UT_NEXT /// ND, + /// + /// Adapter MITSUBISHI con EZCnc lib + /// + MITSUBISHI, + /// /// Adapter ModBus TCP generico /// diff --git a/IOB-WIN-NEXT/AdapterForm.cs b/IOB-WIN-NEXT/AdapterForm.cs index 8af62843..09ce9789 100644 --- a/IOB-WIN-NEXT/AdapterForm.cs +++ b/IOB-WIN-NEXT/AdapterForm.cs @@ -1,4 +1,5 @@ using IOB_UT_NEXT; +using IOB_WIN_NEXT.Iob; using IOB_WIN_NEXT.IobSoap; using MapoSDK; using Newtonsoft.Json; @@ -1690,6 +1691,11 @@ namespace IOB_WIN_NEXT start.Enabled = true; break; + case tipoAdapter.MITSUBISHI: + iobObj = new Mitsubishi(this, IOBConf); + start.Enabled = true; + break; + case tipoAdapter.MODBUS_TCP: iobObj = new IobModbusTCP.ModbusTCP(this, IOBConf); start.Enabled = true; diff --git a/IOB-WIN-NEXT/DATA/CONF/VL28.ini b/IOB-WIN-NEXT/DATA/CONF/VL28.ini index e62241bf..7a68a81d 100644 --- a/IOB-WIN-NEXT/DATA/CONF/VL28.ini +++ b/IOB-WIN-NEXT/DATA/CONF/VL28.ini @@ -52,6 +52,7 @@ BLINK_FILT=0 [OPTPAR] EZNC_SYS=EZNC_SYS_MELDAS700L +ENABLE_PZCOUNT=TRUE ;PZCOUNT_MODE=STD|BIT ;PZCOUNT_MODE=STD.PAR.6711 ;PZGTOT_MODE=STD.PAR.6712 @@ -67,8 +68,8 @@ ENABLE_SEND_PZC_BLOCK=TRUE MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 ; conf cablata set Art/Commessa -SET_NUM_ART=STD.VAR.501 SET_NUM_COM=STD.VAR.500 +SET_NUM_ART=STD.VAR.501 SET_NUM_PZ=STD.VAR.502 MAX_CHAR_DESC=7 ;indica se il numero articolo sia semplicemente il trim dei caratteri alfabetici (chiama comunque server...) diff --git a/IOB-WIN-NEXT/Iob/Fanuc.cs b/IOB-WIN-NEXT/Iob/Fanuc.cs index 90d1553f..34223681 100644 --- a/IOB-WIN-NEXT/Iob/Fanuc.cs +++ b/IOB-WIN-NEXT/Iob/Fanuc.cs @@ -24,6 +24,7 @@ namespace IOB_WIN_NEXT.Iob /// public Fanuc(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { + lgInfo("Start init Fanuc"); // i dati RAW principali sono 6 byte... RawInput = new byte[6]; diff --git a/IOB-WIN-NEXT/Iob/Mitsubishi.cs b/IOB-WIN-NEXT/Iob/Mitsubishi.cs new file mode 100644 index 00000000..2d8121d8 --- /dev/null +++ b/IOB-WIN-NEXT/Iob/Mitsubishi.cs @@ -0,0 +1,2578 @@ +using EgwProxy.MultiCncLib.CNC; +using IOB_UT_NEXT; +using KRcc; +using MapoSDK; +using Newtonsoft.Json; +using Opc.Ua; +using Org.BouncyCastle.Utilities.Collections; +using System; +using System.Collections.Generic; +using System.Data.SqlTypes; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; + +namespace IOB_WIN_NEXT.Iob +{ + public class Mitsubishi : Iob.Generic + { + #region Public Constructors + + /// + /// Controllo specifico da gestire + /// + public enum SYSTEMTYPE + { + /// + /// M700L + /// + EZNC_SYS_MELDAS700L = 5, + /// + /// M700M + /// + EZNC_SYS_MELDAS700M = 6, + /// + /// C70 + /// + EZNC_SYS_MELDASC70 = 7, + /// + /// M800L + /// + EZNC_SYS_MELDAS800L = 8, + /// + /// M800M + /// + EZNC_SYS_MELDAS800M = 9, + /// + /// C80 + /// + EZNC_SYS_CNCC80 = 10, + } + + /// + /// Tipo di controllo gestito + /// + private SYSTEMTYPE sysType = SYSTEMTYPE.EZNC_SYS_MELDAS700L; + + /// + /// Indirizzo partenza lettura Var(100/500) + /// + private int MemVarStart = 500; + /// + /// Num celle Var da leggere + /// + private int MemVarNum = 1; + + /// + /// Array contenuto memorie Var + /// + private Dictionary VarDict { get; set; } = new Dictionary(); + + + /// + /// Indirizzo partenza lettura Param + /// + private int ParamStart = 8000; + /// + /// Num celle Param da leggere + /// + private int ParamNum = 1; + /// + /// Array contenuto memorie Param + /// + private Dictionary ParamDict { get; set; } = new Dictionary(); + + /// + /// Max num caratteri string ammessi VAR label + /// + private int maxVarStrLen = 7; + + /// + /// Nome amcchina x connessione + /// + protected string hostName = "EZNC_LOCALHOST"; + + /// + /// Nome/IP del CN + /// + protected string ipAddr=""; + /// + /// Porta di comunicazione INT + /// + protected int ezPort = 683; + + + /// + /// Obj di comunicazione Mitsubishi + /// + protected EZNCAUTLib.DispEZNcCommunication oEZNcAutCom = null; + + /// + /// Estende l'init della classe base... + /// + /// + /// + public Mitsubishi(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + lgInfo("Start init Mitsubishi"); + // gestione invio ritardato contapezzi + pzCountDelay = utils.CRI("pzCountDelay"); + lastPzCountSend = DateTime.Now; + lastWarnODL = DateTime.Now; + + // inizializzo correttamente aree memoria secondo CONF - iniFileName + IniFile fIni = new IniFile(IOBConf.iniFileName); + + // inizializzo aree di memoria correnti... + MemVarStart = fIni.ReadInteger("MEMORY", "AREAV_START", 500); + MemVarNum = fIni.ReadInteger("MEMORY", "AREAV_SIZE", 1); + ParamStart = fIni.ReadInteger("MEMORY", "PAR_START", 8001); + ParamNum = fIni.ReadInteger("MEMORY", "PAR_SIZE", 1); + + // loggo aree di memoria avviate... + lgInfo($"Avviata area di memoria Var: {MemVarNum} vars"); + lgInfo($"Avviata area di memoria Param: {ParamNum} params"); + + // fix enable prgName + enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); + + + + // effettuo lettura della conf sigLUT... cercando 1:1 i bit... + string currBit = ""; + string memArea = ""; + for (int i = 0; i < 8; i++) + { + currBit = $"BIT{i}"; + memArea = fIni.ReadString("MEMORY", currBit, ""); + // se trovo un valore... + if (!string.IsNullOrEmpty(memArea)) + { + signLUT.Add(currBit, memArea); + } + } + + // recupero sysType del controllo, sennò default M700L... + string sEZNC_SYS = getOptPar("EZNC_SYS"); + if (!string.IsNullOrEmpty(sEZNC_SYS)) + { + sysType = (SYSTEMTYPE)Enum.Parse(typeof(SYSTEMTYPE), sEZNC_SYS); + } + lgInfo($"Start init Mitsubishi | SysType: {sysType}"); + + + // gestione override contapezzi + enablePzCountByApp = utils.CRB("enableContapezzi"); + enablePzCountByIob = (getOptPar("ENABLE_PZCOUNT") == "TRUE"); + disablePzCountByIob = (getOptPar("DISABLE_PZCOUNT") == "FALSE"); + + // gestione override idx articoli... + if (!string.IsNullOrEmpty(getOptPar("NUM_ART_CHR_TRIM"))) + { + string NUM_ART_CHR_TRIM = getOptPar("NUM_ART_CHR_TRIM"); + bool.TryParse(NUM_ART_CHR_TRIM, out numArtCharTrim); + } + if (!string.IsNullOrEmpty(getOptPar("MAX_CHAR_DESC"))) + { + string MAX_CHAR_DESC = getOptPar("MAX_CHAR_DESC"); + int.TryParse(MAX_CHAR_DESC, out maxVarStrLen); + } + + // leggo conf x ricerca valori memoria da tracciare in log di continuo... + mem2trace = fIni.ReadString("OPTPAR", "MEM_2_TRACE", ""); + + // è little endian (NON serve conversione) + hasBigEndian = false; + lgInfoStartup($"Start init Adapter MITSUBISHI | IP {IOBConf.cncIpAddr}:{IOBConf.cncPort} per IOB {IOBConf.codIOB}"); + + // Creo oggetto connessione NC + parentForm.commPlcActive = true; + + // init oggetto + oEZNcAutCom = new EZNCAUTLib.DispEZNcCommunication(); + int.TryParse(IOBConf.cncPort, out ezPort); + ipAddr = IOBConf.cncIpAddr; + +#if false + // Open communication + int iRet = 0; + iRet = oEZNcAutCom.SetTCPIPProtocol(ipAddr, ezPort); + iRet = oEZNcAutCom.Open3((int)sysType, 1, 10, hostName); +#endif + parentForm.commPlcActive = false; + + // effettuo disconnect + connect... + lgInfo("MITSUBISHI startup: tryDisconnect"); + tryDisconnect(); + lgInfo("MITSUBISHI startup: tryConnect"); + tryConnect(); + if ((enablePzCountByApp || enablePzCountByIob) && !(disablePzCountByIob)) + { + lgInfo("MITSUBISHI: inizio gestione contapezzi"); + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) + if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + if (getOptPar("PZCOUNT_MODE").StartsWith("STD")) + { + lgInfo("Init contapezzi MITSUBISHI: pzCntReload(true)"); + pzCntReload(true); + // refresh associazione Macchina - IOB + SendM2IOB(); + // invio altri dati accessori... + SendMachineConf(); + // per adesso imposto lettura MITSUBISHI == contapezzi (poi farà vera lettura...) + contapezziPLC = contapezziIOB; + } + else + { + contapezziIOB = 0; + lgInfo("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE")); + } + } + else + { + contapezziIOB = 0; + lgInfo("Parametro mancante PZCOUNT_MODE"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi MITSUBISHI 01"); + } + } + // finisco INIT ADAPTER + lgInfo("End init Adapter MITSUBISHI"); + } + + #endregion Public Constructors + + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... + Dictionary taskDone = new Dictionary(); + if (task2exe != null) + { + bool taskOk = false; + string taskVal = ""; + string newVal = ""; + string memAddr = ""; + int newValInt = 0; + // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 + foreach (var item in task2exe) + { + taskOk = false; + taskVal = ""; + // converto richiesta in enum... + taskType tName = taskType.nihil; + Enum.TryParse(item.Key, out tName); + switch (tName) + { + case taskType.setArt: + case taskType.setComm: + lgInfo($"Richiesta scrittura {tName}"); + // salvo in memoria il valore richiesto... + if (memMap != null && memMap.mMapWrite != null) + { + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + dataConf currMem = memMap.mMapWrite[item.Key]; + memAddr = currMem.memAddr; + taskVal = $"SET task: {item.Key} --> {newVal} | mem: {currMem.memAddr} - {currMem.size} byte"; + // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà + memMap.mMapWrite[item.Key].value = newVal; + } + else + { + taskVal = $"NO DATA MEM, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + } + else + { + taskVal = $"NO MemMap found, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + // salvo in currProd.. + saveProdData(new KeyValuePair(item.Key, item.Value)); + upsertKey(item.Key, item.Value); + break; + + case taskType.nihil: + case taskType.fixStopSetup: + case taskType.forceResetPzCount: + case taskType.setProg: + case taskType.forceSetPzCount: + case taskType.sendWatchDogMes2Plc: + taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + case taskType.setArtNum: + lgInfo($"Richiesta scrittura CodART numerico"); + // in primis faccio una chiamata per tutta la tab SE fosse vuoto il dict + // di traduzione + if (DictNumArt == null || DictNumArt.Count == 0) + { + getNumArt(""); + lgInfo($"Recuperato DictNumArt, trovati {DictNumArt.Count} rec"); + } + // chiamo server x avere decodifica valore INT + newVal = getNumArt(item.Value); + // se c'è gestione semplificata num articolo --> usa trim dei soli + // caratteri alfabetici lasciando numeri.. + if (numArtCharTrim) + { + newVal = baseUtils.GetNumbers(item.Value); + } + // converto int... + int.TryParse(newVal, out newValInt); + // procedo come il resto cercando mappatura in memMap: recupero dati da memMap... + if (memMap != null && memMap.mMapWrite != null) + { + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + dataConf currMem = memMap.mMapWrite[item.Key]; + memAddr = currMem.memAddr; + taskVal = $"SET task: {item.Key} --> {newVal} | mem: {currMem.memAddr} - {currMem.size} byte"; + // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà + memMap.mMapWrite[item.Key].value = newVal; + } + else + { + taskVal = $"NO DATA MEM, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + } + else + { + taskVal = $"NO MemMap found, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + + // invio a controller... + taskOk = setNumArt(newValInt); + //se ho successo rileggo ed eventualmente sistemo valore + if (taskOk) + { + //var rVal = getValByParam("SET_NUM_ART"); + var rVal = getValByMemAddr(memAddr); + if (rVal == newVal) + { + lgInfo("All OK"); + // invio aggiornamento x reset richiesta... test! + sendOptVal(item.Key, newVal); + } + else + { + lgError($"Error | memName: {memAddr} | rVal: {rVal} | newVal: {newVal}"); + } + } + else + { + lgError("Errore in scrittura SetNumArt"); + } + // salvo in currProd.. + saveProdData(new KeyValuePair(item.Key, newVal)); + upsertKey(item.Key, item.Value); + break; + + case taskType.setCommNum: + lgInfo($"Richiesta scrittura cod COMMESSA numerica"); + // chiamo server x avere decodifica valore INT + newVal = getNumComm(item.Value); + // converto int... + int.TryParse(newVal, out newValInt); + //riscrivo senza eventuali zeri... + newVal = newValInt > 0 ? $"{newValInt}" : newVal; + lgTrace($"Conv.Int numComm | newVal: {newVal} | newValInt: {newValInt}"); + // procedo come il resto cercando mappatura in memMap: recupero dati da memMap... + if (memMap != null && memMap.mMapWrite != null) + { + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + dataConf currMem = memMap.mMapWrite[item.Key]; + memAddr = currMem.memAddr; + taskVal = $"SET task: {item.Key} --> {newVal} | mem: {currMem.memAddr} - {currMem.size} byte"; + // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà + memMap.mMapWrite[item.Key].value = newVal; + } + else + { + taskVal = $"NO DATA MEM, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + } + else + { + taskVal = $"NO MemMap found, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + + // invio a controller... + taskOk = setNumCom(newValInt); + //se ho successo rileggo ed eventualmente sistemo valore + if (taskOk) + { + //var rVal = getValByParam("SET_NUM_COM"); + var rVal = getValByMemAddr(memAddr); + if (rVal == newVal) + { + lgInfo("All OK"); + // invio aggiornamento x reset richiesta... test! + sendOptVal(item.Key, newVal); + } + else + { + lgError($"Error | memName: {memAddr} | rVal: {rVal} | newVal: {newVal}"); + } + } + else + { + lgError("Errore in scrittura SetNumCom"); + } + // salvo in currProd.. + saveProdData(new KeyValuePair(item.Key, newVal)); + upsertKey(item.Key, item.Value); + break; + + case taskType.setPzComm: + int pzReq = 0; + int.TryParse(item.Value, out pzReq); + // set pezzi richiesti inizio setup + taskOk = setPzComm(pzReq); + taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC"; + lgInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}"); + + // salvo in currProd.. + saveProdData(new KeyValuePair(item.Key, newVal)); + upsertKey(item.Key, item.Value); + break; + + case taskType.startSetup: + // reset contapezzi inizio setup + taskOk = resetContapezziPLC(); + taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC"; + lgInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + case taskType.stopSetup: + // reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE") + { + taskOk = resetContapezziPLC(); + } + taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC"; + lgInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + case taskType.setParameter: + lgInfo($"Chiamata setParameter | NO processing: taskOk: {taskOk} | taskVal: {taskVal}"); + taskVal = "setParameter | SKIPPED | NO EXEC"; + break; + + default: + lgInfo($"Chiamata default senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + taskVal = "SKIPPED | NO EXEC"; + break; + } + // aggiungo task! + taskDone.Add(item.Key, taskVal); + } + } + return taskDone; + } + + /// + /// Wrapper chiamata lettura/scrittura INTERO in area macro... + /// + /// + /// + /// + /// + public bool MITSUBISHIMemMacroRW(bool bWrite, Int32 memIndex, ref short Value) + { + bool answ = false; + if (connectionOk) + { + if (MITSUBISHI_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + // provo ad usare SEMPRE double... + short zeroVal = 0; + // in primis scrivo reset a zero... + answ = MITSUBISHI_ref.F_RW_Macro_Short(bWrite, memIndex, ref zeroVal); + // ora scrivo vero valore... + answ = MITSUBISHI_ref.F_RW_Macro_Short(bWrite, memIndex, ref Value); + } + catch (Exception exc) + { + lgError($"Eccezione in MITSUBISHIMemMacroRW | Short{Environment.NewLine}{exc}"); + } + } + } + parentForm.commPlcActive = false; + return answ; + } + + /// + /// Wrapper chiamata lettura/scrittura DOUBLE in area macro... + /// + /// + /// + /// + /// + public bool MITSUBISHIMemMacroRW(bool bWrite, Int32 memIndex, ref double Value) + { + bool answ = false; + if (connectionOk) + { + if (MITSUBISHI_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + short zeroVal = 0; + // in primis scrivo reset a zero... + answ = MITSUBISHI_ref.F_RW_Macro_Short(bWrite, memIndex, ref zeroVal); + // ora scrivo vero valore... + answ = MITSUBISHI_ref.F_RW_Macro_Double(bWrite, memIndex, ref Value); + } + catch (Exception exc) + { + lgError($"Eccezione in MITSUBISHIMemMacroRW | Double{Environment.NewLine}{exc}"); + } + } + } + parentForm.commPlcActive = false; + return answ; + } + + /// + /// wrapper chiamata lettura/scrittura SINGOLO BYTE... + /// + /// + /// + /// + /// + /// + public bool MITSUBISHIMemRW(bool bWrite, MITSUBISHI.MemType MemType, Int32 memIndex, ref byte Value) + { + bool answ = false; + if (connectionOk) + { + if (MITSUBISHI_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + answ = MITSUBISHI_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); + } + catch + { } + } + } + parentForm.commPlcActive = false; + return answ; + } + + /// + /// wrapper chiamata lettura/scrittura MULTI BYTE... + /// + /// + /// + /// + /// + /// + public bool MITSUBISHIMemRW(bool bWrite, MITSUBISHI.MemType MemType, Int32 memIndex, ref byte[] Value) + { + bool answ = false; + if (connectionOk) + { + if (MITSUBISHI_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + answ = MITSUBISHI_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); + } + catch + { } + } + } + parentForm.commPlcActive = false; + return answ; + } + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() + { + Dictionary outVal = new Dictionary(); + // processo SOLO SE connected... + if (connectionOk) + { + if (MITSUBISHI_ref.Connected) + { + stopwatch.Restart(); + EgwProxy.MultiCncLib.Focas1.ODBDY2_1 answ = MITSUBISHI_ref.getAllDynData(); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("PROC-DYN-DATA"), stopwatch.ElapsedTicks); + } + + try + { + string actf = answ.actf.ToString(); + string acts = answ.acts.ToString(); + //string numAlarm = memName.alarm.ToString(); + // preparo i singoli valori dell'array... + //outVal.Add("DYNDATA", string.Format("{0}#{1}#{2}", actf, acts, numAlarm)); + outVal.Add("DYNDATA", string.Format("FEED {0}#SPEED_RPM {1}", actf, acts)); + if (utils.CRB("SendFeedSpeed")) + { + outVal.Add("FEED", actf); + outVal.Add("SPEED_RPM", acts); + //outVal.Add("NUM_ALARM", numAlarm); + } + if (utils.CRB("SendAxPos")) + { + // salvo le posizioni... + EgwProxy.MultiCncLib.Focas1.FAXIS posAx = answ.pos; + int[] currPosAbs = posAx.absolute; + int i = 0; + foreach (var item in currPosAbs) + { + i++; + outVal.Add(string.Format("POS_{0:00}", i), item.ToString()); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in getDynData"); + } + stopwatch.Stop(); + } + } + return outVal; + } + + /// + /// Recupero dati override (da area G che è già stata letta...) + /// + /// + public override Dictionary getOverrides() + { + Dictionary outVal = new Dictionary(); + // processo SOLO SE connected... + if (connectionOk) + { + if (MITSUBISHI_ref.Connected) + { + if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) + { + outVal.Add("FEED_OVER", MemBlockG[30].ToString()); + outVal.Add("RAPID_OVER", MemBlockG[12].ToString()); + } + } + } + return outVal; + } + + /// + /// Recupero programma in lavorazione + /// + /// + public override string getPrgName() + { + string prgName = ""; + // recupero NUOVO prgName... + try + { + // recupero nome programma MAIN + prgName = utils.purgedChar2String(MITSUBISHI_ref.getPrgNameMain()); + // trimmo path del programma, ovvero "CNCMEMUSERPATH1" + prgName = prgName.Replace(utils.CRS("basePrgMemPath"), ""); + lgInfo("Current PROG: {0}", prgName); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; + } + return prgName; + } + + /// + /// Recupero programma in lavorazione come Dictionary MITSUBISHI... + /// - SYSINFO: (prima KEY globale) TUTTI i valori separati da # (x fare check modifica) + /// - altre stringhe: ogni singolo parametro / valore + /// + /// + public override Dictionary getSysInfo() + { + Dictionary outVal = new Dictionary(); + stopwatch.Restart(); + EgwProxy.MultiCncLib.Focas1.ODBSYS answ = MITSUBISHI_ref.getSysInfo(); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("SYS-INFO"), stopwatch.ElapsedTicks); + } + + try + { + string cnc_type = new string(answ.cnc_type); + string mt_type = new string(answ.mt_type); + string series = new string(answ.series); + string version = new string(answ.version); + string axes = new string(answ.axes); + //short addInfo = memName.addinfo; + short max_axis = answ.max_axis; + // preparo i singoli valori dell'array... + outVal.Add("SYSINFO", string.Format("{0}#{1}#{2}#{3}#{4}#{5}", cnc_type, mt_type, series, version, axes, max_axis)); + outVal.Add("CNC", cnc_type); + outVal.Add("MTT", mt_type); + outVal.Add("SER", series); + outVal.Add("VER", version); + outVal.Add("AXS", string.Format("{0}|{1}", axes, max_axis)); + } + catch (Exception exc) + { + lgError(exc, "Errore in getSysInfo"); + connectionOk = false; + } + return outVal; + } + + /// + /// Effettua vero processing contapezzi: + /// 6711: pezzi lavorati + /// 6712: pezzi lavorati totali + /// 6713: pezzi richiesti + /// + public override void processContapezzi() + { + if ((enablePzCountByApp || enablePzCountByIob) && !(disablePzCountByIob)) + { + // procedo SOLO SE ho connessione... + if (connectionOk) + { + try + { + // controllo di AVERE parametri opzionali x conteggi vari + if (cIobConf.optPar.Count > 0) + { + // contapezzi ATTUALE + if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT + // (Custom, con indicazione area) + string memAddr = getOptPar("PZCOUNT_MODE"); + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + } + // var di appoggio + int cntAddr = 0; + object outputVal = new object(); + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 6711; + } + // processo parametro contapezzi (lavorati) + stopwatch.Restart(); + MITSUBISHI_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); + } + // salvo ultimo conteggio rilevato + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + // 2022.05.23 gestione MACRO da testare (Jetco) + else if (memAddr.StartsWith("MACRO.")) + { + lgTrace($"Decodifica memoria MACRO | memName: {memAddr}"); + // recupero parametro... + int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr); + // processo parametro + stopwatch.Restart(); + double macroVal = 0; + MITSUBISHI_ref.F_Read_macro(cntAddr, ref macroVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-MACRO", 5), stopwatch.ElapsedTicks); + } + // salvo ultimo conteggio rilevato + int newVal = -1; + Int32.TryParse($"{macroVal}", out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + // altrimenti se legge da area memoria specifica leggo da li... + // formato tipo STD.D.1604.DW + else + { + memAddressMITSUBISHI areaCounter = new memAddressMITSUBISHI(memAddr); + if (isVerboseLog) + { + lgInfo("processContapezzi [0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo + // conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = 0; + MITSUBISHI_ref.F_RW_Byte(false, areaCounter.mType, areaCounter.mPos, ref valB); + outputVal = valB; + break; + + case "D": + ushort valW = 0; + MITSUBISHI_ref.F_RW_Word(false, areaCounter.mType, areaCounter.mPos, ref valW); + outputVal = valW; + break; + + case "DW": + uint valDW = 0; + MITSUBISHI_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); + if (isVerboseLog) + { + lgInfo("[1] valDW contapezzi: {0}", valDW); + } + + outputVal = valDW; + if (isVerboseLog) + { + lgInfo("[2] outputVal contapezzi: {0}", outputVal); + } + + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + // salvo... + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + //if (isVerboseLog) + //{ + lgInfo("[3] contapezziPLC contapezzi: {0}", contapezziPLC); + //} + } + stopwatch.Stop(); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi MITSUBISHI 02"); + connectionOk = false; + } + } + else + { + lgError("Errore: manca connessione in contapezzi MITSUBISHI"); + } + } + } + + /// + /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) + /// + public override void processMode() + { + // processo SOLO SE connected... + if (connectionOk) + { + if (MITSUBISHI_ref.Connected) + { + if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) + { + try + { + // leggo tutto da 0 a 43... + int memIndex = 0; + // controllo modalità lettura memoria + stopwatch.Restart(); + MITSUBISHIMemRW(R, MITSUBISHI.MemType.G, memIndex, ref MemBlockG); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-G-AREA", MemBlockG.Length), stopwatch.ElapsedTicks); + } + + stopwatch.Stop(); + // verifico modo con valore corrente, se cambia aggiorno... + CNC_MODE newMode = decodeG43(MemBlockG[43]); + if (newMode != currMode) + { + // aggiorno! + currMode = newMode; + // conversione NUM MODE in descrizione da ENUM + string descrMode = Enum.GetName(typeof(CNC_MODE), currMode); + // accodo x invio + string sVal = string.Format("[CNC_MODE]{0}", descrMode); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog("CNC_MODE", descrMode)); + } + } + catch (Exception exc) + { + lgError(exc, string.Format("Errore in process Mode G43: {0}{1}", Environment.NewLine, exc)); + connectionOk = false; + stopwatch.Stop(); + } + } + } + } + } + + /// + /// Recupero altri counters se ci sono + /// + public override void processOtherCounters() + { + try + { + // controllo di AVERE parametri opzionali x conteggi vari + if (cIobConf.optPar.Count > 0) + { + // gestione con ricerca in memoria Write / optPar... + if (string.IsNullOrEmpty(memAddrPzReq)) + { + lgTrace("PzReq disabilitato | NO memConf.Write | NO optPar"); + } + else + { + sendOptVal(memNamePzReq, getValByMemAddr(memAddrPzReq)); + } + if (string.IsNullOrEmpty(memAddrArt)) + { + lgTrace("Articolo disabilitato | NO memConf.Write | NO optPar"); + } + else + { + sendOptVal(memNameArt, getValByMemAddr(memAddrArt)); + } + if (string.IsNullOrEmpty(memAddrCom)) + { + lgTrace("Commessa disabilitata | NO memConf.Write | NO optPar"); + } + else + { + sendOptVal(memNameCom, getValByMemAddr(memAddrCom)); + } + if (string.IsNullOrEmpty(memAddrPzCnt)) + { + lgTrace("PzCount disabilitato | NO memConf.Write | NO optPar"); + } + else + { + sendOptVal(memNamePzCnt, getValByMemAddr(memAddrPzCnt)); + } + if (string.IsNullOrEmpty(memAddrPzCntTot)) + { + lgTrace("PzCntTOT disabilitato | NO memConf.Write | NO optPar"); + } + else + { + sendOptVal(memNamePzCntTot, getValByMemAddr(memAddrPzCntTot)); + } + if (string.IsNullOrEmpty(memAddrCaden)) + { + lgTrace("Cadenza disabilitata | NO memConf.Write | NO optPar"); + } + else + { + sendOptVal(memNameCaden, getValByMemAddr(memAddrCaden)); + } + } + } + catch (Exception exc) + { + lgError(exc, "Eccezione in processOtherCounters"); + } + } + + /// + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + DateTime adesso = DateTime.Now; + base.readSemafori(ref currDispData); + // verifico non sia in veto invio iniziale... + if (queueInEnabCurr) + { + try + { + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + + currDispData.semIn = Semaforo.SV; + // ogni lettura inizia da SUA area inizio controllo area R: se ha dati (> 0 + // byte) --> leggo! + if (MemBlockR.Length > 0) + { + stopwatch.Restart(); + MITSUBISHIMemRW(R, MITSUBISHI.MemType.R, areaR.startIdx, ref MemBlockR); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-R", MemBlockR.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockR.Length; i++) + { + lgInfo(string.Format("MemBlockR{0}: {1}", i, utils.binaryForm(MemBlockR[i]))); + } + } + } + // controllo area X: se ha dati (> 0 byte) --> leggo! + if (MemBlockX.Length > 0) + { + stopwatch.Restart(); + MITSUBISHIMemRW(R, MITSUBISHI.MemType.X, areaX.startIdx, ref MemBlockX); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-X", MemBlockX.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockX.Length; i++) + { + lgInfo(string.Format("MemBlockX{0}: {1}", i, utils.binaryForm(MemBlockX[i]))); + } + } + } + // controllo area Y: se ha dati (> 0 byte) --> leggo! + if (MemBlockY.Length > 0) + { + stopwatch.Restart(); + MITSUBISHIMemRW(R, MITSUBISHI.MemType.Y, areaY.startIdx, ref MemBlockY); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-Y", MemBlockY.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockY.Length; i++) + { + lgInfo(string.Format("MemBlockY{0}: {1}", i, utils.binaryForm(MemBlockY[i]))); + } + } + } + stopwatch.Stop(); + // salvo il solo BYTE dell'input decifrando il semaforo... + decodeToBitmap(); + reportRawInput(ref currDispData); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; + currDispData.semIn = Semaforo.SR; + } + } + else + { + lgDebug($"[VETO readSemafori] | veto attivo alle {adesso:yyyy.MM.dd HH:mm:ss}"); + checkVetoQueueIn(); + } + } + + /// + /// Effettua reset del contapezzi + /// + /// + public override bool resetContapezziPLC() + { + bool answ = false; + // ...SE abilitato da conf IOB + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") + { + // scrivo valore 0 x il contapezzi + try + { + // contapezzi ATTUALE + if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) + string memAddr = getOptPar("PZCOUNT_MODE"); + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + } + // var di appoggio + int cntAddr = 0; + // var contapezzi a zero.... + object newVal = new object(); + newVal = 0; + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 6711; + } + + // processo RESET contapezzi (lavorati) + stopwatch.Restart(); + MITSUBISHI_ref.F_RW_Param_Integer(true, cntAddr, 3, ref newVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("W{0}-PAR", 4), stopwatch.ElapsedTicks); + } + } + else if (memAddr.StartsWith("MACRO.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 9999; + } + // processo SET contapezzi (lavorati) + stopwatch.Restart(); + double vTransf = (double)0; + answ = MITSUBISHIMemMacroRW(true, cntAddr, ref vTransf); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, "MACRO-SHORT", stopwatch.ElapsedTicks); + } + } + // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW + else + { + memAddressMITSUBISHI areaCounter = new memAddressMITSUBISHI(memAddr); + + if (isVerboseLog) + { + lgInfo("resetContapezziPLC [0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = 0; + MITSUBISHI_ref.F_RW_Byte(true, areaCounter.mType, areaCounter.mPos, ref valB); + newVal = valB; + break; + + case "D": + ushort valW = 0; + MITSUBISHI_ref.F_RW_Word(true, areaCounter.mType, areaCounter.mPos, ref valW); + newVal = valW; + break; + + case "DW": + uint valDW = 0; + MITSUBISHI_ref.F_RW_DWord(true, areaCounter.mType, areaCounter.mPos, ref valDW); + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("W-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + } + stopwatch.Stop(); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in RESET contapezzi MITSUBISHI"); + connectionOk = false; + } + answ = true; + } + return answ; + } + + /// + /// Override salvataggio valori in memoria... + /// + /// tipo di DUMP + public override void saveMemDump(dumpType tipo) + { + // se l'area ha una size > 0... + if (areaD.arraySize > 0) + { + dump_MemArea(tipo, MITSUBISHI.MemType.D, areaD.startIdx, areaD.arraySize); + } + // se l'area ha una size > 0... + if (areaR.arraySize > 0) + { + dump_MemArea(tipo, MITSUBISHI.MemType.R, areaR.startIdx, areaR.arraySize); + } + // se l'area ha una size > 0... + if (areaX.arraySize > 0) + { + dump_MemArea(tipo, MITSUBISHI.MemType.X, areaX.startIdx, areaX.arraySize); + } + // se l'area ha una size > 0... + if (areaY.arraySize > 0) + { + dump_MemArea(tipo, MITSUBISHI.MemType.Y, areaY.startIdx, areaY.arraySize); + } + // se l'area ha una size > 0... + if (areaPAR.arraySize > 0) + { + dump_ParArea(tipo, areaPAR.startIdx, areaPAR.arraySize); + } + } + + /// + /// Effettua impostazione del valore numerico ARTICOLO (specifico MITSUBISHI) + /// + /// + public bool setNumArt(int valReq) + { + bool answ = false; + string memAddr = memAddrArt; + lgTrace($"INIT setNumArt | memName: {memAddr}"); + if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(memAddr)) + { + // scrivo valore richiesto in area configurata + try + { + // var di appoggio + int cntAddr = 0; + // verifico se si tratta di lettura MACRO... formato tipo MACRO.6711 + if (memAddr.StartsWith("MACRO.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 9999; + } + lgTrace($"MACRO | ART Write 01 | memName: {memAddr} | idx: {cntAddr}"); + // processo SET contapezzi (lavorati) + stopwatch.Restart(); + // comincio scrivendo reset a zero x cominciare... + + double vTransf = (double)valReq; + answ = MITSUBISHIMemMacroRW(true, cntAddr, ref vTransf); + lgTrace($"MACRO | ART Write 02 | memName: {memAddr} | valReq: {valReq} | vTransf: {vTransf}"); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, "MACRO-SHORT", stopwatch.ElapsedTicks); + } + } + stopwatch.Stop(); + } + catch (Exception exc) + { + lgError(exc, "Errore in setNumArt MITSUBISHI"); + connectionOk = false; + } + } + return answ; + } + + /// + /// Effettua impostazione del valore numerico COMMESSA (specifico MITSUBISHI) + /// + /// + public bool setNumCom(int valReq) + { + bool answ = false; + // verifico quale modalità sia richiesta + string memAddr = memAddrCom; + lgTrace($"INIT setNumCom | memName: {memAddr}"); + if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(memAddr)) + { + lgTrace($"setNumCom | memName: {memAddr} | valReq: {valReq}"); + // scrivo valore richiesto in area configurata + try + { + // var di appoggio + int cntAddr = 0; + // verifico se si tratta di lettura MACRO... formato tipo MACRO.6711 + if (memAddr.StartsWith("MACRO.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 9999; + } + lgTrace($"MACRO | Com Write 01 | memName: {memAddr} | idx: {cntAddr}"); + // processo SET contapezzi (lavorati) + stopwatch.Restart(); + double vTransf = (double)valReq; + answ = MITSUBISHIMemMacroRW(true, cntAddr, ref vTransf); + lgTrace($"MACRO | Com Write 02 | memName: {memAddr} | valReq: {valReq} | vTransf: {vTransf}"); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, "MACRO-SHORT", stopwatch.ElapsedTicks); + } + } + stopwatch.Stop(); + } + catch (Exception exc) + { + lgError(exc, "Errore in setNumCom MITSUBISHI"); + connectionOk = false; + } + answ = true; + } + return answ; + } + + /// + /// Effettua impostazione del conteggio pezzi richiesti + /// + /// + public override bool setPzComm(int pzReq) + { + bool answ = false; + // ...SE abilitato da conf IOB + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_REQ") == "TRUE") + { + // scrivo valore 0 x il contapezzi + try + { +#if false + string memAddr = getOptPar("PZREQ_MODE"); +#endif + string memAddr = memAddrPzReq; + lgTrace($"INIT setPzComm | memName: {memAddr}"); + // contapezzi ATTUALE + if (!string.IsNullOrEmpty(memAddr)) + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con + // indicazione area) + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + } + // var di appoggio + int cntAddr = 0; + // var contapezzi a zero.... + object newVal = new object(); + newVal = pzReq; + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 6711; + } + + // processo SET contapezzi (lavorati) + stopwatch.Restart(); + MITSUBISHI_ref.F_RW_Param_Integer(true, cntAddr, 3, ref newVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("W{0}-PAR", 4), stopwatch.ElapsedTicks); + } + } + else if (memAddr.StartsWith("MACRO.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 9999; + } + lgTrace($"MACRO | Pz Write 01 | memName: {memAddr} | idx: {cntAddr}"); + // processo SET contapezzi (lavorati) + stopwatch.Restart(); + // se > 2^16 scrivo con INT, sennò con double... + short valTrShr = 0; + double valTrDbl = 0; + if (pzReq < Math.Pow(2, 16)) + { + valTrShr = (short)pzReq; + answ = MITSUBISHIMemMacroRW(true, cntAddr, ref valTrShr); + //answ = MITSUBISHI_ref.F_RW_Macro_Short(true, cntAddr, ref valTrShr); + lgTrace($"MACRO | Com Write 02 SHORT | memName: {memAddr} | pzReq: {pzReq} | valTrShr: {valTrShr}"); + } + // sennò double! + else + { + valTrDbl = (double)pzReq; + answ = MITSUBISHIMemMacroRW(true, cntAddr, ref valTrDbl); + //answ = MITSUBISHI_ref.F_RW_Macro_Double(true, cntAddr, ref valTrDbl); + lgTrace($"MACRO | Com Write 02 DOUBLE | memName: {memAddr} | pzReq: {pzReq} | valTrDbl: {valTrDbl}"); + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, "MACRO-SHORT", stopwatch.ElapsedTicks); + } + } + // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW + else + { + memAddressMITSUBISHI areaCounter = new memAddressMITSUBISHI(memAddr); + + if (isVerboseLog) + { + lgInfo("setPzComm [0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = (byte)pzReq; + MITSUBISHI_ref.F_RW_Byte(true, areaCounter.mType, areaCounter.mPos, ref valB); + newVal = valB; + break; + + case "D": + ushort valW = (ushort)pzReq; + MITSUBISHI_ref.F_RW_Word(true, areaCounter.mType, areaCounter.mPos, ref valW); + newVal = valW; + break; + + case "DW": + uint valDW = (uint)pzReq; + MITSUBISHI_ref.F_RW_DWord(true, areaCounter.mType, areaCounter.mPos, ref valDW); + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("W-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + } + stopwatch.Stop(); + } + } + catch (Exception exc) + { + lgError($"Errore in SET PzReq Commessa MITSUBISHI{Environment.NewLine}{exc}"); + connectionOk = false; + } + answ = true; + } + return answ; + } + + /// + /// Override connessione + /// + public override void tryConnect() + { + if (!connectionOk) + { + // controllo che il ping sia stato tentato almeno pingTestSec fa... + if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) + { + if (verboseLog || periodicLog) + { + lgInfo("MITSUBISHI: ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // ora PING!!! + Ping pingSender = new Ping(); + IPAddress address = IPAddress.Loopback; + IPAddress.TryParse(cIobConf.cncIpAddr, out address); + PingReply reply; + try + { + // se != null --> uso address... + if (address != null) + { + reply = pingSender.Send(address, 100); + } + else + { + reply = pingSender.Send(cIobConf.cncIpAddr, 100); + } + } + catch + { + reply = pingSender.Send(IPAddress.Loopback, 100); + } + // se passa il ping faccio il resto... + if (reply.Status == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + + // Open communication + int iRet = 0; + iRet = oEZNcAutCom.SetTCPIPProtocol(ipAddr, ezPort); + iRet = oEZNcAutCom.Open3((int)sysType, 1, 10, hostName); + parentForm.commPlcActive = false; + lgInfo($"Mitubishi | open Result: {iRet}" ); + connectionOk = iRet == 0; + connectionOk = true; + // refresh stato allarmi!!! + if (connectionOk) + { + checkVetoQueueIn(); + dtAvvioAdp = DateTime.Now; + if (adpRunning) + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal(string.Format("Errore nella connessione all'adapter MITSUBISHI: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); + connectionOk = false; + lgInfo(string.Format("Eccezione in TryConnect, Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + if (verboseLog || periodicLog) + { + lgInfo(string.Format("Attenzione: controllo PING fallito per IP {0} - {1}", cIobConf.cncPingAddr, reply.Status)); + } + } + } + } + // se non è ancora connesso faccio procesisng memoria caso disconnesso... + if (!connectionOk) + { + // processo semafori ed invio... + processMemoryDiscon(); + } + } + + /// + /// Override disconnessione + /// + public override void tryDisconnect() + { + if (connectionOk) + { + string szStatusConnection = ""; + try + { + // Close. + var iRet = oEZNcAutCom.Close(); + //Release object + oEZNcAutCom = null; + connectionOk = false; + // resetto timing! + TimingData.resetData(); + lgInfo(szStatusConnection); + lgInfo("Effettuata disconnessione adapter MITSUBISHI!"); + } + catch (Exception exc) + { + lgFatal(exc, "Errore nella disconnessione dall'adapter MITSUBISHI"); + } + } + else + { + lgError("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile..."); + } + queueInEnabCurr = false; + } + + #endregion Public Methods + + #region Internal Fields + + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + internal Dictionary signLUT = new Dictionary(); + + #endregion Internal Fields + + #region Protected Fields + + /// + /// Dati dell'area D + /// + protected memAreaMITSUBISHI areaD; + + /// + /// Dati dell'area PARameters + /// + protected memAreaMITSUBISHI areaPAR; + + /// + /// Dati dell'area R + /// + protected memAreaMITSUBISHI areaR; + + /// + /// Dati dell'area X + /// + protected memAreaMITSUBISHI areaX; + + /// + /// Dati dell'area Y + /// + protected memAreaMITSUBISHI areaY; + + ///// + ///// Oggetto MAIN x connessione MITSUBISHI + ///// + //protected MITSUBISHI MITSUBISHI_ref; + + /// + /// Area memoria G (copia) + /// + protected byte[] MemBlockG = new byte[2]; + + /// + /// Area memoria R (copia) + /// + protected byte[] MemBlockR = new byte[2]; + + /// + /// Area memoria X (copia) + /// + protected byte[] MemBlockX = new byte[2]; + + /// + /// Area memoria Y (copia) + /// + protected byte[] MemBlockY = new byte[2]; + + #endregion Protected Fields + + #region Protected Methods + + /// + /// decodifica il modo dai valori del byte G43 + /// + /// + /// + protected static CNC_MODE decodeG43(byte currVal) + { + // hard coded da valori tabellari a MODI definiti in CNC_MODE... + CNC_MODE answ = CNC_MODE.ND; + switch (currVal) + { + case 0: + answ = CNC_MODE.MDI; + break; + + case 1: + answ = CNC_MODE.MEN; + break; + + case 3: + answ = CNC_MODE.EDIT; + break; + + case 4: + answ = CNC_MODE.HANDLE_INC; + break; + + case 5: + answ = CNC_MODE.JOG; + break; + + case 6: + answ = CNC_MODE.TJOG; + break; + + case 7: + answ = CNC_MODE.THND; + break; + + case 33: + answ = CNC_MODE.RMT; + break; + + case 133: + answ = CNC_MODE.REF; + break; + + default: + answ = CNC_MODE.ND; + break; + } + return answ; + } + + /// + /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC + /// + /// + protected override void plcWriteParams(ref List updatedPar) + { + lgTrace($"plcWriteParams: richiesta per {updatedPar.Count} params"); + foreach (var item in updatedPar) + { + lgInfo($"ITEM | {item.uid} | {item.value}"); + // salvo i valori ricevuti + upsertKey(item.uid, item.reqValue); + // se i valori richiesto e fatto corrispondono... resetto! + if (item.reqValue.Trim() == item.value.Trim()) + { + // resetto richiesta! + item.reqValue = ""; + } + } + } + + #endregion Protected Methods + + #region Private Properties + + private string memAddrArt + { + get + { + string memAddr = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("setArtNum")) + { + memAddr = memMap.mMapWrite["setArtNum"].memAddr; + } + // se vuoto provo altra alternativa... + if (string.IsNullOrEmpty(memAddr) && memMap.mMapWrite.ContainsKey("setArt")) + { + memAddr = memMap.mMapWrite["setArt"].memAddr; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memAddr)) + { + memAddr = getOptPar("SET_NUM_ART"); + } + // bonifica variabile da definizione STD iniziale... + if (memAddr.StartsWith("STD")) + { + memAddr = memAddr.Replace("STD.", ""); + } + return memAddr; + } + } + + private string memAddrCaden + { + get + { + string memAddr = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("Cadenza")) + { + memAddr = memMap.mMapWrite["Cadenza"].memAddr; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memAddr)) + { + memAddr = getOptPar("PZCAD_MODE"); + } + // bonifica variabile da definizione STD iniziale... + if (memAddr.StartsWith("STD")) + { + memAddr = memAddr.Replace("STD.", ""); + } + return memAddr; + } + } + + private string memAddrCom + { + get + { + string memAddr = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("setCommNum")) + { + memAddr = memMap.mMapWrite["setCommNum"].memAddr; + } + // se vuoto provo altra alternativa... + if (string.IsNullOrEmpty(memAddr) && memMap.mMapWrite.ContainsKey("setComm")) + { + memAddr = memMap.mMapWrite["setComm"].memAddr; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memAddr)) + { + memAddr = getOptPar("SET_NUM_COM"); + } + // bonifica variabile da definizione STD iniziale... + if (memAddr.StartsWith("STD")) + { + memAddr = memAddr.Replace("STD.", ""); + } + return memAddr; + } + } + + private string memAddrPzCnt + { + get + { + string memAddr = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("ContatoreParziale")) + { + memAddr = memMap.mMapWrite["ContatoreParziale"].memAddr; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memAddr)) + { + memAddr = getOptPar("PZCOUNT_MODE"); + } + // bonifica variabile da definizione STD iniziale... + if (memAddr.StartsWith("STD")) + { + memAddr = memAddr.Replace("STD.", ""); + } + return memAddr; + } + } + + private string memAddrPzCntTot + { + get + { + string memAddr = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("ContatoreAssoluto")) + { + memAddr = memMap.mMapWrite["ContatoreAssoluto"].memAddr; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memAddr)) + { + memAddr = getOptPar("PZGTOT_MODE"); + } + // bonifica variabile da definizione STD iniziale... + if (memAddr.StartsWith("STD")) + { + memAddr = memAddr.Replace("STD.", ""); + } + return memAddr; + } + } + + private string memAddrPzReq + { + get + { + string memAddr = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("setPzComm")) + { + memAddr = memMap.mMapWrite["setPzComm"].memAddr; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memAddr)) + { + memAddr = getOptPar("PZREQ_MODE"); + } + // bonifica variabile da definizione STD iniziale... + if (memAddr.StartsWith("STD")) + { + memAddr = memAddr.Replace("STD.", ""); + } + return memAddr; + } + } + + private string memNameArt + { + get + { + string memName = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("setArtNum")) + { + memName = "setArtNum"; + } + // se vuoto provo altra alternativa... + if (string.IsNullOrEmpty(memName) && memMap.mMapWrite.ContainsKey("setArt")) + { + memName = "setArt"; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memName)) + { + memName = "PZ_COUNT"; + } + return memName; + } + } + + private string memNameCaden + { + get + { + string memName = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("Cadenza")) + { + memName = "Cadenza"; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memName)) + { + memName = "CICLE_CAD"; + } + return memName; + } + } + + private string memNameCom + { + get + { + string memName = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("setCommNum")) + { + memName = "setCommNum"; + } + // se vuoto provo altra alternativa... + if (string.IsNullOrEmpty(memName) && memMap.mMapWrite.ContainsKey("setComm")) + { + memName = "setComm"; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memName)) + { + memName = "SET_NUM_COM"; + } + return memName; + } + } + + private string memNamePzCnt + { + get + { + string memName = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("ContatoreParziale")) + { + memName = "ContatoreParziale"; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memName)) + { + memName = "PZ_COUNT"; + } + return memName; + } + } + + private string memNamePzCntTot + { + get + { + string memName = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("ContatoreAssoluto")) + { + memName = "ContatoreAssoluto"; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memName)) + { + memName = "PZ_GTOT"; + } + return memName; + } + } + + private string memNamePzReq + { + get + { + string memName = ""; + if (memMap != null && memMap.mMapWrite != null) + { + //cerco in primis modalità NUM altrimenti standard... + if (memMap.mMapWrite.ContainsKey("setPzComm")) + { + memName = "setPzComm"; + } + } + // se non trovato... leggo da OPT_PAR + if (string.IsNullOrEmpty(memName)) + { + memName = "PZ_REQ"; + } + return memName; + } + } + + #endregion Private Properties + + #region Private Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + private void decodeToBitmap() + { + // init a zero... + B_input = 0; + if (connectionOk) + { + // SE SI E' CONNESSO al MITSUBISHI allora è 1=powerON... + if (MITSUBISHI_ref.Connected) + { + B_input += 1 << 0; + } + + // decodifico impiegando dictionary... cercando il TIPO di memoria & co... + string bKey = ""; + string bVal = ""; + char area; + // valore INVERTED (default è false) + bool invSignal = false; + string memArea = ""; + string[] memIdx; + int bitNum = 0; + int byteNum = 0; + int byte2check = 0; + for (int i = 0; i < 8; i++) + { + bKey = string.Format("BIT{0}", i); + // cerco se ci sia in LUT + if (signLUT.ContainsKey(bKey)) + { + // recupero nome variabile... + bVal = signLUT[bKey]; + // se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI... + if (bVal.StartsWith("PZCOUNT")) + { + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo(string.Format("MITSUBISHI | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { + // se variato o scaduto timeout log... + if (periodicLog || ($"{currIdxODL}" != currODL)) + { + lgInfo(string.Format("MITSUBISHI | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + } + // provo a salvare nuovo ODL + int.TryParse(currODL, out currIdxODL); + } + } + catch (Exception exc) + { + if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) + { + lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); + lastWarnODL = DateTime.Now; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"MITSUBISHI | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + if (!string.IsNullOrEmpty(currODL) && currODL != "0") + { + // controllo se è passato intervallo minimo tra 2 + // controlli/elaborazioni x distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // se sono differenti MOSTRO... + if (contapezziPLC != contapezziIOB) + { + // registro contapezzi + lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + + if ((enablePzCountByApp || enablePzCountByIob) && !(disablePzCountByIob)) + { + // verifico se variato contapezzi... + if (contapezziPLC > contapezziIOB) + { + // salvo nuovo contapezzi (incremento di 1...) + + // richiesta refresh conteggio + contapezziIOB++; + needRefreshPzCount = true; + // salvo in semaforo! + B_input += 1 << 2; + // registro contapezzi + lgInfo($"contapezziPLC MITSUBISHI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + // invio a server contapezzi (aggiornato) + string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi MITSUBISHI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC MITSUBISHI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + } + else // area "normale" byte.bit + { + // di norma è segnale normale => 1, altrimenti inverse => 0... + invSignal = false; + // cerco se sia inverse (primo char "!") --> registro e elimino char... + invSignal = bVal.StartsWith("!"); + // se è da tracciare... + if (mem2trace.Contains($"|{bKey}|")) + { + if (invSignal) + { + lgTrace($"Segnale invertito | bVal: {bVal}"); + } + } + // tolgo comunque inversione... + bVal = bVal.Replace("!", ""); + // recupero area... + area = bVal[0]; + // altrimenti decodifico area... + memArea = bVal.Substring(1, bVal.Length - 1); + memIdx = memArea.Split('.'); + // calcolo bit e byte number... + int.TryParse(memIdx[0], out byteNum); + if (memIdx.Length > 1) + { + int.TryParse(memIdx[1], out bitNum); + } + // in base al nome cerco in una delle aree.. e prendo solo solo quel bit + // di quel byte... + switch (area) + { + case 'G': + byte2check = MemBlockG[byteNum]; + break; + + case 'R': + byte2check = MemBlockR[byteNum]; + break; + + case 'X': + byte2check = MemBlockX[byteNum]; + break; + + case 'Y': + byte2check = MemBlockY[byteNum]; + break; + + default: + break; + } + // a secondo che sia segnale normale o inverso... + if (invSignal) + { + // controllo se il bit sia NON attivo (basso)... == 0... + if ((byte2check & (1 << bitNum)) == 0) + { + B_input += 1 << i; + } + } + else + { + // controllo se il bit sia attivo (alto)... != 0 + if ((byte2check & (1 << bitNum)) != 0) + { + B_input += 1 << i; + } + } + + // se è da tracciare... + if (mem2trace.Contains($"|{bKey}|")) + { + var bMapAct = Convert.ToString(byte2check, 2).PadLeft(8, '0'); + var bMapReq = Convert.ToString((1 << bitNum), 2).PadLeft(8, '0'); + lgTrace($"Valore | bKey: {bKey} | bVal: {bVal} | byte: {bMapAct} | tgt: {bMapReq} | B_input: {B_input}"); + } + } + } + } + } + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); + } + } + + /// + /// Dump area D della memoria + /// + /// tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti) + /// tipo memoria + /// area memoria di partenza + /// dimensione memoria + private void dump_MemArea(dumpType tipo, MITSUBISHI.MemType tipoMem, int memIndex, int memSizeByte) + { + DateTime adesso = DateTime.Now; + string nomeFileB = ""; + string nomeFileW = ""; + string nomeFileDW = ""; + Dictionary mappaValori = new Dictionary(); + // per sicurezza verifico < 9999 byte + if (memSizeByte > 9999) + { + memSizeByte = 9999; + } + // leggo TUTTI i (MAX 9999) byte della memoria D... + byte[] MemBlockCurr = new byte[memSizeByte]; + if (verboseLog) + { + lgInfo("START MemDump", tipoMem); + } + + stopwatch.Restart(); + MITSUBISHIMemRW(R, tipoMem, memIndex, ref MemBlockCurr); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-{1}", MemBlockCurr.Length, tipoMem), stopwatch.ElapsedTicks); + } + + if (verboseLog) + { + lgInfo("END MemDump", tipoMem); + } + + // seconda del tipo di lettura definisco i nomi delle variabili... + if (tipo == dumpType.SAMPLE) + { + nomeFileB = string.Format(@"{0}\SAMPLES\{1}_{2}_Byte_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso); + nomeFileW = string.Format(@"{0}\SAMPLES\{1}_{2}_W_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso); + nomeFileDW = string.Format(@"{0}\SAMPLES\{1}_{2}_DW_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso); + } + else + { + // salvo in file i dati letti come BYTE + nomeFileB = string.Format(@"{0}\{1}_{2}_Byte.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem); + nomeFileW = string.Format(@"{0}\{1}_{2}_W.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem); + nomeFileDW = string.Format(@"{0}\{1}_{2}_DW.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem); + } + + // salvo in file i dati letti come BYTE + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockCurr.Length; i++) + { + // versione pre dotNet8 (che usa "b" come stringa formato std) + var bitMap = Convert.ToString(MemBlockCurr[i], 2).PadLeft(8, '0'); + mappaValori.Add($"[{i:0000}]", $"{bitMap}={MemBlockCurr[i]}"); + //mappaValori.Add($"[{i:0000}]", $"{MemBlockCurr[i]:b}={MemBlockCurr[i]}"); + } + utils.WritePlain(mappaValori, nomeFileB); + + // salvo in file i dati letti come Word (2byte) + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockCurr.Length / 2; i++) + { + mappaValori.Add($"[{i:0000}]", BitConverter.ToUInt16(MemBlockCurr, i * 2).ToString()); + } + utils.WritePlain(mappaValori, nomeFileW); + + // salvo in file i dati letti come DWord (4byte) + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockCurr.Length / 4; i++) + { + mappaValori.Add($"[{i:0000}]", BitConverter.ToUInt32(MemBlockCurr, i * 4).ToString()); + } + utils.WritePlain(mappaValori, nomeFileDW); + } + + /// + /// Dump area PARAMETRI + /// + /// tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti) + /// Parametro di partenza + /// Numero parametri da esportare... memoria + private void dump_ParArea(dumpType tipo, int memIndex, int numPar) + { + DateTime adesso = DateTime.Now; + string nomeFile = ""; + Dictionary mappaValori = new Dictionary(); + // per sicurezza verifico < 9999 parametri + if (numPar > 9999) + { + numPar = 9999; + } + + // leggo TUTTI i (MAX 9999) byte della memoria D... + object[] paramsArray = new object[numPar]; + if (verboseLog) + { + lgInfo("START ParamDump"); + } + + stopwatch.Restart(); + for (int i = 0; i < numPar; i++) + { + MITSUBISHI_ref.F_RW_Param_Integer(false, memIndex + i, 3, ref paramsArray[i]); + } + + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4 * numPar), stopwatch.ElapsedTicks); + } + + if (verboseLog) + { + lgInfo("END ParamDump"); + } + + // seconda del tipo di lettura definisco i nomi delle variabili... + if (tipo == dumpType.SAMPLE) + { + nomeFile = string.Format(@"{0}\SAMPLES\{1}_{2}_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, "PAR", adesso); + } + else + { + nomeFile = string.Format(@"{0}\{1}_{2}.dat", utils.dataDatDir, cIobConf.codIOB, "PAR"); + } + + // salvo in file i dati letti + mappaValori = new Dictionary(); + for (int i = 0; i < paramsArray.Length; i++) + { + mappaValori.Add(i.ToString("0000"), paramsArray[i].ToString()); + } + utils.WritePlain(mappaValori, nomeFile); + } + + /// + /// Recupera il valore INT dal nome del parametro per successivo processing + /// + /// + /// + private string getValByMemAddr(string memAddr) + { + lgTrace($"inizio getValByMemAddr | memAddr: {memAddr}"); + string answ = ""; + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) +#if true + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + } +#endif + // var di appoggio + int cntAddr = 0; + object outputVal = new object(); + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + // processo parametro + stopwatch.Restart(); + MITSUBISHI_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); + } + // salvo valore + answ = outputVal.ToString(); + } + // 2022.05.23 gestione MACRO da testare (Jetco) + else if (memAddr.StartsWith("MACRO.")) + { + double macroVal = 0; + // recupero parametro... + int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr); + lgTrace($"MACRO | Read 01 | memName: {memAddr} | idx: {cntAddr} | macroVal: {macroVal}"); + // processo parametro + stopwatch.Restart(); + MITSUBISHI_ref.F_Read_macro(cntAddr, ref macroVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, "R-MACRO", stopwatch.ElapsedTicks); + } + // salvo valore + answ = macroVal.ToString(); + lgTrace($"MACRO | Read 02 | memName: {memAddr} | idx: {cntAddr} | macroVal: {macroVal}"); + } + // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW + else + { + memAddressMITSUBISHI areaCounter = new memAddressMITSUBISHI(memAddr); + + if (isVerboseLog) + { + lgInfo("getValByParam [0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = 0; + MITSUBISHI_ref.F_RW_Byte(false, areaCounter.mType, areaCounter.mPos, ref valB); + outputVal = valB; + break; + + case "D": + ushort valW = 0; + MITSUBISHI_ref.F_RW_Word(false, areaCounter.mType, areaCounter.mPos, ref valW); + outputVal = valW; + break; + + case "DW": + uint valDW = 0; + MITSUBISHI_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); + if (isVerboseLog) + { + lgInfo("[1] valDW PAR: {0}", valDW); + } + + outputVal = valDW; + if (isVerboseLog) + { + lgInfo("[2] outputVal PAR: {0}", outputVal); + } + + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + + // salvo... + answ = outputVal.ToString(); + if (isVerboseLog) + { + lgInfo($"[3] Mem letta: {memAddr} | {answ}"); + } + } + stopwatch.Stop(); + return answ; + } + + /// + /// Recupera il valore INT dal nome del parametro per successivo processing + /// + /// + /// + private string getValByParam(string varName) + { + string memAddr = getOptPar(varName); + string answ = getValByMemAddr(memAddr); + if (isVerboseLog) + { + lgInfo($"[3] PAR letto: {varName} | {answ}"); + } + return answ; + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/TestPrelimCli/Mitsubishi/Program.cs b/TestPrelimCli/Mitsubishi/Program.cs index a77ada93..e449eae5 100644 --- a/TestPrelimCli/Mitsubishi/Program.cs +++ b/TestPrelimCli/Mitsubishi/Program.cs @@ -38,11 +38,11 @@ namespace Mitsubishi // [Local variable declaration] object BlockValue = ""; - int Ret = 0; + int iRet = 0; //Open communication - Ret = oEZNcAutCom.SetTCPIPProtocol("192.168.213.199", 683); - //Console.WriteLine($"R: {Ret}"); - Ret = oEZNcAutCom.Open3(5, 1, 10, "EZNC_LOCALHOST"); + iRet = oEZNcAutCom.SetTCPIPProtocol("192.168.213.199", 683); + //Console.WriteLine($"R: {iRet}"); + iRet = oEZNcAutCom.Open3(5, 1, 10, "EZNC_LOCALHOST"); DoLog(sep); DoLog("Retrieve Serial/Vers"); @@ -90,6 +90,12 @@ namespace Mitsubishi // preparo memorie string prgText = ""; int prgState = 0; + // solo nome... + iRet = oEZNcAutCom.Program_GetProgramNumber2((Int32)PROGRAMTYPE.EZNC_MAINPRG, out String strProgramNo); + DoLog($"ProgramName: {strProgramNo}"); + DoLog(""); + + // leggo contenuto try { oEZNcAutCom.Program_CurrentBlockRead(10, out prgText, out prgState); @@ -125,7 +131,7 @@ namespace Mitsubishi double pdPosit = 0; for (int i = 1; i < 4; i++) { - Ret = oEZNcAutCom.Position_GetCurrentPosition(i, out pdPosit); + iRet = oEZNcAutCom.Position_GetCurrentPosition(i, out pdPosit); DoLog($"Pos: {i} | {pdPosit}"); } DoLog(sep); @@ -287,7 +293,7 @@ namespace Mitsubishi DoLog(""); // Close. - Ret = oEZNcAutCom.Close(); + iRet = oEZNcAutCom.Close(); //Release object oEZNcAutCom = null; @@ -302,6 +308,12 @@ namespace Mitsubishi Console.WriteLine(logMessage); } + public enum PROGRAMTYPE + { + EZNC_MAINPRG = 0, //メインプログラム + EZNC_SUBPRG = 1, //サブプログラム + } + protected static string outPath = ""; private static string sep = "------------------------";