Esempio n. 1
0
class MashStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperature",
                           configurable=True,
                           description="Target Temperature of Mash Step")
    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the mashing takes place")
    timer = Property.Number(
        "Timer in Minutes",
        configurable=True,
        description="Timer is started when the target temperature is reached")

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.set_target_temp(self.temp, self.kettle)

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= float(self.temp):
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)

        # Check if timer finished and go to next step
        if self.is_timer_finished() == True:
            self.notify("Mash Step Completed!",
                        "Starting the next step",
                        timeout=None)
            # if you dont want a beep sound comment out like :  # cbpi.MashStepEndBeep()
            cbpi.MashStepEndBeep()
            self.next()
Esempio n. 2
0
class Chill_CG(StepBase):

    kettle = StepProperty.Kettle("Kettle", description="Kettle in which the chilling takes place")
    chiller = StepProperty.Actor("Chiller", description="Actor that controls the Chiller")
    chillerPump = StepProperty.Actor("chillerPump", description="Actor that controls the chillerPump")
    chillerTemp = StepProperty.Sensor("Chiller Temp", description="Sensor that shows the chiller temperature")
    cutoutvariance = Property.Number("Variance between kettle and chiller for end", configurable=True, default_value=0.3, description="The step will end when the kettle temp falls to within this much of the chiller temp.")
    
    def init(self):
        self.actor_on(int(self.chillerPump))
        self.actor_on(int(self.chiller))
        self.set_target_temp(0, self.kettle)
    
    def start(self):
        pass

    def reset(self):
        pass

    def finish(self):
        self.actor_off(int(self.chillerPump))
        self.actor_off(int(self.chiller))
    
    def execute(self):
        if self.get_kettle_temp(self.kettle) <= (self.get_sensor_value(self.chillerTemp)+float(self.cutoutvariance)):
            self.notify("Chill Stage Complete", "Kettle reached: " + str(self.get_kettle_temp(self.kettle)), type="success", timeout=None)
            self.actor_off(int(self.chiller))
            self.actor_off(int(self.chillerPump))
            self.next()
