Exemple #1
0
class Conditional(CRUDMixin, db.Model):
    __tablename__ = "conditional"

    id = db.Column(db.Integer, unique=True, primary_key=True)
    name = db.Column(db.Text, default='Conditional Name')
    conditional_type = db.Column(db.Text, default=None)
    is_activated = db.Column(db.Boolean, default=False)
    sensor_id = db.Column(db.Integer, db.ForeignKey('sensor.id'),
                          default=None)  # Which sensor does this belong?

    # Relay options
    if_relay_id = db.Column(db.Integer,
                            db.ForeignKey('relay.id'),
                            default=None)  # Watch this relay for action
    if_relay_state = db.Column(db.Text,
                               default='')  # What action to watch relay for
    if_relay_duration = db.Column(db.Float, default=0.0)

    # Sensor options
    if_sensor_period = db.Column(db.Float, default=60.0)
    if_sensor_measurement = db.Column(
        db.Text, default='')  # which measurement to monitor
    if_sensor_edge_select = db.Column(
        db.Text,
        default='edge')  # monitor Rising, Falling, or Both switch edges
    if_sensor_edge_detected = db.Column(db.Text, default='rising')
    if_sensor_gpio_state = db.Column(db.Boolean, default=True)
    if_sensor_direction = db.Column(db.Text,
                                    default='')  # 'above' or 'below' setpoint
    if_sensor_setpoint = db.Column(db.Float, default=0.0)
Exemple #2
0
class ConditionalActions(CRUDMixin, db.Model):
    __tablename__ = "conditional_data"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    conditional_id = db.Column(db.Integer,
                               db.ForeignKey('relay.id'),
                               default=None)

    # Actions
    do_action = db.Column(
        db.Text, default=''
    )  # what action, such as 'email', 'execute command', 'flash LCD'
    do_action_string = db.Column(
        db.Text, default='')  # string, such as the email address or command
    do_relay_id = db.Column(db.Integer,
                            db.ForeignKey('relay.id'),
                            default=None)
    do_relay_state = db.Column(db.Text, default='')  # 'on' or 'off'
    do_relay_duration = db.Column(db.Float, default=0.0)

    do_camera_id = db.Column(db.Integer, db.ForeignKey('lcd.id'), default=None)
    do_camera_duration = db.Column(db.Float, default=0.0)
    do_lcd_id = db.Column(db.Integer, db.ForeignKey('lcd.id'), default=None)
    do_pid_id = db.Column(db.Integer, db.ForeignKey('pid.id'), default=None)

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #3
0
class PID(CRUDMixin, db.Model):
    __tablename__ = "pid"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)  # ID for influxdb entries
    name = db.Column(db.Text, default='PID')

    # PID Controller
    is_activated = db.Column(db.Boolean, default=False)
    is_held = db.Column(db.Boolean, default=False)
    is_paused = db.Column(db.Boolean, default=False)
    is_preset = db.Column(db.Boolean,
                          default=False)  # Is config saved as a preset?
    preset_name = db.Column(db.Text, default='')  # Name for preset
    period = db.Column(db.Float, default=30.0)
    max_measure_age = db.Column(db.Float, default=120.0)
    measurement = db.Column(
        db.Text, default='')  # What condition is the controller regulating?
    direction = db.Column(
        db.Text,
        default='raise')  # Direction of regulation (raise, lower, both)
    setpoint = db.Column(db.Float, default=30.0)  # PID setpoint
    band = db.Column(db.Float, default=0)  # PID hysteresis band
    p = db.Column(db.Float, default=1.0)  # Kp gain
    i = db.Column(db.Float, default=0.0)  # Ki gain
    d = db.Column(db.Float, default=0.0)  # Kd gain
    integrator_min = db.Column(db.Float, default=-100.0)
    integrator_max = db.Column(db.Float, default=100.0)
    raise_output_id = db.Column(db.String,
                                db.ForeignKey('output.unique_id'),
                                default=None)  # Output to raise the condition
    raise_min_duration = db.Column(db.Float, default=0.0)
    raise_max_duration = db.Column(db.Float, default=0.0)
    raise_min_off_duration = db.Column(db.Float, default=0.0)
    lower_output_id = db.Column(db.String,
                                db.ForeignKey('output.unique_id'),
                                default=None)  # Output to lower the condition
    lower_min_duration = db.Column(db.Float, default=0.0)
    lower_max_duration = db.Column(db.Float, default=0.0)
    lower_min_off_duration = db.Column(db.Float, default=0.0)
    store_lower_as_negative = db.Column(db.Boolean, default=True)

    # Setpoint tracking
    method_id = db.Column(db.String,
                          db.ForeignKey('method.unique_id'),
                          default='')
    method_start_time = db.Column(db.Text, default=None)
    method_end_time = db.Column(db.Text, default=None)

    # Autotune
    autotune_activated = db.Column(db.Boolean, default=False)
    autotune_noiseband = db.Column(db.Float, default=0.5)
    autotune_outstep = db.Column(db.Float, default=10.0)

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #4
0
class MethodData(CRUDMixin, db.Model):
    __tablename__ = "method_data"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String, nullable=False, unique=True, default=set_uuid)
    method_id = db.Column(db.String, db.ForeignKey('method.unique_id'), default=None)
    time_start = db.Column(db.Text, default=None)
    time_end = db.Column(db.Text, default=None)
    duration_sec = db.Column(db.Float, default=None)
    duration_end = db.Column(db.Float, default=None)
    output_id = db.Column(db.String, db.ForeignKey('output.unique_id'), default=None)
    output_state = db.Column(db.Text, default=None)
    output_duration = db.Column(db.Float, default=None)
    setpoint_start = db.Column(db.Float, default=None)
    setpoint_end = db.Column(db.Float, default=None)
    amplitude = db.Column(db.Float, default=None)
    frequency = db.Column(db.Float, default=None)
    shift_angle = db.Column(db.Float, default=None)
    shift_y = db.Column(db.Float, default=None)
    x0 = db.Column(db.Float, default=None)
    y0 = db.Column(db.Float, default=None)
    x1 = db.Column(db.Float, default=None)
    y1 = db.Column(db.Float, default=None)
    x2 = db.Column(db.Float, default=None)
    y2 = db.Column(db.Float, default=None)
    x3 = db.Column(db.Float, default=None)
    y3 = db.Column(db.Float, default=None)
    linked_method_id = db.Column(db.String, db.ForeignKey('method.unique_id'), default=None)

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #5
0
class Conditional(CRUDMixin, db.Model):
    __tablename__ = "conditional"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    name = db.Column(db.Text, default='Conditional Name')
    conditional_type = db.Column(db.Text, default=None)
    is_activated = db.Column(db.Boolean, default=False)

    # TODO: Make one variable 'unique_id' instead of non-unique ID, in next major version
    sensor_id = db.Column(db.Integer, db.ForeignKey('sensor.id'), default=None)  # Which sensor does this belong?
    math_id = db.Column(db.Integer, db.ForeignKey('math.id'), default=None)  # Which sensor does this belong?

    # Relay options
    if_relay_id = db.Column(db.Integer, db.ForeignKey('relay.id'), default=None)  # Watch this relay for action
    if_relay_state = db.Column(db.Text, default='')  # What action to watch relay for
    if_relay_duration = db.Column(db.Float, default=0.0)

    # Sensor/Math options
    # TODO: Make variable names more generic in next major version change sensor->measurement
    if_sensor_period = db.Column(db.Float, default=60.0)
    if_sensor_refractory_period = db.Column(db.Float, default=0.0)
    if_sensor_measurement = db.Column(db.Text, default='')  # which measurement to monitor
    if_sensor_max_age = db.Column(db.Integer, default=120.0)  # max age of the measurement
    if_sensor_edge_detected = db.Column(db.Text, default='')
    if_sensor_direction = db.Column(db.Text, default='')  # 'above' or 'below' setpoint
    if_sensor_setpoint = db.Column(db.Float, default=0.0)

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
class MethodData(CRUDMixin, db.Model):
    __tablename__ = "method_data"
    id = db.Column(db.Integer, unique=True, primary_key=True)
    method_id = db.Column(db.Integer, db.ForeignKey('method.id'), default=None)
    time_start = db.Column(db.Text, default=None)
    time_end = db.Column(db.Text, default=None)
    duration_sec = db.Column(db.Float, default=None)
    relay_id = db.Column(db.Integer, db.ForeignKey('relay.id'), default=None)
    relay_state = db.Column(db.Text, default=None)
    relay_duration = db.Column(db.Float, default=None)
    setpoint_start = db.Column(db.Float, default=None)
    setpoint_end = db.Column(db.Float, default=None)
    amplitude = db.Column(db.Float, default=None)
    frequency = db.Column(db.Float, default=None)
    shift_angle = db.Column(db.Float, default=None)
    shift_y = db.Column(db.Float, default=None)
    x0 = db.Column(db.Float, default=None)
    y0 = db.Column(db.Float, default=None)
    x1 = db.Column(db.Float, default=None)
    y1 = db.Column(db.Float, default=None)
    x2 = db.Column(db.Float, default=None)
    y2 = db.Column(db.Float, default=None)
    x3 = db.Column(db.Float, default=None)
    y3 = db.Column(db.Float, default=None)

    def __reper__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #7
