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()
Example #2
0
class PumpStep(StepBase):

    pump = StepProperty.Actor("Pump")
    timer = Property.Number("Timer in Minutes", configurable=True, default_value=0)

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

    def reset(self):
        self.stop_timer()


    def finish(self):
        self.actor_off(int(self.pump))

    def init(self):
        self.actor_on(int(self.pump))

    def execute(self):
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

        if self.is_timer_finished() == True:
            self.next()
Example #3
0
class PumpStep(StepBase):

    pump = StepProperty.Actor("Pump", description="Pump actor gets toogled")
    timer = Property.Number("Timer in Minutes",
                            configurable=True,
                            default_value=0,
                            description="Timer is started immediately")

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

    def reset(self):
        self.stop_timer()

    def finish(self):
        self.actor_off(int(self.pump))

    def init(self):
        self.actor_on(int(self.pump))

    def execute(self):
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

        if self.is_timer_finished() == True:
            # if you dont want a beep sound comment out like :  # cbpi.PumpStepEndBeep()
            cbpi.PumpStepEndBeep()
            self.next()
Example #4
0
class PumpStep(StepBase):

    pump = StepProperty.Actor("Pump", description="Pump actor gets toogled")
    timer = Property.Number("Timer in Minutes", configurable=True, default_value=0, description="Timer is started immediately")

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

    def reset(self):
        self.stop_timer()
        #self.stop_stopwatch()

    def finish(self):
        self.actor_off(int(self.pump))
        #self.stop_stopwatch()

    def init(self):
        self.actor_on(int(self.pump))

    def execute(self):
        if self.is_timer_finished() is None:
            self.start_timer(int(self.timer) * 60)

        if self.is_timer_finished() == True:
            self.next()
class PressureSensor(StepBase):
    volume = Property.Number("volume", configurable=True)
    sensor = StepProperty.Sensor("Sensor")
    actor = StepProperty.Actor("Actor")

    def init(self):
        if self.actor is not None:
            self.actor_on(int(self.actor))

    @cbpi.action("Turn Actor OFF")
    def start(self):
        if self.actor is not None:
            self.actor_off(int(self.actor))

    def reset(self):
        if self.actor is not None:
            self.actor_off(int(self.actor))

    def finish(self):
        if self.actor is not None:
            self.actor_off(int(self.actor))

    def execute(self):
        for key, value in cbpi.cache.get("sensors").iteritems():
            if key == int(self.sensor):
                sensorValue = value.instance.last_value
        if float(sensorValue) >= float(self.volume):
            self.next()
