/// <summary> /// If passed-in event is a SettingsReadEvent, then this routine updates the database with the GasEndPoints. /// </summary> /// <param name="dsEvent"></param> private void SaveGasEndPoints(SettingsReadEvent settingsReadEvent, DataAccessTransaction trx) { // Either settingsReadEvent.DockingStation.GasEndPoints will have // contents or else ChangedGasEndPoints will. Never both. Log.Assert((settingsReadEvent.DockingStation.GasEndPoints.Count > 0 && settingsReadEvent.DockingStation.ChangedGasEndPoints.Count > 0) == false, "Both GasEndPoints and ChangedGasEndPoints cannot contain data."); // If GasEndPoints has contents, then the list contains all known attached // cylinders. // If ChangedGasEndPoints has contents, then the list contains known changes: // e.g.., if there's been no iGas card insertion/removal on, say, // position 2, then there will be no cylinder in the list at that position. GasEndPointDataAccess gepDataAccess = new GasEndPointDataAccess(); if (settingsReadEvent.DockingStation.GasEndPoints.Count > 0) { Log.Debug(string.Format("Calling SaveInstalledCylinders (GasEndPoints.Count={0})", settingsReadEvent.DockingStation.GasEndPoints.Count)); gepDataAccess.SaveInstalledCylinders(settingsReadEvent.DockingStation.GasEndPoints, trx); } // Note that we don't check the ChangedGasEndPoints to see if it's empty or not. // If GasEndPoints is empty, then we assume we're to use ChangedGasEndPoints // If it's empty, then it means there are no known changed cylinders. The call // to SaveInstalledCylinders will handle that. else { Log.Debug("Calling SaveChangedCylinders"); gepDataAccess.SaveChangedCylinders(settingsReadEvent.DockingStation.ChangedGasEndPoints, trx); } }
public DockingStationEvent Execute() { string funcMsg = Name + ".Execute"; Log.Debug(funcMsg); // We copy the PostUpdate and SettingsRefId from the action to the event so they can // be passed on to the followup SettingsRead. See the EventProcessor.GetFollowupAction method. CylinderPressureResetEvent dsEvent = new CylinderPressureResetEvent(this); dsEvent.PostUpdate = this.PostUpdate; dsEvent.SettingsRefId = this.SettingsRefId; List <GasEndPoint> emptyManGasEndPoints = new List <GasEndPoint>(); List <GasEndPoint> manGasEndPoints = new GasEndPointDataAccess().FindAll().FindAll(m => m.InstallationType == GasEndPoint.Type.Manifold || m.InstallationType == GasEndPoint.Type.Manual); // We want to reset low/empty non-iGas cylinders to full. for (int position = 1; position <= Configuration.DockingStation.NumGasPorts; position++) { // We don't want to process (manual) fresh air cylinders on port 1. GasEndPoint man = manGasEndPoints.Find(m => m.Position == position && !(m.Position == 1 && m.Cylinder.IsFreshAir)); if (man != null) { Log.Debug(string.Format("{0}Position {1} {2} found (\"{3}\", \"{4}\") with {5} pressure.", LOG_LABEL, position, man.InstallationType == GasEndPoint.Type.Manifold ? "Manifold" : "Manual Cylinder", man.Cylinder.FactoryId, man.Cylinder.PartNumber, man.Cylinder.Pressure)); if (man.Cylinder.Pressure != PressureLevel.Full) { man.GasChangeType = GasEndPoint.ChangeType.PressureChanged; man.Cylinder.Pressure = PressureLevel.Full; emptyManGasEndPoints.Add(man); } } } if (emptyManGasEndPoints.Count > 0) { // Save the modified cylinders in the local database. The followup SettingsRead with // ChangedSmartCards set to null will take care of updating the cylinders in memory. using (DataAccessTransaction trx = new DataAccessTransaction()) { new GasEndPointDataAccess().SaveChangedCylinders(emptyManGasEndPoints, trx); trx.Commit(); Log.Debug(string.Format("{0}{1} non-iGas cylinders were reset to full.", LOG_LABEL, emptyManGasEndPoints.Count)); } } else { Log.Debug(string.Format("{0}No manifold or manual cylinders were found that needed reset to full.", LOG_LABEL)); } return(dsEvent); }
/// <summary> /// </summary> /// <remarks> /// 1) Updates the cylinder's pressure in the database (change it from Full to Low, or Low to Empty). /// 2) Update cached cylinder (in Configuration.DockingStation.InstalledCylinders) with the pressure /// change. /// 3) Also forces an upload of a SettingsReadEvent in order to notify iNet of the pressure change. /// </remarks> /// <param name="emptyCylinderError"></param> /// <param name="inetUploader"></param> /// <returns></returns> private DockingStationAction ProcessEmptyGasEndPoint(GasEndPoint emptyEndPoint, InetUploader inetUploader) { Log.Debug(string.Format("Empty Cylinder was reported on position {0}", emptyEndPoint.Position)); GasEndPoint gasEndPoint = null; using (DataAccessTransaction trx = new DataAccessTransaction()) { GasEndPointDataAccess gepDataAccess = new GasEndPointDataAccess(); gasEndPoint = gepDataAccess.FindByPosition(emptyEndPoint.Position, trx); if (gasEndPoint == null) { return(null); // should we display an error? } if (gasEndPoint.Cylinder.Pressure == PressureLevel.Full) { gasEndPoint.Cylinder.Pressure = PressureLevel.Low; Log.Warning("Low pressure warning, position " + emptyEndPoint.Position); } else { gasEndPoint.Cylinder.Pressure = PressureLevel.Empty; Log.Warning("Empty pressure warning, position " + emptyEndPoint.Position); } Log.Debug(string.Format("Changing pressure to \"{0}\" for cylinder on position {1}", gasEndPoint.Cylinder.Pressure.ToString(), gasEndPoint.Position)); Log.Debug(string.Format("...PartNumber={0}, FactoryId={1}", gasEndPoint.Cylinder.PartNumber, gasEndPoint.Cylinder.FactoryId)); gepDataAccess.UpdatePressureLevel(gasEndPoint, trx); trx.Commit(); } // After updating the database, we need to update the cached copy of the // installed cylinder, too, which is kept in the global DockingStation. GasEndPoint cachedGasEndPoint = Configuration.DockingStation.GasEndPoints.Find(g => g.Position == gasEndPoint.Position); if (cachedGasEndPoint != null) { cachedGasEndPoint.Cylinder.Pressure = gasEndPoint.Cylinder.Pressure; } // We need to inform iNet whenever a cylinder's pressure changes. We can only do this // by uploading a full docking station with the cylinder information. Which means we // need to immediately do a SettingsRead to get the full docking station info, and then // upload that info along with the currently installed cylinder info. SettingsReadOperation settingsReadOperation = new SettingsReadOperation(); // Explicitly set the ChangedSmartCards to all falses so that no smart cards are read. settingsReadOperation.ChangedSmartCards = new bool[Configuration.DockingStation.NumGasPorts]; SettingsReadEvent settingsReadEvent = (SettingsReadEvent)settingsReadOperation.Execute(); // Copy currently installed cylinder info to the docking station object we're going to upload. settingsReadEvent.DockingStation.GasEndPoints.Clear(); settingsReadEvent.DockingStation.ChangedGasEndPoints.Clear(); foreach (GasEndPoint gep in Configuration.DockingStation.GasEndPoints) { settingsReadEvent.DockingStation.GasEndPoints.Add((GasEndPoint)gep.Clone()); } inetUploader.UploadEvent(settingsReadEvent, Configuration.DockingStation.TimeZoneInfo); // BEGIN INS-8630 RHP v7.5 List <string> consoleMessages = new List <string>(); consoleMessages.Add(gasEndPoint.Cylinder.Pressure.ToString()); if (!string.IsNullOrEmpty(gasEndPoint.Cylinder.PartNumber)) // For ISC Pass the Cylinder Part Number { consoleMessages.Add(gasEndPoint.Cylinder.PartNumber); } // For Non ISC Pass the gas code. But I believe that both ISC and Non-ISC cylinders have their own PArt numbers. // So below condition may not be required ? else if (gasEndPoint.Cylinder.GasConcentrations.Count > 0) { consoleMessages.Add(gasEndPoint.Cylinder.GasConcentrations[0].Type.Symbol); } Log.Info("Sending IDS ReplaceCylinderAction"); DockingStationAction dsAction = new ResourceUnavailableAction(new List <string>() { gasEndPoint.Cylinder.Pressure.ToString() }, consoleMessages); // END INS-8630 return(dsAction); }
/// <summary> /// Return the information from all smart cards that are present. /// </summary> /// <returns>All of the installed cylinders.</returns> static private void ReadChangedCylinders(bool[] changedSmartCards, IList <GasEndPoint> changedGasEndPoints, PortRestrictions port1Restrictions) { const string funcName = "ReadChangedCylinders: "; Log.Assert(changedSmartCards != null, funcName + "changedSmartCards should not be null."); DockingStation dockingStation = Controller.GetDockingStation(); // SGF 8-Nov-2012 INS-2686 changedGasEndPoints.Clear(); for (int i = 0; i < changedSmartCards.Length; i++) { int position = i + 1; Log.Debug(funcName + "POSITION " + position); if (changedSmartCards[position - 1] == false) // No detection of a card insertion, nor a removal? { Log.Debug(string.Format("{0}Position {1} Smart card SKIPPED; No insertion change detected.", funcName, position)); if (position == Controller.FRESH_AIR_GAS_PORT) { GasEndPoint persistedPort1GasEndPoint = new GasEndPointDataAccess().FindByPosition(Controller.FRESH_AIR_GAS_PORT); // If there's nothing known to be installed on port 1, then create a fresh air // cylinder for the port. // This could happen if, while nothing was installed on the port, a SettingsUpdate // just occurred previously where the port setting was changed to allow fresh air. // In that situation, we have to then make the fresh air cylinder. if (persistedPort1GasEndPoint == null) { Log.Debug(string.Format("{0}Position {1}, No persisted cylinder; assuming Fresh Air.", funcName, position)); GasEndPoint freshAirCylinder = GasEndPoint.CreateFreshAir(position); freshAirCylinder.GasChangeType = GasEndPoint.ChangeType.Installed; changedGasEndPoints.Add(freshAirCylinder); } } // SGF 8-Nov-2012 INS-2686 -- begin // Soon, we will check to see if a pressure switch is present, and if so, read the pressure level. // Before we do that, we must check for two scenarios in which it is not necessary or appropriate // to read a pressure switch. // 1. If there is no cylinder attached to the port, there is no reason to check for a pressure switch. // 2. If this is the first port, and we know that the port is drawing fresh air, there is no reason // to check for a pressure switch. This case cannot be handled by case #1, as we define a "logical" // cylinder to represent fresh air. // If we find either scenario for the current port, we skip further processing on this port, and proceed to // the next one. GasEndPoint currentInstalledCylinder = dockingStation.GasEndPoints.Find(ic => ic.Position == position); if (currentInstalledCylinder == null) { Log.Debug(string.Format("{0}Position {1} No cylinder present; do not check for pressure switch.", funcName, position)); continue; } else { bool isFreshAir = currentInstalledCylinder.Cylinder.IsFreshAir; if (isFreshAir) { Log.Debug(string.Format("{0}Position {1} Fresh air; do not check for pressure switch.", funcName, position)); continue; } } // SGF 8-Nov-2012 INS-2686 -- end // SMARTCARD NOT CHANGED (NO INSERT OR REMOVAL DETECTED). // WE NEED TO AT LEAST ALWAYS READ THE PRESSURE SWITCH THEN. if (SmartCardManager.IsPressureSwitchPresent(position)) { GasEndPoint pressureCylinder = new GasEndPoint(); pressureCylinder.Position = position; pressureCylinder.Cylinder.Pressure = ReadPressureLevel(position); pressureCylinder.GasChangeType = GasEndPoint.ChangeType.PressureChanged; Log.Debug(string.Format("{0}Position {1} Pressure Switch reports {2}.", funcName, position, pressureCylinder.Cylinder.Pressure)); changedGasEndPoints.Add(pressureCylinder); } else { Log.Debug(string.Format("{0}Position {1} Pressure Switch not present.", funcName, position)); } continue; } // IF WE MAKE IT TO HERE, THE CARD HAS BEEN EITHER INSERTED OR REMOVED. if (!SmartCardManager.IsCardPresent(position)) // CARD REMOVED? { Log.Debug(string.Format("{0}Position {1} SmartCard not present, Returning CardRemoved", funcName, position)); // Server needs to know specifically that cylinder is missing. // Indicate this with an InstalledCylinder containing an empty Cylinder object. GasEndPoint missingCylinder = new GasEndPoint(); missingCylinder.Position = position; missingCylinder.GasChangeType = GasEndPoint.ChangeType.Uninstalled; changedGasEndPoints.Add(missingCylinder); // If a cylinder is not installed on the fresh air port, then assume fresh air // for the port if (position == Controller.FRESH_AIR_GAS_PORT) { Log.Debug(string.Format("{0}Position {1} is assumed to be Fresh Air.", funcName, position)); GasEndPoint freshAirCylinder = GasEndPoint.CreateFreshAir(position); freshAirCylinder.GasChangeType = GasEndPoint.ChangeType.Installed; changedGasEndPoints.Add(freshAirCylinder); } continue; } // IF WE MAKE IT TO HERE, THE CARD HAS BEEN INSERTED. Cylinder cylinder = SmartCardManager.ReadCard(position); if (cylinder == null) // Couldn't read valid cylinder? Driver error or corrupt card. { Log.Debug(string.Format("{0}Position {1}, ReadCard returned null. SKIPPING cylinder.", funcName, position)); continue; } // Dates read from card will be in 'local' time, but everything we deal with is in UTC. cylinder.ExpirationDate = Configuration.ToUniversalTime(cylinder.ExpirationDate); cylinder.RefillDate = Configuration.ToUniversalTime(cylinder.RefillDate); Thread.Sleep(1000); cylinder.Pressure = ReadPressureLevel(position); GasEndPoint gasEndPoint = new GasEndPoint(cylinder, position, GasEndPoint.Type.iGas); gasEndPoint.GasChangeType = GasEndPoint.ChangeType.Installed; Log.Debug(string.Format("{0}Position {1}, Returning CardInserted. Pressure={2}", funcName, position, cylinder.Pressure)); changedGasEndPoints.Add((GasEndPoint)gasEndPoint.Clone()); } // end-for return; }
/// <summary> /// Return the information from all smart cards, manifolds and manual cylinders that are present at start-up. /// </summary> /// <param name="installedCylinders">Information about the cylinders is placed into this passed-in list.</param> static private void ReadInstalledCylinders(List <GasEndPoint> gasEndPoints, PortRestrictions port1Restrictions) { const string funcName = "ReadInstalledCylinders: "; // Get all currently attached manifolds and manually-assigned cylinders. List <GasEndPoint> manGasEndPoints = new GasEndPointDataAccess().FindAll().FindAll(m => m.InstallationType == GasEndPoint.Type.Manifold || m.InstallationType == GasEndPoint.Type.Manual); for (int position = 1; position <= Configuration.DockingStation.NumGasPorts; position++) { Log.Debug(funcName + "POSITION " + position); // iGas cylinders take precendence if (!SmartCardManager.IsCardPresent(position)) { Log.Debug(string.Format("{0}Position {1}, No iGas card detected.", funcName, position)); // Does the port have a manifold or manual cylinder attached? Then make sure we include // that cylinder in the returned list. If no cylinder exists on port 1, then create a // virtual fresh air cylinder. GasEndPoint man = manGasEndPoints.Find(m => m.Position == position); if (man != null) { Log.Debug(string.Format("{0}Position {1} {2} found (\"{3}\", \"{4}\", Pressure {5}).", funcName, position, man.InstallationType == GasEndPoint.Type.Manifold ? "Manifold" : "Manual Cylinder", man.Cylinder.FactoryId, man.Cylinder.PartNumber, man.Cylinder.Pressure)); gasEndPoints.Add(man); } else if (position == Controller.FRESH_AIR_GAS_PORT) { Log.Debug(string.Format("{0}Position {1} is assumed to be Fresh Air.", funcName, position)); GasEndPoint freshAirEndPoint = GasEndPoint.CreateFreshAir(position); freshAirEndPoint.GasChangeType = GasEndPoint.ChangeType.Installed; gasEndPoints.Add(freshAirEndPoint); } continue; } // IF WE MAKE IT TO HERE, THEN WE KNOW WE HAVE AN INSERTED SMART CARD WHICH MEANS iGas IS ATTACHED. Cylinder cylinder = SmartCardManager.ReadCard(position); if (cylinder == null) // Check for a valid cylinder. { Log.Debug(string.Format("{0}Position {1}, ReadCard returned null. SKIPPING cylinder.", funcName, position)); continue; } // Dates read from card will be in 'local' time, but everything we deal with is in UTC. cylinder.ExpirationDate = Configuration.ToUniversalTime(cylinder.ExpirationDate); cylinder.RefillDate = Configuration.ToUniversalTime(cylinder.RefillDate); Thread.Sleep(1000); if (SmartCardManager.IsPressureSwitchPresent(position)) { if (SmartCardManager.CheckPressureSwitch(position)) { cylinder.Pressure = PressureLevel.Full; } else { cylinder.Pressure = PressureLevel.Low; } Log.Debug(string.Format("{0}Position {1} Pressure Switch reports {2}.", funcName, position, cylinder.Pressure)); } else { Log.Debug(string.Format("{0}Position {1} Pressure Switch not detected.", funcName, position)); } GasEndPoint gasEndPoint = new GasEndPoint(cylinder, position, GasEndPoint.Type.iGas); // Add the installed cylinder to the DockingStation (IDS). gasEndPoints.Add(gasEndPoint); } return; }