0
class LCDData(CRUDMixin, db.Model):
    __tablename__ = "lcd_data"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    lcd_id = db.Column(db.Integer, db.ForeignKey('lcd.id'), default=None)
    line_1_id = db.Column(db.Text, default='')
    line_1_type = db.Column(db.Text, default='')
    line_1_measurement = db.Column(db.Text, default='')
    line_1_max_age = db.Column(db.Integer, default=360)
    line_1_decimal_places = db.Column(db.Integer, default=2)
    line_2_id = db.Column(db.Text, default='')
    line_2_type = db.Column(db.Text, default='')
    line_2_measurement = db.Column(db.Text, default='')
    line_2_max_age = db.Column(db.Integer, default=360)
    line_2_decimal_places = db.Column(db.Integer, default=2)
    line_3_id = db.Column(db.Text, default='')
    line_3_type = db.Column(db.Text, default='')
    line_3_measurement = db.Column(db.Text, default='')
    line_3_max_age = db.Column(db.Integer, default=360)
    line_3_decimal_places = db.Column(db.Integer, default=2)
    line_4_id = db.Column(db.Text, default='')
    line_4_type = db.Column(db.Text, default='')
    line_4_measurement = db.Column(db.Text, default='')
    line_4_max_age = db.Column(db.Integer, default=360)
    line_4_decimal_places = db.Column(db.Integer, default=2)

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
class User(UserMixin, CRUDMixin, db.Model):
    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.VARCHAR(64), unique=True, index=True)
    password_hash = db.Column(db.VARCHAR(255))
    email = db.Column(db.VARCHAR(64), unique=True, index=True)
    role = db.Column(db.Integer, db.ForeignKey('roles.id'), default=None)
    theme = db.Column(db.VARCHAR(64))

    roles = db.relationship("Role", back_populates="user")

    def __repr__(self):
        output = "<User: <name='{name}', email='{email}' is_admin='{isadmin}'>"
        return output.format(name=self.name,
                             email=self.email,
                             isadmin=bool(self.role == 1))

    def set_password(self, new_password):
        """ saves a password hash  """
        self.password_hash = bcrypt.hashpw(new_password.encode('utf-8'),
                                           bcrypt.gensalt())

    @staticmethod
    def check_password(password, hashed_password):
        """ validates a password """
        hashes_match = bcrypt.hashpw(password.encode('utf-8'),
                                     hashed_password.encode('utf-8'))
        return hashes_match
