class OnAtStartup(ActorBase):
    actor_setting = Property.Actor(
        "Actor",
        description="Select the actor you would like to have ON at startup")
    power_setting = Property.Number(
        "Power",
        True,
        100,
        description="Select the power of the actor at startup")

    def init(self):
        if not 0 <= int(self.power_setting) <= 100:
            self.api.notify(headline="OnAtStartup Error",
                            message="Power must be between 0 and 100",
                            timeout=None,
                            type="danger")
            raise ValueError("Power must be between 0 and 100")
        else:
            self.api.switch_actor_on(int(self.actor_setting),
                                     power=int(self.power_setting))

    def set_power(self, power):
        pass

    def off(self):
        pass

    def on(self, power=None):
        pass
Exemple #2
0
class ActorGroup(ActorBase):

    actordesc = "Select an actor to be controlled by this group."
    actor01 = Property.Actor("Actor 1", description=actordesc)
    actor02 = Property.Actor("Actor 2", description=actordesc)
    actor03 = Property.Actor("Actor 3", description=actordesc)
    actor04 = Property.Actor("Actor 4", description=actordesc)
    actor05 = Property.Actor("Actor 5", description=actordesc)
    actor06 = Property.Actor("Actor 6", description=actordesc)
    actor07 = Property.Actor("Actor 7", description=actordesc)
    actor08 = Property.Actor("Actor 8", description=actordesc)

    def init(self):
        self.actors = []

        if isinstance(self.actor01, unicode) and self.actor01:
            self.actors.append(int(self.actor01))
        if isinstance(self.actor02, unicode) and self.actor02:
            self.actors.append(int(self.actor02))
        if isinstance(self.actor03, unicode) and self.actor03:
            self.actors.append(int(self.actor03))
        if isinstance(self.actor04, unicode) and self.actor04:
            self.actors.append(int(self.actor04))
        if isinstance(self.actor05, unicode) and self.actor05:
            self.actors.append(int(self.actor05))
        if isinstance(self.actor06, unicode) and self.actor06:
            self.actors.append(int(self.actor06))
        if isinstance(self.actor07, unicode) and self.actor07:
            self.actors.append(int(self.actor07))
        if isinstance(self.actor08, unicode) and self.actor08:
            self.actors.append(int(self.actor08))

    def set_power(self, power):
        for actor in self.actors:
            self.api.actor_power(actor, power=power)

    def on(self, power=None):
        for actor in self.actors:
            self.api.switch_actor_on(actor, power=power)

    def off(self):
        turnedOnActors = []
        for idx, value in cbpi.cache["actors"].iteritems():
            if (value.type == "ActorGroup" and idx != self.id
                    and value.state == 1):
                actorsIds = map(int, value.config.values())
                intersection = intersect(actorsIds, self.actors)
                turnedOnActors.extend(intersection)

        for actor in self.actors:
            if (actor not in turnedOnActors):
                self.api.switch_actor_off(actor)
class ScalableDependentActor(ActorBase):
    
    base = Property.Actor(label="Dependent Actor", description="Select the actor which will be dependent to master one.")
    dependency = Property.Actor(label="Master Actor", description="Select the actor that will control the dependent one selected above.")

    def init(self):
        # Switch off the Dependent Actor
        self.api.switch_actor_off(int(self.base))
        # Hide Base Actor
        for idx, value in cbpi.cache["actors"].iteritems():
            if idx == int(self.base):
                value.hide = True
        # Synchronize current power setting with the Base Actor
       
    def set_power(self, power):
        
        potenciaMaster = self.api.actor_power(int(self.dependency))
        
        potenciaDif = 100 - int(potenciaMaster)
                       
        self.api.actor_power(int(self.base), power=int(potenciaDif))
        

    def off(self):
        self.api.switch_actor_off(int(self.base))

    def on(self, power=None):
        dependency_name = ""
        for idx, value in cbpi.cache["actors"].iteritems():
            if idx == int(self.dependency):
                dependency_name = value.name
        for idx, value in cbpi.cache["actors"].iteritems():
            if idx == int(self.dependency):
                if (value.state == 0):
                    self.api.switch_actor_on(int(self.base), power=100)
                elif (value.state == 1) & (self.api.actor_power(int(self.dependency))==100):
                    self.api.switch_actor_off(int(self.base))
                elif (value.state == 1) & (self.api.actor_power(int(self.dependency))<100):
                    potenciaMaster = self.api.actor_power(int(self.dependency))
                    potenciaDif = 100 - int(potenciaMaster)
                    self.api.switch_actor_on(int(self.base), power=potenciaDif)
