Skip to content

Commit

Permalink
Add set_custom_option/get_custom_option to Conditionals (kizniche#901)…
Browse files Browse the repository at this point in the history
…, fix Conditional sample_rate not being set from Config
  • Loading branch information
kizniche committed Dec 22, 2020
1 parent 5b8e6eb commit be0b35f
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 34 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- Fix ADS1015 and ADS1115 inputs only measuring channel 0 ([#911](https://github.com/kizniche/mycodo/issues/911))
- Fix install of pyusb dependency of Adafruit_Extended_Bus ([#863](https://github.com/kizniche/mycodo/issues/863))
- Fix Message and New Line options in Custom Options
- Fix Conditional sample_rate not being set from Config

### Features

Expand All @@ -33,6 +34,7 @@
- Add configurable link for navbar brand link
- Add User option to Shell Command Function Action
- Add Message and New Line options to Custom Options of Outputs
- Add set_custom_option/get_custom_option to Conditionals ([#901](https://github.com/kizniche/mycodo/issues/901))

### Miscellaneous

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Add custom_options to function tables
Revision ID: 706a32b64ba2
Revises: 313a6fb99082
Create Date: 2020-12-22 15:11:42.441917
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '706a32b64ba2'
down_revision = '313a6fb99082'
branch_labels = None
depends_on = None


def upgrade():
with op.batch_alter_table("conditional") as batch_op:
batch_op.add_column(sa.Column('custom_options', sa.Text))

op.execute(
'''
UPDATE conditional
SET custom_options=''
'''
)


def downgrade():
with op.batch_alter_table("conditional") as batch_op:
batch_op.drop_column('custom_options')
2 changes: 1 addition & 1 deletion mycodo/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from config_translations import TRANSLATIONS

MYCODO_VERSION = '8.8.8'
ALEMBIC_VERSION = '313a6fb99082'
ALEMBIC_VERSION = '706a32b64ba2'

# FORCE_UPGRADE_MASTER
# Set True to enable upgrading to the master branch of the Mycodo repository.
Expand Down
86 changes: 86 additions & 0 deletions mycodo/controllers/base_conditional.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# coding=utf-8
"""
This module contains the AbstractConditional Class which acts as a template
for all Conditionals. It is not to be used directly. The AbstractConditional Class
ensures that certain methods and instance variables are included in each
Conditional.
All Conditionals should inherit from this class and overwrite methods that raise
NotImplementedErrors
"""
import json

from mycodo.mycodo_client import DaemonControl

control = DaemonControl()
from mycodo.config import SQL_DATABASE_MYCODO
from mycodo.databases.models import Conditional
from mycodo.databases.utils import session_scope
from mycodo.utils.database import db_retrieve_table_daemon

MYCODO_DB_PATH = 'sqlite:///' + SQL_DATABASE_MYCODO


class AbstractConditional:
"""
Base Conditional class that ensures certain methods and values are present
in Conditionals.
"""
def __init__(self, logger, function_id, message):
self.logger = logger
self.function_id = function_id
self.variables = {}
self.message = message
self.running = True

def run_all_actions(self, message=None):
if message is None:
message = self.message
self.message = control.trigger_all_actions(self.function_id, message=message)

def run_action(self, action_id, message=None):
if message is None:
message = self.message
self.message = control.trigger_action(action_id, message=message, single_action=True)

@staticmethod
def condition(condition_id):
return control.get_condition_measurement(condition_id)

@staticmethod
def condition_dict(condition_id):
string_sets = control.get_condition_measurement_dict(condition_id)
if string_sets:
list_ts_values = []
for each_set in string_sets.split(';'):
ts_value = each_set.split(',')
list_ts_values.append({'time': ts_value[0], 'value': float(ts_value[1])})
return list_ts_values
return None

def stop_conditional(self):
self.running = False

def set_custom_option(self, option, value):
try:
with session_scope(MYCODO_DB_PATH) as new_session:
mod_cond = new_session.query(Conditional).filter(
Conditional.unique_id == self.function_id).first()
try:
dict_custom_options = json.loads(mod_cond.custom_options)
except:
dict_custom_options = {}
dict_custom_options[option] = value
mod_cond.custom_options = json.dumps(dict_custom_options)
new_session.commit()
except Exception:
self.logger.exception("set_custom_option")

def get_custom_option(self, option):
conditional = db_retrieve_table_daemon(Conditional, unique_id=self.function_id)
try:
dict_custom_options = json.loads(conditional.custom_options)
except:
dict_custom_options = {}
if option in dict_custom_options:
return dict_custom_options[option]
2 changes: 1 addition & 1 deletion mycodo/controllers/base_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __init__(self, ready, unique_id=None, name=__name__):
self.thread_startup_timer = timeit.default_timer()
self.running = False
self.thread_shutdown_timer = 0
self.sample_rate = 30
self.sample_rate = 10
self.ready = ready

logger_name = "{}".format(name)
Expand Down
6 changes: 6 additions & 0 deletions mycodo/controllers/controller_conditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from mycodo.databases.models import Actions
from mycodo.databases.models import Conditional
from mycodo.databases.models import ConditionalConditions
from mycodo.databases.models import Misc
from mycodo.utils.conditional import save_conditional_code
from mycodo.utils.database import db_retrieve_table_daemon

Expand Down Expand Up @@ -63,6 +64,8 @@ def __init__(self, ready, unique_id):
self.conditional_statement = None
self.timer_period = None
self.file_run = None
self.sample_rate = None
self.time_conditional = None
self.conditional_run = None

def loop(self):
Expand Down Expand Up @@ -95,6 +98,9 @@ def initialize_variables(self):
self.log_level_debug = cond.log_level_debug
self.message_include_code = cond.message_include_code

self.sample_rate = db_retrieve_table_daemon(
Misc, entry='first').sample_rate_controller_conditional

self.set_log_level_debug(self.log_level_debug)

now = time.time()
Expand Down
2 changes: 2 additions & 0 deletions mycodo/databases/models/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class Conditional(CRUDMixin, db.Model):
start_offset = db.Column(db.Float, default=10.0)
message_include_code = db.Column(db.Boolean, default=False)

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


class ConditionalConditions(CRUDMixin, db.Model):
__tablename__ = "conditional_data"
Expand Down
10 changes: 8 additions & 2 deletions mycodo/inputs/base_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,14 +295,20 @@ def set_custom_option(self, option, value):
with session_scope(MYCODO_DB_PATH) as new_session:
mod_input = new_session.query(Input).filter(
Input.unique_id == self.unique_id).first()
dict_custom_options = json.loads(mod_input.custom_options)
try:
dict_custom_options = json.loads(mod_input.custom_options)
except:
dict_custom_options = {}
dict_custom_options[option] = value
mod_input.custom_options = json.dumps(dict_custom_options)
new_session.commit()
except Exception:
self.logger.exception("set_custom_option")

def get_custom_option(self, option):
dict_custom_options = json.loads(self.input_dev.custom_options)
try:
dict_custom_options = json.loads(self.input_dev.custom_options)
except:
dict_custom_options = {}
if option in dict_custom_options:
return dict_custom_options[option]
29 changes: 29 additions & 0 deletions mycodo/outputs/base_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
NotImplementedErrors
"""
import datetime
import json
import logging
import threading
import time
Expand All @@ -18,13 +19,18 @@
from sqlalchemy import or_

from mycodo.abstract_base_controller import AbstractBaseController
from mycodo.config import SQL_DATABASE_MYCODO
from mycodo.databases.models import Output
from mycodo.databases.models import OutputChannel
from mycodo.databases.models import Trigger
from mycodo.databases.utils import session_scope
from mycodo.mycodo_client import DaemonControl
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import write_influxdb_value
from mycodo.utils.outputs import output_types

MYCODO_DB_PATH = 'sqlite:///' + SQL_DATABASE_MYCODO


class AbstractOutput(AbstractBaseController):
"""
Expand Down Expand Up @@ -671,3 +677,26 @@ def output_state(self, output_channel):
return 'on'
else:
return 'off'

def set_custom_option(self, option, value):
try:
with session_scope(MYCODO_DB_PATH) as new_session:
mod_output = new_session.query(Output).filter(
Output.unique_id == self.unique_id).first()
try:
dict_custom_options = json.loads(mod_output.custom_options)
except:
dict_custom_options = {}
dict_custom_options[option] = value
mod_output.custom_options = json.dumps(dict_custom_options)
new_session.commit()
except Exception:
self.logger.exception("set_custom_option")

def get_custom_option(self, option):
try:
dict_custom_options = json.loads(self.output.custom_options)
except:
dict_custom_options = {}
if option in dict_custom_options:
return dict_custom_options[option]
33 changes: 4 additions & 29 deletions mycodo/utils/conditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,20 @@
pre_statement_run = """import os
import sys
sys.path.append(os.path.abspath('/var/mycodo-root'))
from mycodo.controllers.base_conditional import AbstractConditional
from mycodo.mycodo_client import DaemonControl
control = DaemonControl()
class ConditionalRun:
class ConditionalRun(AbstractConditional):
def __init__(self, logger, function_id, message):
super(ConditionalRun, self).__init__(logger, function_id, message)
self.logger = logger
self.function_id = function_id
self.variables = {}
self.message = message
self.running = True
def run_all_actions(self, message=None):
if message is None:
message = self.message
self.message = control.trigger_all_actions(self.function_id, message=message)
def run_action(self, action_id, message=None):
if message is None:
message = self.message
self.message = control.trigger_action(action_id, message=message, single_action=True)
@staticmethod
def condition(condition_id):
return control.get_condition_measurement(condition_id)
@staticmethod
def condition_dict(condition_id):
string_sets = control.get_condition_measurement_dict(condition_id)
if string_sets:
list_ts_values = []
for each_set in string_sets.split(';'):
ts_value = each_set.split(',')
list_ts_values.append({'time': ts_value[0], 'value': float(ts_value[1])})
return list_ts_values
return None
def stop_conditional(self):
self.running = False
def conditional_code_run(self):
"""

Expand Down
2 changes: 1 addition & 1 deletion mycodo/utils/function_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ def action_output_value(cond_action, message):
ch=channel_id,
id=this_output.id,
name=this_output.name,
val=cond_action.do_output_pwm)
val=cond_action.do_output_amount)

output_on = threading.Thread(
target=control.output_on,
Expand Down

0 comments on commit be0b35f

Please sign in to comment.