Esempio n. 3
0
class MashInStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperature", configurable=True)
    kettle = StepProperty.Kettle("Kettle")
    s = False

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return: 
        '''
        # set target tep
        self.s = False
        self.set_target_temp(self.temp, self.kettle)

    def execute(self):
        '''
        This method is execute in an interval
        :return: 
        '''

        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= int(
                self.temp) and self.s is False:
            self.s = True
            self.notify("Step Temp Reached!",
                        "Please press the next button to continue",
                        timeout=None)
Esempio n. 4
0
class AutoSwitch(StepBase):

    # Properties
    a_id = StepProperty.Kettle("Kettle")
    b_auto = Property.Select("Auto Setting", options=["On", "Off"])

    def init(self):
        if isinstance(self.a_id, unicode) and self.a_id:
            self.id = (int(self.a_id))
        self.auto_type = self.b_auto
        try:
            kettle = cbpi.cache.get("kettle").get(self.id)
            if (kettle.state is False) and (self.auto_type = "On"):
                # Start controller
                if kettle.logic is not None:
                    cfg = kettle.config.copy()
                    cfg.update(dict(api=cbpi, kettle_id=kettle.id, heater=kettle.heater, sensor=kettle.sensor))
                    instance = cbpi.get_controller(kettle.logic).get("class")(**cfg)
                    instance.init()
                    kettle.instance = instance
                    def run(instance):
                        instance.run()
                    t = self.api.socketio.start_background_task(target=run, instance=instance)
                kettle.state = True
                cbpi.emit("UPDATE_KETTLE", kettle)
            else (kettle.state is True) and (self.auto_type = "Off"):
                # Stop controller
                kettle.instance.stop()
                kettle.state = False
                cbpi.emit("UPDATE_KETTLE", kettle)
Esempio n. 5
0
class MashInStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperature", configurable=True,  description="Target Temperature of Mash Step")
    kettle = StepProperty.Kettle("Kettle", description="Kettle in which the mashing takes place")
    s = False

    @cbpi.action("Change Power")
    def change_power(self):
        self.actor_power(1, 50)

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target step
        self.s = False
        self.set_target_temp(self.temp, self.kettle)



    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= float(self.temp) and self.s is False:
            self.s = True
            #DBK_added self.actor_off(1)
            self.notify("Step Temp Reached!", "Please press the next button to continue", timeout=None)
Esempio n. 6
0
class Cooling(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperature",
                           configurable=True,
                           description="Target Temperature")
    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the Chilling takes place")
    timer = Property.Number(
        "Timer in Seconds",
        configurable=True,
        description="Timer is started when the target temperature is reached")

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.set_target_temp(self.temp, self.kettle)

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer))

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) <= float(self.temp):
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer))

        # Check if timer finished and go to next step
        if self.is_timer_finished() == True:
            self.notify(
                "Cooling Step Completed! Target temp is: %s C" % (self.temp),
                "Current temp is: %s C" % (self.get_kettle_temp(self.kettle)),
                timeout=10000)
            self.next()
Esempio n. 7
0
class SimpleTargetStep(StepBase):
    # Properties
    auto_mode = Property.Select(
        "Auto Mode", options=["Set to ON", "Set to OFF", "No Change"])
    kettle = StepProperty.Kettle("Kettle")
    target = Property.Number("Target Temp", configurable=True)

    #-------------------------------------------------------------------------------
    def init(self):
        self.set_target_temp(float(self.target), int(self.kettle))
        if self.auto_mode == "Set to ON":
            self.setAutoMode(True)
        elif self.auto_mode == "Set to OFF":
            self.setAutoMode(False)
        next(self)

    #-------------------------------------------------------------------------------
    def setAutoMode(self, auto_state):
        try:
            kettle = cbpi.cache.get("kettle")[int(self.kettle)]
            if (kettle.state is False) and (auto_state is True):
                # turn on
                if kettle.logic is not None:
                    cfg = kettle.config.copy()
                    cfg.update(
                        dict(api=cbpi,
                             kettle_id=kettle.id,
                             heater=kettle.heater,
                             sensor=kettle.sensor))
                    instance = cbpi.get_controller(
                        kettle.logic).get("class")(**cfg)
                    instance.init()
                    kettle.instance = instance

                    def run(instance):
                        instance.run()

                    t = cbpi.socketio.start_background_task(target=run,
                                                            instance=instance)
                kettle.state = not kettle.state
                cbpi.emit("UPDATE_KETTLE",
                          cbpi.cache.get("kettle")[int(self.kettle)])
            elif (kettle.state is True) and (auto_state is False):
                # turn off
                kettle.instance.stop()
                kettle.state = not kettle.state
                cbpi.emit("UPDATE_KETTLE",
                          cbpi.cache.get("kettle")[int(self.kettle)])
        except Exception as e:
            cbpi.notify("Error",
                        "Failed to set Auto mode {}".format(["OFF", "ON"
                                                             ][auto_state]),
                        type="danger",
                        timeout=None)
            cbpi.app.logger.error(e)
Esempio n. 8
0
class Rast(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperatur",
                           configurable=True,
                           description="Zieltemperatur des Schritts")
    kettle = StepProperty.Kettle("Kessel",
                                 description="Auswahl des Braukessels")
    timer = Property.Number(
        "Timer in Minuten",
        configurable=True,
        description="Timer startet, wenn die Zieltemperatur erreicht wurde")

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.set_target_temp(self.temp, self.kettle)


#    @cbpi.action("Timer manuell starten")
#    def start(self):
#        if self.is_timer_finished() is None:
#            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        pass

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= float(self.temp):
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)

        # Check if timer finished and go to next step
        if self.is_timer_finished() == True:
            self.notify("Rast beendet!",
                        "Beginne nächsten Schritt",
                        timeout=None)
            self.next()
Esempio n. 9
0
class ChangeKettleTargetTemp(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperature",
                           configurable=True,
                           description="Target Temperature")
    kettle = StepProperty.Kettle(
        "Kettle",
        description="Kettle in which the target temperature will change")

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target temp
        self.set_target_temp(self.temp, self.kettle)

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''

        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer))

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(self.temp, self.kettle)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        kettles = cbpi.cache["kettle"]
        kettle_name = kettles[int(self.kettle)].name

        self.notify("Changed target temp for %s " % (kettle_name),
                    "New target temp is: %s C" % (self.temp),
                    timeout=10000)
        self.next()
Esempio n. 10
0
class BoilStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    power = Property.Number("Power", configurable=True)
    kettle = StepProperty.Kettle("Kettle")
    timer = Property.Number("Timer in Minutes", configurable=True)

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        print(("class BoilStep(StepBase): power = {}".format(self.kettle)))
        self.actor_power(1, self.power)
        #self.set_target_temp(self.power, self.kettle)

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.actor_power(0, self.power)
        #self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.actor_power(0, 0)
        self.set_target_temp(0, self.kettle)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Timer is Running
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

        # Check if timer finished and go to next step
        if self.is_timer_finished() == True:
            next(self)
Esempio n. 11
0
class TwoKettleLogic(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method. The class name must be unique in the system
    '''
    # Properties
    kettle1 = StepProperty.Kettle("Kettle 1")
    temp1 = Property.Number("Temperature 1", configurable=True)
    kettle2 = StepProperty.Kettle("Kettle 2")
    temp2 = Property.Number("Temperature 2", configurable=True)

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return: 
        '''
        # set target tep
        self.set_target_temp(self.temp1, self.kettle1)
        self.set_target_temp(self.temp2, self.kettle2)

    def finish(self):
        pass

    def execute(self):
        '''
        This method is execute in an interval
        :return: 
        '''

        # Check if Target Temp is reached for both kettles
        if self.get_kettle_temp(self.kettle1) >= int(
                self.temp1) and self.get_kettle_temp(self.kettle2) >= int(
                    self.temp2):
            self.notify("Kettle Temps Reached!",
                        "Starting the next step.",
                        timeout=None)
            self.next()
Esempio n. 12
0
class KettleVolumeStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method. The class name must be unique in the system
    '''
    # Properties
    temp = Property.Number("Temperature", configurable=True)
    kettle = StepProperty.Kettle("Kettle")
    timer = Property.Number("Timer in Minutes", configurable=True)
    sensor = StepProperty.Sensor("Sensor")
    volume = Property.Number("Volume", configurable=True)

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return: 
        '''
        # set target tep
        #self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)

    def execute(self):
        '''
        This method is execute in an interval
        :return: 
        '''
        for key, value in cbpi.cache.get("sensors").iteritems():
            if key == int(self.sensor):
                sensorValue = value.instance.last_value

        # Check if timer finished and go to next step
        if float(sensorValue) <= float(self.volume):
            self.set_target_temp(self.temp, self.kettle)
            kettle_state = cbpi.cache.get("kettle")[int(self.kettle)].state
            if kettle_state is True:
                Kettle2View().toggle(int(self.kettle))
                self.notify("Kettle Update",
                            "Auto is off. Timer started.",
                            timeout=None)
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)

        if self.is_timer_finished() == True:
            self.notify("Mash-in Complete!",
                        "Starting the next step.",
                        timeout=None)
            self.next()
Esempio n. 13
0
class SimpleMashInStep(StepBase):
    # Properties
    a_kettle_prop = StepProperty.Kettle(
        "Kettle", description="Kettle in which the mashing takes place")
    b_target_prop = Property.Number(
        "Temperature",
        configurable=True,
        description="Target Temperature of Mash Step")
    c_agitator_prop = Property.Select("Run agitator while heating?",
                                      options=["Yes", "No"])
    d_kill_heat_prop = Property.Select("Turn off heater when target reached?",
                                       options=["Yes", "No"])

    #-------------------------------------------------------------------------------
    def init(self):
        self.kettle = int(self.a_kettle_prop)
        self.target = float(self.b_target_prop)
        self.agitator_run = self.c_agitator_prop == "Yes"
        self.kill_heat = self.d_kill_heat_prop == "Yes"
        self.done = False

        self.agitator = getAgitator(
            cbpi.cache.get("kettle")[self.kettle].agitator)

        # set target temp
        self.set_target_temp(self.target, self.kettle)
        if self.agitator and self.agitator_run:
            self.actor_on(self.agitator)

    #-------------------------------------------------------------------------------
    def finish(self):
        self.set_target_temp(0, self.kettle)

    #-------------------------------------------------------------------------------
    def execute(self):
        # Check if Target Temp is reached
        if (self.get_kettle_temp(self.kettle) >= self.target) and (self.done is
                                                                   False):
            self.done = True
            if self.kill_heat:
                self.set_target_temp(0, self.kettle)
            if self.agitator:
                self.actor_off(self.agitator)
            self.notify("{} complete".format(self.name),
                        "Press next button to continue",
                        type='warning',
                        timeout=None)
Esempio n. 14
0
class ToggleAuto(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperature",
                           configurable=True,
                           description="Target Temperature of HLT")
    kettle = StepProperty.Kettle("Kettle", description="Set this to your HLT")
    toggle_type = Property.Select("Toggle Type", options=["On", "Off"])

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        #self.notify("props", cbpi.cache.get("kettle")[int(self.kettle)].state, timeout=None)
        self.set_target_temp(self.temp, self.kettle)
        kettle_state = kettle = cbpi.cache.get("kettle")[int(
            self.kettle)].state
        if kettle_state is False and self.toggle_type == "On":
            Kettle2View().toggle(int(self.kettle))
            self.notify("Kettle Update",
                        "Auto is on. Starting the next step.",
                        timeout=None)
            self.next()
        else:
            if kettle_state is False and self.toggle_type == "Off":
                self.notify(
                    "Kettle Error",
                    "Auto is already off, please adjust your brew step!",
                    type="danger",
                    timeout=None)
            else:
                if kettle_state is True:
                    if self.toggle_type == "On":
                        self.notify(
                            "Kettle Error",
                            "Auto is already on, please adjust your brew step!",
                            type="danger",
                            timeout=None)
                    else:
                        Kettle2View().toggle(int(self.kettle))
                        self.notify("Kettle Update",
                                    "Auto is Off. Starting the next step.",
                                    timeout=None)
                        self.next()
Esempio n. 15
0
class Maischen(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number(
        "Temperatur",
        configurable=True,
        description="Benachrichtigung bei Erreichen der Ein/Abmaischtemperatur."
    )
    kettle = StepProperty.Kettle("Kessel",
                                 description="Auswahl des Braukessels")
    s = False

    @cbpi.action("Weiter")
    def next_step(self):
        self.set_target_temp(0, self.kettle)
        self.next()

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.s = False
        self.set_target_temp(self.temp, self.kettle)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= float(
                self.temp) and self.s is False:
            self.s = True
            self.notify(
                "Maischtemperatur erreicht!",
                "Bitte maischen und anschließend bestätigen, um fortzufahren.",
                timeout=None)
Esempio n. 16
0
class SimpleCoolToTemp(StepBase):

    kettle = StepProperty.Kettle("Kettle", description="Kettle")
    c_target = Property.Number("Target", configurable=True)
    c_offset = Property.Number("Offset", configurable=True)

    def init(self):
        self.target = float(self.c_target)
        self.offset = float(self.c_offset)
        self.set_target_temp(self.target, self.kettle)

    def reset(self):
        self.set_target_temp(self.target, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)

    def execute(self):
        if abs(self.get_kettle_temp(self.kettle) - self.target) <= self.offset:
            next(self)
Esempio n. 17
0
class ToBoilStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Power", configurable=True)
    kettle = StepProperty.Kettle("Kettle")
    s = False

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.s = False
        print(("ToBoilStep init: {}".format(int(self.temp))))
        self.set_target_temp(self.temp, self.kettle)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Target Temp is reached
        #if self.get_kettle_temp(self.kettle) >= int(self.temp) and self.s is False:
        #    self.s = True
        #    self.notify("Step Temp Reached!", "Please press the next button to continue", timeout=None)
        #self.actor_power(self.get_target_temp)
        pass
Esempio n. 18
0
class SimpleBoilStep(StepBase):
    # Properties
    textDesc = "Brief description of the addition"
    timeDesc = "Time in minutes before end of boil"
    add_1_text = Property.Text("Addition 1 Name",
                               configurable=True,
                               description=textDesc)
    add_1_time = Property.Number("Addition 1 Time",
                                 configurable=True,
                                 description=timeDesc)
    add_2_text = Property.Text("Addition 2 Name",
                               configurable=True,
                               description=textDesc)
    add_2_time = Property.Number("Addition 2 Time",
                                 configurable=True,
                                 description=timeDesc)
    add_3_text = Property.Text("Addition 3 Name",
                               configurable=True,
                               description=textDesc)
    add_3_time = Property.Number("Addition 3 Time",
                                 configurable=True,
                                 description=timeDesc)
    add_4_text = Property.Text("Addition 4 Name",
                               configurable=True,
                               description=textDesc)
    add_4_time = Property.Number("Addition 4 Time",
                                 configurable=True,
                                 description=timeDesc)
    add_5_text = Property.Text("Addition 5 Name",
                               configurable=True,
                               description=textDesc)
    add_5_time = Property.Number("Addition 5 Time",
                                 configurable=True,
                                 description=timeDesc)
    add_6_text = Property.Text("Addition 6 Name",
                               configurable=True,
                               description=textDesc)
    add_6_time = Property.Number("Addition 6 Time",
                                 configurable=True,
                                 description=timeDesc)
    add_7_text = Property.Text("Addition 7 Name",
                               configurable=True,
                               description=textDesc)
    add_7_time = Property.Number("Addition 7 Time",
                                 configurable=True,
                                 description=timeDesc)
    add_8_text = Property.Text("Addition 8 Name",
                               configurable=True,
                               description=textDesc)
    add_8_time = Property.Number("Addition 8 Time",
                                 configurable=True,
                                 description=timeDesc)

    kettle_prop = StepProperty.Kettle(
        "Kettle", description="Kettle in which the boiling step takes place")
    target_prop = Property.Number("Temperature",
                                  configurable=True,
                                  description="Target temperature for boiling")
    timer_prop = Property.Number(
        "Timer in Minutes",
        configurable=True,
        default_value=90,
        description="Timer is started when target temperature is reached")

    warning_addition_prop = Property.Number(
        "Addition Warning",
        configurable=True,
        default_value=30,
        description="Time in seconds to warn before each addition")
    warning_boil_prop = Property.Number(
        "Boil Warning",
        configurable=True,
        default_value=1,
        description="Degrees below target to warn of impending boil")

    #-------------------------------------------------------------------------------
    def init(self):

        self.target = float(self.target_prop)
        self.kettle = int(self.kettle_prop)
        self.timer = float(self.timer_prop) * 60.0
        self.warn_add = float(self.warning_addition_prop)
        self.warn_boil = float(self.warning_boil_prop)

        self.done_boil_warn = False
        self.done_boil_alert = False

        # set the additions dictionary
        self.additions = dict()
        for i in range(1, 9):
            additionTime = self.__getattribute__("add_{}_time".format(i))
            additionText = self.__getattribute__("add_{}_text".format(i))
            try:
                if additionText is None:
                    additionText = "Addition {}".format(i)
                self.additions[i] = {
                    'text': additionText,
                    'time': float(additionTime) * 60.0,
                    'mins': int(additionTime),
                    'done': False,
                    'warn': False,
                }
            except:
                # empty or invalid addition
                pass
        # set target temp
        self.set_target_temp(self.target, self.kettle)

    #-------------------------------------------------------------------------------
    @cbpi.action("Start Timer Now")
    def start(self):
        if self.is_timer_finished() is None:
            self.start_timer(self.timer)

    #-------------------------------------------------------------------------------
    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.target, self.kettle)

    #-------------------------------------------------------------------------------
    def finish(self):
        self.set_target_temp(0, self.kettle)

    #-------------------------------------------------------------------------------
    def execute(self):
        # Check if Target Temp is reached
        if self.is_timer_finished() is None:
            self.check_boil_warnings()
            if self.get_kettle_temp(self.kettle) >= self.target:
                self.start_timer(self.timer)
        elif self.is_timer_finished() is True:
            self.notify("{} complete".format(self.name),
                        "Starting the next step",
                        type='success',
                        timeout=None)
            next(self)
        else:
            self.check_addition_timers()

    #-------------------------------------------------------------------------------
    def check_addition_timers(self):
        for i in self.additions:
            addition_time = self.timer_end - self.additions[i]['time']
            warning_time = addition_time - self.warn_add
            now = time.time()
            if not self.additions[i]['warn'] and now > warning_time:
                self.additions[i]['warn'] = True
                self.notify("Warning: {} min Additions".format(
                    self.additions[i]['mins']),
                            "Add {} in {} seconds".format(
                                self.additions[i]['text'], self.warn_add),
                            type='info',
                            timeout=(self.warn_add - 1) * 1000)
            if not self.additions[i]['done'] and now > addition_time:
                self.additions[i]['done'] = True
                self.notify("Alert: {} min Additions".format(
                    self.additions[i]['mins']),
                            "Add {} now".format(self.additions[i]['text']),
                            type='warning',
                            timeout=None)

    #-------------------------------------------------------------------------------
    def check_boil_warnings(self):
        if (not self.done_boil_warn) and (self.get_kettle_temp(self.kettle) >=
                                          self.target - self.warn_boil):
            self.notify("Warning: Boil Approaching",
                        "Current Temp {:.1f}".format(
                            self.get_kettle_temp(self.kettle)),
                        type="info",
                        timeout=self.warn_add * 1000)
            self.done_boil_warn = True
        if (not self.done_boil_alert) and (self.get_kettle_temp(self.kettle) >=
                                           self.target):
            self.notify("Alert: Boil Imminent",
                        "Current Temp {:.1f}".format(
                            self.get_kettle_temp(self.kettle)),
                        type="warning",
                        timeout=None)
            self.done_boil_alert = True
Esempio n. 19
0
class SimpleMashStep(StepBase):
    # Properties
    a_kettle_prop = StepProperty.Kettle(
        "Kettle", description="Kettle in which the mashing takes place")
    b_target_prop = Property.Number(
        "Temperature",
        configurable=True,
        description="Target Temperature of Mash Step")
    c_timer_prop = Property.Number(
        "Timer in minutes",
        configurable=True,
        description="Amount of time to maintain taget temperature in this step"
    )
    d_offset_prop = Property.Number(
        "Target timer offset",
        configurable=True,
        default_value=0,
        description=
        "Start timer when temperature is this close to target. Useful for PID heaters that approach target slowly."
    )
    e_agitator_start_prop = Property.Select("Turn agitator on at start?",
                                            options=["Yes", "No"])
    f_agitator_stop_prop = Property.Select("Turn agitator off at end?",
                                           options=["Yes", "No"])

    #-------------------------------------------------------------------------------
    def init(self):
        self.kettle = int(self.a_kettle_prop)
        self.target = float(self.b_target_prop)
        self.timer = float(self.c_timer_prop)
        self.offset = float(self.d_offset_prop)
        self.agitator_start = self.e_agitator_start_prop == "Yes"
        self.agitator_stop = self.f_agitator_stop_prop == "Yes"

        self.agitator = getAgitator(
            cbpi.cache.get("kettle")[self.kettle].agitator)

        # set target temp
        self.set_target_temp(self.target, self.kettle)
        if self.agitator and self.agitator_start:
            self.actor_on(self.agitator)

    #-------------------------------------------------------------------------------
    @cbpi.action("Start Timer Now")
    def start(self):
        if self.is_timer_finished() is None:
            self.start_timer(self.timer * 60)

    #-------------------------------------------------------------------------------
    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.target, self.kettle)

    #-------------------------------------------------------------------------------
    def finish(self):
        self.set_target_temp(0, self.kettle)
        if self.agitator and self.agitator_stop:
            self.actor_off(self.agitator)

    #-------------------------------------------------------------------------------
    def execute(self):
        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= self.target - self.offset:
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(self.timer * 60)

        # Check if timer finished and go to next step
        if self.is_timer_finished() is True:
            self.notify("{} complete".format(self.name),
                        "Starting the next step",
                        type='success',
                        timeout=None)
            next(self)
Esempio n. 20
0
class BoilStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperature", configurable=True, default_value=100, description="Target temperature for boiling")
    kettle = StepProperty.Kettle("Kettle", description="Kettle in which the boiling step takes place")
    timer = Property.Number("Timer in Minutes", configurable=True, default_value=90, description="Timer is started when target temperature is reached")
    hop_1 = Property.Number("Hop 1 Addition", configurable=True, description="First Hop alert (minutes before finish)")
    hop_1_added = Property.Number("",default_value=None)
    hop_2 = Property.Number("Hop 2 Addition", configurable=True, description="Second Hop alert (minutes before finish)")
    hop_2_added = Property.Number("", default_value=None)
    hop_3 = Property.Number("Hop 3 Addition", configurable=True, description="Third Hop alert (minutes before finish)")
    hop_3_added = Property.Number("", default_value=None)
    hop_4 = Property.Number("Hop 4 Addition", configurable=True, description="Fourth Hop alert (minutes before finish)")
    hop_4_added = Property.Number("", default_value=None)
    hop_5 = Property.Number("Hop 5 Addition", configurable=True, description="Fifth Hop alert (minutes before finish)")
    hop_5_added = Property.Number("", default_value=None)

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.set_target_temp(self.temp, self.kettle)




    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)


    def check_hop_timer(self, number, value):
        if (value != ""
            and self.__getattribute__("hop_%s_added" % number) is not True 
            and (time.time() > (self.timer_end - int(value)*60))):
            self.__setattr__("hop_%s_added" % number, True)
            self.notify("Hop Alert", "Please add Hop %s" % number, timeout=None)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''
        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= float(self.temp):
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)
        
        # Check if hop time reached
        if self.is_timer_finished() == False:
            self.check_hop_timer(1, self.hop_1)
            self.check_hop_timer(2, self.hop_2)
            self.check_hop_timer(3, self.hop_3)
            self.check_hop_timer(4, self.hop_4)
            self.check_hop_timer(5, self.hop_5)
                
        # Check if timer finished and go to next step
        if self.is_timer_finished() == True:
            self.notify("Boil Step Completed!", "Starting the next step", timeout=None)
            self.next()
Esempio n. 21
0
class ChillerToTemp(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method. The class name must be unique in the system
    '''
    # Properties
    temp = Property.Number("Desired Temperature", configurable=True)
    kettle = StepProperty.Kettle("Kettle")
    prime_pump = StepProperty.Actor("Chiller Primary Pump")
    sec_pump = StepProperty.Actor("Secondary Pump")
    timer = Property.Number(
        "Upper Bound in Minutes",
        description="The time after which this step will conclude,"
        " regardless of the current temp",
        configurable=True)
    # num of times to check target temp has been reached (in order to rule out bad readings)
    Samples = Property.Number(
        "Number of Temp Readings before ShutDown",
        default_value=DEF_SAMPLES,
        description="A safety against false positive detection",
        configurable=True)
    sample_streak = 0

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.set_target_temp(self.temp, self.kettle)
        self.start_timer(int(self.timer) * 60)
        # turns pump on
        if self.sec_pump is not None:
            self.actor_on(int(self.sec_pump))
        self.actor_on(int(self.prime_pump))

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)
        self.start_timer(int(self.timer) * 60)

    def finish(self):
        self.set_target_temp(0, self.kettle)
        # turns pump off at finish
        self.actor_off(int(self.prime_pump))
        if self.sec_pump is not None:
            self.actor_off(int(self.sec_pump))

    def execute(self):
        '''
        This method is executed in intervals
        :return:
        '''

        # Check if Target Temp has been reached
        if self.get_kettle_temp(self.kettle) <= float(self.temp):
            self.sample_streak += 1
            # Checks if Target Amount of Samples is reached
            if self.sample_streak == self.Samples:
                self.notify("Yeast Pitch Temp Reached!",
                            "Move to fermentation tank",
                            timeout=None)
                # turns pump off at finish
                self.actor_off(int(self.prime_pump))
                if self.sec_pump is not None:
                    self.actor_off(int(self.sec_pump))
                self.next()
        else:
            # Nullifies The samples streak
            self.sample_streak = 0
        # Check if timer finished and go to next step
        if self.is_timer_finished():
            self.notify("Step Temp Wasn't Reached!",
                        "Good luck:(",
                        timeout=None)
            # turns pump off at finish
            self.actor_off(int(self.prime_pump))
            if self.sec_pump is not None:
                self.actor_off(int(self.sec_pump))
            self.next()