Exemple #4
0
class ActorGroup(ActorBase):

    actordesc = "Select an actor to be controlled by this group."
    actor01 = Property.Actor("Actor 1", description=actordesc)
    actor02 = Property.Actor("Actor 2", description=actordesc)
    actor03 = Property.Actor("Actor 3", description=actordesc)
    actor04 = Property.Actor("Actor 4", description=actordesc)
    actor05 = Property.Actor("Actor 5", description=actordesc)
    actor06 = Property.Actor("Actor 6", description=actordesc)
    actor07 = Property.Actor("Actor 7", description=actordesc)
    actor08 = Property.Actor("Actor 8", description=actordesc)

    def init(self):
        self.actors = []

        if isinstance(self.actor01, unicode) and self.actor01:
            self.actors.append(int(self.actor01))
        if isinstance(self.actor02, unicode) and self.actor02:
            self.actors.append(int(self.actor02))
        if isinstance(self.actor03, unicode) and self.actor03:
            self.actors.append(int(self.actor03))
        if isinstance(self.actor04, unicode) and self.actor04:
            self.actors.append(int(self.actor04))
        if isinstance(self.actor05, unicode) and self.actor05:
            self.actors.append(int(self.actor05))
        if isinstance(self.actor06, unicode) and self.actor06:
            self.actors.append(int(self.actor06))
        if isinstance(self.actor07, unicode) and self.actor07:
            self.actors.append(int(self.actor07))
        if isinstance(self.actor08, unicode) and self.actor08:
            self.actors.append(int(self.actor08))

    def set_power(self, power):
        for actor in self.actors:
            self.api.actor_power(actor, power=power)

    def on(self, power=None):
        for actor in self.actors:
            self.api.switch_actor_on(actor, power=power)

    def off(self):
        for actor in self.actors:
            self.api.switch_actor_off(actor)
class MCP4728Actor(ActorBase):
    """An actor that uses a four channel MCP4728 12-bit DAC i2c module to control power using output voltages between
    0-Vdd or 0-Vref x Gain on a single channel.

    The on/off state of the actor can be controlled either by setting the DAC output to zero, or using an additional
    actor.
    """
    a_address = Property.Select("DAC Address", [0, 1, 2, 3, 4, 5, 6, 7],
                                description="Minor address of the MCP4728 DAC unit. Use 0 unless you have changed the address manually")
    b_channel = Property.Select("Channel", [0, 1, 2, 3],
                                description="DAC channel to use")
    c_volt_ref = Property.Select("Reference Voltage", ["Vdd", "Internal 2.048V", "Internal 4.096V"],
                                 description="Voltage Reference for DAC channel")
    d_power_ctrl = Property.Select("Power Control", ["Zero DAC", "Actor"],
                                   description="Power control method")
    e_power_actor = Property.Actor("Power On/Off Actor", description="Actor to use to control power")
    timeout = Property.Number("Notification duration (ms)", True, 1000,
                              description="0ms will disable notifications completely")
    z_debug = Property.Select("Debug Messages", ["Off", "On"], description="Display debug notifications")

    def init(self):
        address = int(self.a_address)
        channel = int(self.b_channel)

        self.dac = mcp4728.MCP4728(address)
        if self.z_debug == "On":
            cbpi.notify("Connected to MCP4728",
                        "DAC Address {:d}: DAC Channel {:d}".format(address, channel),
                        timeout=self.timeout)

        if self.c_volt_ref == "Vdd":
            self.dac.set_vref(channel, 0)
        else:
            self.dac.set_vref(channel, 1)
            if self.c_volt_ref == "Internal 4.096V":
                self.dac.set_gain(channel, 1)
            else:
                self.dac.set_gain(channel, 0)

        # CBPI Actor sets UI state to 0 and power to 100 in post_init_callback, called after this method,
        # so set power here to 100 and state to off to make sure we start in a consistent state.
        #
        # Have to predefine .state and .power, because they aren't defined by ActorAPI.init
        self.api.cache.get("actors").get(self.id).state = 0
        self.api.cache.get("actors").get(self.id).power = 100

        self.api.switch_actor_off(self.id)
        self.api.actor_power(self.id, 100)
        self.value = 4095

    def set_power(self, power):
        """Set the power as a percentage of the range between minimum and maximum power"""
        channel = int(self.b_channel)

        self.power = power
        self.value = int((4095 * power) / 100)

        if self.d_power_ctrl == "Zero DAC":
            if self.state == 0:
                pass
            elif self.state == 1:
                self.dac.set_value(channel, self.value)
        else:
            self.dac.set_value(channel, self.value)

        if self.z_debug == "On":
            value = self.dac.get_value(channel)
            cbpi.notify("MCP4728 Set Value", "Channel {:d}: Value {:d}".format(channel, value), timeout=self.timeout)

    def off(self):
        """Switch the actor off"""
        channel = int(self.b_channel)

        if self.d_power_ctrl == "Actor":
            self.api.switch_actor_off(int(self.e_power_actor))
        else:
            self.dac.set_value(channel, 0)

        self.state = 0
        if self.z_debug == "On":
            value = self.dac.get_value(channel)
            cbpi.notify("MCP4728 Current Value", "Channel {:d}: Value {:d}".format(channel, value),
                        timeout=self.timeout)

    def on(self, power=None):
        """Switch the actor on. Set the power to the given value or the current power setting."""
        channel = int(self.b_channel)

        if self.d_power_ctrl == "Actor":
            self.api.switch_actor_on(int(self.e_power_actor))

        self.state = 1
        if power:
            self.set_power(power)
        else:
            self.dac.set_value(channel, self.value)

        if self.z_debug == "On":
            value = self.dac.get_value(channel)
            cbpi.notify("MCP4728 Current Value", "Channel {:d}: Value {:d}".format(channel, value),
                        timeout=self.timeout)
