internal Brewery(string breweryMacAddress) { ID = breweryMacAddress; RemoteState = new BreweryState(); LastMessage = DateTime.Now; Settings = new SettingsData(); }
private void breweryState_MessageReceived(BreweryState _breweryState) { if(_breweryState != breweryState) { breweryState = _breweryState; if (breweryState == BreweryState.HLT_Fill) { SessionTimer(); } StepTimer(); } }
public TimerViewModel() { // Initialize local variables breweryState = BreweryState.StandBy; sessionTime = new TimeSpan(); sessionStartTime = new TimeSpan(); stepStartTime = new TimeSpan(); stepTime = new TimeSpan(); // Register to incoming messages Messenger.Default.Register<BreweryState>(this, breweryState_MessageReceived); // Timer Initialisation UpdateTimer = new DispatcherTimer(); }
// Starts a Brew Session when the MenuSubItem : Start Session is selected private void startBrewSessionClickCommand() { // Verify brewery connection if (!brewery.IsConnected) { process.Session.StartRequested = true; connectionSetupClickCommand(); return; } // Verify Session Status if (process.Session.IsStarted) { process.Session.StartRequested = false; process.Session.IsStarted = false; RaisePropertyChanged(StartSessionButtonContentPropertyName); UpdateTempSensorTimer.Stop(); UpdateVolSensorTimer.Stop(); return; } // Get recipe file if not chosen already if (process.Session.TotalWaterNeeded == 0) { process.Session.StartRequested = true; loadRecipeClickCommand(); return; } // Set Session properties process.Session.IsStarted = true; process.Session.StartRequested = false; RaisePropertyChanged(StartSessionButtonContentPropertyName); // Check if Design Session and skip the sensor update timers if true if (DesignMode) { goto SkipDAQTimers; } // Setting Temperature Timer Properties UpdateTempSensorTimer.Interval = TimeSpan.FromMilliseconds(hardwareSettings.TempRefreshRate); UpdateTempSensorTimer.Tick += UpdateTempSensorTimer_Tick; UpdateTempSensorTimer.Start(); // Setting Volume Timer Properties UpdateVolSensorTimer.Interval = TimeSpan.FromMilliseconds(hardwareSettings.VolResfreshRate); UpdateVolSensorTimer.Tick += UpdateVolSensorTimer_Tick; UpdateVolSensorTimer.Start(); SkipDAQTimers: // Run state Machine breweryState = BreweryState.StandBy; RunAutoStateMachine(); }
private void RunAutoStateMachine() { switch(breweryState) { case BreweryState.StandBy: { if(process !=null) { // Set the fill and temp set point and send the data to the HLT view brewery.HLT.Volume.SetPoint = process.Session.TotalWaterNeeded; brewery.HLT.Temp.SetPoint = process.Strike.Temp; brewery.HLT.Temp.SetPointReached = false; brewery.HLT.Volume.SetPointReached = false; Messenger.Default.Send<Brewery>(brewery, "HLTVolumeSetPointUpdate"); Messenger.Default.Send<Brewery>(brewery, "HLTVolumeSetPointReachedUpdate"); Messenger.Default.Send<Brewery>(brewery, "HLTTempSetPointUpdate"); Messenger.Default.Send<Brewery>(brewery, "HLTTempSetPointReachedUpdate"); if(!userAlarm.MessageSent) { PlayAlarm("", false, true, true); } if(userAlarm.ProceedIsPressed) { breweryState = BreweryState.HLT_Fill; RaisePropertyChanged(BreweryStateDisplayPropertyName); userAlarm = new UserAlarm(); } } break; } case BreweryState.HLT_Fill: { // Send User Alarm message to update the UserAction display text if(!userAlarm.MessageSent) { PlayAlarm("", false, false, true); } // Set the fill set point and send the data to the HLT view brewery.HLT.Volume.SetPoint = process.Session.TotalWaterNeeded; brewery.HLT.Temp.SetPoint = process.Strike.Temp; Messenger.Default.Send<Brewery>(brewery, "HLTVolumeSetPointUpdate"); Messenger.Default.Send<Brewery>(brewery, "HLTTempSetPointUpdate"); // Check if HLT volume reached SetPoint if(brewery.HLT.Volume.Value >= brewery.HLT.Volume.SetPoint) { // Set the SetPointReached property and send the data to the HLT view brewery.HLT.Volume.SetPointReached = true; Messenger.Default.Send<Brewery>(brewery, "HLTVolumeSetPointReachedUpdate"); // Go to Strike heat state breweryState = BreweryState.Strike_Heat; RaisePropertyChanged(BreweryStateDisplayPropertyName); userAlarm = new UserAlarm(); } break; } case BreweryState.Strike_Heat: { // Send Message to light the pilots if (!userAlarm.MessageSent) { PlayAlarm("Pilot", true, true, true); } // Check for user confirmation of pilots if(userAlarm.ProceedIsPressed) { // Get to HLT Set point and Hold breweryCommand.HoldTemp(Vessels.HLT, process.Strike.Temp); } // Check if temperature range is reached if (brewery.HLT.Temp.SetPointReached) { // Change State breweryState = BreweryState.Strike_Transfer; brewery.MLT.Volume.SetPointReached = false; RaisePropertyChanged(BreweryStateDisplayPropertyName); userAlarm = new UserAlarm(); } break; } case BreweryState.Strike_Transfer: { // Define SetPoint for initial MLT volume (dough in) brewery.MLT.Volume.SetPoint = process.MashSteps[0].Volume; Messenger.Default.Send<Brewery>(brewery, "MLTVolumeSetPointUpdate"); Messenger.Default.Send<Brewery>(brewery, "MLTVolumeSetPointReachedUpdate"); // Confirm the correct Valves operations are complete before starting the pump if (!userAlarm.MessageSent) { PlayAlarm("Valves", true, true, true); } // Hold Strike Temp breweryCommand.HoldTemp(Vessels.HLT, process.Strike.Temp); // If the user did not confirm, hold temperature and wait if (!userAlarm.ProceedIsPressed) { return; } if (brewery.MLT.Volume.Value < brewery.MLT.Volume.SetPoint) { // Let a delay for pump priming if the pump is off and not primed if (!brewery.Pump1.IsPrimed && !brewery.Pump1.IsOn && !brewery.Pump1.IsPriming) { StartPrimingDelay(1); PlayAlarm("Priming", false, false, false); } // Else if pump is primed but off else if (brewery.Pump1.IsPrimed && !brewery.Pump1.IsOn) { HLTStartVolume = brewery.HLT.Volume.Value; breweryCommand.ActivatePump1(true); PlayAlarm("Transfering", false, false, false); } // Update the transfered volume else if(brewery.Pump1.IsOn) { brewery.MLT.Volume.Value = HLTStartVolume - brewery.HLT.Volume.Value; Messenger.Default.Send<Brewery>(brewery, "MLTVolumeUpdate"); } } else { // Stop the transfer if (brewery.Pump1.IsOn) { breweryCommand.ActivatePump1(false); } // Set the Volume Set point reached property brewery.MLT.Volume.SetPointReached = true; Messenger.Default.Send<Brewery>(brewery, "MLTVolumeSetPointReachedUpdate"); // Go to dough in state breweryState = BreweryState.DoughIn; RaisePropertyChanged(BreweryStateDisplayPropertyName); userAlarm = new UserAlarm(); } break; } case BreweryState.DoughIn: { // Ask user to set the valves in recirculation mode and play alarm sound to request user action if (RecirculationConfirmed) { goto SkipRecirculationAlarm; } if (!userAlarm.MessageSent) { PlayAlarm("Recirculation", true, true, true); } else if(userAlarm.ProceedIsPressed) { RecirculationConfirmed = true; userAlarm = new UserAlarm(); } SkipRecirculationAlarm: // Hold MLT temp at set point (dough in temp) breweryCommand.HoldTemp(Vessels.MLT, process.Strike.Temp); // Hold HLT temp at set point breweryCommand.HoldTemp(Vessels.HLT, process.Sparge.Temp); // Check if the temperature is within range and set the SetPointReached property if (brewery.MLT.Temp.SetPointReached) { // Ask user to dough in and confirm BEFORE putting the grains play alarm sound to request user action if (!userAlarm.MessageSent && RecirculationConfirmed) { PlayAlarm("DoughIn", true, true, true); } // If user confirmed go to Mash step #1 if(userAlarm.ProceedIsPressed) { // Start the mash process breweryCommand.LightBurner(Vessels.MLT, false); breweryState = BreweryState.Mash; RaisePropertyChanged(BreweryStateDisplayPropertyName); userAlarm = new UserAlarm(); } } break; } case BreweryState.Mash: { // If first iteration start mash timer if(FirstMashStep) { // Get the step start and end time StepStartTime = DateTime.Now.TimeOfDay; StepEndTime = StepStartTime.Add(TimeSpan.FromMinutes(process.MashSteps[step].Time)); // Start the step timer MashStepTimer.Interval = TimeSpan.FromMilliseconds(500); MashStepTimer.Tick += MashStepTimer_Tick; MashStepTimer.Start(); FirstMashStep = false; } // If the mash step is completed increment if(MashStepComplete) { // Set the new mash step as incomplete MashStepComplete = false; // Check if all steps are completed if (process.MashSteps.Count <= step+1) { breweryState = BreweryState.Sparge; RaisePropertyChanged(BreweryStateDisplayPropertyName); userAlarm = new UserAlarm(); return; } // Get the step start and end time StepStartTime = DateTime.Now.TimeOfDay; StepEndTime = StepStartTime.Add(TimeSpan.FromMinutes(process.MashSteps[step].Time)); // Start the step timer MashStepTimer.Interval = TimeSpan.FromMilliseconds(500); MashStepTimer.Tick += MashStepTimer_Tick; MashStepTimer.Start(); } // Hold HLT temp set point at mash step temp breweryCommand.HoldTemp(Vessels.MLT, process.MashSteps[step].Temp); // Hold HLT temp at sparge temp breweryCommand.HoldTemp(Vessels.HLT, process.Sparge.Temp); // Start recirculating if(!brewery.Pump2.IsPrimed && !brewery.Pump2.IsPriming) { StartPrimingDelay(2); } else if(brewery.Pump2.IsPrimed && !brewery.Pump2.IsOn) { breweryCommand.ActivatePump2(true); } break; } case BreweryState.Sparge: { // Send Sparging Message if(!userAlarm.MessageSent && !SpargeModeOn) { PlayAlarm("ValveSpargeMode", false, false, true); breweryCommand.ActivatePump2(false); SpargeModeOn = true; userAlarm = new UserAlarm(); } // Hold HLT at Sparge Temp breweryCommand.HoldTemp(Vessels.HLT, process.Sparge.Temp); // If HLT temp is in range then start the pumps if(brewery.HLT.Temp.SetPointReached && userAlarm.ProceedIsPressed && (!brewery.Pump1.IsOn || !brewery.Pump2.IsOn) && FirstSparge) { // Save the HLT Start Volume and start the pumps HLTStartVolume = brewery.HLT.Volume.Value; breweryCommand.ActivatePump1(true); breweryCommand.ActivatePump2(true); FirstSparge = false; // Turn off MLT Temp monitoring breweryCommand.HoldTemp(Vessels.MLT, 0); // Set The HLT Volume Set Point and save the MLT Start Volume MLTStartVolume = brewery.MLT.Volume.Value; brewery.HLT.Volume.SetPoint = HLTStartVolume - process.Sparge.Volume; if (brewery.HLT.Volume.SetPoint < 0) { brewery.HLT.Volume.SetPoint = 0; } brewery.HLT.Volume.SetPointReached = false; Messenger.Default.Send<Brewery>(brewery, "HLTVolumeSetPointUpdate"); Messenger.Default.Send<Brewery>(brewery, "HLTVolumeSetPointReachedUpdate"); // Set the BK volume Set Point brewery.BK.Volume.SetPoint = process.Boil.Volume; brewery.BK.Volume.SetPointReached = false; Messenger.Default.Send<Brewery>(brewery, "BKVolumeSetPointUpdate"); Messenger.Default.Send<Brewery>(brewery, "BKVolumeSetPointReachedUpdate"); } // Update the MLT volume based on the HLT volume pumped out and set the Volume Set Points brewery.MLT.Volume.Value = MLTStartVolume + HLTStartVolume - brewery.HLT.Volume.Value - brewery.BK.Volume.Value; Messenger.Default.Send<Brewery>(brewery, "MLTVolumeUpdate"); // Monitor HLT Sparge volume if (brewery.HLT.Volume.Value <= HLTStartVolume-process.Sparge.Volume) { if (brewery.Pump1.IsOn) { breweryCommand.ActivatePump1(false); } if(brewery.HLT.Volume.Value <= 10 && brewery.HLT.Burner.IsOn) { breweryCommand.LightBurner(Vessels.HLT, false); brewery.HLT.Temp.SetPointReached = false; Messenger.Default.Send<Brewery>(brewery, "HLTTempSetPointReachedUpdate"); } brewery.HLT.Volume.SetPointReached = true; Messenger.Default.Send<Brewery>(brewery, "HLTVolumeSetPointReachedUpdate"); } // Check if sparge water is missing and send alarm else if (brewery.HLT.Volume.SetPoint == 0 && brewery.HLT.Volume.Value == 0 && !userAlarm.MessageSent) { // Send alarm to indicate forced continue and initial water level was low PlayAlarm("MissingSpargeWater", true, true, false, process.Sparge.Volume - HLTStartVolume); if (brewery.Pump1.IsOn) { breweryCommand.ActivatePump1(false); } if (brewery.HLT.Volume.Value <= 10 && brewery.HLT.Burner.IsOn) { breweryCommand.LightBurner(Vessels.HLT, false); brewery.HLT.Temp.SetPointReached = false; Messenger.Default.Send<Brewery>(brewery, "HLTTempSetPointReachedUpdate"); } brewery.HLT.Volume.SetPointReached = true; Messenger.Default.Send<Brewery>(brewery, "HLTVolumeSetPointReachedUpdate"); } // Monitor BK Volume if over 10 start heating if(brewery.BK.Volume.Value>= 10 && !brewery.BK.Burner.IsOn) { breweryCommand.HoldTemp(Vessels.BK, 100); } // Monitor Bk Volume for process target if(brewery.BK.Volume.Value >= process.Boil.Volume) { if (brewery.Pump2.IsOn) { breweryCommand.ActivatePump2(false); } brewery.BK.Volume.SetPointReached = true; // Switch to boil state breweryState = BreweryState.Boil; RaisePropertyChanged(BreweryStateDisplayPropertyName); userAlarm = new UserAlarm(); Messenger.Default.Send<Brewery>(brewery, "BKVolumeSetPointReachedUpdate"); } break; } case BreweryState.Boil: { // Hold boil temp in BK breweryCommand.HoldTemp(Vessels.BK, 100); // Monitor BK and send an alarm to warn boil over if (brewery.BK.Temp.Value>=97 && !BoilOverSent) { // Send Boil Over Message if (!userAlarm.MessageSent) { PlayAlarm("BoilOver", true, true, false); BoilOverSent = true; userAlarm = new UserAlarm(); } } // Boil is reached if (brewery.BK.Temp.Value >= 99.5) { brewery.BK.Temp.BoilReached = true; } // Start Boil Timer if Boil is Reached if(brewery.BK.Temp.BoilReached && !BoilTimer.IsEnabled && !BoilComplete) { // Get the step start and end time BoilStartTime = DateTime.Now.TimeOfDay; BoilEndTime = StepStartTime.Add(TimeSpan.FromMinutes(process.Boil.Time)); // Start the step timer BoilTimer.Interval = TimeSpan.FromMilliseconds(500); BoilTimer.Tick += BoilTimer_Tick; BoilTimer.Start(); } // Check if boil is complete if(BoilComplete) { // Turn off BK burner breweryCommand.HoldTemp(Vessels.BK, 0); // Switch to Chill State breweryState = BreweryState.Chill; RaisePropertyChanged(BreweryStateDisplayPropertyName); userAlarm = new UserAlarm(); } break; } case BreweryState.Chill: { // Send chill temperature info if (!userAlarm.MessageSent) { PlayAlarm("Chill", true, true, false); breweryState = BreweryState.Fermenter_Transfer; userAlarm = new UserAlarm(); } break; } case BreweryState.Fermenter_Transfer: { // Monitor BK Level if(brewery.BK.Volume.Value == 0) { PlayAlarm("Ferment", false, false, false); UpdateTempSensorTimer.Stop(); UpdateVolSensorTimer.Stop(); breweryCommand.Disconnect(); } break; } } }
// MainViewModel Class Constructor public MainViewModel() { // Creating new instance of model breweryCommand = new BreweryCommands(); hardwareSettings = new HardwareSettings(); brewery = new Brewery(); process = new Process(); probes = new Probes(); userAlarm = new UserAlarm(); // Initializing RelayCommand Instances ConnectionSetupClickCommand = new RelayCommand(connectionSetupClickCommand); HardwareSetupClickCommand = new RelayCommand(hardwareSetupClickCommand); StartBrewSessionClickCommand = new RelayCommand(startBrewSessionClickCommand); MainClosingCommand = new RelayCommand(mainClosing); LoadRecipeClickCommand = new RelayCommand(loadRecipeClickCommand); DebugDesignSessionClickCommand = new RelayCommand(debugDesignClickCommand); // Initializing Timers UpdateTempSensorTimer = new DispatcherTimer(); UpdateVolSensorTimer = new DispatcherTimer(); AlarmTimer = new DispatcherTimer(); PrimingTimer = new DispatcherTimer(); MashStepTimer = new DispatcherTimer(); BoilTimer = new DispatcherTimer(); // Initializing Sound Player Player = new MediaPlayer(); // Initializing Machine State Variables MashStepComplete = false; FirstMashStep = true; FirstSparge = true; SpargeModeOn = false; BoilOverSent = false; BoilComplete = false; StepStartTime = new TimeSpan(); RemainingTime = new TimeSpan(); StepEndTime = new TimeSpan(); // Initializing the brewery State breweryState = BreweryState.StandBy; RaisePropertyChanged(BreweryStateDisplayPropertyName); // Initializing Messenger Registers Messenger.Default.Register<NotificationMessage>(this, "BreweryCommand", BreweryCommand_MessageReceived); Messenger.Default.Register<Brewery>(this, "ConnectionUpdate" , ConnectionUpdate_MessageReceived); Messenger.Default.Register<HardwareSettings>(this, "HardwareSettingsUpdate", HardwareSettings_MessageReceived); Messenger.Default.Register<Brewery>(this, "TemperatureUpdate", TemperatureUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "VolumeUpdate", VolumeUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "HLTBurnerUpdate", HLTBurnerUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "MLTBurnerUpdate", MLTBurnerUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "BKBurnerUpdate", BKBurnerUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "Pump1Update", Pump1Update_MessageReceived); Messenger.Default.Register<Brewery>(this, "Pump2Update", Pump2Update_MessageReceived); Messenger.Default.Register<string>(this, "SelectedcomPort", SelectedcomPort_MessageReceived); Messenger.Default.Register<Process>(this, Process_MessageReceived); Messenger.Default.Register<Probes>(this, "GetConnectedProbes", GetConnectedProbes_MessageReceived); Messenger.Default.Register<UserAlarm>(this, "UserAlarmReturn", UserAlarmReturn_MessageReceived); Messenger.Default.Register<Brewery>(this, "HLTTempSetPointUpdate", HLTTempSetPointUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "MLTTempSetPointUpdate", MLTTempSetPointUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "BKTempSetPointUpdate", BKTempSetPointUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "HLTTempSetPointReachedUpdate", HLTTempSetPointReachedUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "MLTTempSetPointReachedUpdate", MLTTempSetPointReachedUpdate_MessageReceived); Messenger.Default.Register<Brewery>(this, "BKTempSetPointReachedUpdate", BKTempSetPointReachedUpdate_MessageReceived); }