class BoilStepWithCountdownReminders(StepBase):
    '''
    BoilStep with reminders that are set relative to end of boil
    '''
    REMINDER_NAMES = [
        "Hop 1 Addition", "Hop 2 Addition", "Hop 3 Addition", "Hop 4 Addition",
        "Hop 5 Addition", "Prepare yeast", "Prepare finings",
        "Prepare cooling system", "Dose finings",
        "Start hot-side cooling loop", "Prepare fermenter"
    ]
    # Properties
    temp = Property.Number("Temperature",
                           configurable=True,
                           default_value=100,
                           description="Target temperature for boiling")
    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the boiling step takes place")
    timer = Property.Number(
        "Timer in Minutes",
        configurable=True,
        default_value=90,
        description="Timer is started when target temperature is reached")

    reminder_00 = Property.Number(REMINDER_NAMES[0], configurable=True)
    reminder_00_displayed = Property.Number(
        "", default_value=None, description="Reminder displayed status")
    reminder_01 = Property.Number(REMINDER_NAMES[1], configurable=True)
    reminder_01_displayed = Property.Number("", default_value=None)
    reminder_02 = Property.Number(REMINDER_NAMES[2], configurable=True)
    reminder_02_displayed = Property.Number("", default_value=None)
    reminder_03 = Property.Number(REMINDER_NAMES[3], configurable=True)
    reminder_03_displayed = Property.Number("", default_value=None)
    reminder_04 = Property.Number(REMINDER_NAMES[4], configurable=True)
    reminder_04_displayed = Property.Number("", default_value=None)
    reminder_05 = Property.Number(REMINDER_NAMES[5], configurable=True)
    reminder_05_displayed = Property.Number("", default_value=None)
    reminder_06 = Property.Number(REMINDER_NAMES[6], configurable=True)
    reminder_06_displayed = Property.Number(
        "", default_value=None, description="Reminder displayed status")
    reminder_07 = Property.Number(REMINDER_NAMES[7], configurable=True)
    reminder_07_displayed = Property.Number(
        "", default_value=None, description="Reminder displayed status")
    reminder_08 = Property.Number(REMINDER_NAMES[8], configurable=True)
    reminder_08_displayed = Property.Number(
        "", default_value=None, description="Reminder displayed status")
    reminder_09 = Property.Number(REMINDER_NAMES[9], configurable=True)
    reminder_09_displayed = Property.Number(
        "", default_value=None, description="Reminder displayed status")
    reminder_10 = Property.Number(REMINDER_NAMES[10], configurable=True)
    reminder_10_displayed = Property.Number(
        "", default_value=None, description="Reminder displayed status")

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        self.set_target_temp(self.temp, self.kettle)
        self._logger = logging.getLogger(type(self).__name__)

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)

    def check_reminder(self, number):
        raw_value = self.__getattribute__("reminder_%02d" % number)

        if isinstance(raw_value,
                      unicode) and raw_value != '' and self.__getattribute__(
                          "reminder_%02d_displayed" % number) is not True:
            value = int(raw_value)
            if self.countdown_time_has_expired(value):
                self.__setattr__("reminder_%02d_displayed" % number, True)
                reminder = self.REMINDER_NAMES[number]
                self.notify("Countdown Reminder", reminder, timeout=None)

    def countdown_time_has_expired(self, value):
        return time.time() > (self.timer_end - (value * 60))

    def execute(self):
        '''
        This method is executed in an interval
        :return:
        '''
        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= float(self.temp):
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)
            else:
                for i in range(11):
                    self.check_reminder(i)

        if self.is_timer_finished() == True:
            self.notify("Boil Step Completed!",
                        "Starting the next step",
                        timeout=None)
            self.next()