Exemple #9
0
class DeviceMeasurements(CRUDMixin, db.Model):
    __tablename__ = "device_measurements"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)

    name = db.Column(db.Text, default='')
    device_type = db.Column(db.Text, default=None)
    device_id = db.Column(db.Text, default=None)

    # Default measurement/unit
    is_enabled = db.Column(db.Boolean, default=True)
    measurement = db.Column(db.Text, default='')
    measurement_type = db.Column(db.Text, default='')
    unit = db.Column(db.Text, default='')
    channel = db.Column(db.Integer, default=None)

    # Rescale measurement
    invert_scale = db.Column(db.Boolean, default=False)
    rescaled_measurement = db.Column(db.Text, default='')
    rescaled_unit = db.Column(db.Text, default='')
    scale_from_min = db.Column(db.Float, default=0)
    scale_from_max = db.Column(db.Float, default=10)
    scale_to_min = db.Column(db.Float, default=0)
    scale_to_max = db.Column(db.Float, default=20)

    conversion_id = db.Column(db.Text,
                              db.ForeignKey('conversion.unique_id'),
                              default='')
Exemple #10
0
class ConditionalConditions(CRUDMixin, db.Model):
    __tablename__ = "conditional_data"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)
    conditional_id = db.Column(db.String,
                               db.ForeignKey('conditional.unique_id'),
                               default=None)
    condition_type = db.Column(db.Text, default=None)

    # Sensor/Math
    measurement = db.Column(db.Text,
                            default='')  # which measurement to monitor
    max_age = db.Column(db.Integer, default=120)  # max age of the measurement

    # GPIO State
    gpio_pin = db.Column(db.Integer, default=0)

    # Output State
    output_id = db.Column(db.Text, default='')

    # Controller
    controller_id = db.Column(db.Text, default='')

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #11
0
class PID(CRUDMixin, db.Model):
    __tablename__ = "pid"

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)  # ID for influxdb entries
    name = db.Column(db.Text, default='PID')
    is_activated = db.Column(db.Boolean, default=False)
    is_held = db.Column(db.Boolean, default=False)
    is_paused = db.Column(db.Boolean, default=False)
    is_preset = db.Column(db.Boolean,
                          default=False)  # Is config saved as a preset?
    preset_name = db.Column(db.Text, default='')  # Name for preset
    period = db.Column(db.Float, default=30.0)
    max_measure_age = db.Column(db.Float, default=120.0)
    measurement = db.Column(
        db.Text, default='')  # What condition is the controller regulating?
    direction = db.Column(
        db.Text,
        default='Raise')  # Direction of regulation (raise, lower, both)
    setpoint = db.Column(db.Float, default=30.0)  # PID setpoint
    method_id = db.Column(db.Integer, db.ForeignKey('method.id'), default=None)
    method_start_time = db.Column(db.Text, default=None)
    method_end_time = db.Column(db.Text, default=None)
    p = db.Column(db.Float, default=1.0)  # Kp gain
    i = db.Column(db.Float, default=0.0)  # Ki gain
    d = db.Column(db.Float, default=0.0)  # Kd gain
    integrator_min = db.Column(db.Float, default=-100.0)
    integrator_max = db.Column(db.Float, default=100.0)
    raise_relay_id = db.Column(db.Integer,
                               db.ForeignKey('relay.id'),
                               default=None)  # Output to raise the condition
    raise_min_duration = db.Column(db.Float, default=0.0)
    raise_max_duration = db.Column(db.Float, default=0.0)
    raise_min_off_duration = db.Column(db.Float, default=0.0)
    lower_relay_id = db.Column(db.Integer,
                               db.ForeignKey('relay.id'),
                               default=None)  # Output to lower the condition
    lower_min_duration = db.Column(db.Float, default=0.0)
    lower_max_duration = db.Column(db.Float, default=0.0)
    lower_min_off_duration = db.Column(db.Float, default=0.0)

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #12
0
class LCDData(CRUDMixin, db.Model):
    __tablename__ = "lcd_data"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String, nullable=False, unique=True, default=set_uuid)
    lcd_id = db.Column(db.String, db.ForeignKey('lcd.unique_id'), default=None)

    line_1_id = db.Column(db.Text, default='')
    line_1_text = db.Column(db.Text, default='Text to display')
    line_1_measurement = db.Column(db.Text, default='')
    line_1_max_age = db.Column(db.Integer, default=360)
    line_1_decimal_places = db.Column(db.Integer, default=2)

    line_2_id = db.Column(db.Text, default='')
    line_2_text = db.Column(db.Text, default='Text to display')
    line_2_measurement = db.Column(db.Text, default='')
    line_2_max_age = db.Column(db.Integer, default=360)
    line_2_decimal_places = db.Column(db.Integer, default=2)

    line_3_id = db.Column(db.Text, default='')
    line_3_text = db.Column(db.Text, default='Text to display')
    line_3_measurement = db.Column(db.Text, default='')
    line_3_max_age = db.Column(db.Integer, default=360)
    line_3_decimal_places = db.Column(db.Integer, default=2)

    line_4_id = db.Column(db.Text, default='')
    line_4_text = db.Column(db.Text, default='Text to display')
    line_4_measurement = db.Column(db.Text, default='')
    line_4_max_age = db.Column(db.Integer, default=360)
    line_4_decimal_places = db.Column(db.Integer, default=2)

    line_5_id = db.Column(db.Text, default='')
    line_5_text = db.Column(db.Text, default='Text to display')
    line_5_measurement = db.Column(db.Text, default='')
    line_5_max_age = db.Column(db.Integer, default=360)
    line_5_decimal_places = db.Column(db.Integer, default=2)

    line_6_id = db.Column(db.Text, default='')
    line_6_text = db.Column(db.Text, default='Text to display')
    line_6_measurement = db.Column(db.Text, default='')
    line_6_max_age = db.Column(db.Integer, default=360)
    line_6_decimal_places = db.Column(db.Integer, default=2)

    line_7_id = db.Column(db.Text, default='')
    line_7_text = db.Column(db.Text, default='Text to display')
    line_7_measurement = db.Column(db.Text, default='')
    line_7_max_age = db.Column(db.Integer, default=360)
    line_7_decimal_places = db.Column(db.Integer, default=2)

    line_8_id = db.Column(db.Text, default='')
    line_8_text = db.Column(db.Text, default='Text to display')
    line_8_measurement = db.Column(db.Text, default='')
    line_8_max_age = db.Column(db.Integer, default=360)
    line_8_decimal_places = db.Column(db.Integer, default=2)

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #13
0
class EnergyUsage(CRUDMixin, db.Model):
    __tablename__ = "energy_usage"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String, nullable=False, unique=True, default=set_uuid)  # ID for influxdb entries
    name = db.Column(db.Text, default='Name')
    device_id = db.Column(db.Text, default='')
    measurement_id = db.Column(db.Text, db.ForeignKey('device_measurements.unique_id'), default='')
