def handle_measurement(self, parent, meas): """ eval a measurement value, see what actions, if any, it will trigger args: - the Action instance that is our parent - a Measurement instance returns: None """ now = datetime.datetime.utcnow().replace(second=0, microsecond=0) trigger = None if parent.triggers: trigger = parent.triggers[0] def make_trigger(): closed = now + datetime.timedelta(minutes=self.on_minutes) if parent.sleep_minutes: closed = closed + datetime.timedelta( minutes=parent.sleep_minutes) opts = { 'action_id': parent.id, 'created': now, 'closed': closed, } t = Trigger(**opts) db_session.add(t) db_session.commit() if not trigger and eval_condition( meas.value, " ".join( ('value', self.on_condition, self.on_value))): oc = OutletController() success = oc.turn_on(self.outlet) if success: make_trigger() # create an action that our ActionRouter handler will recognize # to switch the outlet off at a future time data = {'outlet': {'state': 0}} data['outlet'].update(self.outlet) future_time = now + datetime.timedelta(minutes=self.on_minutes) sa = SingularAction( utc_runtime=future_time, action=json.dumps(data), ) db_session.add(sa) db_session.commit() return
def post(self): """Accept post data to switch outlet state to 1 (on) or 0 (off).""" data, errors = GenericOutletSchema().load(request.get_json()) if errors: return errors, 400 oc = OutletController() result = oc.switch_outlet(data) if result: return data, 200 else: return {'msg': 'failed to switch outlet'}, 500
def html_interface(self): """ Return html data used by web gui to present and validate input data. Each element must have an ID that is like "plugin_" + attribute_name The MVC Controller function that handles the form must strip the plugin_ prefix from the id names as required. args: - none returns: str: html data raises: none """ oc = OutletController() outlets = oc.available_outlets() conditions = [('lt', 'less than'), ('gt', 'greater than')] template = Template(""" <div class="row"> Outlet <select id="plugin_outlet"> {% for o in outlets %} <option value={{ o | tojson }}>{{ o['name'] }}</option> {% endfor %} </select> </div> <div class="row"> ON Condition <select id="plugin_on_condition"> {% for c in conditions %} <option value="{{ c[0] }}">{{ c[1] }}</option> {% endfor %} </select> ON Value <input type="text" id="plugin_on_threshold"> </div> <div class="row"> OFF Condition <select id="plugin_off_condition"> {% for c in conditions %} <option value="{{ c[0] }}">{{ c[1] }}</option> {% endfor %} </select> OFF Value <input type="text" id="plugin_off_threshold"> </div> """) return template.render(outlets=outlets, conditions=conditions)
def interface(self): """Return JSON descriptor of input interface.""" oc = OutletController() outlets = oc.available_outlets() conditions = [('lt', 'less than'), ('gt', 'greater than')] data = [ {'outlet': { 'type': 'select', 'choices': outlets, 'required': True, 'label': 'Outlet', 'id': 'plugin_outlet', } }, {'on_condition': { 'type': 'select', 'choices': conditions, 'required': True, 'label': 'On Condition', 'id': 'plugin_on_condition', }, 'on_value': { 'type': 'int', 'required': True, 'label': 'On Value', 'id': 'plugin_on_value' } }, {'off_condition': { 'type': 'select', 'choices': conditions, 'required': True, 'label': 'Off Condition', 'id': 'plugin_off_condition', }, 'off_value': { 'type': 'int', 'required': True, 'label': 'Off Value', 'id': 'plugin_off_value', } } ] return json.dumps(data)
def handle_measurement(self, parent, meas): """ Eval a measurement value, see what actions, if any, it will trigger args: - the Action instance that is our parent - a Measurement instance returns: a dict of action details, or None """ logger.debug("handling measurement {}, {}".format(parent, meas)) now = datetime.datetime.utcnow().replace(second=0, microsecond=0) trigger = None if parent.triggers: trigger = parent.triggers[0] def make_trigger(): opts = { 'action_id': parent.id, 'created': now, } if parent.sleep_minutes: opts['closed'] = now + datetime.timedelta(minutes=parent.sleep_minutes) t = Trigger(**opts) db_session.add(t) db_session.commit() if eval_condition(meas.value, " ".join(('value', self.on_condition, self.on_value))): logger.debug("turning outlet '{}' ON".format(self.outlet)) oc = OutletController() result = oc.turn_on(self.outlet) # create a trigger only if action was successful if result: if trigger is None: make_trigger() return if eval_condition(meas.value, " ".join(('value', self.off_condition, self.off_value))): logger.debug("turning outlet '{}' OFF".format(self.outlet)) oc = OutletController() result = oc.turn_off(self.outlet) if result and trigger and trigger.closed == None: trigger.closed = now db_session.commit() return
from flask import Blueprint, request, current_app from flask_restful import Api, Resource from flask_jwt_extended import jwt_required from potnanny_core.models.outlet import OutletController, Outlet from potnanny_core.models.wireless import WirelessInterface from potnanny_core.schemas.outlet import GenericOutletSchema, OutletSchema bp = Blueprint('outlet_api', __name__, url_prefix='/api/1.0/outlets') api = Api(bp) oc = OutletController() class OutletListApi(Resource): """Class to interface with Generic Power Outlets.""" @jwt_required def get(self): """Get list of all available outlets.""" results = oc.available_outlets() if not results: return {'msg': 'no outlets found'}, 404 data, errors = GenericOutletSchema(many=True).load(results) if errors: return errors, 400 return data, 200 @jwt_required def post(self):