Esempio n. 23
0
class KRimsMashStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Kettle Temperature",
                           configurable=True,
                           description="Target Temperature of the Kettle")
    mash_temp = Property.Number(
        "Mash Temperature",
        configurable=True,
        description="Target Temperature of the Mash Step")
    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the mashing takes place")
    timer = Property.Number(
        "Timer in Minutes",
        configurable=True,
        description="Timer is started when the target temperature is reached")
    sensor = StepProperty.Sensor("Sensor",
                                 description="Selectable secondary sensor")
    pump = StepProperty.Actor("Pump, etc.")
    mode = Property.Select("Mode", ["Timer", "User input"],
                           "Selects how the step operates")

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.set_target_temp(self.temp, self.kettle)
        self.actor_on(int(self.pump))

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)
        self.actor_off(int(self.pump))

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Target Temp is reached
        if self.mode == "Timer":
            if cbpi.get_sensor_value(int(self.sensor)) >= float(
                    self.mash_temp):
                if self.is_timer_finished() is None:
                    self.start_timer(int(self.timer) * 60)

            # Check if timer finished and go to next step
            if self.is_timer_finished() == True:
                self.notify("Mash Step Completed!",
                            "Starting the next step",
                            timeout=None)
                self.next()

        if self.mode == "User input":
            if cbpi.get_sensor_value(int(self.sensor)) >= float(
                    self.mash_temp):
                self.notify("Mash Temp reached!",
                            "User input needed to proceed to next step",
                            timeout=None)
                self.mode = "All done. Wait for user"