Exemple #14
0
class User(UserMixin, CRUDMixin, db.Model):
    __tablename__ = "users"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)
    name = db.Column(db.VARCHAR(64), unique=True, index=True)
    password_hash = db.Column(db.VARCHAR(255))
    code = db.Column(db.Integer, default=None)
    api_key = db.Column(db.BLOB, unique=True)
    email = db.Column(db.VARCHAR(64), unique=True, index=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'), default=None)
    theme = db.Column(db.VARCHAR(64))
    landing_page = db.Column(db.Text, default='live')
    index_page = db.Column(db.Text, default='landing')
    language = db.Column(
        db.Text,
        default=None)  # Force the web interface to use a specific language
    password_reset_code = db.Column(db.Text, default=None)
    password_reset_code_expiration = db.Column(db.DateTime, default=None)
    password_reset_last_request = db.Column(db.DateTime, default=None)

    # roles = db.relationship("Role", back_populates="user")

    def __repr__(self):
        output = "<User: <name='{name}', email='{email}' is_admin='{isadmin}'>"
        return output.format(name=self.name,
                             email=self.email,
                             isadmin=bool(self.role_id == 1))

    def set_password(self, new_password):
        """saves a password hash  """
        if isinstance(new_password, str):
            new_password = new_password.encode('utf-8')
        self.password_hash = bcrypt.hashpw(new_password, bcrypt.gensalt())

    @staticmethod
    def check_password(password, hashed_password):
        """validates a password."""
        # Check type of password hashed_password to determine if it is a str
        # and should be encoded
        if isinstance(password, str):
            password = password.encode('utf-8')
        if isinstance(hashed_password, str):
            hashed_password = hashed_password.encode('utf-8')

        hashes_match = bcrypt.hashpw(password, hashed_password)
        return hashes_match
Exemple #15
0
class Camera(CRUDMixin, db.Model):
    __tablename__ = "camera"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)
    name = db.Column(db.Text, unique=True, nullable=False)
    library = db.Column(db.Text, nullable=False)
    device = db.Column(db.Text, nullable=False, default='/dev/video0')
    opencv_device = db.Column(db.Integer, default=0)
    hflip = db.Column(db.Boolean, default=False)  # Horizontal flip image
    vflip = db.Column(db.Boolean, default=False)  # Vertical flip image
    rotation = db.Column(db.Integer, default=0)  # Rotation degree (0-360)
    height = db.Column(db.Integer, default=480)
    width = db.Column(db.Integer, default=640)
    brightness = db.Column(db.Float, default=None)
    contrast = db.Column(db.Float, default=None)
    exposure = db.Column(db.Float, default=None)
    gain = db.Column(db.Float, default=None)
    hue = db.Column(db.Float, default=None)
    saturation = db.Column(db.Float, default=0.3)
    white_balance = db.Column(db.Float, default=0.0)
    custom_options = db.Column(db.Text, default='')
    output_id = db.Column(db.String,
                          db.ForeignKey('output.unique_id'),
                          default=None)  # Turn output on during capture
    output_duration = db.Column(db.Float, default=3.0)
    cmd_pre_camera = db.Column(db.Text,
                               default='')  # Command to execute before capture
    cmd_post_camera = db.Column(db.Text,
                                default='')  # Command to execute after capture
    stream_started = db.Column(db.Boolean, default=False)
    timelapse_started = db.Column(db.Boolean, default=False)
    timelapse_paused = db.Column(db.Boolean, default=False)
    timelapse_start_time = db.Column(db.Float, default=None)
    timelapse_end_time = db.Column(db.Float, default=None)
    timelapse_interval = db.Column(db.Float, default=None)
    timelapse_next_capture = db.Column(db.Float, default=None)
    timelapse_capture_number = db.Column(db.Integer, default=None)
    path_still = db.Column(db.Text, default='')
    path_timelapse = db.Column(db.Text, default='')
    path_video = db.Column(db.Text, default='')

    def __repr__(self):
        return "<{cls}(id={s.id}, name='{s.name}', library='{s.library}')>".format(
            s=self, cls=self.__class__.__name__)