Exemple #6
0
class DefinedState(ActorBase):
    #custom property
    actordesc = "select an actor to control state"
    actor01 = Property.Actor("Actor 1", description=actordesc)
    actor01_On_Off = Property.Select("On or OFF",
                                     options=["On", "Off"],
                                     description="On or Off")
    actor02 = Property.Actor("Actor 2", description=actordesc)
    actor02_On_Off = Property.Select("On or OFF",
                                     options=["On", "Off"],
                                     description="On or Off")
    actor03 = Property.Actor("Actor 3", description=actordesc)
    actor03_On_Off = Property.Select("On or OFF",
                                     options=["On", "Off"],
                                     description="On or Off")
    actor04 = Property.Actor("Actor 4", description=actordesc)
    actor04_On_Off = Property.Select("On or OFF",
                                     options=["On", "Off"],
                                     description="On or Off")
    actor05 = Property.Actor("Actor 5", description=actordesc)
    actor05_On_Off = Property.Select("On or OFF",
                                     options=["On", "Off"],
                                     description="On or Off")
    actor06 = Property.Actor("Actor 6", description=actordesc)
    actor06_On_Off = Property.Select("On or OFF",
                                     options=["On", "Off"],
                                     description="On or Off")
    actor07 = Property.Actor("Actor 7", description=actordesc)
    actor07_On_Off = Property.Select("On or OFF",
                                     options=["On", "Off"],
                                     description="On or Off")
    actor08 = Property.Actor("Actor 8", description=actordesc)
    actor08_On_Off = Property.Select("On or OFF",
                                     options=["On", "Off"],
                                     description="On or Off")

    #ta_stop  = Property.Number("Pause Timer", configurable=True, description="Defines how long the Agitator should stop before run again.")

    def init(self):
        self.actors = []
        self.YesNo = []

        if isinstance(self.actor01, unicode) and self.actor01:
            self.actors.append(int(self.actor01))
            self.YesNo.append(self.actor01_On_Off)
        if isinstance(self.actor02, unicode) and self.actor02:
            self.actors.append(int(self.actor02))
            self.YesNo.append(self.actor02_On_Off)
        if isinstance(self.actor03, unicode) and self.actor03:
            self.actors.append(int(self.actor03))
            self.YesNo.append(self.actor03_On_Off)
        if isinstance(self.actor04, unicode) and self.actor04:
            self.actors.append(int(self.actor04))
            self.YesNo.append(self.actor04_On_Off)
        if isinstance(self.actor05, unicode) and self.actor05:
            self.actors.append(int(self.actor05))
            self.YesNo.append(self.actor05_On_Off)
        if isinstance(self.actor06, unicode) and self.actor06:
            self.actors.append(int(self.actor06))
            self.YesNo.append(self.actor06_On_Off)
        if isinstance(self.actor07, unicode) and self.actor07:
            self.actors.append(int(self.actor07))
            self.YesNo.append(self.actor07_On_Off)
        if isinstance(self.actor08, unicode) and self.actor08:
            self.actors.append(int(self.actor08))
            self.YesNo.append(self.actor08_On_Off)

    def set_power(self, power):
        for actor in self.actors:
            self.api.actor_power(actor, power=power)
#self.sleep(int(self.ta_stop))

    def on(self, power=None):
        i = 0
        for actor in self.actors:
            if self.YesNo[i] == "On":
                self.api.switch_actor_on(actor, power=power)
            else:
                self.api.switch_actor_off(actor)
            i = i + 1
        #self.sleep(int(self.ta_stop))
        #self.api.cache.get("actors").get(int(self.id)).timer = int(time.time()) + int(self.ta_stop) -1
#self.api.notify(headline="Timed Agitator", message="Timed Agitator started", type="info")

    def off(self):
        for actor in self.actors:
            self.api.switch_actor_off(actor)
Exemple #7
0
class SlaveActorControl(ActorBase):

    actordesc = "Select an actor to be controlled by this group."
    a_actor= Property.Actor("Slave Actor", description= "Actor to be driven if any others on")
    actor01 = Property.Actor("Actor 1", description=actordesc)
    actor02 = Property.Actor("Actor 2", description=actordesc)
    actor03 = Property.Actor("Actor 3", description=actordesc)
    actor04 = Property.Actor("Actor 4", description=actordesc)
    actor05 = Property.Actor("Actor 5", description=actordesc)
    actor06 = Property.Actor("Actor 6", description=actordesc)
    actor07 = Property.Actor("Actor 7", description=actordesc)
    actor08 = Property.Actor("Actor 8", description=actordesc)

    def init(self):
        self.actors = []
        self.manual_on = False
        if isinstance(self.a_actor, unicode) and self.a_actor:
            self.slave_actor = (int(self.a_actor))
        else:
            self.slave_actor = None
        if isinstance(self.actor01, unicode) and self.actor01:
            self.actors.append(int(self.actor01))
        if isinstance(self.actor02, unicode) and self.actor02:
            self.actors.append(int(self.actor02))            
        if isinstance(self.actor03, unicode) and self.actor03:
            self.actors.append(int(self.actor03))
        if isinstance(self.actor04, unicode) and self.actor04:
            self.actors.append(int(self.actor04))
        if isinstance(self.actor05, unicode) and self.actor05:
            self.actors.append(int(self.actor05))            
        if isinstance(self.actor06, unicode) and self.actor06:
            self.actors.append(int(self.actor06))
        if isinstance(self.actor07, unicode) and self.actor07:
            self.actors.append(int(self.actor07))
        if isinstance(self.actor08, unicode) and self.actor08:
            self.actors.append(int(self.actor08))
      
        if not int(self.id) in master_actor_ids:
            master_actor_ids.append(int(self.id))  
    
  
    def execute_func(self):
        active = False
        if self.manual_on == True:
            active = True
        for actor in self.actors:
            if cbpi.cache.get("actors").get(actor).state == True:
                active = True
        if (self.slave_actor is not None) and (cbpi.cache.get("actors").get(self.slave_actor).state != active):
            if active == True:
                self.api.switch_actor_on(self.slave_actor)
            else:
                self.api.switch_actor_off(self.slave_actor)
  
  
    def set_power(self, power):
        if self.slave_actor is not None:
            self.api.actor_power(self.slave_actor, power=power)

    def on(self, power=None):
        print "Slave on"
        self.manual_on = True
        if self.slave_actor is not None:
            self.api.switch_actor_on(self.slave_actor)

    def off(self):
        print "Slave off"
        self.manual_on = False