class SimpleChillToTemp(StepBase):
    # Properties
    actor1 = StepProperty.Actor(
        "Actor 1", description="Actor to turn on until target temp is reached")
    actor2 = StepProperty.Actor(
        "Actor 2", description="Actor to turn on until target temp is reached")
    kettle_prop = StepProperty.Kettle(
        "Kettle", description="Kettle in which the chilling takes place")
    target_prop = Property.Number(
        "Temperature",
        configurable=True,
        description="Target temperature of chill step")

    #-------------------------------------------------------------------------------
    def init(self):
        self.actors = [self.actor1, self.actor2]
        self.target = float(self.target_prop)
        self.kettle = int(self.kettle_prop)

        # set target temp
        if self.kettle:
            self.set_target_temp(self.target, self.kettle)
            self.start_time = time.time()
            self.actors_on()
        else:
            cbpi.notify("No kettle defined",
                        "Starting the next step",
                        type="danger",
                        timeout=None)
            next(self)

    #-------------------------------------------------------------------------------
    def reset(self):
        self.set_target_temp(self.target, self.kettle)

    #-------------------------------------------------------------------------------
    def finish(self):
        self.actors_off()

    #-------------------------------------------------------------------------------
    def execute(self):
        # Check if Target Temp is reached
        if float(self.get_kettle_temp(self.kettle)) <= self.target:
            elapsed_time = int(time.time() - self.start_time)
            hours, remainder = divmod(elapsed_time, 3600)
            minutes, seconds = divmod(remainder, 60)
            if hours:
                elapsed_text = '{}:{:0>2d}:{:0>2d}'.format(
                    hours, minutes, seconds)
            else:
                elapsed_text = '{}:{:0>2d}'.format(minutes, seconds)

            self.notify("{} complete".format(self.name),
                        "Chill temp reached in {}".format(elapsed_text),
                        timeout=None)
            next(self)

    #-------------------------------------------------------------------------------
    def actors_on(self):
        for actor in self.actors:
            try:
                self.actor_on(int(actor))
            except:
                pass

    def actors_off(self):
        for actor in self.actors:
            try:
                self.actor_off(int(actor))
            except:
                pass
