def test_api_version(): sock_path = os.getenv('RTR_SCGI_SOCKET_PATH', SOCK_PATH) remote = Remote(sock_path) g = remote.get_global() assert g.system_client_version == os.getenv('RTR_SYSTEM_CLIENT_VERSION', '0.0.0') assert g.system_api_version == int(os.getenv('RTR_SYSTEM_API_VERSION', 0))
def main(): print('Receptor de Senales de Alarma Version 1.65') Lic = LicCheck() if Lic == True: if Modo != None: t = threading.Thread(target=AvisodeApertura, args=[Lic]) t.setDaemon(False) t.start() #AvisodeApertura(Lic) app = QApplication(sys.argv) import qt4reactor qt4reactor.install() from twisted.internet import reactor #app.setStyle(QStyleFactory.create("plastique")) w = MainWindow(reactor) #Retornamos en BD 'No hay BD' en caso de que no se consiga la BD #Si el receptor esta en MODO de BD. Para que no muestre nunca la #Ventana. bd = w.IniciarReceptores() w.show() a = Remote(w) a.Iniciar() if bd == 'No hay BD': pass else: reactor.run() #sys.exit(app.exec_()) else: AvisodeApertura(Lic) pass
async def global_data_updater(): remote = Remote(SOCK_PATH) while True: try: new_data = {} data = remote.get_global() diff = await Cached.update_global(data) if diff: new_data['global'] = diff data = remote.get_torrents() diff = await Cached.update_torrents(data) if diff: new_data['torrents'] = diff plugins_data = {} for plugin in Cached.plugins: plugin_output = await plugin.get(False) if plugin_output is not None: plugins_data[plugin.name()] = plugin_output if plugins_data: new_data['plugins'] = plugins_data if len(new_data) > 0: await Cached.notify_clients(new_data) except Exception as e: logger.error(e, exc_info=e) asyncio.get_running_loop().stop() return await asyncio.sleep(RTR_RETR_INTERVAL)
def test_peers(): remote = Remote(SOCK_PATH) for hash in [ 'A6B69431743F085D96692A81C6282617C50243C4', '67DD1659106DCDDE0FEC4283D7B0C84B6C292675' ]: peers = remote.get_peers(hash) assert len(peers) == 0
def remote(cmd): r=Remote() if cmd == "on": r.on() else: r.off() return "ok"
def attemptConnection(self, ip_address, port, username, password): kodi = Kodi(username, password, ip_address, port) isConnected = kodi.Connect() if isConnected: print('Connected. Load remote window') self.builder.get_object('windowSetup').hide() remoteWin = Remote({'ip_address': ip_address, 'port': port, 'username': username, 'password': password}) remoteWin.load_window(self.builder) else: print('Unable to connect. Keep showing setup window')
def test_trackers(): remote = Remote(SOCK_PATH) trackers = remote.get_trackers('A6B69431743F085D96692A81C6282617C50243C4') assert len(trackers) == 2 for t in trackers: assert t.is_enabled == 1 trackers = remote.get_trackers('67DD1659106DCDDE0FEC4283D7B0C84B6C292675') assert len(trackers) == 6 for t in trackers: assert t.is_enabled == 1
def test_files(): remote = Remote(SOCK_PATH) files = remote.get_files('A6B69431743F085D96692A81C6282617C50243C4') assert len(files) == 1 assert files[0].path == 'debian-10.2.0-amd64-DVD-1.iso' assert files[0].size_bytes == 3918200832 files = remote.get_files('67DD1659106DCDDE0FEC4283D7B0C84B6C292675') assert len(files) == 1 assert files[0].path == '2ROrd80' assert files[0].size_bytes == 6964641792
def __init__(self, address="0.0.0.0:8081", stderr=sys.stderr): if (':' in address): self.port = address.split(":")[1] else: self.port = "8081" self.commands = {} with open("commands.config") as f: self.commands = json.load(f) self.error_message = "Command '%s' not found" self.stderr = stderr self.habitat_remote = Remote(address)
def main(): remote = Remote() lights = Lights() lights_on_command = LightsOnCommand(lights) lights_off_command = LightsOffCommand(lights) remote.set_command(lights_on_command) remote.pressButton() remote.set_command(lights_off_command) remote.pressButton()
def join(self, remote_address = None): # initially just set successor self.finger_ = map(lambda x: None, range(LOGSIZE)) self.predecessor_ = None if remote_address: remote = Remote(remote_address) self.finger_[0] = remote.find_successor(self.id()) else: self.finger_[0] = self self.log("joined")
def join(self, remote_address = None): # initially just set successor self.finger_ = list(map(lambda x: None, range(LOGSIZE))) self.predecessor_ = None if remote_address: remote = Remote(remote_address) self.finger_[0] = remote.find_successor(self.id()) else: self.finger_[0] = self self.log("joined")
def join(self, remote_address=None): # initially just set successor self.finger_ = [None for x in range(LOGSIZE)] self.predecessor_ = None if remote_address: remote = Remote(remote_address) self.finger_[0] = remote.find_successor(self.id()) else: self.finger_[0] = self self.log("joined")
def run(): log.basicConfig(format="[ %(asctime)s ] [ %(levelname)s ] %(message)s", level=log.INFO, stream=sys.stdout) # GrowBot 2 r = Remote("e3dde6f2-5925-42e4-b37d-5214f18ae798", "ws://localhost:8080") print("Test") r.create_log_entry(LogType.UNKNOWN, "Hello, world!") print("Created") asyncio.ensure_future(r.connect()) loop = asyncio.get_event_loop() pending = asyncio.Task.all_tasks() loop.run_until_complete(asyncio.gather(*pending))
def __new__(self, hostfile, passfile): self.hostfile = hostfile self.passfile = passfile if not self._instance: self._instance = super(MyServer, self).__new__(self) self.remote_server = Remote(self.hostfile, self.passfile) return self._instance
def test_global_data(): g = Remote(SOCK_PATH).get_global() assert g.throttle_global_down_max_rate == 1024 assert g.throttle_global_up_max_rate == 1024 assert g.network_max_open_files == 8000 assert g.network_port_range == '22400-22400' assert g.network_listen_port == 22400
def setNext(self, ip, port) -> None: if (ip == self.ip and int(port) == self.port): self.next = self else: self.next = Node(ip, port) self.next.connection = Remote(self.next.ip, self.next.port) print('Added %s:%s as next' % (ip, port))
def join(self, remote_address = None): # initially just set successor print "joining" self.finger_ = [None for x in range(LOGSIZE)] self.predecessor_ = None if remote_address: print "poking", remote_address remote = Remote(remote_address) print "fingering" self.finger_[0] = remote.find_successor(self.id()) else: self.finger_[0] = self print "joined" self.log("joined")
def process_request(self, command, request): # default : "" = not respond anything result = json.dumps("") if command == 'get_successor': successor = self.successor() result = json.dumps( (successor.address_.ip, successor.address_.port)) if command == 'get_predecessor': # we can only reply if we have a predecessor pred = self.predecessor_ if pred != None: predecessor = pred result = json.dumps( (predecessor.address_.ip, predecessor.address_.port)) if command == 'find_successor': successor = self.find_successor(int(request)) result = json.dumps( (successor.address_.ip, successor.address_.port)) if command == 'closest_preceding_finger': closest = self.closest_preceding_finger(int(request)) result = json.dumps((closest.address_.ip, closest.address_.port)) if command == 'notify': npredecessor = Address( request.split(' ')[0], int(request.split(' ')[1])) self.notify(Remote(npredecessor)) if command == 'get_successors': result = json.dumps(self.get_successors()) # or it could be a user specified operation for t in self.command_: if command == t[0]: result = t[1](request) self.log('sending response: ' + result) return result
def __init__(self): self.active_event = None self.lamp_timeout = 10 self.double_timeout = 0.3 self.inactive_events = { Spotify.NAME: Spotify(), Kodi.NAME: Kodi(), WatchTv.NAME: WatchTv(), WatchPlay.NAME: WatchPlay() } self.input_keys = { "up": Kodi, "down": WatchTv, "left": Spotify, "right": WatchPlay } self.lamp_keys = { "up": "ceiling", "left": "bed", "right": "sofa", "down": "all" } self.lamp_group = LampGroup({ "sofa": Lamp(100, 1), "ceiling": Lamp(100, 2), "bed": Lamp(100, 3), }) self.remotes = [Remote()] self.active_modkey = None
def test_api_11_global(): g = Remote(SOCK_PATH).get_global() if g.system_api_version >= 11: values = { cmd.replace('.', '_') for cmd in Remote.COMMANDS_PER_API_VERSION[11] } assert len(g.__dict__.keys() & values) == len(values)
def setPrevious(self, ip, port) -> None: if (ip == self.ip and int(port) == self.port): self.previous = self else: self.previous = Node(ip, port) self.previous.connection = Remote(self.previous.ip, self.previous.port) print('Added %s:%s as previous' % (ip, port))
def remotes(self): """ A list of Remote objects allowing to access and manipulate remotes Returns ``git.IterableList(Remote, ...)`` """ return Remote.list_items(self)
def kill_pid(self,p): "" if p == 'trendnet.ini': remote=Remote(self.server) print 'kill -9 %s' % self.pids['trendnet.ini'] remote.execute('kill -9 %s' % self.pids['trendnet.ini']) elif p == 'weather.ini': remote=Remote(self.source) print 'kill -9 %s' % self.pids['weather.ini'] remote.execute('kill %s' % self.pids['weather.ini']) elif p == 'scheduler.ini': remote=Remote(self.server) print 'kill -9 %s' % self.pids['scheduler.ini'] remote.execute('kill %s' % self.pids['scheduler.ini'])
def setup(self): self.config = Config.load('config.json') self.remote = Remote() self.deviceMgr = devices.DeviceManager(self.remote) self.deviceMgr.setEventHandler( lambda device, event, data: self.handleEvent(device, event, data)) Config.loadDevicesFromConfigData(self.config, self.deviceMgr) self.deviceMgr.initDevices()
def remote(self, name='origin'): """ Return Remote with the specified name Raise ValueError if no remote with such a name exists """ return Remote(self, name)
def sendResponse(self, request, response): responseNodeIP = request['responseNodeIP'] responseNodePort = int(request['responseNodePort']) if (self.ip == responseNodeIP and self.port == responseNodePort and 'requestID' not in request): return response try: requestID = request['requestID'] except: return None conn = Remote(responseNodeIP, responseNodePort) res = json.dumps({ 'type': 'response', 'requestID': requestID, 'response': response }) conn.send(res) return None
def run(self): # should have a threadpool here :/ # listen to incomming connections self.socket_ = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket_.bind((self.address_.ip, int(self.address_.port))) self.socket_.listen(10) while 1: self.log("run loop") try: conn, addr = self.socket_.accept() except socket.error: self.shutdown_ = True break request = read_from_socket(conn) command = request.split(' ')[0] # we take the command out request = request[len(command) + 1:] # defaul : "" = not respond anything result = json.dumps("") if command == 'get_successor': successor = self.successor() result = json.dumps((successor.address_.ip, successor.address_.port)) if command == 'get_predecessor': # we can only reply if we have a predecessor if self.predecessor_ != None: predecessor = self.predecessor_ result = json.dumps((predecessor.address_.ip, predecessor.address_.port)) if command == 'find_successor': successor = self.find_successor(int(request)) result = json.dumps((successor.address_.ip, successor.address_.port)) if command == 'closest_preceding_finger': closest = self.closest_preceding_finger(int(request)) result = json.dumps((closest.address_.ip, closest.address_.port)) if command == 'notify': npredecessor = Address(request.split(' ')[0], int(request.split(' ')[1])) self.notify(Remote(npredecessor)) if command == 'get_successors': result = json.dumps(self.get_successors()) # or it could be a user specified operation for t in self.command_: if command == t[0]: result = t[1](request) send_to_socket(conn, result) conn.close() if command == 'shutdown': self.socket_.close() self.shutdown_ = True self.log("shutdown started") break self.log("execution terminated")
def __init__(self, jobs_data, remote): """Create the submitter object Args: jobs_data: dict type, all information of the jobs to be managed remote: string type, the remote machine """ super(SubmitterBase, self).__init__() self._data = jobs_data self._remote = Remote(remote)
def __init__(self): self.vision = Vision(RobotController.model_xml, RobotController.model_bin, self, is_headless=True, live_stream=True, confidence_interval=0.5) self.received_frame = None self.qr_reader = QRReader() self.last_qr_approached = None self.current_qr_approached = None self.approach_complete = True self.retrying_approach = False self.standby_mode = True self.standby_invoked = True self.serial_io = SerialIO('/dev/ttyACM0', 115200, self) self.actions = {} self.watered = False if config.RESPOND_TO_API: host = config.API_HOST if config.API_SECURE: host = "wss://" + host else: host = "ws://" + host self.remote = Remote(config.UUID, host) self.remote.add_callback(RPCType.MOVE_IN_DIRECTION, self.remote_move) self.remote.add_callback(RPCType.EVENTS, self.on_events_received) self.remote.add_callback(RPCType.SET_STANDBY, self.set_standby) rm_thread = threading.Thread(target=self.thread_remote, name="remote", daemon=True) rm_thread.start() # rm_thread.join() # Create the navigation system self.navigator = Navigator(self, verbose=True) threading.Thread(target=self.vision.start, name="vision").start()
def get_pids(self,target): d=Remote.gen_login(target) # print d remote=Remote(d) lines=remote.execute("ps aux | grep python | grep -v grep",d['base_dir']) lines=lines.splitlines() d={} # print res for l in lines: sl=re.split(r' *', l) if len(sl) > 5: k=sl[-1] v=sl[1] d[k]=v return d
def remote_cmd(req): username = req.COOKIES.get('name', '') if req.method == 'POST' and req.POST: #type = req.POST.get("submit_type",None) if 'sendcmd' in req.POST: ip = req.POST['ip'] usr = req.POST['username'] passwd = req.POST['password'] cmd = req.POST['cmd'] if req.POST['port']: port = int(req.POST['port']) else: port = 22 #存储到历史指令 db_cmd = CmdList() db_cmd.cmd = cmd db_cmd.host = ip db_cmd.time = datetime.datetime.now() print db_cmd.time db_cmd.save() #远程发送指令 handler = Remote(ip, usr, passwd, port) recv = handler.ssh(cmd) showTag = 'recv' return render(req, 'remote_cmd.html', locals()) elif 'history' in req.POST: #查询最近8条命令 CMDs = CmdList.objects.order_by('-id')[:8] result = [] for item in CMDs: result.append({ 'time': item.time.strftime('%m-%d %H:%M:%S'), 'cmd': item.cmd, 'host': item.host }) showTag = 'result' # print result return render(req, 'remote_cmd.html', locals()) else: return render(req, 'remote_cmd.html') else: return render(req, 'remote_cmd.html')
def create_remote(self, name, url, **kwargs): """ Create a new remote. For more information, please see the documentation of the Remote.create methods Returns Remote reference """ return Remote.create(self, name, url, **kwargs)
def init_widgets(self): self.remote = Remote(self.ui.console) self.widgets = [ self.ui.tabWidget, self.ui.ccButton, self.ui.rcButton, self.ui.attackButton, self.ui.attackComboBox, self.ui.gpsCheckBox, self.ui.enclCheckBox, self.ui.encrCheckBox, self.ui.saveButton, self.ui.desiredSpeedLabel, self.ui.desiredSpeedEdit, self.ui.setSpeedButton, self.ui.kpLabel, self.ui.kpEdit, self.ui.setKPButton, self.ui.kiLabel, self.ui.kiEdit, self.ui.setKIButton, self.ui.trimLabel, self.ui.trimValueLabel, self.ui.setTrimLeftButton, self.ui.setTrimRightButton, self.ui.actualSpeedLabel, self.ui.actualSpeedLCD, self.ui.estimatedSpeedLabel, self.ui.estimatedSpeedLCD, self.ui.outputPlot, self.ui.outputPlotLabel, self.ui.inputPlot, self.ui.inputPlotLabel, self.ui.rightPlot, self.ui.rightPlotLabel ] #self.ui.mapView.setScene(MapnikScene(self.ui.mapView)) #self.ui.mapView = MapView(self.ui.mapWidget) self.init_signals() self.init_plots()
def __init__(self): # 读取配置和脚本文件 conf = ConfigParser.ConfigParser() conf.read('../configs/global.ini') process_file = ('../configs/process/' + conf.get('ControlProcess', 'file') + '.cp') with open(process_file, 'r') as f: self.__process = f.readlines() # 去除注释和空行 self.__process = [i for i in self.__process if not i.startswith(';') and i != '\r\n' and i != '\n'] self.__step_num = len(self.__process) self.__step = 0 self.__record = Record() self.__serial_com = SerialCom(self.__record.display_status) self.__remote = Remote() self.__relay = Relay() thread.start_new_thread(self.__serial_com.read_ser, ()) self.log_name = self.__record.recording_log
def main(): print('Initialising...') port = '/dev/tty.RN42-B597-SPP' connected = False while not connected: try: rem = Remote(port) except RemoteConnectionError: print('\x1b[31;1mConnection on port {} unsuccessful\x1b[0m'.format(port)) port = input('Please enter the right serial port: ') print('attempting another connection...') else: connected = True while True: data = input('Input: ') rem.send(data) rem.send('0')
class Listener(threading.Thread): def __init__(self, r, channels): threading.Thread.__init__(self) self.redis = redis.Redis() self.pubsub = self.redis.pubsub() self.pubsub.subscribe(channels) self.remote = Remote(app.config["PIONEER"]) def work(self, item): if item["type"] == "message" and item["channel"] == "remote": print item['channel'], ":", item['data'] self.remote.send_cmd(item['data']) def run(self): for item in self.pubsub.listen(): if item['data'] == "KILL": self.pubsub.unsubscribe() print self, "unsubscribed and finished" break else: self.work(item)
def archive_files(): "" def get_fidx(): "" def get_idx_mock(): "" p=os.curdir() return list_files_ext(p,'png') # fidx=get_fidx_mock() fidx=[] # curr_dt=get_timestamp() # for f in fidx: # sl.move(f,curr_dt) tm=get_current_time() remote=Remote(Remote.gen_login('dataserver')) remote.execute('mkdir %s'%tm)
def restart(self,p): self.pids=self.get_all_pids() if p == 'trendnet.ini': remote=Remote(self.server) if p in self.pids.keys(): self.kill_pid('trendnet.ini') remote.daemon('twistd smap trendnet.ini',self.server['base_dir']) elif p == 'weather.ini': remote=Remote(self.source) if p in self.pids.keys(): self.kill_pid('weather.ini') # print remote.daemon('twistd smap weather.ini',self.source['base_dir']) elif p == 'scheduler.ini': remote=Remote(self.server) if p in self.pids.keys(): self.kill_pid('scheduler.ini') remote.daemon('twistd --pidfile=scheduler.pid smap scheduler.ini',self.server['base_dir'])
def __init__(self): QtGui.QMainWindow.__init__(self) self.setupUi(self) # init subsystems self.config = Config() self.config.read() self.config.set_defaults() self.remote = Remote(self.config) self.updates_layout = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.updates_layout.setMargin(1) self.storage = UpdatesStorage(os.path.expanduser(self.config['qttt']['db_path']), self.updates_layout, self.remote) # gui options self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.tray = QtGui.QSystemTrayIcon(self) icon = QtGui.QIcon(os.path.join(os.path.dirname(__file__), 'icon.png')) self.tray.setIcon(icon) self.setWindowIcon(icon) self.tray.show() self.gb_current.hide() self.move( self.config['qttt']['geometry']['left'], self.config['qttt']['geometry']['top'] ) self.resize(self.config['qttt']['geometry']['width'], self.config['qttt']['geometry']['height'] ) self.setWindowTitle('QTTT - %s' % self.config['site']['base_url']) self.lb_current.setWordWrap(True) # connections self.connect(self.action_Qt, QtCore.SIGNAL('activated()'), QtGui.qApp.aboutQt) self.connect(self.pb_update, QtCore.SIGNAL('clicked()'), self.sendUpdate) self.connect(self.le_update, QtCore.SIGNAL('returnPressed()'), self.sendUpdate) self.connect(self.pb_stop, QtCore.SIGNAL('clicked()'), self.finishLast) self.connect(self.tray, QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self.trayActivated) self.connect(QtGui.qApp, QtCore.SIGNAL('lastWindowClosed()'),self.writeConfig) self.refresh_timer = QtCore.QTimer() self.refresh_timer.setInterval(5*60*1000) # 5 minutes self.connect(self.refresh_timer, QtCore.SIGNAL('timeout()'), self.getUpdates) self.refresh_timer.start() self.last_update_timer = QtCore.QTimer() self.last_update_timer.setInterval(1000) # 1 second self.connect(self.last_update_timer, QtCore.SIGNAL('timeout()'), self.refreshLastUpdateTime) # retrieve data try: user = self.remote.getUser() except: QtGui.QMessageBox.warning(self, u"Ошибка", u"Не могу соединиться с сервером") # it's hard but it's WORKING! :) exit() if user.get('error') is not None: QtGui.QMessageBox.warning(self, u"Ошибка", u"Неверный api-key указан в .tttrc файле") # it's hard but it's WORKING! :) exit() Update.set_current_user(user['nickname']) self.storage.loadUpdatesFromDB() self.getUpdates() self.getProjects()
def delete_remote(self, remote): """ Delete the given remote. """ return Remote.remove(self, remote)
app =flask.Flask(__name__) app.secret_key = settings.secret_key #Routes app.add_url_rule('/', view_func=Main.as_view('main'), methods=['GET']) app.add_url_rule('/<page>/', view_func=Main.as_view('page'), methods=['GET']) app.add_url_rule('/login', view_func=Login.as_view('login'), methods=['GET','POST']) app.add_url_rule('/remote', view_func=Remote.as_view('remote'), methods=['GET','POST']) app.add_url_rule('/music', view_func=Music.as_view('music'), methods=['GET']) @app.errorhandler(404) def page_not_found(error): return flask.render_template('404.html'),404 app.debug=True app.run()
def run_interval( interval ): def interval_decorator( func ): last_run = [0.0] def func_wrapper( *args ): if time.time() - last_run[0] > interval: func( *args ) last_run[0] = time.time() return func_wrapper return interval_decorator if __name__ == "__main__": curtain = Curtain() light = Light() env = Environment() remote = Remote( 'firebase.txt' ) curtain.setencoder( limits=(0,50) ) curtain.engage() @run_interval( 10 ) def remote_check(): print "Getting data from remote... ", remote.update() print "Done" @run_interval( 5 ) def env_check(): print "Getting data from environment... ", env.update()
def __init__(self): # self.remote=Remote(Remote.gen_login(target)) self.cfg=Env().getConfig() self.pids=self.get_all_pids() self.source=Remote.gen_login('smapsource') self.server=Remote.gen_login('smapserver')
def __init__(self, r, channels): threading.Thread.__init__(self) self.redis = redis.Redis() self.pubsub = self.redis.pubsub() self.pubsub.subscribe(channels) self.remote = Remote(app.config["PIONEER"])
def _connect(self, port): try: self.rem = Remote(port) return True except RemoteConnectionError: return False
from remote import Remote servo = Servo(port=1, min_pulse=750, max_pulse=2250, min_position=0.30, max_position=0.7) motor = Motor(port=1, duty_cycle=0) def wave(min=0.0, max=1.0, n=1, pause=0.4): for x in range(n): servo.set(min) time.sleep(pause) servo.set(max) time.sleep(pause) servo.set(0.5) api = Api() api.demonize() remote = Remote() while True: # api events for event, kwargs in api.events: if event == "wave": wave(**kwargs) if event == "set": servo.set(0.75-float(kwargs["position"])*0.5) if event == "set_speed": motor.duty_cycle = kwargs['position'] api.events = [] if not remote.wm: motor.tick()
from music import Music from events import Events from users import Users from docs import Docs # configuration DATABASE = 'test.json' app = flask.Flask(__name__) app.secret_key = settings.secret_key #URL rules: add as needed for the various dynamic pages app.add_url_rule('/', view_func=Main.as_view('main'), methods=('get','post')) app.add_url_rule('/<page>/', view_func=Main.as_view('main'), methods=('get','post')) app.add_url_rule('/login/', view_func=Login.as_view('login'), methods=('get','post')) app.add_url_rule('/remote/', view_func=Remote.as_view('remote'), methods=('get','post')) app.add_url_rule('/music/', view_func=Music.as_view('music'), methods=('get', 'post')) app.add_url_rule('/events/', view_func=Events.as_view('events'), methods=('get','post')) app.add_url_rule('/users/', view_func=Users.as_view('users'), methods=('get','post')) app.add_url_rule('/docs/', view_func=Docs.as_view('docs'), methods=('get','post')) #error handling wrapper @app.errorhandler(404) def page_not_found(error): return flask.render_template('404.html'), 404 #database handling wrappers @app.before_request def before_request(): """Make sure we are connected to the database each request.""" try:
class MainWindow(QtGui.QMainWindow, Ui_MainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) self.setupUi(self) # init subsystems self.config = Config() self.config.read() self.config.set_defaults() self.remote = Remote(self.config) self.updates_layout = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.updates_layout.setMargin(1) self.storage = UpdatesStorage(os.path.expanduser(self.config['qttt']['db_path']), self.updates_layout, self.remote) # gui options self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.tray = QtGui.QSystemTrayIcon(self) icon = QtGui.QIcon(os.path.join(os.path.dirname(__file__), 'icon.png')) self.tray.setIcon(icon) self.setWindowIcon(icon) self.tray.show() self.gb_current.hide() self.move( self.config['qttt']['geometry']['left'], self.config['qttt']['geometry']['top'] ) self.resize(self.config['qttt']['geometry']['width'], self.config['qttt']['geometry']['height'] ) self.setWindowTitle('QTTT - %s' % self.config['site']['base_url']) self.lb_current.setWordWrap(True) # connections self.connect(self.action_Qt, QtCore.SIGNAL('activated()'), QtGui.qApp.aboutQt) self.connect(self.pb_update, QtCore.SIGNAL('clicked()'), self.sendUpdate) self.connect(self.le_update, QtCore.SIGNAL('returnPressed()'), self.sendUpdate) self.connect(self.pb_stop, QtCore.SIGNAL('clicked()'), self.finishLast) self.connect(self.tray, QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self.trayActivated) self.connect(QtGui.qApp, QtCore.SIGNAL('lastWindowClosed()'),self.writeConfig) self.refresh_timer = QtCore.QTimer() self.refresh_timer.setInterval(5*60*1000) # 5 minutes self.connect(self.refresh_timer, QtCore.SIGNAL('timeout()'), self.getUpdates) self.refresh_timer.start() self.last_update_timer = QtCore.QTimer() self.last_update_timer.setInterval(1000) # 1 second self.connect(self.last_update_timer, QtCore.SIGNAL('timeout()'), self.refreshLastUpdateTime) # retrieve data try: user = self.remote.getUser() except: QtGui.QMessageBox.warning(self, u"Ошибка", u"Не могу соединиться с сервером") # it's hard but it's WORKING! :) exit() if user.get('error') is not None: QtGui.QMessageBox.warning(self, u"Ошибка", u"Неверный api-key указан в .tttrc файле") # it's hard but it's WORKING! :) exit() Update.set_current_user(user['nickname']) self.storage.loadUpdatesFromDB() self.getUpdates() self.getProjects() def writeConfig(self): self.config['qttt']['geometry']['width'] = self.size().width() self.config['qttt']['geometry']['height'] = self.size().height() self.config['qttt']['geometry']['left'] = self.pos().x() self.config['qttt']['geometry']['top'] = self.pos().y() self.config.write() def showMessage(self, title, message, status=None, only_status=False): self.statusBar().showMessage(status if status else message, 5000) if not only_status: self.tray.showMessage(title, message) def showLastUpdate(self, upd): self.lb_current.setText(upd.message) self.last_update_started_at = upd.started_at # it's easy to remember this time self.refreshLastUpdateTime() self.last_update_timer.start() self.gb_current.show() def hideLastUpdate(self): self.last_update_timer.stop() self.gb_current.hide() self.tray.setToolTip('') def refreshLastUpdateTime(self): now = datetime.datetime.now(dateutil.tz.tzlocal()) delta = dateutil.relativedelta.relativedelta(now, self.last_update_started_at) self.lb_time.setText('%02i:%02i:%02i' % (delta.hours, delta.minutes, delta.seconds)) self.tray.setToolTip(self.lb_current.text() + ' ' + self.lb_time.text()) def sendUpdate(self): text = self.le_update.text() if text.isEmpty(): self.getUpdates() return res = self.remote.sendUpdate(text) if res[0]: self.showMessage(u'Отправка апдейта', u'Апдейт успешно отправлен', only_status = True) self.le_update.clear() else: errors = res[1]['error'] if len(res[1]['error']) > 1: text = u'Произошли ошибки:\n%s' else: text = u'Произошла ошибка:\n%s' self.showMessage(u'Отправка апдейта', text % '\n'.join(errors), u'Произошли ошибки') self.getUpdates() self.getProjects() def continueUpdate(self, upd): self.le_update.setText(upd.message) self.le_update.setFocus() def editUpdateDialog(self, upd): dlg = EditUpdate(upd, upd.widget) if dlg.exec_() == 0: return upd_data = dlg.changed_update() res = self.remote.editUpdate(upd, upd_data) if res[0]: self.showMessage(u'Редактирование апдейта', u'Апдейт успешно отредактирован', only_status = True) else: errors = res[1]['error'] # cause we could receive one string or list of them if errors.__class__ is not list: errors = [errors] if len(errors) > 1: text = u'Произошли ошибки:\n%s' else: text = u'Произошла ошибка:\n%s' self.showMessage(u'Редактирование апдейта', text % '\n'.join(errors), u'Произошли ошибки') self.getUpdates() self.getProjects() def deleteUpdateDialog(self, upd): if QtGui.QMessageBox.Yes == QtGui.QMessageBox.question(self, u'Подтверждение', u'Вы действительно хотите удалить этот апдейт?', QtGui.QMessageBox.Yes | QtGui.QMessageBox.No): res = self.remote.deleteUpdate(upd) if res[0]: self.showMessage(u'Удаление апдейта', u'Апдейт успешно удален', only_status = True) self.storage.deleteUpdate(upd) else: errors = res[1]['error'] # cause we could receive one string or list of them if errors.__class__ is not list: errors = [errors] if len(errors) > 1: text = u'Произошли ошибки:\n%s' else: text = u'Произошла ошибка:\n%s' self.showMessage(u'Удаление апдейта', text % '\n'.join(errors), u'Произошли ошибки') def getUpdates(self): # get all updates last_update = self.remote.getLastUpdate() all_updates = self.remote.getUpdates(self.storage.last_refresh) all_updates.reverse() # cause we got reversed in time array for upd in all_updates: self.storage.addOrRefreshUpdate(upd) self.storage.refreshLayout() # check we can now render last_update if last_update is None: self.hideLastUpdate() else: self.showLastUpdate(self.storage.updates[last_update['uuid']]) def finishLast(self): self.remote.finishLast() self.getUpdates() def getProjects(self): # retrieve projects list projs = self.remote.getProjects()['projects'] proj_names = map(lambda x: u'#'+x['shortname'], projs) # set QCompleter for le_update completer = QtGui.QCompleter(proj_names, self) completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.le_update.setCompleter(completer) def closeEvent(self, event): # TODO: в трей, если нажат крестик # если Файл->Выход или Ctrl-Q то закрыть программу pass def trayActivated(self, reason): if reason in ( QtGui.QSystemTrayIcon.DoubleClick, QtGui.QSystemTrayIcon.Trigger, QtGui.QSystemTrayIcon.MiddleClick ): self.setVisible(not self.isVisible())
class HACMSWindow(QMainWindow): def __init__(self): super(HACMSWindow, self).__init__() def init_window(self): self.ui.setupUi(self) self.init_data_structs() self.init_widgets() def init_data_structs(self): self.trimIncrement = 0.001 self.windowSize = 300 self.in_Base = deque(maxlen=self.windowSize) self.in_Ref = deque(maxlen=self.windowSize) self.out_Odom = deque(maxlen=self.windowSize) self.out_EncL = deque(maxlen=self.windowSize) self.out_EncR = deque(maxlen=self.windowSize) self.out_GPS = deque(maxlen=self.windowSize) def init_widgets(self): self.remote = Remote(self.ui.console) self.widgets = [ self.ui.tabWidget, self.ui.ccButton, self.ui.rcButton, self.ui.attackButton, self.ui.attackComboBox, self.ui.gpsCheckBox, self.ui.enclCheckBox, self.ui.encrCheckBox, self.ui.saveButton, self.ui.desiredSpeedLabel, self.ui.desiredSpeedEdit, self.ui.setSpeedButton, self.ui.kpLabel, self.ui.kpEdit, self.ui.setKPButton, self.ui.kiLabel, self.ui.kiEdit, self.ui.setKIButton, self.ui.trimLabel, self.ui.trimValueLabel, self.ui.setTrimLeftButton, self.ui.setTrimRightButton, self.ui.actualSpeedLabel, self.ui.actualSpeedLCD, self.ui.estimatedSpeedLabel, self.ui.estimatedSpeedLCD, self.ui.outputPlot, self.ui.outputPlotLabel, self.ui.inputPlot, self.ui.inputPlotLabel, self.ui.rightPlot, self.ui.rightPlotLabel ] #self.ui.mapView.setScene(MapnikScene(self.ui.mapView)) #self.ui.mapView = MapView(self.ui.mapWidget) self.init_signals() self.init_plots() #self.init_waypoints() def init_signals(self): self.ui.actionAbout.triggered.connect(self.about) self.ui.actionQuit.triggered.connect(self.fileQuit) self.ui.landsharkButton.toggled.connect(self.landshark) self.ui.ccButton.toggled.connect(self.cc) self.ui.rcButton.toggled.connect(self.rc) self.ui.attackButton.toggled.connect(self.attack) self.ui.attackComboBox.currentIndexChanged.connect(self.attackMode) self.ui.gpsCheckBox.toggled.connect(self.attackSensor) self.ui.enclCheckBox.toggled.connect(self.attackSensor) self.ui.encrCheckBox.toggled.connect(self.attackSensor) self.ui.saveButton.toggled.connect(self.saveData) self.ui.setSpeedButton.clicked.connect(self.setLandsharkSpeed) self.ui.setKPButton.clicked.connect(self.setKP) self.ui.setKIButton.clicked.connect(self.setKI) self.ui.setTrimLeftButton.clicked.connect(self.setTrimLeft) self.ui.setTrimRightButton.clicked.connect(self.setTrimRight) # Set Validator for parameter fields self.validator = QDoubleValidator() self.validator.setNotation(QDoubleValidator.StandardNotation) self.ui.desiredSpeedEdit.setValidator(self.validator) self.ui.kpEdit.setValidator(self.validator) self.ui.kiEdit.setValidator(self.validator) def init_plots(self): self.ui.inputPlot.disableAutoRange(pg.ViewBox.YAxis) self.ui.inputPlot.setYRange(0, 1.3, 0) self.ui.inputPlot.setBackground('w') self.ui.inputPlot.hideButtons() self.ui.inputPlot.showGrid(False, True) #self.ui.inputPlot.addLegend() #self.ui.inputPlot.setLabel('left', 'speed') self.ui.inputPlot.setLabel('top', ' ') self.ui.inputPlot.setLabel('right', ' ') self.ui.inputPlot.setLabel('bottom', 'time') #self.ui.inputPlot.setTitle('Input') self.inputPlotBase = self.ui.inputPlot.plot(self.in_Base, name='CMD') self.inputPlotBase.setPen(pg.mkPen(width=3, color='r')) self.inputPlotRef = self.ui.inputPlot.plot(self.in_Ref, name='REF') self.inputPlotRef.setPen(pg.mkPen(width=3, color='c')) self.inputPlotTimer = QTimer() self.inputPlotTimer.timeout.connect(self.updateInputPlot) self.ui.outputPlot.setBackground('w') self.ui.outputPlot.hideButtons() self.ui.outputPlot.showGrid(False, True) #self.ui.outputPlot.addLegend() #self.ui.outputPlot.setLabel('left', 'speed') self.ui.outputPlot.setLabel('top', ' ') self.ui.outputPlot.setLabel('right', ' ') self.ui.outputPlot.setLabel('bottom', 'time') #self.ui.outputPlot.setTitle('Output') self.outputPlotGPS = self.ui.outputPlot.plot(self.out_GPS, name='GPS') self.outputPlotGPS.setPen(pg.mkPen(width=3, color='m')) self.outputPlotLE = self.ui.outputPlot.plot(self.out_EncL, name='ENC LEFT') self.outputPlotLE.setPen(pg.mkPen(width=3, color='b')) self.outputPlotRE = self.ui.outputPlot.plot(self.out_EncR, name='ENC RIGHT') self.outputPlotRE.setPen(pg.mkPen(width=3, color='g')) self.outputPlotTimer = QTimer() self.outputPlotTimer.timeout.connect(self.updateOutputPlot) self.ui.rightPlot.disableAutoRange(pg.ViewBox.YAxis) self.ui.rightPlot.setYRange(0, 1.3, 0) self.ui.rightPlot.setBackground('w') self.ui.rightPlot.hideButtons() self.ui.rightPlot.showGrid(False, True) #self.ui.rightPlot.addLegend() #self.ui.rightPlot.setLabel('left', 'speed') self.ui.rightPlot.setLabel('top', ' ') self.ui.rightPlot.setLabel('right', ' ') self.ui.rightPlot.setLabel('bottom', 'time') #self.ui.rightPlot.setTitle('Odometry') self.rightPlotOdom = self.ui.rightPlot.plot(self.out_Odom, name='SPEED') self.rightPlotOdom.setPen(pg.mkPen(width=3, color='b')) self.rightPlotRef = self.ui.rightPlot.plot(self.in_Ref, name='REF') self.rightPlotRef.setPen(pg.mkPen(width=3, color='c')) self.rightPlotTimer = QTimer() self.rightPlotTimer.timeout.connect(self.updateRightPlot) def startPlotTimers(self): timerMsec = 500 self.inputPlotTimer.start(timerMsec) self.outputPlotTimer.start(timerMsec) self.rightPlotTimer.start(timerMsec) def stopPlotTimers(self): self.inputPlotTimer.stop() self.outputPlotTimer.stop() self.rightPlotTimer.stop() def init_waypoints(self): self.waypointList = QStringList() self.waypointList.append("test") self.waypointModel = QStringListModel() self.ui.waypointListView.setModel(self.waypointModel) self.waypointModel.setStringList(self.waypointList) def about(self): about = QDialog() about.ui = ui.about_ui.Ui_Dialog() about.ui.setupUi(about) about.exec_() def fileQuit(self): if self.ui.landsharkButton.isChecked(): self.stop_landshark_comm() self.close() def closeEvent(self, ce): self.fileQuit() def zeroData(self): self.in_Base.clear() self.in_Ref.clear() self.out_Odom.clear() self.out_EncL.clear() self.out_EncR.clear() self.out_GPS.clear() def enableAllElements(self): for widget in self.widgets: widget.setEnabled(True) self.zeroData() def disableAllElements(self): self.cc(False) self.rc(False) self.attack(False) self.saveData(False) for widget in self.widgets: widget.setEnabled(False) def landshark(self, checked): if checked: res = self.remote.startLandshark() self.start_landshark_comm() self.enableAllElements() self.startPlotTimers() else: self.stopPlotTimers() self.disableAllElements() self.stop_landshark_comm() res = self.remote.stopLandshark() self.ui.landsharkButton.setChecked(res) def cc(self, checked): if checked: res = self.remote.startCC() self.zeroData() else: self.saveData(False) self.rc(False) self.attack(False) res = self.remote.stopCC() self.ui.ccButton.setChecked(res) def saveData(self, checked): if checked: res = self.remote.startSaveData() else: res = self.remote.stopSaveData() self.ui.saveButton.setChecked(res) def rc(self, checked): if checked: try: self.run_rc_pub.publish(Int32(1)) except: self.ui.rcButton.setChecked(False) return else: try: self.run_rc_pub.publish(Int32(0)) except: self.ui.rcButton.setChecked(True) return # For when the button is set via direct method call, not by event call self.ui.rcButton.setChecked(checked) def attack(self, checked): if checked: try: self.run_attack_pub.publish(Int32(self.ui.attackComboBox.currentIndex()+1)) self.sensor_attack_pub.publish(Int32(self.getAttackSensorValue())) except: self.ui.attackButton.setChecked(False) return else: try: self.run_attack_pub.publish(Int32(0)) except: self.ui.attackButton.setChecked(True) return # For when the button is set via direct method call, not by event call self.ui.attackButton.setChecked(checked) # Called by attackMode combobox when there is a change in the selected index. def attackMode(self, index): if self.ui.attackButton.isChecked(): try: self.run_attack_pub.publish(Int32(index+1)) # Start base index at 1 except: return # Called by sensor checkboxes when there is a check or uncheck event. def attackSensor(self): if self.ui.attackButton.isChecked(): try: self.sensor_attack_pub.publish(Int32(self.getAttackSensorValue())) except: return # Determine the appropriate binary-style representation for which sensor checkboxes are checked. def getAttackSensorValue(self): value = 0 if self.ui.gpsCheckBox.isChecked(): value += 4 if self.ui.enclCheckBox.isChecked(): value += 2 if self.ui.encrCheckBox.isChecked(): value += 1 return value def getWidgetColor(self, widget): style = widget.styleSheet() if "background-color: green;" in style: return "green" if "background-color: red;" in style: return "red" def toggleWidgetColor(self, widget, setColor=None): style = widget.styleSheet() if setColor is None: if self.getWidgetColor(widget) is "green": widget.setStyleSheet(string.replace(style, "background-color: green;", "background-color: red;")) elif self.getWidgetColor(widget) is "red": widget.setStyleSheet(string.replace(style, "background-color: red;", "background-color: green;")) else: if setColor is "red": widget.setStyleSheet(string.replace(style, "background-color: green;", "background-color: red;")) elif setColor is "green": widget.setStyleSheet(string.replace(style, "background-color: red;", "background-color: green;")) def updateActualSpeedLCD(self, value): self.ui.actualSpeedLCD.display(value) def updateEstimatedSpeedLCD(self, value): self.ui.estimatedSpeedLCD.display(value) def updateInputPlot(self): """ Redraws the input plot """ self.inputPlotBase.setData(self.in_Base) self.inputPlotRef.setData(self.in_Ref) def updateOutputPlot(self): """ Redraws the output plot """ self.outputPlotGPS.setData(self.out_GPS) self.outputPlotLE.setData(self.out_EncL) self.outputPlotRE.setData(self.out_EncR) def updateRightPlot(self): """ Redraws the righthand plot """ self.rightPlotOdom.setData(self.out_Odom) self.rightPlotRef.setData(self.in_Ref) def setLandsharkSpeed(self): self.desired_speed_pub.publish(Float32(float(self.ui.desiredSpeedEdit.text()))) def setKP(self): self.kp_pub.publish(Float32(float(self.ui.kpEdit.text()))) def setKI(self): self.ki_pub.publish(Float32(float(self.ui.kiEdit.text()))) def setTrimLeft(self): # Get current trim value trim = float(self.ui.trimValueLabel.text()) # Decrement trim value trim -= self.trimIncrement # Display updated trim value self.ui.trimValueLabel.setText(str(trim)) # Publish new trim value self.trim_pub.publish(Float32(trim)) def setTrimRight(self): # Get current trim value trim = float(self.ui.trimValueLabel.text()) # Increment trim value trim += self.trimIncrement # Display updated trim value self.ui.trimValueLabel.setText(str(trim)) # Publish new trim value self.trim_pub.publish(Float32(trim)) def start_landshark_comm(self): # Initialize ROS node rospy.init_node('landshark_demo', disable_signals=True) # Subscribe to HACMS Demo topics self.base_sub = rospy.Subscriber("/landshark_demo/base_vel", TwistStamped, self.captureBase) self.ref_sub = rospy.Subscriber("/landshark_demo/ref_vel", TwistStamped, self.captureRef) self.est_sub = rospy.Subscriber("/landshark_demo/est_vel", TwistStamped, self.captureEst) self.odom_sub = rospy.Subscriber("/landshark_demo/odom", Odometry, self.captureOdom) self.encL_sub = rospy.Subscriber("/landshark_demo/left_enc_vel", TwistStamped, self.captureEncL) self.encR_sub = rospy.Subscriber("/landshark_demo/right_enc_vel", TwistStamped, self.captureEncR) self.gps_sub = rospy.Subscriber("/landshark_demo/gps_vel", TwistStamped, self.captureGPS) # Publish to HACMS Demo topics self.desired_speed_pub = rospy.Publisher('/landshark_demo/desired_speed', Float32) self.trim_pub = rospy.Publisher('/landshark_demo/trim', Float32) self.kp_pub = rospy.Publisher('/landshark_demo/kp', Float32) self.ki_pub = rospy.Publisher('/landshark_demo/ki', Float32) self.run_rc_pub = rospy.Publisher('/landshark_demo/run_rc', Int32) self.run_attack_pub = rospy.Publisher('/landshark_demo/run_attack', Int32) self.sensor_attack_pub = rospy.Publisher('/landshark_demo/sensor_attack', Int32) return True def stop_landshark_comm(self): # Unregister HACMS Demo subscribed topics self.base_sub.unregister() self.ref_sub.unregister() self.est_sub.unregister() self.odom_sub.unregister() self.encL_sub.unregister() self.encR_sub.unregister() self.gps_sub.unregister() # Unregister HACMS Demo published topics self.desired_speed_pub.unregister() self.trim_pub.unregister() self.kp_pub.unregister() self.ki_pub.unregister() self.run_rc_pub.unregister() self.run_attack_pub.unregister() self.sensor_attack_pub.unregister() #rospy.signal_shutdown("Turning off ROSPy") TODO - How do we restart ROSPy # Keep in mind ROSPy doesn't properly start back up when this is uncommented. return True def captureBase(self, msg): self.in_Base.append(msg.twist.linear.x) def captureRef(self, msg): self.in_Ref.append(msg.twist.linear.x) def captureEst(self, msg): self.updateEstimatedSpeedLCD(msg.twist.linear.x) def captureOdom(self, msg): self.updateActualSpeedLCD(msg.twist.twist.linear.x) self.out_Odom.append(msg.twist.twist.linear.x) def captureEncL(self, msg): self.out_EncL.append(msg.twist.linear.x) def captureEncR(self, msg): self.out_EncR.append(msg.twist.linear.x) def captureGPS(self, msg): self.out_GPS.append(msg.twist.linear.x) return
class RemoteGUI: def __init__(self, master, debug=False): # get the screen size so we can calculate the offset screenwidth = master.winfo_screenwidth() screenheight = master.winfo_screenheight() # centre it (sort of) xoffset = round(screenwidth / 2) yoffset = round(screenheight / 3) # set the root window size master.geometry('{width}x{height}+{xoffset}+{yoffset}'.format(width=200, height=100, xoffset=xoffset, yoffset=yoffset)) self._get_port(master) def _connect(self, port): try: self.rem = Remote(port) return True except RemoteConnectionError: return False def _get_port(self, master): def set_port(): port = entry.get() if self._connect(port): connect_frame.destroy() self._draw_interface(master) else: messagebox.showerror('Connection error', "Could not connect on '{}'".format(port)) connect_frame = tk.Frame(master) connect_frame.pack() message = tk.Message(connect_frame, width=100, text='Enter port') message.pack() entry = tk.Entry(connect_frame, takefocus=True) entry.pack() entry.insert(0, 'port') connect_button = tk.Button(connect_frame, text='connect', command=set_port) connect_button.pack() def _draw_interface(self, master): master.geometry('{width}x{height}'.format(width=200, height=150)) frame = tk.Frame(master) frame.pack() forward_button = tk.Button(frame, text="forward", command=self.go_forward) forward_button.pack(side='top') back_button = tk.Button(frame, text="back", command=self.go_back) back_button.pack(side='bottom') left_button = tk.Button(frame, text='left', command=self.go_left) left_button.pack(side='left') right_button = tk.Button(frame, text='right', command=self.go_right) right_button.pack(side='right') # bind keyboard keys to events master.bind('<Up>', self.go_forward) master.bind('w', self.go_forward) master.bind('<Down>', self.go_back) master.bind('s', self.go_back) master.bind('<Left>', self.go_left) master.bind('a', self.go_left) master.bind('<Right>', self.go_right) master.bind('d', self.go_right) def terminate_command(f): def wrapper(*args): # when we use a keyboard key binding # it also passes an Event object along # so we want to ignore it without breaking things self = args[0] f(self) self.rem.send('0') return wrapper @terminate_command def go_forward(self): self.rem.send('f') @terminate_command def go_back(self): self.rem.send('b') @terminate_command def go_left(self): self.rem.send('l') @terminate_command def go_right(self): self.rem.send('r')
import flask import settings #Views from main import Main from login import Login from remote import Remote from music import Music app = flask.Flask(__name__) app.secret_key = settings.secret_key #Routes app.add_url_rule('/', view_func=Main.as_view('main'), methods=["GET"]) app.add_url_rule('/<page>/', view_func=Main.as_view('main'), methods=["GET"]) app.add_url_rule('/login/', view_func=Login.as_view('login'), methods=["GET", "POST"]) app.add_url_rule('/remote/', view_func=Remote.as_view('remote'), methods=["GET", "POST"]) app.add_url_rule('/music/', view_func=Music.as_view('music'), methods=["GET"]) @app.errorhandler(404) def page_not_found(error): return flask.render_template('404.html'), 404 app.debug = True app.run()