Exemple #16
0
class ConditionalActions(CRUDMixin, db.Model):
    __tablename__ = "conditional_data"

    id = db.Column(db.Integer, unique=True, primary_key=True)
    conditional_id = db.Column(db.Integer,
                               db.ForeignKey('relay.id'),
                               default=None)

    # Actions
    do_action = db.Column(
        db.Text, default=''
    )  # what action, such as 'email', 'execute command', 'flash LCD'
    do_action_string = db.Column(
        db.Text, default='')  # string, such as the email address or command
    do_relay_id = db.Column(db.Integer,
                            db.ForeignKey('relay.id'),
                            default=None)
    do_relay_state = db.Column(db.Text, default='')  # 'on' or 'off'
    do_relay_duration = db.Column(db.Float, default=0.0)

    do_camera_id = db.Column(db.Integer, db.ForeignKey('lcd.id'), default=None)
    do_camera_duration = db.Column(db.Float, default=0.0)
    do_lcd_id = db.Column(db.Integer, db.ForeignKey('lcd.id'), default=None)
    do_pid_id = db.Column(db.Integer, db.ForeignKey('pid.id'), default=None)
class Timer(CRUDMixin, db.Model):
    __tablename__ = "timer"

    id = db.Column(db.Integer, unique=True, primary_key=True)
    name = db.Column(db.Text, default='Timer')
    is_activated = db.Column(db.Boolean, default=False)
    timer_type = db.Column(db.Text, default=None)
    relay_id = db.Column(db.Integer, db.ForeignKey('relay.id'), default=None)
    state = db.Column(db.Text, default=None)  # 'on' or 'off'
    time_start = db.Column(db.Text, default=None)
    time_end = db.Column(db.Text, default=None)
    duration_on = db.Column(db.Float, default=None)
    duration_off = db.Column(db.Float, default=None)

    def __reper__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #18
0
class Camera(CRUDMixin, db.Model):
    __tablename__ = "camera"

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)
    name = db.Column(db.Text, unique=True, nullable=False)
    camera_type = db.Column(db.Text, nullable=False)
    library = db.Column(db.Text, nullable=False)
    opencv_device = db.Column(db.Integer, default=0)
    hflip = db.Column(db.Boolean, default=False)  # Horizontal flip image
    vflip = db.Column(db.Boolean, default=False)  # Vertical flip image
    rotation = db.Column(db.Integer, default=0)  # Rotation degree (0-360)
    height = db.Column(db.Integer, default=640)
    width = db.Column(db.Integer, default=480)
    brightness = db.Column(db.Float, default=0.75)
    contrast = db.Column(db.Float, default=0.2)
    exposure = db.Column(db.Float, default=0.0)
    gain = db.Column(db.Float, default=0.0)
    hue = db.Column(db.Float, default=0.0)
    saturation = db.Column(db.Float, default=0.3)
    white_balance = db.Column(db.Float, default=0.0)
    relay_id = db.Column(db.Integer, db.ForeignKey('relay.id'),
                         default=None)  # Turn relay on during capture
    cmd_pre_camera = db.Column(db.Text,
                               default='')  # Command to execute before capture
    cmd_post_camera = db.Column(db.Text,
                                default='')  # Command to execute after capture
    stream_started = db.Column(db.Boolean, default=False)
    timelapse_started = db.Column(db.Boolean, default=False)
    timelapse_paused = db.Column(db.Boolean, default=False)
    timelapse_start_time = db.Column(db.Float, default=None)
    timelapse_end_time = db.Column(db.Float, default=None)
    timelapse_interval = db.Column(db.Float, default=None)
    timelapse_next_capture = db.Column(db.Float, default=None)
    timelapse_capture_number = db.Column(db.Integer, default=None)

    def __reper__(self):
        return "<{cls}(id={s.id}, name='{s.name}', camera_type='{s.camera_type}')>".format(
            s=self, cls=self.__class__.__name__)