Esempio n. 25
0
class PumpMash(StepBase):
    '''
    A step replacing the default mash step. Adds the functionality of temp overshoot and pump activation.
    '''
    # Properties
    temp = Property.Number("Temperature",
                           configurable=True,
                           description="Target Temperature of Mash Step")
    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the mashing takes place")
    pump = StepProperty.Actor("Pump", description="Please select the agitator")
    timer = Property.Number(
        "Timer in Minutes",
        configurable=True,
        description="Timer is started when the target temperature is reached")
    # the diff in celsius degrees from mash temp to desired strike temp
    overshoot = Property.Number(
        "Overshoot Temperature Difference",
        configurable=True,
        default_value=1,
        description=
        "The difference between the initial heating temp and the mash temp."
        "Reset doesn't use overshoot")
    pump_work_time = Property.Number(
        "Mash pump work time",
        True,
        600,
        description="Rest the pump after this many seconds during the mash.")
    pump_rest_time = Property.Number(
        "Mash pump rest time",
        True,
        60,
        description="Rest the pump for this many seconds every rest interval.")
    # the temp above which the pump starts its working cycles
    pump_min_temp = Property.Number(
        "The Min Temperature",
        True,
        40,
        description="The temperature in which the pump starts working.")
    pump_on = False  # current state of the pump
    last_toggle_time = None
    pump_cycle = None

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        self.pump_cycle = {
            True: float(self.pump_work_time),
            False: float(self.pump_rest_time)
        }
        self.actor_off(int(self.pump))
        self.last_toggle_time = time.time()

        # set target temp
        self.set_target_temp(
            float(self.temp) + float(self.overshoot), self.kettle)

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)
        self.actor_off(int(self.pump))  # turns pump off

    def toggle_pump(self):
        '''
        Toggles between pump states (on/off)
        '''
        if self.pump_on:
            self.pump_on = False
            self.actor_off(int(self.pump))
        else:
            self.pump_on = True
            self.actor_on(int(self.pump))
        self.last_toggle_time = time.time()

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''
        # Pump action
        if self.get_kettle_temp(self.kettle) >= float(self.pump_min_temp) and time.time() >= self.last_toggle_time + \
                self.pump_cycle[self.pump_on]:
            self.toggle_pump()
        # Check if Target Temp is reached
        if self.get_kettle_temp(
                self.kettle) >= float(self.temp) + float(self.overshoot):
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)
                # sets target temp to mash temp
                self.set_target_temp(self.temp, self.kettle)
                self.notify("Mash Temp Reached!", "Insert Grain", timeout=None)
        # Check if timer finished and go to next step
        if self.is_timer_finished():
            self.actor_off(int(self.pump))  # turns pump off
            self.notify("Mash Step Completed!",
                        "Starting the next step",
                        timeout=None)
            self.next()
Esempio n. 26
0
class PumpBoil(StepBase):
    '''
    A step replacing the default boil step. Adds the functionality of pump activation.
    '''
    # Properties
    temp = Property.Number("Temperature",
                           configurable=True,
                           default_value=100,
                           description="Target temperature for boiling")
    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the boiling step takes place")
    pump = StepProperty.Actor("Pump", description="Please select the agitator")
    timer = Property.Number(
        "Timer in Minutes",
        configurable=True,
        default_value=90,
        description="Timer is started when target temperature is reached")
    hop_1 = Property.Number("Hop 1 Addition",
                            configurable=True,
                            description="Fist Hop alert")
    hop_1_added = Property.Number("", default_value=None)
    hop_2 = Property.Number("Hop 2 Addition",
                            configurable=True,
                            description="Second Hop alert")
    hop_2_added = Property.Number("", default_value=None)
    hop_3 = Property.Number("Hop 3 Addition", configurable=True)
    hop_3_added = Property.Number("",
                                  default_value=None,
                                  description="Third Hop alert")
    hop_4 = Property.Number("Hop 4 Addition", configurable=True)
    hop_4_added = Property.Number("",
                                  default_value=None,
                                  description="Fourth Hop alert")
    hop_5 = Property.Number("Hop 5 Addition", configurable=True)
    hop_5_added = Property.Number("",
                                  default_value=None,
                                  description="Fives Hop alert")

    pump_work_time = Property.Number(
        "Mash pump work time",
        True,
        200,
        description="Rest the pump after this many seconds during the mash.")
    pump_rest_time = Property.Number(
        "Mash pump rest time",
        True,
        100,
        description="Rest the pump for this many seconds every rest interval.")
    # the pump above which the pump stops working
    pump_max_temp = Property.Number(
        "The Max Temperature",
        True,
        100,
        description="The temperature in which the pump stops its cycles.")
    pump_on = False  # the current state of the pump
    pump_time = None
    pump_cycle = None

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.set_target_temp(self.temp, self.kettle)
        self.pump_cycle = {
            True: int(self.pump_work_time),
            False: int(self.pump_rest_time)
        }
        self.pump_time = time.time()
        self.actor_off(int(self.pump))

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)
        self.actor_off(int(self.pump))

    def check_hop_timer(self, number, value):

        if self.__getattribute__(
                "hop_%s_added" % number) is not True and time.time() > (
                    self.timer_end - (int(self.timer) * 60 - int(value) * 60)):
            self.__setattr__("hop_%s_added" % number, True)
            self.notify("Hop Alert",
                        "Please add Hop %s" % number,
                        timeout=None)

    def toggle_pump(self):
        """
        Toggles between pump states (on/off)
        """
        if self.pump_on:
            self.pump_on = False
            self.actor_off(int(self.pump))
        else:
            self.pump_on = True
            self.actor_on(int(self.pump))
        self.pump_time = time.time()

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''
        # Pump action
        if self.get_kettle_temp(self.kettle) > float(self.pump_max_temp):
            self.actor_off(int(self.pump))
        elif time.time() >= self.pump_time + self.pump_cycle[self.pump_on]:
            self.toggle_pump()
        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= float(self.temp):
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)
            else:
                self.check_hop_timer(1, self.hop_1)
                self.check_hop_timer(2, self.hop_2)
                self.check_hop_timer(3, self.hop_3)
                self.check_hop_timer(4, self.hop_4)
                self.check_hop_timer(5, self.hop_5)
        # Check if timer finished and go to next step
        if self.is_timer_finished():
            self.actor_off(int(self.pump))  # turns pump off
            self.notify("Boil Step Completed!",
                        "Starting the next step",
                        timeout=None)
            self.next()