class GPIODependentActor(ActorBase):
    base = Property.Actor(
        label="Base Actor",
        description="Select the actor you would like to add a dependency to.")
    dependent_gpio = Property.Select("Dependent GPIO",
                                     options=[
                                         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
                                         12, 13, 14, 15, 16, 17, 18, 19, 20,
                                         21, 22, 23, 24, 25, 26, 27
                                     ])
    dependency_type = Property.Select(
        label="Dependency Type",
        options=["HIGH", "LOW"],
        description=
        "Select the dependency type. With 'HIGH', the 'GPIO' is required to be HIGH in order to switch the 'Base Actor' ON. With 'LOW', the 'GPIO' is required to be LOW in order to switch the 'Base Actor' ON."
    )
    timeout = Property.Number(
        "Notification duration (ms)",
        True,
        5000,
        description="0ms will disable notifications completely")
    actor_shouldbeon = False
    actor_ison = False
    actor_flagbackground = False

    def init(self):
        GPIO.setup(int(self.dependent_gpio),
                   GPIO.IN,
                   pull_up_down=GPIO.PUD_DOWN)
        super(GPIODependentActor, self).init()
        cbpi.GPIODependentActors += [self]

    def set_power(self, power):
        self.api.actor_power(int(self.base), power=power)

    def off(self):
        self.api.switch_actor_off(int(self.base))
        self.actor_shouldbeon = False
        self.actor_ison = False

    def on(self, power=None):
        self.actor_shouldbeon = True
        if GPIO.input(int(self.dependent_gpio)) == 0:
            if self.dependency_type == "HIGH":
                if self.actor_ison:
                    self.api.switch_actor_off(int(self.base))
                    self.actor_ison = False
                    if self.timeout > 0.0:
                        self.api.notify(
                            "Actor turned off",
                            "Actor turned off because dependent PIN turned LOW",
                            type="warning",
                            timeout=self.timeout)
                elif not self.actor_flagbackground and self.timeout > 0.0:
                    self.api.notify(
                        "Actor not turned on",
                        "Actor was not turned on because dependent PIN is LOW",
                        type="warning",
                        timeout=self.timeout)
            elif self.dependency_type == "LOW":
                if not self.actor_ison:
                    self.api.switch_actor_on(int(self.base), power=power)
                    self.actor_ison = True
                    if self.actor_flagbackground and self.timeout > 0.0:
                        self.api.notify(
                            "Actor turned on",
                            "Actor turned on because dependent PIN turned LOW",
                            type="success",
                            timeout=self.timeout)
        elif GPIO.input(int(self.dependent_gpio)) == 1:
            if self.dependency_type == "HIGH":
                if not self.actor_ison:
                    self.api.switch_actor_on(int(self.base), power=power)
                    self.actor_ison = True
                    if self.actor_flagbackground and self.timeout > 0.0:
                        self.api.notify(
                            "Actor turned on",
                            "Actor turned on because dependent PIN turned HIGH",
                            type="success",
                            timeout=self.timeout)
            elif self.dependency_type == "LOW":
                if self.actor_ison:
                    self.api.switch_actor_off(int(self.base))
                    self.actor_ison = False
                    if self.timeout > 0.0:
                        self.api.notify(
                            "Actor turned off",
                            "Actor turned off because dependent PIN turned HIGH",
                            type="warning",
                            timeout=self.timeout)
                elif not self.actor_flagbackground and self.timeout > 0.0:
                    self.api.notify(
                        "Actor not turned on",
                        "Actor was not turned on because dependent PIN is HIGH",
                        type="warning",
                        timeout=self.timeout)
        self.actor_flagbackground = False