Exemple #19
0
class Timer(CRUDMixin, db.Model):
    __tablename__ = "timer"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    name = db.Column(db.Text, default='Timer')
    is_activated = db.Column(db.Boolean, default=False)
    timer_type = db.Column(db.Text, default=None)
    method_id = db.Column(
        db.Integer, default=None)  # TODO: Add ForeignKey in next major release
    method_start_time = db.Column(db.Text, default=None)
    method_end_time = db.Column(db.Text, default=None)
    method_period = db.Column(db.Float, default=None)
    relay_id = db.Column(db.Integer, db.ForeignKey('relay.id'), default=None)
    state = db.Column(db.Text, default=None)  # 'on' or 'off'
    time_start = db.Column(db.Text, default=None)
    time_end = db.Column(db.Text, default=None)
    duration_on = db.Column(db.Float, default=None)
    duration_off = db.Column(db.Float, default=None)

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #20
0
class Input(CRUDMixin, db.Model):
    __tablename__ = "input"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)
    name = db.Column(db.Text, default='Input Name')
    is_activated = db.Column(db.Boolean, default=False)
    log_level_debug = db.Column(db.Boolean, default=False)
    is_preset = db.Column(db.Boolean,
                          default=False)  # Is config saved as a preset?
    preset_name = db.Column(db.Text, default=None)  # Name for preset
    device = db.Column(
        db.Text, default='')  # Device name, such as DHT11, DHT22, DS18B20
    interface = db.Column(
        db.Text, default=None)  # Communication interface (I2C, UART, etc.)
    period = db.Column(db.Float, default=15.0)  # Duration between readings
    start_offset = db.Column(db.Float, default=0.0)
    power_output_id = db.Column(db.String, default=None)
    resolution = db.Column(db.Integer, default=0)
    resolution_2 = db.Column(db.Integer, default=0)
    sensitivity = db.Column(db.Integer, default=0)
    thermocouple_type = db.Column(db.Text, default=None)
    ref_ohm = db.Column(db.Integer, default=None)
    calibrate_sensor_measure = db.Column(
        db.Text, default=None)  # sensor ID and measurement (CSV)

    location = db.Column(
        db.Text,
        default='')  # GPIO pin or i2c address to communicate with sensor
    gpio_location = db.Column(
        db.Integer, default=None)  # Pin location for GPIO communication

    # I2C
    i2c_location = db.Column(
        db.Text, default=None)  # Address location for I2C communication
    i2c_bus = db.Column(db.Integer,
                        default=1)  # I2C bus the sensor is connected to

    # FTDI
    ftdi_location = db.Column(
        db.Text, default=None)  # Device location for FTDI communication

    # Communication (SPI)
    uart_location = db.Column(
        db.Text, default=None)  # Device location for UART communication
    baud_rate = db.Column(db.Integer,
                          default=None)  # Baud rate for UART communication
    pin_clock = db.Column(db.Integer, default=None)
    pin_cs = db.Column(db.Integer, default=None)
    pin_mosi = db.Column(db.Integer, default=None)
    pin_miso = db.Column(db.Integer, default=None)

    # Communication (Bluetooth)
    bt_adapter = db.Column(db.Text, default='hci0')

    # Switch options
    switch_edge = db.Column(db.Text, default='rising')
    switch_bouncetime = db.Column(db.Integer, default=50)
    switch_reset_period = db.Column(db.Integer, default=10)

    # Pre-measurement output options
    pre_output_id = db.Column(
        db.String, db.ForeignKey('output.unique_id'),
        default=None)  # Output to turn on before sensor read
    pre_output_duration = db.Column(
        db.Float, default=0.0)  # Duration to turn output on before sensor read
    pre_output_during_measure = db.Column(db.Boolean, default=True)

    # SHT sensor options
    sht_voltage = db.Column(db.Text, default='3.5')

    # Analog to digital converter options
    adc_gain = db.Column(db.Integer, default=1)
    adc_resolution = db.Column(db.Integer, default=18)
    adc_sample_speed = db.Column(db.Text, default='')

    # Command options
    cmd_command = db.Column(db.Text, default=None)

    # PWM and RPM options
    weighting = db.Column(db.Float, default=0.0)
    rpm_pulses_per_rev = db.Column(db.Float, default=1.0)
    sample_time = db.Column(db.Float, default=2.0)

    # Server options
    port = db.Column(db.Integer, default=80)
    times_check = db.Column(db.Integer, default=1)
    deadline = db.Column(db.Integer, default=2)

    # The Things Network: Data Storage
    datetime = db.Column(db.DateTime, default=None)

    custom_options = db.Column(db.Text, default='')

    def is_active(self):
        """
        :return: Whether the sensor is currently activated
        :rtype: bool
        """
        return self.is_activated

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #21
0
class Sensor(CRUDMixin, db.Model):
    __tablename__ = "sensor"

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)  # ID for influxdb entries
    name = db.Column(db.Text, default='Sensor')
    is_activated = db.Column(db.Boolean, default=False)
    is_preset = db.Column(db.Boolean,
                          default=False)  # Is config saved as a preset?
    preset_name = db.Column(db.Text, default=None)  # Name for preset
    device = db.Column(
        db.Text, default='')  # Device name, such as DHT11, DHT22, DS18B20
    interface = db.Column(
        db.Text, default=None)  # Communication interface (I2C, UART, etc.)
    device_loc = db.Column(
        db.Text, default=None)  # Device location for UART communication
    calibrate_sensor_measure = db.Column(
        db.Text, default=None)  # sensor ID and measurement (CSV)
    baud_rate = db.Column(db.Integer,
                          default=None)  # Baud rate for UART communication
    period = db.Column(db.Float, default=15.0)  # Duration between readings
    i2c_bus = db.Column(db.Integer,
                        default='')  # I2C bus the sensor is connected to
    location = db.Column(
        db.Text,
        default='')  # GPIO pin or i2c address to communicate with sensor
    power_relay_id = db.Column(db.Integer,
                               db.ForeignKey('relay.id'),
                               default=None)  # Relay to power sensor
    measurements = db.Column(db.Text,
                             default='')  # Measurements separated by commas
    resolution = db.Column(db.Integer, default=0)
    sensitivity = db.Column(db.Integer, default=0)

    # Multiplexer options
    multiplexer_address = db.Column(db.Text, default=None)
    multiplexer_bus = db.Column(db.Integer, default=1)
    multiplexer_channel = db.Column(db.Integer, default=0)

    # Switch options
    switch_edge = db.Column(db.Text, default='rising')
    switch_bouncetime = db.Column(db.Integer, default=50)
    switch_reset_period = db.Column(db.Integer, default=10)

    # Pre-measurement relay options
    pre_relay_id = db.Column(
        db.Integer, db.ForeignKey('relay.id'),
        default=None)  # Relay to turn on before sensor read
    pre_relay_duration = db.Column(
        db.Float, default=0.0)  # Duration to turn relay on before sensor read

    # SHT sensor options
    sht_clock_pin = db.Column(db.Integer, default=0)
    sht_voltage = db.Column(db.Text, default='3.5')

    # Analog to digital converter options
    adc_channel = db.Column(db.Integer, default=0)
    adc_gain = db.Column(db.Integer, default=1)
    adc_resolution = db.Column(db.Integer, default=18)
    adc_measure = db.Column(db.Text, default='Condition')
    adc_measure_units = db.Column(db.Text, default='unit')
    adc_volts_min = db.Column(db.Float, default=None)
    adc_volts_max = db.Column(db.Float, default=None)
    adc_units_min = db.Column(db.Float, default=0)
    adc_units_max = db.Column(db.Float, default=10)

    def is_active(self):
        """
        :return: Whether the sensor is currently activated
        :rtype: bool
        """
        return self.is_activated

    def __reper__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #22