Esempio n. 27
0
class SimpleWhirlpoolStep(StepBase):

    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the chilling takes place")
    chiller = StepProperty.Actor("Chiller",
                                 description="Actor that controls the Chiller")
    chillerPump = StepProperty.Actor(
        "chillerPump", description="Actor that controls the chillerPump")
    temp = Property.Number("Whirlpool Temperature",
                           configurable=True,
                           default_value=80,
                           description="Target Temperature of Whirlpool")
    timer = Property.Number(
        "Total Whirlpool Timer in Minutes (incl. Santise Time)",
        configurable=True,
        default_value=30,
        description="Timer is started immediately")
    sanitiseTimer = Property.Number("Sanitise Timer in Minutes",
                                    configurable=True,
                                    default_value=5,
                                    description="Time at sanitisation temp")
    sanitiseTemp = Property.Number(
        "Sanitise Temperature",
        configurable=True,
        default_value=95,
        description="Target Temperature for sanitisation")
    s_end = 1
    stage = "init"  #This process goes through the following stages: init, waithookup, sanitise, whirlpool
    c_cut = 0

    def init(self):
        self.stage = "init"
        self.actor_off(int(self.chillerPump))
        self.actor_off(int(self.chiller))
        self.set_target_temp(self.sanitiseTemp, self.kettle)
        self.s_end = 1
        self.c_cut = 0

    def start(self):
        pass

    def reset(self):
        self.stop_timer()

    def finish(self):
        self.actor_off(int(self.chillerPump))
        self.actor_off(int(self.chiller))

    @cbpi.action("Chiller Connected")
    def chiller_connected(self):
        if self.stage == "waithookup":
            self.stage = "sanitise"
            self.actor_on(int(self.chillerPump))
            self.s_end = (self.timer_remaining() -
                          (60 * int(self.sanitiseTimer)))
        else:
            self.notify(
                "No Action Taken",
                "Function only works in \"waithookup\" sub-stage. Current stage: "
                + self.stage,
                type="info",
                timeout=5000)

    def execute(self):
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)
        if self.is_timer_finished() == True:
            if self.stage != "whirlpool":
                self.notify(
                    "ERROR - Whirlpool incomplete",
                    "Step completed without reaching internal whirlpool stage",
                    type="danger",
                    timeout=None)
            self.actor_off(int(self.chiller))
            self.actor_off(int(self.chillerPump))
            next(self)
        else:
            if self.get_kettle_temp(self.kettle) >= (
                    self.get_target_temp(self.kettle) +
                    10):  #This option determines when the chiller is full on
                self.actor_on(int(self.chiller))
            elif self.get_kettle_temp(self.kettle) >= self.get_target_temp(
                    self.kettle
            ):  #This option specifies partial activation - alternate 3secs on and off
                self.c_cut = int((self.timer_remaining() / 3))
                if self.c_cut % 2:
                    self.actor_on(int(self.chiller))
                else:
                    self.actor_off(int(self.chiller))
            else:
                self.actor_off(int(self.chiller))
        if self.stage == "init":
            self.notify("Put on the lid and connect the chiller",
                        "Please select \"Chiller Connected\" to continue",
                        type="warning",
                        timeout=None)
            self.stage = "waithookup"
        elif self.stage == "sanitise":
            if self.s_end >= self.timer_remaining():
                self.stage = "whirlpool"
                self.set_target_temp(self.temp, self.kettle)
Esempio n. 28
0
class BoilStepWithHopDropper(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    temp = Property.Number("Temperature",
                           configurable=True,
                           default_value=100,
                           description="Target temperature for boiling")
    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the boiling step takes place")
    timer = Property.Number(
        "Timer in Minutes",
        configurable=True,
        default_value=90,
        description="Timer is started when target temperature is reached")
    hop_dropper = StepProperty.Actor(
        "Hop Dropper", description="Please select the hop dropper actor")
    hop_1 = Property.Number("Hop 1 Addition",
                            default_value="9999",
                            configurable=True,
                            description="First Hop alert")
    hop_1_added = Property.Number("", default_value=None)
    hop_1_desc = Property.Text(
        label="Hop 1 Description",
        configurable=True,
        default_value="",
        description="Enter Hop 1 descriptions, like how much use and hop name."
    )
    hop_2 = Property.Number("Hop 2 Addition",
                            default_value="9999",
                            configurable=True,
                            description="Second Hop alert")
    hop_2_added = Property.Number("", default_value=None)
    hop_2_desc = Property.Text(
        label="Hop 2 Description",
        configurable=True,
        default_value="",
        description="Enter Hop 2 descriptions, like how much use and hop name."
    )
    hop_3 = Property.Number("Hop 3 Addition",
                            default_value="9999",
                            configurable=True,
                            description="Third Hop alert")
    hop_3_added = Property.Number("", default_value=None)
    hop_3_desc = Property.Text(
        label="Hop 3 Description",
        configurable=True,
        default_value="",
        description="Enter Hop 3 descriptions, like how much use and hop name."
    )
    hop_4 = Property.Number("Hop 4 Addition",
                            default_value="9999",
                            configurable=True,
                            description="Fourth Hop alert")
    hop_4_added = Property.Number("", default_value=None)
    hop_4_desc = Property.Text(
        label="Hop 4 Description",
        configurable=True,
        default_value="",
        description="Enter Hop 4 descriptions, like how much use and hop name."
    )
    hop_5 = Property.Number("Hop 5 Addition",
                            default_value="9999",
                            configurable=True,
                            description="Fives Hop alert")
    hop_5_added = Property.Number("", default_value=None)
    hop_5_desc = Property.Text(
        label="Hop 5 Description",
        configurable=True,
        default_value="",
        description="Enter Hop 5 descriptions, like how much use and hop name."
    )
    hop_6 = Property.Number("Hop 6 Addition",
                            default_value="9999",
                            configurable=True,
                            description="Sixth Hop alert")
    hop_6_added = Property.Number("", default_value=None)
    hop_6_desc = Property.Text(
        label="Hop 6 Description",
        configurable=True,
        default_value="",
        description="Enter Hop 6 descriptions, like how much use and hop name."
    )
    hop_7 = Property.Number("Hop 7 Addition",
                            default_value="9999",
                            configurable=True,
                            description="Seventh Hop alert")
    hop_7_added = Property.Number("", default_value=None)
    hop_7_desc = Property.Text(
        label="Hop 7 Description",
        configurable=True,
        default_value="",
        description="Enter Hop 7 descriptions, like how much use and hop name."
    )

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target tep
        self.set_target_temp(self.temp, self.kettle)

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.temp, self.kettle)

    def finish(self):
        self.set_target_temp(0, self.kettle)

    def check_hop_timer(self, number, value):

        if self.__getattribute__(
                "hop_%s_added" % number) is not True and time.time() > (
                    self.timer_end - (int(self.timer) * 60 - int(value) * 60)):
            self.__setattr__("hop_%s_added" % number, True)
            if self.hop_dropper is not None:
                self.actor_on(int(self.hop_dropper))
            self.notify(
                "Hop Alert",
                "Adding Hops #%s: %s" %
                (number, self.__getattribute__("hop_%s_desc" % number)),
                timeout=10000)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''
        # Check if Target Temp is reached
        if self.get_kettle_temp(self.kettle) >= float(self.temp):
            # Check if Timer is Running
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)
            else:
                self.check_hop_timer(1, self.hop_1)
                self.check_hop_timer(2, self.hop_2)
                self.check_hop_timer(3, self.hop_3)
                self.check_hop_timer(4, self.hop_4)
                self.check_hop_timer(5, self.hop_5)
                self.check_hop_timer(6, self.hop_6)
                self.check_hop_timer(7, self.hop_7)
        # Check if timer finished and go to next step
        if self.is_timer_finished() == True:
            self.notify("Boil Step Completed!",
                        "Starting the next step",
                        timeout=None)
            self.next()
