using System; using System.Collections.Generic; namespace IOB_WIN { /// /// Configuraizone eventi da simulare /// public class simPar { /// /// Attesa per evento /// public int wait = 10; /// /// Durata dell'evento /// public int duration = 1; /// /// DateTime ultimo evento /// public DateTime lastEv = DateTime.Now; } public class IobSimula : IobGeneric { /// /// pallet corrente /// protected int cP = 1; /// /// pallet successivo (next) /// protected int nP = 1; /// /// periodo base del simulatore (in secondi) /// protected int periodoMSec = 1000; /// /// BOOL: indica se simulare powerOn/Off (bit 0 e 1) compresi WarmUp e CoolDown /// protected bool simPowerOnOff; /// /// Ora dia ccensione (standard) /// public int tOn = 6; /// /// Ora spegniemnto (standard) /// public int tOff = 22; /// /// Parametri simulazione oscillazione bit 2 /// protected simPar bit2; /// /// Parametri simulazione oscillazione bit 3 /// protected simPar bit3; /// /// Parametri simulazione oscillazione bit 4 /// protected simPar bit4; /// /// Parametri simulazione oscillazione bit 5 /// protected simPar bit5; /// /// ultimo controllo decremento eventi /// protected DateTime lastEvCheck; /// /// estende l'init della classe base... /// /// /// public IobSimula(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { // gestione invio ritardato contapezzi pzCountDelay = utils.CRI("pzCountDelay"); lastPzCountSend = DateTime.Now; lastWarnODL = DateTime.Now; lastEvCheck = DateTime.Now; // sistemo parametri x simulazione... if (cIobConf.optPar.Count > 0) { if (getOptPar("PER_BASE") != "") { int.TryParse(getOptPar("PER_BASE"), out periodoMSec); // aggiungo NOISE... +/- 20% Random rnd = new Random(); int noise = rnd.Next(1, periodoMSec / 5); periodoMSec += noise - (periodoMSec / 10); } simPowerOnOff = false; bool.TryParse(getOptPar("SIM_POW_ON_OFF"), out simPowerOnOff); int.TryParse(getOptPar("T_ON"), out tOn); int.TryParse(getOptPar("T_OFF"), out tOff); bit2 = setupSimPar("SIM_PZCNT"); bit3 = setupSimPar("SIM_ALARM"); bit4 = setupSimPar("SIM_MANU"); bit5 = setupSimPar("SIM_SLOW"); } } /// /// Effettua reset del contapezzi /// /// public override bool resetContapezziCNC() { bool answ = false; // ...SE abilitato da conf IOB if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") { // fingo di aver fatto... answ = true; } return answ; } /// /// Setup aprametri di simulazione per BIT indicato /// /// private simPar setupSimPar(string keyName) { simPar answ = new simPar(); if (cIobConf.optPar.Count > 0) { if (cIobConf.optPar.ContainsKey(keyName)) { string fullVal = getOptPar(keyName); if (fullVal != "" && fullVal.IndexOf("|") > 0) { string[] param = fullVal.Split('|'); int.TryParse(param[0], out answ.wait); int.TryParse(param[1], out answ.duration); // aggiongo noise, +/- 40%... Random rnd = new Random(); int noise = rnd.Next(1, answ.wait * 40 / 100); answ.wait += noise - (answ.wait * 20 / 100); } } } return answ; } /// /// Setup singolo parametro /// /// /// private int setIntSimPar(string keyName) { int answ = 1; int.TryParse(getOptPar(keyName), out answ); // aggiongo noise, +/- 20%... Random rnd = new Random(); int noise = rnd.Next(1, answ / 5); answ += noise - (answ / 10); return answ; } /// /// Verifica se sia machcina multi = DoppioPallet da CONF /// public bool isMulti { get { bool answ = false; string keyName = "SIM_MULTI"; if (cIobConf.optPar.Count > 0) { if (cIobConf.optPar.ContainsKey(keyName)) { string SIM_MULTI = getOptPar(keyName); answ = SIM_MULTI == "1"; } } return answ; } } public override void tryConnect() { base.tryConnect(); connectionOk = true; } public override void tryDisconnect() { base.tryDisconnect(); connectionOk = false; } #region Metodi specifici (da verificare/completare in implementazione) /// /// Effettua vero processing contapezzi /// public override void processContapezzi() { } /// /// lettura bit semafori /// public override void readSemafori() { base.readSemafori(); // decodifica e gestione decodeToBaseBitmap(); decodeOtherData(); } /// /// Processo contatori eventi... /// public override void processVHF() { if (lastEvCheck.AddMilliseconds(periodoMSec) < DateTime.Now) { // decremento contatore ultimo evento bit2.wait--; bit3.wait--; bit4.wait--; bit5.wait--; lastEvCheck = DateTime.Now; } } /// /// Effettua decodifica aree memoria alla bitmap usata x MAPO /// private void decodeToBaseBitmap() { // init a zero... B_input = 0; bool sendContapezzi = false; /* ----------------------------------------------------- * bitmap MAPO * B0: POWER_ON * B1: RUN * B2: pzCount * B3: allarme * B4: manuale * B5: emergenza - non usato x ora * B6: pallet 1 (SE doppio pallet) * B7: pallet 2 (SE doppio pallet) ----------------------------------------------------- */ // di base macchina in RUN B_input = 3; /*---------------------------------------- * Simulazione segnali con priorità: * - Power ON / OFF (bit0/1) * - ALLARMI * - SLOW * - MANUALE * - contapezzi * *----------------------------------------*/ // se simulo PowerOn/Off --> spegnimento con CoolDown e accensione con WarmUp.. if (simPowerOnOff) { DateTime adesso = DateTime.Now; // se l'orario è dopo le tOff (tipicamente 22) --> NO RUN... if (adesso.Hour >= tOff || adesso.Hour <= tOn) { // se prima/ultima mezz'ora è ancora accesa NON in run... if (adesso.AddMinutes(-30).Hour < tOff || adesso.AddMinutes(30).Hour > tOn) { B_input = 1; } else { B_input = 0; } } } // questa aprte la processo SOLO SE sono in run --> B_input == 3 if (B_input == 3) { if (bit3.wait <= 0) { // segnalo BIT B_input += (1 << 3); // decremento duration bit3.duration--; // controllo se sia scaduta la duration... in quel caso reset... if (bit3.duration <= 0) { bit3 = setupSimPar("SIM_ALARM"); } } else if (bit4.wait <= 0) { // segnalo BIT B_input += (1 << 4); // decremento duration bit4.duration--; // controllo se sia scaduta la duration... in quel caso reset... if (bit4.duration <= 0) { bit4 = setupSimPar("SIM_MANU"); } } else if (bit5.wait <= 0) { // segnalo BIT B_input += (1 << 5); // decremento duration bit5.duration--; // controllo se sia scaduta la duration... in quel caso reset... if (bit5.duration <= 0) { bit5 = setupSimPar("SIM_SLOW"); } } else if (bit2.wait <= 0) { // se multipallet --> cP a zero! if (isMulti) { cP = 0; } // se NON Multi fa contapezzi... else { // segnalo BIT B_input += (1 << 2); } // decremento duration bit2.duration--; // controllo se sia scaduta la duration... in quel caso reset... if (bit2.duration <= 0) { bit2 = setupSimPar("SIM_PZCNT"); // salvo nuovo contapezzi (incremento di 1...) contapezzi++; sendContapezzi = true; // registro contapezzi lgInfo(string.Format("Contapezzi SIMULAZIONE: {0}", contapezzi)); } if (sendContapezzi) { // controllo se ALMENO sia pingabile il server if (checkServerAlive) { // invio a server contapezzi (aggiornato) string retVal = utils.callUrl(urlSetPzCount + contapezzi.ToString()); // verifica se tutto OK if (retVal != "OK") { // errore salvataggio contapezzi lgInfo(string.Format("Errore salvataggio Contapezzi SIMULAZIONE {0} | Errore salvataggio: {1}", contapezzi, retVal)); } // resetto timer... lastPzCountSend = DateTime.Now; } } } // se multi gestisco il bit delle tavole... if (isMulti) { // se sono in fase di fronte d'uscita (invio contapezzi) INVERTO nP... if (sendContapezzi) { nP = nP == 1 ? 2 : 1; // assegno a cP il valore nP... cP = nP; } // se cP > 0 --> segnalo bit tavola... if (cP == 1) { B_input += (1 << 6); } else if (cP == 2) { B_input += (1 << 7); } } } } /// /// Decodifica il resto dell'area x i dati accessori (allarmi, ...) /// private void decodeOtherData() { } /// /// Recupero programma in lavorazione /// /// public override string getPrgName() { // valore non presente in vers default... se gestito fare override string prgName = string.Format("DEMO_{0:00}", DateTime.Now.Minute); return prgName; } /// /// Recupero dati override (da area G che è già stata letta...) /// /// public override Dictionary getOverrides() { Dictionary outVal = new Dictionary(); // processo SOLO SE connected... if (connectionOk) { Random rnd = new Random(); int feedOvr = rnd.Next(1, 100); int rapdOvr = rnd.Next(1, 120); outVal.Add("FEED_OVER", feedOvr.ToString()); outVal.Add("RAPID_OVER", rapdOvr.ToString()); } return outVal; } /// /// Recupero info sistema generiche /// public override Dictionary getSysInfo() { // valore non presente in vers default... se gestito fare override Dictionary outVal = new Dictionary(); outVal.Add("MACHINE", "IOB_SIM"); return outVal; } /// /// Recupero dati dinamici... /// public override Dictionary getDynData() { // valore non presente in vers default... se gestito fare override Dictionary outVal = new Dictionary(); Random rnd = new Random(); int posX = rnd.Next(1, 1000); int posY = rnd.Next(1, 1000); int posZ = rnd.Next(1, 1000); outVal.Add("POS_X", posX.ToString()); outVal.Add("POS_Y", posY.ToString()); outVal.Add("POS_Z", posZ.ToString()); return outVal; } /// /// Recupera e processa allarmi CNC... /// public override Dictionary getCncAlarms() { Dictionary outVal = new Dictionary(); return outVal; } #endregion } }