class IndexController(FlaskView): interface = featureBroker.RequiredFeature( 'entityInterfaces', featureBroker.HasMethods('getCommand', 'getButtons')) commander = featureBroker.RequiredFeature( 'commander', featureBroker.HasMethods('runCommand')) route_base = '/' @route('/favicon.ico') def favicon(self): return send_from_directory(os.path.join(app.web.root_path, 'static', 'images'), 'favicon.ico', mimetype='image/vnd.microsoft.icon') @route('/') def index(self): """Renders the home page.""" return render_template('index.html', title='Power', buttons=self.interface.getButtons(), year=datetime.now().year) @route('/code/<code>/send', methods=['POST']) def codeSend(self, code): """Send a command.""" drivers.rf.send([int(code)]) return "{}", 200 @route('/button/<button_ref>/<command_ref>', methods=['POST']) def button(self, button_ref, command_ref): """Processes a button request.""" command = self.interface.getCommand(button_name=button_ref, command_name=command_ref) if (command == None): try: command = self.interface.getCommand(button_id=int(button_ref), command_name=command_ref) except: command = None if (command == None): try: command = self.interface.getCommand( button_id=int(button_ref), command_id=int(command_ref)) except: command = None if (command == None): try: command = self.interface.getCommand( button_name=button_ref, command_id=int(command_ref)) except: command = None if (command == None): return abort(400) # Find Code self.commander.runCommand(command) return "{}", 200
def runCommand(jobId, commandId, deleteWhenDone): # Load Necessary Components interface = featureBroker.RequiredFeature('entityInterfaces', featureBroker.HasMethods('getCommand')).result commander = featureBroker.RequiredFeature('commander', featureBroker.HasMethods('runCommand')).result # Find command and run it command = interface.getCommand(command_id = commandId) if (command != None): commander.runCommand(command) # Delete when done? if (deleteWhenDone): scheduler = featureBroker.RequiredFeature('scheduler').result scheduler.remove_job(jobId)
class ScheduleController(FlaskView): route_base = '/schedule/' interface = featureBroker.RequiredFeature( 'entityInterfaces', featureBroker.HasMethods('getCommand')) scheduledCommands = featureBroker.RequiredFeature( 'scheduledCommands', featureBroker.HasMethods('scheduleSingleCommand')) @route('/button/<button_ref>/<command_ref>', methods=['POST']) def scheduleCommand(self, button_ref, command_ref): """Processes a button request.""" # Get Command command = self.interface.getCommand(button_name=button_ref, command_name=command_ref) if (command == None): try: command = self.interface.getCommand(button_id=int(button_ref), command_name=command_ref) except: command = None if (command == None): try: command = self.interface.getCommand( button_id=int(button_ref), command_id=int(command_ref)) except: command = None if (command == None): try: command = self.interface.getCommand( button_name=button_ref, command_id=int(command_ref)) except: command = None if (command == None): return abort(400) # Get JSON data from post jsonData = request.get_json(force=True) # Get Hours/Min from time in body time = jsonData['time'].split(':') if (len(time) != 2): return abort(400) hour = time[0] min = time[1] # Schedule Command self.scheduledCommands.scheduleSingleCommand( command, 'cron', jsonData['deleteWhenDone'], hour=hour, minute=min) return "{}", 200
class AutoLight(featureBroker.Component): interface = featureBroker.RequiredFeature('entityInterfaces', featureBroker.HasMethods('getButtons')) config = featureBroker.RequiredFeature('conf_AutoLight') commander = featureBroker.RequiredFeature('commander', featureBroker.HasMethods('runCommand')) def __init__(self, *args, **kwargs): self.triggered = False self._jobName = 'AutoLight' self._scheduler = None self.triggered = False self.log = logging.getLogger('AutoLight') return super(AutoLight, self).__init__(*args, **kwargs) def disabler(self): self.log.info("AutoLight is being disabled") self._scheduler.pause_job(self._jobName+' Checker') if self.triggered: self.runCommands('disable') def enabler(self): self.log.info("AutoLight is being enabled") self.triggered = False; self._scheduler.resume_job(self._jobName+' Checker') self.checkLight() def register(self, scheduler): self._scheduler = scheduler # Schedule jobs self._scheduler.add_job(self.enabler, 'cron', id=self._jobName+' Enabler', hour=int(self.config['enablehour']), minute=int(self.config['enablemin']), max_instances=1) self._scheduler.add_job(self.disabler, 'cron', id=self._jobName+' Disabler', hour=int(self.config['disablehour']), minute=int(self.config['disablemin']), max_instances=1) self._scheduler.add_job(self.checkLight, 'interval', id=self._jobName+' Checker', minutes=1, next_run_time=None, max_instances=1) def checkLight(self): try: # Get Lux Value lux = self.getLux() # Check Lighting if ((lux != None) and (lux < int(self.config['luxlimit']))): self.log.info('AutoLight is in Valid Range (Lux = {lux}).'.format(lux=lux)) self.triggered = True self._scheduler.pause_job(self._jobName+' Checker') self.runCommands('enable') except Exception, e: self.log.exception(e)
class ScheduledCommands(featureBroker.Component): scheduler = featureBroker.RequiredFeature('scheduler') def __init__(self, *args, **kwargs): return super(ScheduledCommands, self).__init__(*args, **kwargs) def scheduleSingleCommand(self, command, jobType, deleteWhenDone, **kwargs): kwargs['jobstore'] = 'db'; kwargs['id'] = "["+str(random.randint(0, 99999999999))+"]Button '"+command.button.name+"' (ID: "+str(command.button.id)+"); Command '"+command.name+"' (ID: "+str(command.id)+")"; kwargs['args'] = (kwargs['id'], command.id, deleteWhenDone); self.scheduler.add_job(runCommand, jobType, **kwargs)
class JobController(FlaskView): route_base = '/jobs' scheduler = featureBroker.RequiredFeature('scheduler') @route('/') def jobs(self): """Renders the jobs page.""" return render_template( 'jobs.html', title='Jobs', year=datetime.now().year ) @route('/scheduler/run', methods=['POST']) def runJob(self): """Removes a job from the scheduler.""" try: job = self.scheduler.get_job(request.get_json(force=True)['job_id']); job.func(*job.args, **job.kwargs) return "{}", 200 except: return abort(400) @route('/scheduler/remove', methods=['POST']) def removeJob(self): """Removes a job from the scheduler.""" try: self.scheduler.remove_job(request.get_json(force=True)['job_id']); return "{}", 200 except: return abort(400) @route('/scheduler/resume', methods=['POST']) def resumeJob(self): """Resumes a job in the scheduler.""" try: self.scheduler.resume_job(request.get_json(force=True)['job_id']); return "{}", 200 except: return abort(400) @route('/scheduler/pause', methods=['POST']) def pauseJob(self): """Pauses a job in the scheduler.""" try: self.scheduler.pause_job(request.get_json(force=True)['job_id']); return "{}", 200 except: return abort(400)
class RFSnifferCleanup(featureBroker.Component): config = featureBroker.RequiredFeature('conf_RFSniffer') def register(self, scheduler): scheduler.add_job(self.doCleanup, 'cron', id='RF Sniffer History Cleanup', hour=2, max_instances=1) def doCleanup(self): cleanupDate = datetime.datetime.utcnow() - datetime.timedelta( days=int(self.config['cleanup_age_days'])) dbSession = None try: dbSession = app.db.session dbSession.query(RFSniffer).filter( RFSniffer.date_created < cleanupDate).delete() dbSession.commit() except: dbSession.rollback() traceback.print_exc() raise
def run(self, isDaemon=False): #################################################### # Setup Logging #################################################### self.setup_logging() #################################################### # Setup Configuration #################################################### parser = SafeConfigParser() parser.read('RF.conf') for section_name in parser.sections(): featureBroker.features.Provide( 'conf_{name}'.format(name=section_name), dict(parser.items(section_name))) #################################################### # Start Flask #################################################### app.web = Flask("__main__") # Create Scheduler if not app.web.debug or os.environ.get('WERKZEUG_RUN_MAIN') == 'true': app.web.config['SCHEDULER_VIEWS_ENABLED'] = True app.web.config['SCHEDULER_JOBSTORES'] = { 'default': MemoryJobStore(), 'db': SQLAlchemyJobStore( url='sqlite:///' + featureBroker.RequiredFeature('conf_DB').result['jobs']) } scheduler = APScheduler() jobs = featureBroker.RequiredFeatures( 'job', featureBroker.HasMethods('register')).result for job in jobs: job.register(scheduler.scheduler) scheduler.init_app(app.web) scheduler.start() featureBroker.features.Provide('scheduler', scheduler.scheduler) # Register Controllers controllers = featureBroker.RequiredFeatures( 'controller', featureBroker.HasMethods('register')).result for controller in controllers: controller.register(app.web) # Set secret Key app.web.secret_key = 'A0ew:DE~7/T6yA^8vqNgjVB5tZr98j/3yX R~XHH!jmew:DE~7/T6yA^8vqNgjVB5tN]LWX/,?RT' # Flask-SQLAlchemy app.web.config[ 'SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + featureBroker.RequiredFeature( 'conf_DB').result['rf'] app.db = SQLAlchemy(app.web) entities.Base.metadata.create_all(app.db.engine, checkfirst=True) # RF Sniffer if not app.web.debug or os.environ.get('WERKZEUG_RUN_MAIN') == 'true': sniffer = rfSniffer() app.web.run(host='0.0.0.0', port=parser.getint("Web", "port"), debug=(not isDaemon))
class ManageController(FlaskView): route_base = '/manage/' interface = featureBroker.RequiredFeature( 'entityInterfaces', featureBroker.HasMethods('getCodes', 'getButton', 'removeButton', 'addButton')) autolightConfig = featureBroker.RequiredFeature('conf_AutoLight') @route('/') def index(self): """Management Page.""" return render_template('manage.html', title='Manage', year=datetime.datetime.now().year) @route('/buttons/remote_add', methods=['POST']) def addremoteButton(self): '''Create a new Button from incoming remote signal''' try: now = datetime.datetime.utcnow() timeLimit = now + timedelta(seconds=10) code = None while ((code == None) and (datetime.datetime.utcnow() <= timeLimit)): for record in app.db.session.query(RFSniffer).filter( RFSniffer.date_created >= now).order_by( RFSniffer.date_created): code = record.code break sleep(1 / 4.) if (code == None): return abort(408) codes = drivers.rf.analyseCode(code) data = request.get_json(force=True) button = self.interface.addButton(data['name'], **data) button.save() button.addCommand("On", style="success", codes=[codes['on']]) button.addCommand("Off", style="danger", codes=[codes['off']]) button.save() return json.dumps({'id': button.id}) except: return abort(400) @route('/buttons/add', methods=['POST']) def addButton(self): '''Create a new Button''' try: data = request.get_json(force=True) button = self.interface.addButton(data['name'], **data) button.save() code = None allCodes = self.interface.getCodes() while (True): code = random.randint(10000, 9999999) for c in allCodes: if c == code: code = None break if code != None: break codes = drivers.rf.analyseCode(code) button.addCommand("On", style="success", codes=[codes['on']]) button.addCommand("Off", style="danger", codes=[codes['off']]) button.save() return json.dumps({'id': button.id}) except: return abort(400) @route('/buttons/<button_id>/remove', methods=['POST']) def removeButton(self, button_id): '''Remove a Button''' try: self.interface.removeButton(id=int(button_id)) return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/hide', methods=['POST']) def hideButton(self, button_id): '''Hide a Button''' try: button = self.interface.getButton(id=int(button_id)) button.visible = False button.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/show', methods=['POST']) def showButton(self, button_id): '''Show a Button''' try: button = self.interface.getButton(id=int(button_id)) button.visible = True button.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/rename', methods=['POST']) def renameButton(self, button_id): '''Rename a Button''' try: button = self.interface.getButton(id=int(button_id)) data = request.get_json(force=True) button.name = data['name'] button.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/updateIcon', methods=['POST']) def updateIcon(self, button_id): '''Change the icon of a Button''' try: button = self.interface.getButton(id=int(button_id)) data = request.get_json(force=True) button.icon = data['icon'] button.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/edit') def edit(self, button_id): """Edit Button Page.""" button = self.interface.getButton(id=int(button_id)) if (button == None): flash('Unable to find button with the id of ' + button_id + '.', 'error') return redirect(url_for('ManageController:index')) return render_template('edit.html', title=button.name, button=button, autolightConfig=self.autolightConfig, year=datetime.datetime.now().year) @route('/buttons/<button_id>/command/add', methods=["POST"]) def addCommand(self, button_id): '''Add a new command to a Button''' try: button = self.interface.getButton(id=int(button_id)) data = request.get_json(force=True) button.addCommand(data['name'], style="primary") button.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/command/<command_id>/remove', methods=["POST"]) def removeCommand(self, button_id, command_id): '''Remove a command''' try: button = self.interface.getButton(id=int(button_id)) button.removeCommand(id=int(command_id)) button.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/command/<command_id>/rename', methods=["POST"]) def renameCommand(self, button_id, command_id): '''Rename a command''' try: command = self.interface.getCommand(command_id=int(command_id)) data = request.get_json(force=True) command.name = data['name'] command.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/command/<command_id>/style', methods=["POST"]) def styleCommand(self, button_id, command_id): '''Rename a command''' try: command = self.interface.getCommand(command_id=int(command_id)) data = request.get_json(force=True) command.style = data['style'] command.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/command/<command_id>/autolight/enable/set', methods=["POST"]) def setAutolightEnableCommand(self, button_id, command_id): '''Set Autolight Enable Command''' try: command = self.interface.getCommand(command_id=int(command_id)) command.setAsAutoLightEnable() command.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/command/<command_id>/autolight/disable/set', methods=["POST"]) def setAutolightdisableCommand(self, button_id, command_id): '''Set Autolight disable Command''' try: command = self.interface.getCommand(command_id=int(command_id)) command.setAsAutoLightDisable() command.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/command/<command_id>/autolight/enable/remove', methods=["POST"]) def removeAutolightEnableCommand(self, button_id, command_id): '''Remove Autolight Enable Command''' try: button = self.interface.getButton(id=int(button_id)) if (button.autolight['enable'].id != int(command_id)): return abort(400) button.clearAutoLightEnable() button.save() return "{}", 200 except: return abort(400) @route( '/buttons/<button_id>/command/<command_id>/autolight/disable/remove', methods=["POST"]) def removeAutolightDisableCommand(self, button_id, command_id): '''Remove Autolight disable Command''' try: button = self.interface.getButton(id=int(button_id)) if (button.autolight['disable'].id != int(command_id)): return abort(400) button.clearAutoLightDisable() button.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/command/<command_id>/code/add', methods=["POST"]) def addCode(self, button_id, command_id): '''Add a new code to a command''' try: command = self.interface.getCommand(command_id=int(command_id)) data = request.get_json(force=True) command.addCode(int(data['code'])) command.save() return "{}", 200 except: return abort(400) @route('/buttons/<button_id>/command/<command_id>/code/<code>/remove', methods=["POST"]) def removeCode(self, button_id, command_id, code): '''Add a new code to a command''' try: command = self.interface.getCommand(command_id=int(command_id)) command.removeCode(code=int(code)) command.save() return "{}", 200 except: return abort(400)
class DataController(FlaskView): route_base = '/data/' interface = featureBroker.RequiredFeature( 'entityInterfaces', featureBroker.HasMethods('getCommand')) @route('/button/<button_ref>/command/<command_ref>') def command(self, button_ref, command_ref): """Processes a command request.""" command = self.interface.getCommand(button_name=button_ref, command_name=command_ref) if (command == None): try: command = self.interface.getCommand(button_id=int(button_ref), command_name=command_ref) except: command = None if (command == None): try: command = self.interface.getCommand( button_id=int(button_ref), command_id=int(command_ref)) except: command = None if (command == None): try: command = self.interface.getCommand( button_name=button_ref, command_id=int(command_ref)) except: command = None if (command == None): return abort(400) return json.dumps({ 'id': command.id, 'name': command.name, 'style': command.style, 'codes': command.codes, }) @route('/button/<button_ref>') def button(self, button_ref): """Processes a button request.""" def processCommand(command): if (command == None): return None return { 'id': command.id, 'name': command.name, 'style': command.style, 'codes': command.codes, } def processCommands(commandList): commands = [] for c in commandList: commands.append(processCommand(c)) return commands b = self.interface.getButton(id=button_ref) if b == None: b = self.interface.getButton(name=button_ref) if b == None: return abort(400) return json.dumps({ 'id': b.id, 'name': b.name, 'icon': b.icon, 'visible': b.visible, 'autolight': { 'enable': processCommand(b.autolight['enable']) if 'enable' in b.autolight else None, 'disable': processCommand(b.autolight['disable']) if 'disable' in b.autolight else None }, 'commands': processCommands(b.commands) }) @route('/buttons') def buttons(self): """Get Buttons Details""" def processCommand(command): if (command == None): return None return { 'id': command.id, 'name': command.name, 'style': command.style, 'codes': command.codes, } def processCommands(commandList): commands = [] for c in commandList: commands.append(processCommand(c)) return commands results = [] for b in self.interface.getButtons(): results.append({ 'id': b.id, 'name': b.name, 'icon': b.icon, 'visible': b.visible, 'autolight': { 'enable': processCommand(b.autolight['enable']) if 'enable' in b.autolight else None, 'disable': processCommand(b.autolight['disable']) if 'disable' in b.autolight else None }, 'commands': processCommands(b.commands) }) return json.dumps(results) @route('/lookup/code/<code>') def lookupCode(self, code): def processCommand(command): if (command == None): return None return { 'id': command.id, 'name': command.name, 'style': command.style, 'codes': command.codes, } def processCommands(commandList): commands = [] for c in commandList: commands.append(processCommand(c)) return commands results = [] for c in self.interface.lookupCode(code): results.append({ 'button': { 'id': c['button'].id, 'name': c['button'].name, 'icon': c['button'].icon, 'visible': c['button'].visible, 'autolight': { 'enable': processCommand(c['button'].autolight['enable']) if 'enable' in c['button'].autolight else None, 'disable': processCommand(c['button'].autolight['disable']) if 'disable' in c['button'].autolight else None }, 'commands': processCommands(c['button'].commands) }, 'command': processCommand(c['command']) }) return json.dumps(results)