Exemple #9
0
class DependentActor(ActorBase):
    base = Property.Actor(
        label="Base Actor",
        description="Select the actor you would like to add a dependency to.")
    dependency_type = Property.Select(
        label="Dependency Type",
        options=["Restriction", "Prerequisite"],
        description=
        "Select the dependency type. With 'Restriction', the 'Actor Dependency' is required to be OFF in order to switch the 'Base Actor' ON. With 'Prerequisite', the 'Actor Dependency' is required to be ON in order to switch the 'Base Actor' ON."
    )
    dependency = Property.Actor(
        label="Actor Dependency",
        description="Select the actor that the base actor will depend upon.")
    timeout = Property.Number(
        "Notification duration (ms)",
        True,
        5000,
        description="0ms will disable notifications completely")

    def init(self):
        # Make sure the Base Actor is off
        self.api.switch_actor_off(int(self.base))
        # Hide Base Actor
        for idx, value in cbpi.cache["actors"].iteritems():
            if idx == int(self.base):
                value.hide = True
        # Synchronize current power setting with the Base Actor
        # TODO

    def set_power(self, power):
        self.api.actor_power(int(self.base), power=power)

    def off(self):
        self.api.switch_actor_off(int(self.base))

    def on(self, power=None):
        dependency_name = ""
        for idx, value in cbpi.cache["actors"].iteritems():
            if idx == int(self.dependency):
                dependency_name = value.name
        for idx, value in cbpi.cache["actors"].iteritems():
            if idx == int(self.dependency):
                if (value.state == 0) & (self.dependency_type
                                         == "Restriction"):
                    self.api.switch_actor_on(int(self.base), power=power)
                elif (value.state == 1) & (self.dependency_type
                                           == "Prerequisite"):
                    self.api.switch_actor_on(int(self.base), power=power)
                else:
                    self.api.switch_actor_off(int(self.base))
                    if self.timeout > 0.0:
                        self.api.notify(
                            headline="Powering of actor prevented",
                            message=
                            "This is due to the current power state of it's dependency, %s"
                            % (dependency_name),
                            timeout=self.timeout,
                            type="danger")
                    raise UserWarning(
                        "Powering of actor prevented by the state of it's dependency"
                    )
Exemple #10
0
class MQTTListenerControlActor(SensorActive):
    a_topic = Property.Text("Topic",
                            configurable=True,
                            default_value="",
                            description="MQTT TOPIC")
    b_payload = Property.Text(
        "Payload Dictioanry",
        configurable=True,
        default_value="",
        description="Where to find msg in patload, leave blank for raw payload"
    )
    c_unit = Property.Text("Unit",
                           configurable=True,
                           default_value="",
                           description="Units to display")
    base = Property.Actor(
        label="Base Actor",
        description="Select the actor you would like to control from MQTT.")

    last_value = None

    def init(self):
        self.topic = self.a_topic
        if self.b_payload == "":
            self.payload_text = None
        else:
            self.payload_text = self.b_payload.split('.')
        self.unit = self.c_unit[0:3]

        SensorActive.init(self)

        def on_message(client, userdata, msg):

            try:
                print "payload " + msg.payload
                json_data = json.loads(msg.payload)
                #print json_data
                print json_data
                val = json_data
                if self.payload_text is not None:
                    for key in self.payload_text:
                        val = val.get(key, None)
                #print val
                print val
                if isinstance(val, (int, float, basestring)):
                    q.put({"id": on_message.sensorid, "value": val})
            except Exception as e:
                print e

        on_message.sensorid = self.id
        self.api.cache["mqtt"].client.subscribe(self.topic)
        self.api.cache["mqtt"].client.message_callback_add(
            self.topic, on_message)

    def get_value(self):
        # Control base actor from MQTT.
        if (self.last_value == 0):
            self.api.switch_actor_off(int(self.base))
#                self.api.switch_actor_on(int(self.base), power=power)
        elif (self.last_value == 1):
            self.api.switch_actor_on(int(self.base))


#                self.api.switch_actor_on(int(self.base), power=power)
#        else:
#                self.api.switch_actor_off(int(self.base))

        return {"value": self.last_value, "unit": self.unit}

    def get_unit(self):
        return self.unit

    def stop(self):
        self.api.cache["mqtt"].client.unsubscribe(self.topic)
        SensorActive.stop(self)

    def execute(self):
        '''
        Active sensor has to handle his own loop
        :return:
        '''
        self.sleep(5)
Exemple #11
0
class MQTTListenerControlObject(SensorActive):
    #    a_topic = Property.Text("Topic", configurable=True, default_value="", description="MQTT TOPIC")
    a_topic = "cbpi/homebrewing/uuid/commands"
    b_payload = Property.Text(
        "Object payload",
        configurable=True,
        default_value="",
        description="Object in patload, e.g. pump, leave blank for raw payload"
    )
    base = Property.Actor(
        label="Base Actor",
        description="Select the actor you would like to control from MQTT.")

    #logfile
    f = open("gs.log", "w+")
    f.write("test\n")
    f.write(a_topic)
    f.write("\n")
    f.close()

    last_value = None

    def init(self):
        self.topic = self.a_topic
        if self.b_payload == "":
            self.payload_text = None
        else:
            self.payload_text = self.b_payload.split('.')
#            self.payload_text = self.b_payload
        SensorActive.init(self)

        def on_message(client, userdata, msg):

            try:
                print "payload " + msg.payload
                #                f.write("payload " + msg.payload\n)
                json_data = json.loads(msg.payload)
                #print json_data
                #		f.write(json_data\n)
                print json_data
                val = json_data
                if self.payload_text is not None:
                    for key in self.payload_text:
                        val = val.get(key, None)
                #print val
                print val
                if isinstance(val, (int, float, basestring)):
                    q.put({"id": on_message.sensorid, "value": val})
            except Exception as e:
                print e

        on_message.sensorid = self.id
        self.api.cache["mqtt"].client.subscribe(self.topic)
        self.api.cache["mqtt"].client.message_callback_add(
            self.topic, on_message)