Example #6
0
class SimpleActorTimer(StepBase):
    # Properties
    actor1 = StepProperty.Actor("Actor 1")
    actor2 = StepProperty.Actor("Actor 2")
    timer = Property.Number("Timer in Minutes",
                            configurable=True,
                            description="Timer is started immediately.")

    #-------------------------------------------------------------------------------
    def init(self):
        self.actors = [self.actor1, self.actor2]
        self.actors_on()

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

    #-------------------------------------------------------------------------------
    def execute(self):
        # Check if Timer is Running
        if self.is_timer_finished() is None:
            self.start_timer(float(self.timer) * 60)

        # Check if timer finished and go to next step
        if self.is_timer_finished() == True:
            self.notify("{} complete".format(self.name),
                        "Starting the next step",
                        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
Example #7
0
class BaseColletingStep(object):
    collectingActor = StepProperty.Actor(
        "Устройство отбора", description="Исполнительное устройство отбора")
    collectingSensor = StepProperty.Sensor(
        "Индикатор отбора", description="Индикатор скорости отбора")

    isPaused = False
    power = 0
    maxSpeed = 0

    @cbpi.action("Начать отбор")
    def start(self):
        if self.isPaused:
            self.time = datetime.utcnow()
            self.notify("", "Отбор продолжен", type="success", timeout=2000)
            self.isPaused = False

    @cbpi.action("Остановить отбор")
    def stop(self):
        if not self.isPaused:
            self.notify("",
                        "Отбор приостановлен",
                        type="success",
                        timeout=2000)
            self.isPaused = True

    def notifySensor(self):
        try:
            sensor = self.api.cache.get("sensors").get(
                int(self.collectingSensor)).instance
            sensor.collecting = int(self.collectingSpeed)
        except:
            pass

    def updateMaxCollectingSpeed(self):
        try:
            actor = self.api.cache.get("actors").get(int(
                self.collectingActor)).instance
            self.maxSpeed = actor.get_max_speed()
        except:
            self.maxSpeed = 0

    def manageActor(self):
        actorId = int(self.collectingActor)
        self.actor_power(power=self.power, id=actorId)
        if self.isPaused:
            self.actor_off(actorId)
        else:
            self.actor_on(power=self.power, id=actorId)

    def calculateActorPower(self):
        if self.maxSpeed > 0:
            self.power = min(
                round(float(self.collectingSpeed) / self.maxSpeed * 100), 100)
Example #8
0
class Flowmeter(StepBase):
    sensor = StepProperty.Sensor("Sensor")
    actorA = StepProperty.Actor("Actor")
    volume = Property.Number("Volume", configurable=True)
    resetFlowmeter = Property.Number(
        "Reset flowmeter when done. 1 = Yes 0 = No",
        configurable=True,
        default_value="1")

    def init(self):
        if int(self.actorA) is not None:
            self.actor_on(int(self.actorA))

    @cbpi.action("Turn Actor OFF")
    def start(self):
        if self.actorA is not None:
            self.actor_off(int(self.actorA))

    def reset(self):
        if self.actorA is not None:
            self.actor_off(int(self.actorA))

    def finish(self):
        if self.actorA is not None:
            self.actor_off(int(self.actorA))
        if self.resetFlowmeter == "1":
            for key, value in list(cbpi.cache.get("sensors").items()):
                if key == int(self.sensor):
                    value.instance.reset()

    def execute(self):
        for key, value in list(cbpi.cache.get("sensors").items()):
            if key == int(self.sensor):
                sensorValue = value.instance.getValue()
        if float(sensorValue) >= float(self.volume):
            next(self)
Example #9
0
class SimpleToggleStep(StepBase):

    # Properties
    actor = StepProperty.Actor("Actor")
    power = Property.Number("Power", configurable=True)
    toggle_type = Property.Select("Toggle Type",
                                  options=["On", "Off", "Power Only"])

    def init(self):
        if self.toggle_type == "On":
            if self.power is not None and self.power:
                self.actor_on(int(self.actor), int(self.power))
            else:
                self.actor_on(int(self.actor))
        if self.toggle_type == "Off":
            self.actor_off(int(self.actor))
        if self.toggle_type == "Power Only" and self.power is not None and self.power:
            self.actor_power(int(self.actor), int(self.power))

    def finish(self):
        pass

    def execute(self):
        next(self)
Example #10
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()
Example #11
0
class FlowSensorCalibrate(StepBase):
    # properties
    actor_prop = StepProperty.Actor("Actor")
    sensor_prop = StepProperty.Sensor("Sensor")
    timer_prop = Property.Number("Timer", configurable=True, default_value=10)
    threshold_prop = Property.Number(
        "Flow threshold",
        configurable=True,
        default_value=0.1,
        description="Value at which flow is considered stopped")

    #-------------------------------------------------------------------------------
    def init(self):
        # convert properties to usable attributes
        self.actor = int(self.actor_prop)
        self.sensor = cbpi.cache.get("sensors")[int(self.sensor_prop)].instance
        self.threshold = float(self.threshold_prop)
        self.flowing = False

        # reset sensor volume to start calibration
        self.sensor.reset_volume()
        # turn on actor
        self.actor_on(self.actor)
        # start timer
        if self.is_timer_finished() is None:
            self.start_timer(float(self.timer_prop) * 60)

    #-------------------------------------------------------------------------------
    def execute(self):
        sensor_data = self.sensor.read_sensor_data()
        if (not self.flowing) and (sensor_data['flow'] >= self.threshold):
            # flow has started
            cbpi.app.logger.info(
                "FlowSensor '{}' calibrate flow started".format(
                    self.sensor.name))
            self.flowing = True
        elif (self.flowing) and (sensor_data['flow'] <= self.threshold):
            # flow has stopped
            cbpi.app.logger.info(
                "FlowSensor '{}' calibrate flow stopped".format(
                    self.sensor.name))
            self.next()
        elif self.is_timer_finished() == True:
            # timer has expired
            cbpi.app.logger.info(
                "FlowSensor '{}' calibrate timer expired".format(
                    self.sensor.name))
            self.next()

    #-------------------------------------------------------------------------------
    def finish(self):
        # turn off actor
        self.actor_off(self.actor)

        # notify complete and total pulses
        sensor_data = self.sensor.read_sensor_data()
        self.notify("Flow Sensor Calibration Complete",
                    self.sensor.name,
                    type="success",
                    timeout=None)
        self.notify("Pulse Count: {}".format(sensor_data['count']),
                    self.sensor.name,
                    type="info",
                    timeout=None)

    #-------------------------------------------------------------------------------
    def reset(self):
        self.actor_off(self.actor)
Example #12
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()
Example #13
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"
Example #14
0
class SpargeStep(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("Boil Kettle")
    kettle2 = StepProperty.Kettle("HLT Kettle")
    actor1 = StepProperty.Actor("Wort Pump")
    actor2 = StepProperty.Actor("Water Pump")
    sensor1 = StepProperty.Sensor("BK Volume Sensor")
    sensor2 = StepProperty.Sensor("HLT Volume Sensor")
    volume1 = Property.Number("BK Volume Target", configurable=True)
    volume2 = Property.Number("HLT Volume Min", configurable=True)
    volumeStart = Property.Number("HLT Volume Start", configurable=True)
    volumeDiff = Property.Number("Volume Difference", configurable=True)
    timer = Property.Number("Timer in Minutes", configurable=True)
    temp = Property.Number("BK Temp", configurable=True)
    volumeBoil = Property.Number("BK Boil Volume", configurable=True)

    volumeState1 = 0
    volumeState2 = 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)

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

    def execute(self):
        '''
        This method is execute in an interval
        :return: 
        '''
        sensorValue1 = cbpi.get_sensor_value(int(self.sensor1))
        sensorValue2 = cbpi.get_sensor_value(int(self.sensor2))
        volumeChange1 = float(sensorValue1) - float(self.volumeState1)
        volumeChange2 = float(self.volumeState2) - float(sensorValue2)
        kettle1_state = cbpi.cache.get("kettle")[int(self.kettle1)].state
        kettle2_state = cbpi.cache.get("kettle")[int(self.kettle2)].state

        for key, value in cbpi.cache["actors"].iteritems():
            if key == int(self.actor1):
                actorState1 = value.state
            if key == int(self.actor2):
                actorState2 = value.state

        if float(sensorValue1) >= float(
                self.volumeBoil) and kettle1_state is False:
            Kettle2View().toggle(int(self.kettle1))
            self.notify("Kettle Update", "Kettle 1 Auto is on.", timeout=None)
            self.set_target_temp(self.temp, self.kettle1)

        # Check if kettle2 volume limit reached
        if float(sensorValue2) <= float(self.volume2):
            if kettle2_state is True:
                self.set_target_temp(0, self.kettle2)
                Kettle2View().toggle(int(self.kettle2))
                self.notify("Kettle Update",
                            "Kettle 2 Auto is off.",
                            timeout=None)
            if self.is_timer_finished() is None:
                self.start_timer(int(self.timer) * 60)
            # Make sure kettle1 hasn't reached target
            if float(sensorValue1) < float(self.volume1):
                self.actor_on(int(self.actor1))
                if self.is_timer_finished() == True:
                    self.actor_off(int(self.actor2))
                else:
                    self.actor_on(int(self.actor2))
        else:
            if self.volumeState1 > 0:
                totalDiff = float(volumeChange2) - float(volumeChange1)
                if totalDiff > 0:
                    if abs(totalDiff) > float(self.volumeDiff):
                        self.actor_off(int(self.actor2))
                        self.actor_on(int(self.actor1))
                    else:
                        self.actor_on(int(self.actor2))
                else:
                    if abs(totalDiff) > float(self.volumeDiff):
                        self.actor_off(int(self.actor1))
                        self.actor_on(int(self.actor2))
                    else:
                        self.actor_on(int(self.actor1))
            else:
                if volumeChange >= 10:
                    self.volumeState2 = sensorValue2
                    self.volumeState1 = sensorValue1

        # Check if kettle1 target volume has been reached
        if float(sensorValue1) >= float(self.volume1):
            self.set_target_temp(0, self.kettle2)
            self.stop_timer()
            self.start_timer(0)
            self.notify("Sparge Complete!",
                        "Starting the next step.",
                        timeout=None)
            self.next()
Example #15
0
class FlowSensorTransfer(StepBase):
    a_sensor_prop = StepProperty.Sensor(
        "Flow Sensor", description="Sensor that contols this step")
    b_actor1_prop = StepProperty.Actor(
        "Actor 1",
        description="Actor to turn on for the duration of this step")
    c_actor2_prop = StepProperty.Actor(
        "Actor 2",
        description="Actor to turn on for the duration of this step")
    d_volume_prop = Property.Number(
        "Target Volume",
        configurable=True,
        description="Leave blank to continue until flow stops")
    e_reset_start_prop = Property.Select("Reset sensor at start?",
                                         options=["Yes", "No"])
    f_reset_finish_prop = Property.Select("Reset sensor at finish?",
                                          options=["Yes", "No"])
    g_threshold_prop = Property.Number(
        "Flow threshold",
        configurable=True,
        default_value=0.1,
        description="Value at which flow is considered stopped")

    #-------------------------------------------------------------------------------
    def init(self):
        # convert properties to usable attributes
        self.sensor = cbpi.cache.get("sensors")[int(
            self.a_sensor_prop)].instance
        self.actors = [self.b_actor1_prop, self.c_actor2_prop]
        try:
            self.target_volume = float(self.d_volume_prop)
        except:
            self.target_volume = 0.0
        self.reset_start = self.e_reset_start_prop == "Yes"
        self.reset_finish = self.f_reset_finish_prop == "Yes"
        try:
            self.threshold = float(self.g_threshold_prop)
        except:
            self.threshold = 0.1
        self.flowing = False

        # reset sensor volume if indicated
        if self.reset_start:
            self.sensor.reset_volume()
        # turn on actors
        self.actors_on()

    #-------------------------------------------------------------------------------
    def execute(self):
        sensor_data = self.sensor.read_sensor_data()
        if (not self.flowing) and (sensor_data['flow'] >= self.threshold):
            # flow has started
            cbpi.app.logger.info(
                "FlowSensor '{}' transfer flow started".format(
                    self.sensor.name))
            self.flowing = True
        elif (self.flowing) and (sensor_data['flow'] <= self.threshold):
            # flow has stopped
            cbpi.app.logger.info(
                "FlowSensor '{}' transfer flow stopped".format(
                    self.sensor.name))
            self.next()
        elif self.target_volume and (sensor_data['volume'] >=
                                     self.target_volume):
            # target volume reached
            cbpi.app.logger.info(
                "FlowSensor '{}' transfer target volume reached".format(
                    self.sensor.name))
            self.next()

    #-------------------------------------------------------------------------------
    def finish(self):
        # turn actors off
        self.actors_off()

        # notify complete and total volume
        sensor_data = self.sensor.read_sensor_data()
        self.notify("{} complete".format(self.name),
                    "Total Volume: {:.2f}{}".format(sensor_data['volume'],
                                                    self.sensor.volume_units),
                    timeout=None)

        # reset sensor volume if indicated
        if self.reset_finish:
            self.sensor.reset_volume()

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

    #-------------------------------------------------------------------------------
    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
Example #16
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 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
Example #18
0
class Mod_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")

    # Temp Protection modification start
    protection_temp_diff = Property.Number(
        "Temperature Difference",
        configurable=True,
        description=
        "Treshold Temperature = Temperature + Temperature Difference. Timer will stop if this temperature si reached and brewing procces will be interrupted",
        default_value=8)
    protection_actor = StepProperty.Actor(
        "Portective Circuit Actor",
        description=
        "Please select an Actor which will be activated if treshold temperature is reached"
    )
    s = False

    # Temp Protection modification  end

    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.s = False
        #de-activate temperature protection
        self.actor_off(self.protection_actor)

    @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)

        # Temp Protection modification start
        #de-activate temperature protection
        self.actor_off(self.protection_actor)
        s = False
        # Temp Protection modification end

    def finish(self):
        self.set_target_temp(0, self.kettle)
        # Temp Protection modification start
        #de-activate temperature protection
        self.actor_off(self.protection_actor)
        s = False
        # Temp Protection modification end

    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)

        #Temp protection start modification and overshoot deteection. If temperature is over N Celsius, protection will stop the process
        if (int(self.get_kettle_temp(self.kettle)) >=
            (int(self.temp) +
             int(self.protection_temp_diff))) and self.s is False:
            self.s = True
            self.notify(
                "ALARM",
                "Exiting brewing process - critical temperature is reached",
                timeout=0,
                type="danger")
            #Activate temperature protection
            self.actor_on(self.protection_actor)
            #Dont go to the next step, show "Alarm" and remaining time
            self.notify(str(
                time.strftime('%H:%M:%S',
                              time.gmtime(int((self.timer_remaining()))))),
                        "time until the end of this step",
                        timeout=0)
            #Reset and stop timer
            self.timer_end = True
        #Temp protection end modification

        # Check if timer finished and go to next step
        if self.is_timer_finished() == True and self.s == False:
            self.s = True
            self.notify("Mash Step Completed!",
                        "Starting the next step",
                        timeout=None)
            next(self)
Example #19
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)
Example #20
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()