0
class Output(CRUDMixin, db.Model):
    __tablename__ = "output"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)  # ID for influxdb entries
    output_type = db.Column(
        db.Text, default='wired'
    )  # Options: 'command', 'wired', 'wireless_rpi_rf', 'pwm'
    output_mode = db.Column(db.Text, default=None)
    interface = db.Column(db.Text, default='')
    location = db.Column(db.Text, default='')
    i2c_bus = db.Column(db.Integer, default=None)
    baud_rate = db.Column(db.Integer, default=None)
    name = db.Column(db.Text, default='Output')
    measurement = db.Column(db.Text, default=None)
    unit = db.Column(db.Text, default=None)
    conversion_id = db.Column(db.Text,
                              db.ForeignKey('conversion.unique_id'),
                              default='')
    channel = db.Column(db.Integer, default=None)
    pin = db.Column(db.Integer,
                    default=None)  # Pin connected to the device/output
    on_state = db.Column(
        db.Boolean,
        default=True)  # GPIO output to turn output on (True=HIGH, False=LOW)
    amps = db.Column(
        db.Float,
        default=0.0)  # The current drawn by the device connected to the output
    on_until = db.Column(
        db.DateTime,
        default=None)  # Stores time to turn off output (if on for a duration)
    off_until = db.Column(
        db.DateTime, default=None)  # Stores time the output can turn on again
    last_duration = db.Column(
        db.Float, default=None)  # Stores the last on duration (seconds)
    on_duration = db.Column(
        db.Boolean,
        default=None)  # Stores if the output is currently on for a duration
    protocol = db.Column(db.Integer, default=None)
    pulse_length = db.Column(db.Integer, default=None)
    on_command = db.Column(db.Text, default=None)
    off_command = db.Column(db.Text, default=None)
    pwm_command = db.Column(db.Text, default=None)
    trigger_functions_at_start = db.Column(db.Boolean, default=True)

    state_startup = db.Column(db.Text, default=None)
    startup_value = db.Column(db.Float, default=0)
    state_shutdown = db.Column(db.Text, default=None)
    shutdown_value = db.Column(db.Float, default=0)

    # PWM
    pwm_hertz = db.Column(db.Integer, default=None)  # PWM Hertz
    pwm_library = db.Column(db.Text, default=None)  # Library to produce PWM
    pwm_invert_signal = db.Column(
        db.Boolean, default=False)  # 90% duty cycle would become 10%

    # Atlas EZO-PMP
    flow_rate = db.Column(db.Float, default=None)  # example: ml per minute

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)

    def _is_setup(self):
        """
        This function checks to see if the GPIO pin is setup and ready to use.  This is for safety
        and to make sure we don't blow anything.

        # TODO Make it do that.

        :return: Is it safe to manipulate this output?
        :rtype: bool
        """
        if self.output_type == 'wired' and self.pin:
            self.setup_pin()
            return True

    def setup_pin(self):
        """
        Setup pin for this output

        :rtype: None
        """
        try:
            from RPi import GPIO
            GPIO.setmode(GPIO.BCM)
            GPIO.setwarnings(True)
            GPIO.setup(self.pin, GPIO.OUT)
        except:
            print("RPi.GPIO and Raspberry Pi required for this action")

    def is_on(self):
        """
        :return: Whether the output is currently "ON"
        :rtype: bool
        """
        if self.output_type == 'wired' and self._is_setup():
            return self.on_state == GPIO.input(self.pin)
Exemple #23
0
class Input(CRUDMixin, db.Model):
    __tablename__ = "input"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)
    name = db.Column(db.Text, default='Input Name')
    is_activated = db.Column(db.Boolean, default=False)
    is_preset = db.Column(db.Boolean,
                          default=False)  # Is config saved as a preset?
    preset_name = db.Column(db.Text, default=None)  # Name for preset
    device = db.Column(
        db.Text, default='')  # Device name, such as DHT11, DHT22, DS18B20
    interface = db.Column(
        db.Text, default=None)  # Communication interface (I2C, UART, etc.)
    device_loc = db.Column(
        db.Text, default=None)  # Device location for UART communication
    calibrate_sensor_measure = db.Column(
        db.Text, default=None)  # sensor ID and measurement (CSV)
    baud_rate = db.Column(db.Integer,
                          default=None)  # Baud rate for UART communication
    period = db.Column(db.Float, default=15.0)  # Duration between readings
    i2c_bus = db.Column(db.Integer,
                        default='')  # I2C bus the sensor is connected to
    location = db.Column(
        db.Text,
        default='')  # GPIO pin or i2c address to communicate with sensor
    power_output_id = db.Column(db.String, default=None)
    measurements = db.Column(db.Text,
                             default='')  # Measurements separated by commas
    resolution = db.Column(db.Integer, default=0)
    sensitivity = db.Column(db.Integer, default=0)
    thermocouple_type = db.Column(db.Text, default=None)
    ref_ohm = db.Column(db.Integer, default=None)
    convert_to_unit = db.Column(db.Text, default='')

    # Communication (SPI)
    pin_clock = db.Column(db.Integer, default=None)
    pin_cs = db.Column(db.Integer, default=None)
    pin_mosi = db.Column(db.Integer, default=None)
    pin_miso = db.Column(db.Integer, default=None)

    # Switch options
    switch_edge = db.Column(db.Text, default='rising')
    switch_bouncetime = db.Column(db.Integer, default=50)
    switch_reset_period = db.Column(db.Integer, default=10)

    # Pre-measurement output options
    pre_output_id = db.Column(
        db.String, db.ForeignKey('output.unique_id'),
        default=None)  # Output to turn on before sensor read
    pre_output_duration = db.Column(
        db.Float, default=0.0)  # Duration to turn output on before sensor read
    pre_output_during_measure = db.Column(db.Boolean, default=True)

    # SHT sensor options
    sht_voltage = db.Column(db.Text, default='3.5')

    # Analog to digital converter options
    adc_channel = db.Column(db.Integer, default=0)
    adc_gain = db.Column(db.Integer, default=1)
    adc_resolution = db.Column(db.Integer, default=18)
    adc_measure = db.Column(db.Text, default=None)
    adc_measure_units = db.Column(db.Text, default=None)
    adc_volts_min = db.Column(db.Float, default=None)
    adc_volts_max = db.Column(db.Float, default=None)
    adc_units_min = db.Column(db.Float, default=0.0)
    adc_units_max = db.Column(db.Float, default=10)
    adc_inverse_unit_scale = db.Column(db.Boolean, default=False)

    # Command options
    cmd_command = db.Column(db.Text, default=None)
    cmd_measurement = db.Column(db.Text, default=None)
    cmd_measurement_units = db.Column(db.Text, default=None)

    # PWM and RPM options
    weighting = db.Column(db.Float, default=0.0)
    rpm_pulses_per_rev = db.Column(db.Float, default=1.0)
    sample_time = db.Column(db.Float, default=2.0)

    # Server options
    port = db.Column(db.Integer, default=80)
    times_check = db.Column(db.Integer, default=1)
    deadline = db.Column(db.Integer, default=2)

    def is_active(self):
        """
        :return: Whether the sensor is currently activated
        :rtype: bool
        """
        return self.is_activated

    def __repr__(self):
        return "<{cls}(id={s.id})>".format(s=self, cls=self.__class__.__name__)
