using IOB_UT_NEXT; using MapoSDK; using System; using System.Collections.Generic; using System.IO; using static MapoSDK.WharehouseData; namespace IOB_WIN_NEXT { /* -------------------------------------------------------------------------------- * Controlli ModBusTCP SAIM * - protocollo ModBus TCP * - specifico comportamento impianti sanificazione ad ozono SAIM (Giacovelli) * - gestione allarmi * * STRUTTURA MEMORIA a banchi di UInt16, convertiti successivamente in int EVENTUALMENTE divisi per 10/100/1000 * G:\Drive condivisi\30_Clienti\Giacovelli - WIL\SAIM * * -------------------------------------------------------------------------------- */ public class IobModbusTCPSaim : IobModbusTCP { #region Public Constructors /// /// Classe base con i metodi x ModBusTCP /// /// /// public IobModbusTCPSaim(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { lgInfo("NEW IOB ModBus TCP Saim"); // provo lettura una prima volta i dati DYN if (currPLC != null && currPLC.Connected) { try { processDynData(); if (EnableTest) { processDataSync(); testReadExt(); } } catch (Exception exc) { lgError($"Eccezione in processDynData iniziale x ModBus TCP SAIM:{Environment.NewLine}{exc}"); } } } #endregion Public Constructors #region Protected Properties /// /// Restituisce controllo IN ALLARME /// protected bool AlarmState { get { return testDisInBitCondition("AlarmBitCond"); } } /// /// Restituisce status di ESTOP triggered (triggered = premuta, altrimenti armed) /// protected bool EStopTriggered { get { return testDisInBitCondition("EStopBitCond"); } } /// /// Restituisce status di Manuale, hard coded /// protected bool ManualState { get { return testDisInBitCondition("ManualBitCond"); } } /// /// Restituisce status di LAVORA, hard coded /// protected bool Work { get { return testDisInBitCondition("WorkBitCond"); } } /// /// Restituisce status di WORK (auto + lavora), hard coded /// protected bool WorkState { get { return testDisInBitCondition("WorkBitCond"); } } #endregion Protected Properties #region Protected Methods /// /// Effettua decodifica aree memoria alla bitmap usata x MAPO /// protected override void decodeToBaseBitmap() { // init a zero... B_input = 0; /* ----------------------------------------------------- * bitmap MAPO STANDARD 60 * B0: POWER_ON * B1: RUN * B2: pzCount * B3: allarme * B4: manuale * B5: slowTC * B6: WarmUpCoolDown * B7: EmergArmata * ----------------------------------------------------- */ var MemInt = new byte[2]; int byteSignals = 0; // bit 0 (poweron) imposto a 1 SE connected... if (currPLC.Connected) { byteSignals += (1 << 0); } // se ho qualcosa nella holding register... if (HoldingRegisterLUT != null && HoldingRegisterLUT.Count > 0) { // se emergenza NON premuta (triggered) indico OK (armata...) FARE !!! togliere true //if (!EStopTriggered) if (true) { byteSignals += (1 << 7); } // impiego controlli da setup IntConditions... processo dagli stati + gravi... if (AlarmState || hasAlarms()) { byteSignals += (1 << 3); } else if (ManualState) { byteSignals += (1 << 4); } else if (WorkState) { byteSignals += (1 << 1); } } else { lgInfo("HoldingRegisterLUT vuoto!"); } // salvo! B_input = byteSignals; } /// /// Procedura di import file... formato excel Giacovelli /// /// protected override bool importFile(string fileItem) { bool fatto = false; int numErr = 0; // test procedura di import files excel x Giacovelli... var currExcel = new ExcelMan(fileItem); // creo lista dati in formato RegGiacenze... Dictionary listaGiac = new Dictionary(); var dtSet = currExcel.getDataSet(); if (dtSet != null && dtSet.Tables != null && dtSet.Tables.Count > 0) { string nomeFile = Path.GetFileName(fileItem); nomeFile = nomeFile.Substring(0, nomeFile.LastIndexOf(".")); var elSheet = dtSet.Tables; int idxTab = 0; //cerco lo sheet corretto se > 1 if (dtSet.Tables.Count > 1) { for (int i = 0; i < dtSet.Tables.Count; i++) { if (nomeFile.Contains(dtSet.Tables[i].TableName)) { idxTab = i; } } } var tabella = dtSet.Tables[idxTab]; int numRighe = tabella.Rows.Count; int idxODL = 0; DateTime dataDoc = DateTime.Today; DateTime.TryParse(nomeFile, out dataDoc); // cerco lotto x giornata... string sIdxODL = utils.callUrl(urlGetOdlAtDate(dataDoc)); int.TryParse(sIdxODL, out idxODL); for (int i = 0; i < numRighe; i++) { if (numErr < 5) { try { // variabili di appoggio... DateTime dtRif = DateTime.Today; double qtyTot = 0; int numPack = 0; string ddt = tabella.Rows[i].ItemArray[FileDecod["ExtDoc"]].ToString().Trim(); string sDate = tabella.Rows[i].ItemArray[FileDecod["DateRif"]].ToString().Trim(); string prod = tabella.Rows[i].ItemArray[FileDecod["Product"]].ToString().Trim(); // verifiche x import: header, data e DDT (vuoti o "-") --> SKIP! bool checkHeaderKo = (ddt == "DDT" || prod == "PRODOTTO"); bool checkEmptyDdt = (string.IsNullOrEmpty(ddt) || ddt == "-"); bool checkEmptyDate = (string.IsNullOrEmpty(sDate) || sDate == "-"); if (checkHeaderKo) { lgTrace($"SKIP header"); } else if (checkEmptyDdt || checkEmptyDate) { lgTrace($"SKIP linea vuota | i: {i} | ddt: {ddt} | date: {sDate} | prod: {prod}"); } else { string variety = tabella.Rows[i].ItemArray[FileDecod["Variety"]].ToString().Trim(); string suppl = tabella.Rows[i].ItemArray[FileDecod["Supplier"]].ToString().Trim(); string sQty = tabella.Rows[i].ItemArray[FileDecod["QtyTot"]].ToString().Trim(); string sNum = tabella.Rows[i].ItemArray[FileDecod["NumPack"]].ToString().Trim(); string numPed = tabella.Rows[i].ItemArray[FileDecod["NumPed"]].ToString().Trim(); string packPed = tabella.Rows[i].ItemArray[FileDecod["PackPed"]].ToString().Trim(); string pesoPack = tabella.Rows[i].ItemArray[FileDecod["PesoPack"]].ToString().Trim(); DateTime.TryParse(sDate, out dtRif); int.TryParse(sNum, out numPack); double.TryParse(sQty, out qtyTot); string identRG = ddt.Length > 2 ? $"{strFixId(ddt)}.{strFixId(prod)}.{strFixId(variety)}.{strFixId(suppl)}" : $"{dtRif:yyyyMMdd}.{strFixId(prod)}.{strFixId(variety)}.{strFixId(suppl)}"; string notes = $"{numPed}x{packPed}x{pesoPack}"; // verifico di avere dati per proseguire... bool checkIdent = !string.IsNullOrEmpty($"{prod}{variety}{suppl}"); if (checkIdent) { BatchRec newRow = new BatchRec() { IdxODL = idxODL, IdentRG = identRG, DateRif = dtRif, ExtDoc = ddt, Product = prod, Variety = variety, Supplier = suppl, NumPack = numPack, QtyTot = qtyTot, Notes = notes }; // verifico: se manca aggiungo if (!listaGiac.ContainsKey(identRG)) { listaGiac.Add(identRG, newRow); } else { // altrimenti aggiorno giacenza con valori numerici listaGiac[identRG].NumPack += newRow.NumPack; listaGiac[identRG].QtyTot += newRow.QtyTot; } } else { lgError($"Errore verifica identità riga | prod: {prod} | variety: {variety} | suppl: {suppl}"); numErr++; } } } catch (Exception exc) { numErr++; } } } } if (listaGiac.Count > 0) { // converto in una nuova lista... int rCounter = 1; Dictionary list2Send = new Dictionary(); foreach (var item in listaGiac) { list2Send.Add(rCounter, item.Value); rCounter++; } // ora invio i file con json... accodaRawData(rawTransfType.RegGiacenze, list2Send); fatto = true; } return fatto; } /// /// Effettua sync dati /// protected override void processDataSync() { // richiesta check autoODL processAutoOdl(); // effettua gestione import file... processFileImport(); } #endregion Protected Methods } }