From f0049295539f8ac6c298f53b0557ea0545b41777 Mon Sep 17 00:00:00 2001 From: erik Date: Sat, 3 Jan 2015 11:50:15 +0100 Subject: [PATCH] Initial commit --- console.py | 50 ++++++++++++++++++++++++++++++++++ json_client.py | 61 +++++++++++++++++++++++++++++++++++++++++ scheduler.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100755 console.py create mode 100755 json_client.py create mode 100755 scheduler.py diff --git a/console.py b/console.py new file mode 100755 index 0000000..4534df1 --- /dev/null +++ b/console.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-15 -*- + +import os +import rlcompleter +import readline +import code +import atexit + + +class irlcompleter(rlcompleter.Completer): + def complete(self, text, state): + if text == "": + # you could replace \t to 4 or 8 spaces if you prefer indent via spaces + return ['\t', None][state] + else: + return rlcompleter.Completer.complete(self, text, state) + + +class HistoryConsole(code.InteractiveConsole): + def __init__(self, locales=None, filename="", histfile=os.path.expanduser("~/.console-history"), custom_interpreter=None): + code.InteractiveConsole.__init__(self, locales, filename) + self.init_history(histfile) + self.custom_interpreter = custom_interpreter + + def init_history(self, histfile): + readline.parse_and_bind("tab: complete") + readline.set_completer(irlcompleter().complete) + + if hasattr(readline, "read_history_file"): + try: + readline.read_history_file(histfile) + except IOError: + pass + atexit.register(self.save_history, histfile) + + def save_history(self, histfile): + readline.write_history_file(histfile) + + def push(self, line): + line = line.encode("iso-8859-15", "replace") + if self.custom_interpreter: + if self.custom_interpreter(line): + return + return code.InteractiveConsole.push(self, line) + + +if __name__ == "__main__": + con = HistoryConsole(locales=locals()) + con.interact(banner="") diff --git a/json_client.py b/json_client.py new file mode 100755 index 0000000..43634d6 --- /dev/null +++ b/json_client.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-15 -*- + +import sys +import socket +import json + +def set_keepalive(sock, after_idle_sec=1, interval_sec=3, max_fails=5): + """Set TCP keepalive on an open socket. + + It activates after 1 second (after_idle_sec) of idleness, + then sends a keepalive ping once every 3 seconds (interval_sec), + and closes the connection after 5 failed ping (max_fails), or 15 seconds + """ + sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails) +if not hasattr(socket, "set_keepalive"): + socket.set_keepalive = set_keepalive + +class JsonClient: + def __init__(self, addr = ("panda", 10002)): + self.pSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.pSocket.settimeout(1) + socket.set_keepalive(self.pSocket) + self.pSocket.connect(addr) + self.lMsgs = [] + + def write(self, cmd): + data = {'command': cmd} + num = self.pSocket.sendall(json.dumps(data)) + while True: + msg = json.loads(self.pSocket.recv(4096)) + if msg.has_key("return"): return msg["return"] + elif msg.has_key("error"): return msg["error"] + self.lMsgs.insert(0, msg) + + def read(self): + if len(self.lMsgs) > 0: + return self.lMsgs.pop() + self.pSocket.setblocking(False) + try: + return json.loads(self.pSocket.recv(4096)) + except socket.error: + pass + finally: + self.pSocket.setblocking(True) + +if __name__ == "__main__": + print JsonClient().write(sys.argv[1]) + + #from datetime import datetime + #from time import sleep + #pClient = JsonClient() + #while True: + # msg = pClient.read() + # if msg: + # print "Got async", msg + # print datetime.now(), float(pClient.write("get distance forward lower")) + # sleep(0.1) diff --git a/scheduler.py b/scheduler.py new file mode 100755 index 0000000..8310a6d --- /dev/null +++ b/scheduler.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-15 -*- + +import logging +import threading +from time import sleep + + +logger = logging.getLogger(__name__) + +class Scheduler: + def __init__(self): + self.lThreads = [] + self.pause = False + self.autoclean() + self.__lock_delay = threading.Lock() + + def autoclean(self): + logger.debug("Current number of threads: %d" % threading.active_count()) + self.add_thread(10, self.autoclean) + for t in self.lThreads: + if not t.isAlive(): + self.lThreads.remove(t) + + def stop(self): + for t in self.lThreads: + t.cancel() + + def add_thread(self, time, function, args=[], kwargs={}): + while(self.pause): + sleep(1) + k = [function, None, args, kwargs] + t = threading.Timer(time, self.dispatch, k) + t.setDaemon(True) + t.setName(str(function)) + k[1] = t + t.delayed = True + t.start() + self.lThreads.append(t) + + def dispatch(self, function, timer, args, kwargs): + while True: + with self.__lock_delay: + still_running = False + for t in self.lThreads: + if t.name == str(function) and t.isAlive() and t.ident != timer.ident and not t.delayed: + still_running = True + break + if not still_running: + t.delayed = False + break + logger.debug("Delaying execution of Thread %s", t.name) + # Another Thread still running, delay execution + sleep(0.1) + try: + function(*args, **kwargs) + except: + logger.exception("Dispatcher exception of %s:", t.name) + logger.error("Current number of threads: %d" % threading.active_count()) + + +pScheduler = Scheduler() + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG) + def test(): + pScheduler.add_thread(0.1, test) + print "test" + sleep(1) + print "end" + test() + + while(1): + sleep(0.1) -- 2.39.2