using MapoSDK; using System; using System.Collections.Generic; using System.Linq; namespace IOB_WIN_NEXT { /// /// Controllo Siemens specifico x impianti COMECA (gestione GNL x Pizzaferri) /// public class IobSiemensComeca : IobSiemens { /* -------------------------------------------------------------------------------- * Controlli SIEMENS COMECA * - basasto su SIEMENS * - S7 vers 1500 * * STRUTTURA MEMORIA DB85: * lettura: 260 byte, * scrittura 32 byte * G:\Drive condivisi\30_Clienti\Pizzaferri\Impianti\Comeca * * Si intende lettura/scrittura con DB85.DBxx * * READ * Si leggono parametri impianti + eventuali allarmi * 000...151 R --> Variabili ANALOGICHE * 152...183 R --> parametri * 232...259 R --> allarmi * * WRITE * 268...271 R --> Word conferma comandi (ACK) * 280...288 W --> parametri inviati (WRITE) * 308...309 W --> conferma invio (STR) * * -------------------------------------------------------------------------------- */ #region Protected Fields protected int strobeVal = 0; #endregion Protected Fields #region Public Constructors /// /// Classe base con i metodi x Siemens /// /// /// public IobSiemensComeca(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { lgInfo("NEW IOB SIEMENS versione Comeca"); } #endregion Public Constructors #region Protected Properties protected bool hasAlarms { get { bool answ = false; int numErrors = 0; uint currStatus = 0; if (alarmMaps != null) { // leggo a ciclo le aree degli allarmi CONFIGURATI, se ne trovo --> segnalo allarme... foreach (var item in alarmMaps) { // banchi in WORD (2 byte) --> scompongo for (int i = 0; i < item.size / 2; i++) { currStatus = S7.Net.Types.Counter.FromByteArray(RawInput.Skip(item.index + 2 * i).Take(2).ToArray()); // verifica e decremento blink... item.checkBlinkCounter(i, (uint)currStatus); // verifico SE sia variato... confronto allarmi filtrato stile blink per bit status: // - allarmi che iniziano per # IGNORATI // - altri allarmi con un countdown da MAX_COUNTER_BLINK a 0 per il fronte di discesa if (item.isChanged(i, currStatus)) { if (currStatus > 0) { numErrors++; } // registro gli allarmi attivi e trasmetto... if (sendAlarmVariations(item.memAddr, i, item.alarmsState[i], (uint)(item.alarmsMask[i] & currStatus), item.messages)) { // se inviato --> salvo stato da current... item.updStatusVal(i, (uint)(item.alarmsMask[i] & currStatus)); } } } } } answ = numErrors > 0; return answ; } } #endregion Protected Properties #region Private Methods private void checkStrobeHack() { // verifico SE ho un hack sulla var DB85.DB268 byte[] byteCtrlW = new byte[2]; bool fatto = S7ReadBB(ref byteCtrlW, "DB85.DBB268", 2); ushort valCtrlW = S7.Net.Types.Word.FromByteArray(byteCtrlW.ToArray()); // se vale 1 --> resetto strobe! if (valCtrlW == 1) { // aggiunta finale bit a 0 x chiusura processing.. var MemBlock = S7.Net.Types.Int.ToByteArray(0); var memAddrWrite = "DB85.DBB308"; // imposto valore strobe x check successivi var taskOk = S7WriteBB(ref MemBlock, memAddrWrite); if (taskOk) { strobeVal = 0; } } else { lgInfo("SiemensComeca: Strobe attivo su DBB308, ack non rilevato su DBB268"); } } #endregion Private Methods #region Protected Methods /// /// Effettua decodifica aree memoria alla bitmap usata x MAPO /// - per lo scopo specifico IN REALTA' non conta lo stato macchina.... ma lo inviamo lo stesso /// protected override void decodeToBaseBitmap() { // init a zero... B_input = 0; /* ----------------------------------------------------- * bitmap MAPO STANDARD * B0: POWER_ON * B1: RUN * B2: pzCount * B3: allarme * ----------------------------------------------------- */ //bool fatto = false; //ushort valW = 0; var MemInt = new byte[2]; int byteSignals = 0; // bit 0 (poweron) imposto a 1 SE connected... if (currPLC.IsConnected) { byteSignals += (1 << 0); } // processo dagli stati + gravi... if (hasAlarms) { byteSignals += (1 << 3); } else { byteSignals += (1 << 1); } // verifico SE ho strobe/hack da chiudere if (strobeVal != 0) { checkStrobeHack(); } // salvo! B_input = byteSignals; } #endregion Protected Methods #region Public Methods /// /// Processo i task richiesti e li elimino dalla coda 1:1 /// /// public override Dictionary executeTasks(Dictionary task2exe) { lgInfo($"Chiamata executeTasks specifica IobSiemensComeca: {task2exe.Count} task ricevuti"); // Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti... Dictionary taskDone = new Dictionary(); bool taskOk = false; string taskVal = ""; // inizio con 1 byte di default byte[] MemBlock = new byte[1]; string memAddrWrite = ""; if (task2exe != null) { // cerco task specifici foreach (var item in task2exe) { taskOk = false; taskVal = ""; // converto richiesta in enum... taskType tName = taskType.nihil; Enum.TryParse(item.Key, out tName); // controllo sulla KEY switch (tName) { case taskType.nihil: case taskType.fixStopSetup: case taskType.forceResetPzCount: case taskType.forceSetPzCount: case taskType.setProg: case taskType.sendWatchDogMes2Plc: case taskType.startSetup: case taskType.stopSetup: case taskType.setPzComm: case taskType.setArt: case taskType.setComm: taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; break; case taskType.setParameter: // richiedo da URL i parametri WRITE da popolare lgInfo("Chiamata processMemWriteRequests"); taskVal = processMemWriteRequests(); // se restituiscce "" faccio altra prova... if (string.IsNullOrEmpty(taskVal)) { // i parametri me li aspetto come stringa composta paramName|paramvalue if (item.Value.Contains("|")) { string[] paramsJob = item.Value.Split('|'); taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; } else { taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value"; } } // aggiunta finale bit a 1 x richiesta processing.. MemBlock = S7.Net.Types.Int.ToByteArray(1); memAddrWrite = "DB85.DBB308"; // imposto valore strobe x check successivi strobeVal = 1; break; default: taskVal = "SKIPPED | NO EXEC"; break; } // aggiungo task! taskDone.Add(item.Key, taskVal); if (!string.IsNullOrEmpty(memAddrWrite)) { // scrivo! taskOk = S7WriteBB(ref MemBlock, memAddrWrite); } if (!taskOk) { lgError($"Errore in S7WriteBB durante executeTasks: {item.Key} | {item.Value}"); } } } return taskDone; } #endregion Public Methods } }