#
#	f.close()

    def get_value(self):
        # Control base actor from MQTT.
        if (self.last_value == "off"):
            self.api.switch_actor_off(int(self.base))
        elif (self.last_value == "on"):
            self.api.switch_actor_on(int(self.base))

        return {"value": self.last_value}

    def get_unit(self):
        return self.unit

    def stop(self):
        self.api.cache["mqtt"].client.unsubscribe(self.topic)
        SensorActive.stop(self)

    def execute(self):
        '''
        Active sensor has to handle his own loop
        :return:
        '''

        #	f.close()

        self.sleep(5)
Exemple #12
0
class SimulatedFlowSensor(SensorActive):
    # properties
    a_flow_actor_prop = Property.Actor(
        "Actor", description="The actor this sensor responds to")
    a_flow_rate_prop = Property.Number("Flow Rate",
                                       configurable=True,
                                       default_value=2)
    b_display_prop = Property.Select("Display", options=["volume", "flow"])
    c_volume_units_prop = Property.Text("Volume Units",
                                        configurable=True,
                                        default_value="L",
                                        description="Can by anything")
    d_time_units_prop = Property.Select("Flow Time Units",
                                        options=["/s", "/m"])

    #-------------------------------------------------------------------------------
    def init(self):
        # convert properties to usable attributes
        try:
            self.flow_actor = int(self.a_flow_actor_prop)
            self.flow_rate = float(self.a_flow_rate_prop)
        except:
            self.flow_actor = None
            self.flow_rate = 0.0
        self.display_type = self.b_display_prop if self.b_display_prop else 'volume'
        self.time_units = str(self.d_time_units_prop)
        self.period_adjust = 1.0 / 60.0 if (self.d_time_units_prop
                                            == "/m") else 1.0
        self.volume_units = "Units" if self.c_volume_units_prop == "" else self.c_volume_units_prop
        self.flow_device = None

        # initialize
        self.reset_volume()
        SensorActive.init(self)

    #-------------------------------------------------------------------------------
    def execute(self):
        # at startup, wait for actors to initialze
        while cbpi.cache.get("actors") is None:
            self.sleep(5)
        self.flow_device = cbpi.cache.get("actors").get(self.flow_actor, None)

        # primary sensor loop
        while self.is_running():
            sensor_data = self.read_sensor_data()
            self.data_received("{:.2f}".format(sensor_data[self.display_type]))
            self.sleep(1.0)

    #-------------------------------------------------------------------------------
    def read_sensor_data(self):
        time_now = time.time()
        if self.flow_device and int(self.flow_device.state):
            # configured flow rate x actor power level
            flow = self.flow_rate * (float(self.flow_device.power) / 100.0)
            # increment by flow rate x elapsed time
            self._volume += flow * (time_now -
                                    self._time_last) * self.period_adjust
        else:
            flow = 0.0
        self._time_last = time_now
        return {'count': 0, 'flow': flow, 'volume': self._volume}

    #-------------------------------------------------------------------------------
    @cbpi.action("Reset Volume")
    def reset_volume(self):
        self._volume = 0.0
        self._time_last = time.time()

    #-------------------------------------------------------------------------------
    def get_unit(self):
        unit = self.volume_units
        if self.display_type == "flow":
            unit += self.time_units
        return unit
class RescaledActor(ActorBase):
    """An actor that wraps a base actor, and rescales the requested power
    linearly according to the min and max power properties.

    This allows you to set a maximum power output for an over powered heater
    or to set a minimum power output for something like a pump that stalls below
    a certain power setting.

    CraftBeerPi3 uses integers between 0 and 100 for the power settings for
    many actors, and so this plugin may cause quantization issues if the range
    between minimum and maximum power is small.
    """
    base = Property.Actor(label="Base Actor", description="Select the actor you would like to rescale")
    min_power = Property.Number("Minimum Power (%)", True, 0, description="The minimum output power of the actor when switched on. Use with caution on heaters!")
    max_power = Property.Number("Maximum Power (%)", True, 100, description="The maximum output power of the actor when switched on.")
    timeout = Property.Number("Notification duration (ms)", True, 5000, description="0ms will disable notifications completely")

    def init(self):
        # Where should we check that maximum is greater than minimum?
        # using set_power method for now, but it should be when min and max are set
        # on closing settings dialog
        pass

    def set_power(self, power):
        """Set the power as a percentage of the range between minimum and maximum power"""
        self.power = power
        self.api.actor_power(int(self.base), power=self.rescale_power(power))

    def rescale_power(self, power):
        """Calculate the rescaled power from the requested power"""
        # We carry out the maths in a standalone function so that on and set_power
        # can use it

        # If power supplied is None, return our own power, so that base actor is
        # controlled to our power. If our power hasn't been set yet, set it to 100.0
        if power is None:
            try:
                power = self.power
            except AttributeError:
                self.power = 100.
                power = 100.

        min_power = float(self.min_power)
        max_power = float(self.max_power)

        if min_power > max_power:
            self.api.notify(headline="Invalid Settings",
                message="Minium power is set to a value greater than the maximum power",
                timeout=self.timeout,
                type="danger")
            raise UserWarning("Minimum power is set to a value greater than maximum power")

        if min_power == max_power:
            raise UserWarning("Maximum and minimum power are equal")
            self.api.notify(headline="Invalid Settings",
                message="Minimum power is set equal to the maximum power",
                timeout=self.timeout,
                type="danger")
            raise UserWarning("Minimum power is set equal to maximum power")

        rescaled_power = min_power + (max_power - min_power)/100. * power

        return rescaled_power

    def off(self):
        """Switch the actor off"""
        self.api.switch_actor_off(int(self.base))

    def on(self, power=None):
        """Switch the actor on. Always set the power to the max_power or current power setting."""
        self.api.switch_actor_on(int(self.base), power=self.rescale_power(power))