Exemple #24
0
class Camera(CRUDMixin, db.Model):
    __tablename__ = "camera"
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, unique=True, primary_key=True)
    unique_id = db.Column(db.String,
                          nullable=False,
                          unique=True,
                          default=set_uuid)
    name = db.Column(db.Text, unique=True, nullable=False)
    library = db.Column(db.Text, nullable=False)
    device = db.Column(db.Text, nullable=False, default='/dev/video0')
    opencv_device = db.Column(db.Integer, default=0)
    hflip = db.Column(db.Boolean, default=False)  # Horizontal flip image
    vflip = db.Column(db.Boolean, default=False)  # Vertical flip image
    rotation = db.Column(db.Integer, default=0)  # Rotation degree (0-360)
    brightness = db.Column(db.Float, default=0)
    contrast = db.Column(db.Float, default=0)
    exposure = db.Column(db.Float, default=None)
    gain = db.Column(db.Float, default=None)
    hue = db.Column(db.Float, default=None)
    saturation = db.Column(db.Float, default=0)
    white_balance = db.Column(db.Float, default=0.0)
    custom_options = db.Column(db.Text, default='')
    output_id = db.Column(db.String,
                          db.ForeignKey('output.unique_id'),
                          default=None)  # Turn output on during capture
    output_duration = db.Column(db.Float, default=3.0)
    cmd_pre_camera = db.Column(db.Text,
                               default='')  # Command to execute before capture
    cmd_post_camera = db.Column(db.Text,
                                default='')  # Command to execute after capture
    stream_started = db.Column(db.Boolean, default=False)
    hide_still = db.Column(db.Boolean, default=False)
    hide_timelapse = db.Column(db.Boolean, default=False)
    url_still = db.Column(db.Text, default='')
    url_stream = db.Column(db.Text, default='')
    show_preview = db.Column(db.Boolean, default=False)
    output_format = db.Column(db.Text, default=None)

    # Timelapse
    timelapse_started = db.Column(db.Boolean, default=False)
    timelapse_paused = db.Column(db.Boolean, default=False)
    timelapse_start_time = db.Column(db.Float, default=None)
    timelapse_end_time = db.Column(db.Float, default=None)
    timelapse_interval = db.Column(db.Float, default=None)
    timelapse_next_capture = db.Column(db.Float, default=None)
    timelapse_capture_number = db.Column(db.Integer, default=None)
    timelapse_last_file = db.Column(db.Text, default=None)
    timelapse_last_ts = db.Column(db.Float, default=None)

    # Still tracking
    still_last_file = db.Column(db.Text, default=None)
    still_last_ts = db.Column(db.Float, default=None)

    # Paths
    path_still = db.Column(db.Text, default='')
    path_timelapse = db.Column(db.Text, default='')
    path_video = db.Column(db.Text, default='')

    # Resolutions and stream
    width = db.Column(db.Integer, default=1024)
    height = db.Column(db.Integer, default=768)
    resolution_stream_width = db.Column(db.Integer, default=1024)
    resolution_stream_height = db.Column(db.Integer, default=768)
    stream_fps = db.Column(db.Integer, default=5)

    # picamera options  # TODO: Change to generic variable names next major release
    picamera_shutter_speed = db.Column(db.Integer, default=0)
    picamera_sharpness = db.Column(db.Integer, default=0)
    picamera_iso = db.Column(db.Integer, default=0)
    picamera_awb = db.Column(db.Text, default='auto')
    picamera_awb_gain_red = db.Column(db.Float, default=0.5)
    picamera_awb_gain_blue = db.Column(db.Float, default=0.5)
    picamera_exposure_mode = db.Column(db.Text, default='auto')
    picamera_meter_mode = db.Column(db.Text, default='average')
    picamera_image_effect = db.Column(db.Text, default='none')

    def __repr__(self):
        return "<{cls}(id={s.id}, name='{s.name}', library='{s.library}')>".format(
            s=self, cls=self.__class__.__name__)