Esempio n. 29
0
class SimpleMashOutStep(StepBase):

    kettle = StepProperty.Kettle(
        "Kettle", description="Kettle in which the chilling takes place")
    temp = Property.Number("MashOut Temperature",
                           configurable=True,
                           default_value=76.7,
                           description="Target Temperature of Mashout")
    timer = Property.Number("MashOut Timer in Minutes",
                            configurable=True,
                            default_value=10,
                            description="Time to be held at Mashout temp")
    stage = "init"  #This process goes through the following stages: init, mashout, sparge, preboil, hotbreak
    preboiltemp = 90
    hotbreaktemp = 99
    wait_user = False

    def init(self):
        self.stage = "init"
        self.wait_user = False
        self.set_target_temp(self.temp, self.kettle)
        # self.preboiltemp = self.api.cache.get("kettle").get(self.kettle).get_config_parameter("e_max_temp_pid")
        # self.hotbreaktemp = 99

    def start(self):
        pass

    def reset(self):
        pass

    def finish(self):
        pass

    @cbpi.action("Sparge Complete")
    def sparge_complete(self):
        if self.stage == "sparge":
            self.stage = "preboil"
            self.wait_user = False
            self.set_target_temp(self.preboiltemp, self.kettle)
        else:
            self.notify(
                "No Action Taken",
                "Function only works in \"sparge\" sub-stage. Current stage: "
                + self.stage,
                type="info",
                timeout=5000)

    @cbpi.action("Removed Lid")
    def lid_removed(self):
        if self.stage == "preboil":
            self.stage = "hotbreak"
            self.wait_user = False
            self.set_target_temp(self.hotbreaktemp, self.kettle)
        else:
            self.notify(
                "No Action Taken",
                "Function only works in \"preboil\" sub-stage. Current stage: "
                + self.stage,
                type="info",
                timeout=5000)

    @cbpi.action("Hotbreak Finished")
    def hotbreak_finished(self):
        if self.stage == "hotbreak":
            self.wait_user = False
            next(self)
        else:
            self.notify(
                "No Action Taken",
                "Function only works in \"hotbreak\" sub-stage. Current stage: "
                + self.stage,
                type="info",
                timeout=5000)

    def execute(self):
        if self.stage == "init":  #let the kettle heat to mash out temp
            if self.get_kettle_temp(self.kettle) >= self.temp:
                self.stage = "mashout"
        elif self.stage == "mashout":  #run the mash timer
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)
            if self.is_timer_finished() == True:
                self.stage = "sparge"
        elif self.stage == "sparge":  #wait for user confirmation to continue
            if self.wait_user == False:
                self.notify(
                    "MASH OUT COMPLETE",
                    "Sparge and then select \"Sparge Complete\" to continue.",
                    type="warning",
                    timeout=None)
                self.wait_user = True
        elif self.stage == "preboil":  #let the kettle heat to pre-boil, then wait for user to remove lid
            if self.get_kettle_temp(self.kettle) >= self.preboiltemp:
                if self.wait_user == False:
                    self.notify(
                        "REMOVE THE LID",
                        "Heated to Pre-Boil. Remove the lid and click \"Removed Lid\" to continue.",
                        type="warning",
                        timeout=None)
                    self.wait_user = True
        elif self.stage == "hotbreak":  #heat kettle to boil, then wait for user for user to go to boil stage
            if self.get_kettle_temp(self.kettle) >= self.hotbreaktemp:
                if self.wait_user == False:
                    self.notify(
                        "WATCH FOR HOTBREAK",
                        "When hotbreak is complete click \"Hotbreak Finished\" to continue.",
                        type="warning",
                        timeout=None)
                    self.wait_user = True
        else:  #An error has occured! Not in a valid status
            self.notify("INVALID STAGE",
                        "An invalid stage has been returned. Current stage: " +
                        self.stage,
                        type="dangar",
                        timeout=None)
Esempio n. 30
0
class HERMSStep(StepBase):
    '''
    Just put the decorator @cbpi.step on top of a method
    '''
    # Properties
    target_temp = Property.Number(
        "Target Temp",
        configurable=True,
        description="Target Temperature of Mash Step")
    mash_tun = StepProperty.Kettle(
        "Mash Tun", description="Kettle in which the mashing takes place")
    hlt = StepProperty.Kettle(
        "HLT", description="Kettle used for heat transfer, hot liquor tank")
    timer = Property.Number("Rest (m)",
                            configurable=True,
                            description="Minutes of rest at target temp")
    hlt_offset = Property.Number(
        "HLT Offset",
        configurable=True,
        default_value=8,
        description=
        "Temp relative to mash target to maintain in HLT while rising")

    def init(self):
        '''
        Initialize Step. This method is called once at the beginning of the step
        :return:
        '''
        # set target temp
        self.set_target_temp(self.target_temp, self.mash_tun)
        self.set_target_temp(
            int(self.target_temp) + int(self.hlt_offset), self.hlt)

    @cbpi.action("Start Timer Now")
    def start(self):
        '''
        Custom Action which can be execute form the brewing dashboard.
        All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
        :return:
        '''
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

    def reset(self):
        self.stop_timer()
        self.set_target_temp(self.target_temp, self.mash_tun)
        self.set_target_temp(
            int(self.target_temp) + int(self.hlt_offset), self.hlt)

    def finish(self):
        self.set_target_temp(0, self.mash_tun)
        self.set_target_temp(0, self.hlt)

    def execute(self):
        '''
        This method is execute in an interval
        :return:
        '''

        # Check if Target Temp is reached
        if self.get_kettle_temp(self.mash_tun) >= int(self.target_temp):
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)

        # Check if timer finished and go to next step
        if self.is_timer_finished() == True:
            self.notify("Mash Step Completed!",
                        "Starting the next step",
                        timeout=None)
            self.next()