class FunctionActor(ActorBase):
    global function_actor_ids

    #Properties
    a_output_actor = Property.Actor(
        "Slave Actor", description="Select an Actor to be controlled")
    b_on_delay = Property.Number("On Delay",
                                 configurable=True,
                                 default_value=0,
                                 description="On wait time in seconds")
    c_off_delay = Property.Number("Off Delay",
                                  configurable=True,
                                  default_value=0,
                                  description="Off wait time in seconds")
    d_cycle_delay = Property.Number(
        "Cycle Delay",
        configurable=True,
        default_value=0,
        description="Minimum time before next turn on in seconds")
    h_control_word = Property.Text(
        "Control Func",
        configurable=True,
        default_value="",
        description=
        "Control function executed when actor switches on, see Readme for more info"
    )

    trigger_sensor_a = Property.Sensor(
        "Trigger Sensor 1 (S1 or sensor)",
        description="Select a Sensor to be used as a trigger")
    trigger_sensor_b = Property.Sensor(
        "Trigger Sensor 2 (S2)",
        description="Select a Sensor to be used as a trigger")
    trigger_text = Property.Text(
        "Trigger Rule",
        configurable=True,
        default_value="True",
        description="Trigger eqation, use sensor as key word, eg sensor > 25")

    def init(self):
        try:
            cbpi.app.logger.info("Func Actor init")

            #guards and stored vals
            self.out = dict.fromkeys(
                [
                    "on", "req", "active", "im_on", "im_off", "no_force",
                    "last_on"
                ], False
            )  #on: slave state, active: actor state trig: actor is triggered req: slave on is requested
            self.power = 100

            #output timers
            time_now = datetime.utcnow()
            self.times = dict.fromkeys(["onoff", "cycle"], time_now)
            self.delay = {}
            self.delay["on"] = timedelta(seconds=tryfloat(self.b_on_delay))
            self.delay["off"] = timedelta(seconds=tryfloat(self.c_off_delay))
            self.delay["cycle"] = timedelta(
                seconds=tryfloat(self.d_cycle_delay))

            self.pulse = {
                "on_list": [],
                "off_list": [],
                "next": [],
                "loop": False
            }

            #remove 'ordering' letter
            self.control_word = self.h_control_word
            self.output_actor = self.a_output_actor

            #check for sensor and trigger config
            if (((isinstance(self.trigger_sensor_a, unicode)
                  and self.trigger_sensor_a) or
                 (isinstance(self.trigger_sensor_b, unicode)
                  and self.trigger_sensor_b))
                    and isinstance(self.trigger_text, unicode)
                    and self.trigger_text):

                self.trig = {"s1": None, "s2": None, "text": self.trigger_text}
                if isinstance(self.trigger_sensor_a,
                              unicode) and self.trigger_sensor_a:
                    self.trig["s1"] = self.trigger_sensor_a
                if isinstance(self.trigger_sensor_b,
                              unicode) and self.trigger_sensor_b:
                    self.trig["s2"] = self.trigger_sensor_b

                self.trig.update(
                    dict.fromkeys(["last", "im_on", "im_off", "type"], False))
            else:
                self.trig = None

            #check for control word config
            if isinstance(self.control_word, unicode) and self.control_word:
                self.control_word = self.decode_control_word()
            else:
                self.control_word = None

            #add actor to list to execute
            if not int(self.id) in function_actor_ids:
                function_actor_ids.append(int(self.id))
            self.api.switch_actor_off(int(self.output_actor))
            self.display_power(0)

        except Exception as e:
            print "Function init fail"
            traceback.print_exc()
            e.throw

    def decode_control_word(self):

        try:
            #pulse vars

            word_temp = self.control_word.replace("_", "")
            word_temp = word_temp.replace("(", "[")
            word_temp = word_temp.replace(")", "]")
            words_temp = word_temp.split()

            for word in words_temp:
                if word[0] == "P":  #Pulse command
                    print "On Pulse command"
                    self.pulse["on_list"] = tuple(eval(word[1:]))
                    self.pulse["loop"] = False
                elif word[0] == "p":  #Pulse command
                    print "Off Pulse command"
                    self.pulse["off_list"] = tuple(eval(word[1:]))
                elif word[0] == "L":  #Pulse command
                    print "Loop command"
                    self.pulse["on_list"] = tuple(eval(word[1:]))
                    self.pulse["loop"] = True
                elif word[0] == "R":  #Ramp command
                    print "On Ramp command not implemented"
                elif word[0] == "r":  #Ramp command
                    print "Off Ramp command not implemented"
                elif word == "trigSwitchActor":
                    self.trig["type"] = "Sw"
                elif word == "trigToggleActor":
                    self.trig["type"] = "Tog"
                elif word == "trigImOn":
                    self.trig["im_on"] = True
                elif word == "trigImOff":
                    self.trig["im_off"] = True
                elif word == "UiImOn":
                    self.out["im_on"] = True
                elif word == "UiImOff":
                    self.out["im_off"] = True
                elif word == "noForce":
                    self.out["no_force"] = True
                else:
                    print word
                    raise ValueError("Control word not valid")
        except Exception as e:
            print e
            cbpi.app.logger.error("Control Word not valid")
            return False
        return True

    def trigger_eval(self):
        #print "trigger"
        if self.trig["s1"]:
            sensor = tryfloat(cbpi.get_sensor_value(tryint(self.trig["s1"])))
        else:
            sensor = 0
        s1 = sensor
        if self.trig["s2"]:
            s2 = tryfloat(cbpi.get_sensor_value(tryint(self.trig["s2"])))
        else:
            s2 = 0
        on = self.out["active"]
        state = self.out["on"]
        off = not self.out["active"]
        trig_sig = bool(eval(self.trig["text"]))

        #based on trigger and immediate settings, enable or disable actor
        if trig_sig == True:
            if self.trig["last"] is False:
                if self.trig["type"] == "Tog":
                    pass  #toggle actor
                    self.update_self(self.power, "Tog")
                elif self.trig["type"] == "Sw":
                    pass  # switch actor on
                    self.update_self(self.power, True)
                if not self.trig["im_on"]:
                    self.times["onoff"] = datetime.utcnow() + self.delay["on"]
                self.trig["last"] = True
            return self.out["req"]
        else:
            if self.trig["last"] is True:
                if self.trig["type"] == "NTog":
                    pass  #toggle actor on negative switch
                elif self.trig["type"] == "Sw":
                    pass  # switch actor off
                    self.update_self(self.power, False)
                if not self.trig["im_off"]:
                    self.times["onoff"] = datetime.utcnow() + self.delay["off"]
                self.trig["last"] = False
            if self.trig["type"] is False:
                return False
            else:
                return self.out["req"]

        #should not get here
        print "Failure: should not be here"
        return False

    def execute_func(self):

        #evaluate trigger if setup was valid
        if self.trig is not None:
            trigger = self.trigger_eval()
        else:
            trigger = self.out["req"]

        #evalute active condition
        right_now = datetime.utcnow()
        if trigger != self.out["active"]:
            if (right_now >= self.times["onoff"]) and (
                (right_now >= self.times["cycle"]) or not trigger):
                self.out["active"] = trigger
                self.out["on"] = trigger
                if trigger:
                    self.pulse["next"] = list(self.pulse["on_list"])
                else:
                    self.pulse["next"] = list(self.pulse["off_list"])
                if len(self.pulse["next"]) > 0:
                    self.times["pulse"] = right_now + timedelta(
                        seconds=tryfloat(self.pulse["next"][0]))

        #set output_actor and change func actor power displayed
        if ((cbpi.cache.get("actors").get(int(self.output_actor)).state !=
             self.out["on"]) or (self.out["no_force"] == True)):
            if ((self.out["no_force"] == False)
                    or (self.out["on"] != self.out["last_on"])):
                self.out["last_on"] = self.out["on"]
                if self.out["on"] == True:
                    self.api.switch_actor_on(int(self.output_actor),
                                             power=self.power)
                    self.display_power(self.power)
                else:
                    self.api.switch_actor_off(int(self.output_actor))
                    self.display_power(0)

        # overwrite displayed power as Zero if slave actor is off
        if self.out["on"] == False and cbpi.cache.get("actors").get(
                int(self.id)).power != 0:
            self.display_power(0)

        #evalute output pulsing
        if len(self.pulse["next"]) > 0:
            if right_now > self.times["pulse"]:
                self.out["on"] = not self.out["on"]
                del self.pulse["next"][0]
                if len(self.pulse["next"]) == 0:
                    if self.pulse["loop"] and self.out["active"]:
                        self.pulse["next"] = list(self.pulse["on_list"])
                if len(self.pulse["next"]) > 0:
                    self.times["pulse"] = right_now + timedelta(
                        seconds=tryfloat(self.pulse["next"][0]))

        else:
            if not self.out["active"]:
                self.out["on"] = False
                if self.out["last_on"]:
                    self.times["cycle"] = right_now + self.delay["cycle"]

    def on(self, power=None):
        if power is not None:
            self.power = power

        if self.out["req"] is False:
            self.out["req"] = True
            if self.out["im_on"] is False:
                self.times["onoff"] = datetime.utcnow() + self.delay["on"]

    def off(self):
        if self.out["req"] == True:
            self.out["req"] = False
            if self.out["im_off"] is False:
                self.times["onoff"] = datetime.utcnow() + self.delay["off"]

    def set_power(self, power=None):
        if power is not None:
            self.power = power
        self.api.actor_power(int(self.output_actor), power=self.power)

    def update_self(self, pwr, state):
        actor = cbpi.cache.get("actors").get(int(self.id))
        actor.power = pwr
        if state == "Tog":
            state = not actor.state
        if actor.state != state:
            actor.state = state
            self.out["req"] = state
            cbpi.emit("SWITCH_ACTOR", actor)

    def display_power(self, pwr):
        actor = cbpi.cache.get("actors").get(int(self.id))
        actor.power = pwr
        cbpi.emit("SWITCH_ACTOR", actor)