Exemple #1
0
class YetiSocket():
    def __init__(self, host='localhost', port=5001):
        self.io = SocketIO(host, port)
        self.cam = self.io.define(CamNamespace, '/cam')

        self.cam.on('config_update', self.config_update)
        self.cam.on('manual_capture', self.manual_capture)

        self._thread = threading.Thread(target=self.io.wait)
        self._thread.daemon = True
        self._thread.start()

    def send(self, event, data):
        self.cam.emit(event, data)

    def config_update(self, data):
        print 'config update: %s' % data

    def manual_capture(self, data):
        print 'manual capture: ' + data
        
    def connect(self):
        self.cam.connect()

    def disconnect(self):
        self.cam.disconnect()
        self.io.disconnect()

    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_value, exc_tb):
        self.disconnect()
Exemple #2
0
class SocketIOHandler(object):

    def __init__(self, cfg):
        """
        save the server config..
        """
        self.server_address = cfg['graphite_ip']
        self.server_port = cfg['graphite_port']
        self.namespace = cfg['graphite_namespace']
        self.socketIO = None
        self.channel = None

    def handle(self, non_metrics):
        if len(non_metrics) == 0:
            logging.debug('No metrics be handled!')
            return

        nm_list = []
        for nm in non_metrics:
            nm_list.append(dumps(nm.to_dict()))  # serialized to json
        msg_type = non_metrics[0].type
        self.socketIO = SocketIO(self.server_address, self.server_port, BaseNamespace)
        self.channel = self.socketIO.connect(self.namespace, BaseNamespace)
        self.channel.emit(msg_type, nm_list, self.on_response)  # send to server
        self.socketIO.wait(forCallbacks=True)
        logging.debug('SokcetIOHandler emitting %s to sever:\n %s' % (msg_type, dumps(nm_list)))

    def on_response(self, *args):
        # is it necessary?
        self.socketIO.disconnect()
        logging.debug('emit non metrics success!')
Exemple #3
0
class LoveSocket:
    def __init__(self):
        self.io = None
        self.hearts = 0
        self.poos = 0

    def start(self):
        threading.Thread(target=self.__start).start()

    def __start(self):
        self.io = SocketIO(LOVE_SOCKET_URL, verify=False)
        self.io.on("love", self.__add_love)
        self.io.on("poo", self.__add_poo)
        self.io.wait()

    def stop(self):
        self.io.disconnect()
        self.io = None

    def reset_hearts(self):
        hearts = self.hearts
        self.hearts = 0
        return hearts

    def reset_poos(self):
        poos = self.poos
        self.poos = 0
        return poos

    def __add_love(self, *args):
        self.hearts += 1

    def __add_poo(self, *args):
        self.poos += 1
class TestClient(object):
    def on_bot_uttered(self, event):
        self.flusso.append((logging.INFO, '[-] bot_uttered: ' + event['text']))
        try:
            self.answerList.append(event['text'])
        except KeyError:
            pass

    def __init__(self, section, server, port, flusso, secs):
        self.answerList = []
        self.flusso = flusso
        i = 0
        self.newSocket = SocketIO(server, port)
        self.newSocket.on('bot_uttered', self.on_bot_uttered)
        for client_msg in section['client']:
            self.flusso.append(
                (logging.INFO, "[+] usr_uttered: " + client_msg))
            self.newSocket.emit('user_uttered', {
                'message': client_msg,
                'customData': ""
            })
            self.newSocket.wait(seconds=secs)
        self.newSocket.disconnect()
        flag_num = (len(self.answerList) == len(section['server']))
        flag_test = all(
            list(
                map(lambda x: bool(re.search(x[1], x[0])),
                    zip(self.answerList, section['server']))))
        if flag_num and flag_test:
            self.flusso.append((logging.INFO, "[!] Test PASSED"))
        else:
            self.flusso.append((logging.ERROR, "[!] Test FAILED"))
Exemple #5
0
def send(to, value):
    Peers.init()
    Mongo.init()
    used_inputs = []
    new_inputs = []

    try:
        transaction = TransactionFactory(fee=0.01,
                                         public_key=Config.public_key,
                                         private_key=Config.private_key,
                                         outputs=[Output(to=to, value=value)])
    except NotEnoughMoneyException as e:
        print "not enough money yet"
        return
    except:
        raise
    try:
        transaction.transaction.verify()
    except:
        print 'transaction failed'
    TU.save(transaction.transaction)
    print 'Transaction generated successfully. Sending:', value, 'To:', to
    for peer in Peers.peers:
        try:
            socketIO = SocketIO(peer.host,
                                peer.port,
                                wait_for_connection=False)
            chat_namespace = socketIO.define(ChatNamespace, '/chat')
            chat_namespace.emit('newtransaction',
                                transaction.transaction.to_dict())
            socketIO.disconnect()
            print 'Sent to:', peer.host, peer.port
        except Exception as e:
            print e
def emit_message_to_OMRMS(status, message):
    clientSocket = SocketIO('127.0.0.1', 8000, LoggingNamespace)
    clientSocket.emit(status, message)
    clientSocket.disconnect()


#clientSocket.on('salutation', on_salutation)
class SocketProxy(object):
    def __init__(self, id, host, port):
        self.client = SocketIO(host, port, BaseNamespace)
        self.client.on('log', self.on_log)
        self.client.on('end', self.on_end)
        self.client.on('playbook-start', self.on_playbook_start)
        self.client.on('playbook-stop', self.on_playbook_stop)
        self.client.on('playbook-error', self.on_playbook_error)
        self.client.emit('join', id)

    def on_log(self, message):
        emit("log", message)

    def on_end(self, message):
        emit("end")
        self.client.disconnect()

    def on_playbook_start(self, playbook):
        emit("playbook-start", playbook)

    def on_playbook_stop(self, playbook):
        emit("playbook-stop", playbook)

    def on_playbook_error(self, playbook):
        emit("playbook-error", playbook)

    def wait(self):
        self.client.wait()  # seconds=5)
        # Hack! _close is needed to *really* close the connection
        self.client._close()
class WxSocket(threading.Thread):
    def __init__(self, callbacks, host, port):
        super(WxSocket, self).__init__()
        self.callbacks = callbacks
        self.host = host
        self.port = port
        self.daemon = True  #this will kill the thread when the main thread exits
        self.start()

    #this is the worker function that will be held in the other thread
    def run(self):
        self.io = SocketIO(self.host, self.port, LoggingNamespace)

        for event, callback in self.callbacks.iteritems():
            self.io.on(event, callback)

        self.io.wait()

    def connect(self):
        self.io.connect()

    def disconnect(self):
        self.io.disconnect()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, exc_tb):
        self.disconnect()
Exemple #9
0
class DocumentSyncTest(BaseTestCase):
    def setUp(self):
        super(DocumentSyncTest, self).setUp()
        self.client = SocketIO('localhost', config.SERVER_PORT, DocumentNamespace)
        self.doc = self.client.define(DocumentNamespace, DOCUMENT_NAMESPACE)
        global RECEIVED
        RECEIVED = {}

    def tearDown(self):
        super(DocumentSyncTest, self).tearDown()
        self.client.disconnect()

    def test_echo(self):
        self.doc.on('echo', on_echo_response)

        self.doc.emit('echo', 'hello world')
        self.client.wait(seconds=1)

        self.assertTrue(RECEIVED.get('on_echo_response', False))

    def test_single_client(self):
        self.doc.on('userlist', on_userlist_response)
        self.doc.on('document', on_document_response)

        self.doc.emit('join', {'username': '******', 'document': DOCUMENT_ID})

        self.client.wait(seconds=1)

        self.doc.emit('leave', {'username': '******', 'document': DOCUMENT_ID})

        self.assertTrue(RECEIVED.get('on_userlist_response', False))
        self.assertTrue(RECEIVED.get('on_document_response', False))
Exemple #10
0
def Volumio(server, port):
    global volumioIO
    global volumioThread

    class VolumioNamespace(LoggingNamespace):
        def on_pushState(self, state):
            logger.debug("Received event 'pushState' from Volumio")
            global volumioState
            volumioState = state

        def on_event(self, event, *args):
            logger.debug("Received event '%s' from Volumio (unhandled)", event)

    logger.debug("[Volumio] Connect to '%s:%d'", server, port)
    volumioIO = SocketIO(server,
                         port,
                         VolumioNamespace,
                         wait_for_connection=False)
    volumioThread = threading.Thread(target=volumioIO.wait)
    volumioThread.start()
    try:
        yield volumioIO
    finally:
        logger.debug("[Volumio] Disconnect from '%s:%d'", server, port)
        volumioIO.disconnect()
        volumioIO = None
        volumioThread.join()
        volumioThread = None
Exemple #11
0
class AtlasStream(object):

    CHANNEL_RESULT = "atlas_result"
    CHANNEL_PROBE = "atlas_probestatus"
    CHANNEL_ERROR = "atlas_error"
    CHANNELS = {
        "result": CHANNEL_RESULT,
        "probe": CHANNEL_PROBE,
        "error": CHANNEL_ERROR,
    }

    def __init__(self):
        """Initialize stream"""

        self.iosocket_server = "atlas-stream.ripe.net"
        self.iosocket_resource = "/stream/socket.io"

        self.socketIO = None

    def connect(self):
        """Initiate the channel we want to start streams from."""
        self.socketIO = SocketIO(host=self.iosocket_server,
                                 port=80,
                                 resource=self.iosocket_resource,
                                 transports=["websocket"])

    def disconnect(self):
        """Exits the channel k shuts down connection."""
        self.socketIO.disconnect()
        self.socketIO.__exit__([])

    def bind_channel(self, channel, callback):
        """Bind given channel with the given callback"""
        try:
            self.socketIO.on(self.CHANNELS[channel], callback)
        except KeyError:
            print("The given channel: <{0}> is not valid".format(channel))

    def start_stream(self, stream_type, **stream_parameters):
        """Starts new stream for given type with given parameters"""
        if stream_type in ("result", "probestatus"):
            self.subscribe(stream_type, **stream_parameters)
        else:
            print("Given stream type: <{0}> is not valid".format(stream_type))

    def subscribe(self, stream_type, **parameters):
        """Subscribe to stream with give parameters."""
        parameters.update({"stream_type": stream_type})
        self.socketIO.emit('atlas_subscribe', parameters)

    def timeout(self, seconds=None):
        """
        Times out all streams after n seconds or wait forever if seconds is
        None
        """
        if seconds is None:
            self.socketIO.wait()
        else:
            self.socketIO.wait(seconds=seconds)
Exemple #12
0
class ExaBGP():
    def __init__(self, prefixes, host):
        self.host = host
        self.prefixes = prefixes
        self.sio = None
        signal.signal(signal.SIGTERM, self.exit)
        signal.signal(signal.SIGINT, self.exit)
        signal.signal(signal.SIGCHLD, signal.SIG_IGN)

    def start(self):
        with Connection(RABBITMQ_HOST) as connection:
            self.connection = connection
            self.exchange = Exchange('bgp-update',
                                     channel=connection,
                                     type='direct',
                                     durable=False)
            self.exchange.declare()

            try:
                self.sio = SocketIO('http://' + self.host,
                                    namespace=BaseNamespace)

                def exabgp_msg(bgp_message):
                    msg = {
                        'type': bgp_message['type'],
                        'communities': bgp_message.get('communities', []),
                        'timestamp': float(bgp_message['timestamp']),
                        'path': bgp_message.get('path', []),
                        'service': 'exabgp|{}'.format(self.host),
                        'prefix': bgp_message['prefix'],
                        'peer_asn': int(bgp_message['peer_asn'])
                    }
                    if mformat_validator(msg):
                        with Producer(connection) as producer:
                            msgs = normalize_msg_path(msg)
                            for msg in msgs:
                                key_generator(msg)
                                log.debug(msg)
                                producer.publish(msg,
                                                 exchange=self.exchange,
                                                 routing_key='update',
                                                 serializer='json')
                    else:
                        log.warning('Invalid format message: {}'.format(msg))

                self.sio.on('exa_message', exabgp_msg)
                self.sio.emit('exa_subscribe', {'prefixes': self.prefixes})
                self.sio.wait()
            except KeyboardInterrupt:
                self.exit()
            except Exception:
                log.exception('exception')

    def exit(self):
        print('Exiting ExaBGP')
        if self.sio is not None:
            self.sio.disconnect()
            self.sio.wait()
class Sentiment():

    HOST = 'https://emosapi.com'
    PORT = 443
    APPKEY = '<APP KEY>'
    APPSECRET = '<APP SECRET>'
    
    socket_io = None
    s_thread_login = None
    s_thread_post = None
    
    def connect(self):
        self.socket_io = SocketIO(self.HOST, self.PORT, verify=False)
        self.socket_io.on('success', self.on_success)
        self.socket_io.on('response', self.on_response)
        self.socket_io.emit(
            'login',
            {'appkey': self.APPKEY, 'appsecret': self.APPSECRET}
        )

        self.s_thread_login = threading.Thread(target=self.socket_io.wait)
        self.s_thread_login.start()

    def on_success(self, res):
        print("SUCCESS:", res)
        if res.get('action') == 'login' and res.get('code') == 100:
            self.socket_io.emit(
                'post',
                {
                    'api': 'Sentimentv2',
                    'version': 'emotion',
                    'params': {
                        'text': 'required parameter', # Hard coded test text.
                        'lang':'en-us'
                    }
                }
            )
            self.s_thread_post = threading.Thread(target=self.socket_io.wait)
            self.s_thread_post.start()
        else:
            raise Exception("Login failed")
    
    def on_response(self, res):
        print("RESPONSE", res)
        # Disconnect when get API response. 
        self.disconnect()
        
    def disconnect(self):
        if not self.socket_io:
            raise Exception("Please connect first.")

        print("disconnect before:", self.socket_io.connected)
        self.socket_io.disconnect()        
        print("disconnect after:", self.socket_io.connected)

        self.socket_io = None
        self.s_thread_login = None
        self.s_thread_post = None
class ClientSocketIO:
    def __init__(self, host, port, lamp_code):
        self.host = host
        self.port = port
        self.lamp_code = lamp_code
        self.socket_client = None

    def connect(self):
        if self.socket_client is None:
            self.socket_client = SocketIO(
                self.host,
                self.port,
                LoggingNamespace,
                params={'code': self.lamp_code},
            )
            self.socket_client.on('connect', self.on_connect)
            self.socket_client.on('disconnect', self.on_disconnect)
            self.socket_client.on('reconnect', self.on_reconnect)
            self.socket_client.on('message', self.on_message_response)
            self.socket_client.on('close', self.close)

    def close(self):
        self.socket_client.disconnect()

    def on_connect(self):
        print('Connected to host = ' + self.host + ' port = ' + str(self.port))

    def on_disconnect(self):
        print('disconnect to host = ' + self.host + ' port = ' +
              str(self.port))

    def on_reconnect(self):
        print('reconnect to host = ' + self.host + ' port = ' + str(self.port))

    def add_new_event(self, event, callback):
        self.socket_client.on(event, callback)

    def on_message_response(self, *args):
        for item in args:
            print('message response', item)

    def on_value_response(self, value):
        print('Value = ', value)

    def on_color_response(self, color):
        print('Color = ', color)

    def emit(self, message):
        if self.socket_client is not None:
            print('Sending message: ', message)
            self.socket_client.emit('message', message)

    def emit_close(self):
        if self.socket_client is not None:
            self.socket_client.emit('close', True)

    def wait(self):
        self.socket_client.wait()
def ices_get_next():
    global io, file, HOST, PORT, STATION, TOKEN
    io = SocketIO(HOST, PORT, Namespace)
    io.emit('next', { 'station': STATION, 'token': TOKEN })
    io.wait(seconds=1)
    io.disconnect()
    path = file.encode('utf8') # Path to audio file, must be of 'str' type (not 'unicode'), e.g. "/music/Beatles - Yesterday.mp3"
    file = '' # Clear so it wont repeat in case the 'next' callback timeouts
    return path
Exemple #16
0
class CanvasClient(object):
    def __init__(self, options):
        self.name = options["name"]
        self.moduleName = options["moduleName"]
        self.className = options["className"]
        if not self.className:
            raise Exception("Must give python modules a class name in options")
        self.serverIP = options["serverIP"]
        self.serverPort = options["serverPort"]
        self.options = options

        module = importlib.import_module("modules.%s" % self.moduleName)
        klass = getattr(module, self.className)
        self.module = klass(self, self.options)
        self.socket = None

    def connect(self):
        self.socketIO = SocketIO(self.serverIP, self.serverPort)
        self.socketIO.on('event', self.onEvent)
        self.socketIO.on('action', self.onAction)
        self.socketIO.wait()

    def disconnect(self):
        self.socketIO.disconnect()

    def onEvent(self, message):
        print "%s %s %s" % (self.name, "onEvent", message)
        self.module.onEvent(message)
        sys.stdout.flush()

    def onAction(self, message):
        print "%s %s %s" % (self.name, "onAction", message)
        if "to" in message and message["to"] == self.name:
            self.module.onAction(message)
        sys.stdout.flush()

    def emitEvent(self, event, eventData):
        message = {
            "from": self.name,
            "event": event,
            "data": eventData
        }
        print "%s %s %s" % (self.name, "emitEvent", message)
        self.socketIO.emit("event", message)
        sys.stdout.flush()

    def emitAction(self, to, action, data):
        message = {
            "from": self.name,
            "to": to,
            "action": action,
            "data": data
        }
        print "%s %s %s" % (self.name, "emitAction", message)
        self.socketIO.emit("action", message)
        sys.stdout.flush()
def ices_init():
    global io, alive, HOST, PORT, STATION, TOKEN
    io = SocketIO(HOST, PORT, Namespace)
    io.emit('alive', { 'station': STATION, 'token': TOKEN })
    io.wait(seconds=1)
    io.disconnect()
    if alive:
        return 1 # Succees
    else:
        return 0 # Failure
Exemple #18
0
 def run(self):
     i = 0
     for i in range(0, 3):
         socket_client = SocketIO('192.168.43.120', 3000, LoggingNamespace)
         socket_client.on('/r/home/kitchen', on_subscribe)
         socket_client.emit('subscribe', 'home/kitchen')
         # socket_client.wait(seconds=10000000)
         #socket_client.on_message
         socket_client.disconnect()
         p1(i)
Exemple #19
0
 def broadcast_transaction(self, transaction):
     for peer in Peers.peers:
         try:
             print peer.to_string()
             socketIO = SocketIO(peer.host, peer.port, wait_for_connection=False)
             chat_namespace = socketIO.define(ChatNamespace, '/chat')
             chat_namespace.emit('newtransaction', transaction.to_dict())
             socketIO.disconnect()
         except Exception as e:
             print e
Exemple #20
0
    def run(cls, config, mongo):
        used_inputs = []
        new_inputs = []
        for x in mongo.site_db.faucet.find({'active': True}):
            balance = BU.get_wallet_balance(config, mongo, x['address'])
            if balance >= 25:
                mongo.site_db.faucet.update({'_id': x['_id']}, {
                    'active': False,
                    'address': x['address']
                })

                continue
            last_id_in_blockchain = x.get('last_id')
            if last_id_in_blockchain and not mongo.db.blocks.find({
                    'transactions.id':
                    last_id_in_blockchain
            }).count():

                continue

            try:
                transaction = TransactionFactory(
                    config,
                    mongo,
                    block_height=BU.get_latest_block(config, mongo)['index'],
                    fee=0.01,
                    public_key=config.public_key,
                    private_key=config.private_key,
                    outputs=[Output(to=x['address'], value=5)])
            except NotEnoughMoneyException as e:
                print "not enough money yet"
                return
            except Exception as e:
                print x
            try:
                transaction.transaction.verify()
            except:
                mongo.site_db.failed_faucet_transactions.insert(
                    transaction.transaction.to_dict())
                print 'faucet transaction failed'
            TU.save(config, mongo, transaction.transaction)
            x['last_id'] = transaction.transaction.transaction_signature
            mongo.site_db.faucet.update({'_id': x['_id']}, x)
            print 'saved. sending...', x['address']
            for peer in Peers.peers:
                try:
                    socketIO = SocketIO(peer.host,
                                        peer.port,
                                        wait_for_connection=False)
                    chat_namespace = socketIO.define(ChatNamespace, '/chat')
                    chat_namespace.emit('newtransaction',
                                        transaction.transaction.to_dict())
                    socketIO.disconnect()
                except Exception as e:
                    print e
Exemple #21
0
class Client:
    def __init__(self,
                 target_env_class,
                 i_cfg,
                 project_name=None,
                 retrain_model=False):
        # Thread.__init__(self)

        self.env_name = project_name
        self.socketIO = SocketIO('127.0.0.1', 5000)
        self.socketIO.on('connect', self.on_connect)
        self.socketIO.on('disconnect', self.on_disconnect)
        self.socketIO.on('reconnect', self.on_reconnect)
        self.socketIO.on('session_response', self.on_session_response)

        # for ctrl+C
        signal.signal(signal.SIGINT, self.signal_handler)

        # send_cfg = cfg if i_cfg == None else cfg

        self.send_cfg = i_cfg
        self.target_env_class = target_env_class

        #self.socketIO.emit('session', project_name, cfg)
        self.socketIO.emit('session', project_name, self.send_cfg,
                           retrain_model)
        self.socketIO.wait()

    def signal_handler(self, signal, frame):
        #print(signal)
        print('You pressed Ctrl+C!')
        self.target_env_class.close()
        self.socketIO.disconnect()

        sys.exit(0)

    def on_connect(self):
        print('[I] Client connect')

    def on_reconnect(self):
        print('[I] Client reconnect')

    def on_disconnect(self):
        print('[I] Client disconnect')

    def on_session_response(self, new_id):
        print('[I] Get id = {}'.format(new_id))
        new_ns = '/' + str(new_id) + '/rl_session'
        self.connect_with_ns(new_ns)

    def connect_with_ns(self, ns):
        # print('get ns ={}'.format(ns))
        new_env = self.socketIO.define(self.target_env_class, ns)
        new_env.set_cfg(self.send_cfg)
        new_env.set_name(self.env_name)
class AtlasStream(object):

    CHANNEL_RESULT = "atlas_result"
    CHANNEL_PROBE = "atlas_probe"
    CHANNEL_ERROR = "atlas_error"
    CHANNELS = {"result": CHANNEL_RESULT, "probe": CHANNEL_PROBE, "error": CHANNEL_ERROR}

    def __init__(self, **kwargs):
        """Initialize stream"""

        self.iosocket_server = "atlas-stream.ripe.net"
        self.iosocket_resource = "/stream/socket.io"

        self.socketIO = None

    def connect(self):
        """Initiate the channel we want to start streams from."""
        self.socketIO = SocketIO(
            host=self.iosocket_server, port=80, resource=self.iosocket_resource, transports=["websocket"]
        )

    def disconnect(self):
        """Exits the channel k shuts down connection."""
        self.socketIO.disconnect()
        self.socketIO.__exit__([])

    def bind_stream(self, stream_type, callback):
        """Bind given type stream with the given callback"""
        try:
            self.socketIO.on(self.CHANNELS[stream_type], callback)
        except KeyError:
            print "The given stream type: <{}> is not valid".format(stream_type)

    def start_stream(self, stream_type, **stream_parameters):
        """Starts new stream for given type with given parameters"""
        if stream_type in ("result", "probestatus"):
            self.subscribe(stream_type, **stream_parameters)
        else:
            print "Given stream type: <%s> is not valid" % stream_type

    def subscribe(self, stream_type, **parameters):
        """Subscribe to stream with give parameters."""
        parameters.update({"stream_type": stream_type})
        self.socketIO.emit("atlas_subscribe", parameters)

    def timeout(self, seconds=None):
        """
        Times out all streams after n seconds or wait forever if seconds is
        None
        """
        if seconds is None:
            self.socketIO.wait()
        else:
            self.socketIO.wait(seconds=seconds)
class EtherpadIO(object):
    def __init__(self, pad, cb,
                       host='localhost', path='p/', port='9001', secure=False,
                       verbose = False,
                       transports=['xhr-polling', 'websocket'],
                       **kwarg):
        log.debug('EtherpadIO(%s://%s:%s/%s%s")' % ('https' if secure else 'http', host,
                                                  port, path, pad))
        res = requests.get("%s://%s:%s/%s%s" % ('https' if secure else 'http',
                                                  host, port, path, pad))

        cookie = res.headers['set-cookie']
        self.cookie = dict([(cookie[:cookie.find("=")], cookie[cookie.find("=")+1:])])

        self.pad = pad
        self.cb = cb
        self.host = host
        self.path = path
        self.port = port
        self.secure = secure
        self.kwarg = kwarg
        self.transports = transports
        self.__init()

    def __init(self):
        self.epad = SocketIO(self.host, self.port,
                        EtherpadService,
                        secure=self.secure,
                        transports=self.transports,
                        cookies=self.cookie,
                        padid=self.pad,
                        cb=self.cb, **self.kwarg)

    def wait(self):
        reconnect = True
        while reconnect:
            reconnect = self.epad.wait()
            del self.epad
            if reconnect:
                self.__init()

    def has_ended(self):
        return self.epad.has_ended()

    def stop(self):
        self.epad.disconnect()

    def pause(self):
        self.epad.pause()

    def patch_text(self, old, new):
        cs = pack(old.diff(new))
        if cs:
            self.epad.namespace.send_user_changes(old.get_revision(), old.get_apool(), cs)
class Connection:
    def __init__(self, application, server, port):
        self.application = application
        self.server = server
        self.port = port
        self.connection_opened = False
        self.trip_started = False
        self.trip_id = None
        #self.open_connection()
    def send_data(self, data):
        to_send = {'_id':self.trip_id, "sensorData":data}
        print("tries to send: ",to_send)
        self.socket.emit('rt-sensordata', json.dumps(to_send))
    def open_connection(self):
        self.socket = SocketIO(self.server, self.port)
        self.socket.on('server_message', self.on_response)
        self.connection_opened = True
        self.thread = threading.Thread(name='connection', target=self.action)
        self.thread.start()
    def close_connection(self):
        self.socket.disconnect()
    def start_trip(self):
        data = {'purpose':'realtime-sender', 'groupID':self.application.group_id, 'userID':self.application.user_id}
        self.socket.emit('start', json.dumps(data))
    def stop_trip(self):
        data = {'_id':self.trip_id, "meta":None}
        self.socket.emit('endBikeTrip', json.dumps(data))
        self.trip_started = False
    def live_trip_active(self):
        return self.connection_opened and self.trip_started
    def on_response(self, *args):
        parsed = args[0]
        print "received data:",args[0]
        if "Connection accepted. Ready to receive realtime data." in parsed:
            self.trip_started = True
            self.trip_id = parsed['_id']
            print("trip started, id = ", self.trip_id)
        elif "bikeTrip saved to Database" in parsed:
            self.trip_started = False
            print("trip saved to database!")
        elif "illegal JSON data received" in parsed:
            print("saving data to database failed")
        elif u'Welcome' in parsed:
            print("Welcome! ", parsed)
        else:
            print("error: ",parsed)
    def action(self):
        while self.socket.connected:
            self.wait()

    def wait(self):
        self.application.send_data()
        time.sleep(.2)
        self.socket.wait(.5)
Exemple #25
0
class WsThread(threading.Thread):
    def __init__(self, did):
        super(WsThread, self).__init__()
        self.ready = False
        self.did = did
        self.condition = threading.Condition()

    def _set_ready(self):
        self.condition.acquire()
        self.ready = True
        self.condition.notify_all()
        self.condition.release()

    def run(self):
        self.socketIO = SocketIO(IP, 3000, params={'did': self.did})
        self.device_namespace = self.socketIO.define(Namespace, '/device')
        self._set_ready()
        self.socketIO.wait()

    def register_cmd_callbacks(self, handle, app):
        self.condition.acquire()
        while not self.ready:
            self.condition.wait()
        self.device_namespace.register_cmd_callbacks(handle, app)
        self.condition.release()

    def stop(self):
        self.condition.acquire()
        self.socketIO.disconnect()
        self.condition.release()

    def sendLog(self, critical, log):
        self.condition.acquire()
        while not self.ready:
            self.condition.wait()
        self.device_namespace.emit('device-log', {
            'critical': critical,
            'log': log
        })

        self.condition.release()

    def sendVar(self, handle, value):
        self.condition.acquire()
        while not self.ready:
            self.condition.wait()
        self.device_namespace.emit('device-updateVariable', {
            'handle': handle,
            'value': value
        })
        self.condition.release()

    def __del__(self):
        self.stop()
Exemple #26
0
class mySockIo(object):
    def __init__(self, host, port, router):
        self.sock = SocketIO(host, port)
        self.sock.on(router, self.on_message)

    def on_message(self, *args):
        return args[0] if isinstance(args[0], dict) else None

    def send(self, data):
        self.sock.send(data)
        result = self.sock.wait_for_callbacks(2)
        return result

    def close(self):
        self.sock.disconnect()
Exemple #27
0
class RTMClient(object):
    def __init__(self,
                 rtm_token,
                 client_id,
                 host="https://rtm.yellowant.com/",
                 port=80):
        self.client = SocketIOClient(host,
                                     port,
                                     params={
                                         "rtm_token": rtm_token,
                                         "client_id": client_id
                                     })

    def wait(self):
        self.client.wait()

    def disconnect(self):
        self.client.disconnect()

    def bind_connect_event_handler(self, on_connect):
        self.client.on(RTMEvents.CONNECT, on_connect)

    def bind_disconnect_event_handler(self, on_disconnect):
        self.client.on(RTMEvents.DISCONNECT, on_disconnect)

    def bind_yellowant_command_event_handler(self, on_yellowant_command):
        def data_handler(data):
            return on_yellowant_command(data.get("event_id"),
                                        data.get("request_data"))

        self.client.on(RTMEvents.YELLOWANT_COMMAND, data_handler)

    def bind_yellowant_webhook_subscription_event_handler(
            self, on_yellowant_webhook_subscription):
        self.client.on(RTMEvents.YELLOWANT_WEBHOOK_SUBSCRIPTION,
                       on_yellowant_webhook_subscription)

    def bind_error_event_handler(self, on_error):
        self.client.on(RTMEvents.ERROR, on_error)

    def emit_yellowant_message(self, event_id, yellowant_message):
        data = {
            "event_id": event_id,
            "message": yellowant_message,
        }
        self.client.emit(RTMEvents.YELLOWANT_MESSAGE, data)
Exemple #28
0
class GameChainMonitor:
    def __init__(self, wait_time=60):
        self._tx_handler = None
        monitor_thread = threading.Thread(target=self._start_monitor)
        monitor_thread.start()

    def _start_monitor(self):
        self._socketIO = SocketIO(SOCKETIO_SERVER, namespace=LoggingNamespace)
        self._socketIO.on('connect', self.on_connect)
        self._socketIO.on('disconnect', self.on_disconnect)
        self._socketIO.on('reconnect', self.on_reconnect)
        self._socketIO.on("tx", self.on_tx)

        self._socketIO.wait()

    def on_connect(self):
        print('connect')
        self._socketIO.emit('subscribe', "inv")

    def on_disconnect(self):
        print('disconnect')

    def on_reconnect(self):
        print('reconnect')

    def on_aaa_response(*args):
        print('on_aaa_response', args)

    def on_tx(self, data):
        if self._tx_handler is not None:
            self._tx_handler(data)

    def register_tx_handler(self, tx_handler):
        self._tx_handler = tx_handler

    def un_register_tx_handler(self, tx_handler):
        if self._tx_handler is tx_handler:
            self._tx_handler = None
        else:
            raise Exception("Invalid tx handler")

    def stop(self):
        if hasattr(self, "_socketIO"):
            self._socketIO.disconnect()
Exemple #29
0
    def get_project_infos(self, project_id):
        """
        Get detailed project infos about the project

        Params:
        project_id: the id of the project

        Returns: project details
        """
        project_infos = None

        # Callback function for the joinProject emitter
        def set_project_infos(a, project_infos_dict, c, d):
            # Set project_infos variable in outer scope
            nonlocal project_infos
            project_infos = project_infos_dict

        # Convert cookie from CookieJar to string
        cookie = "gke-route={}; overleaf_session2={}" \
            .format(
                reqs.utils.dict_from_cookiejar(self._cookie)["gke-route"],
                reqs.utils.dict_from_cookiejar(self._cookie)["overleaf_session2"]
            )

        # Connect to Overleaf Socket.IO, send a time parameter and the cookies
        socket_io = SocketIO(
            BASE_URL,
            params={'t': int(time.time())},
            headers={'Cookie': cookie}
        )

        # Wait until we connect to the socket
        socket_io.on('connect', lambda: None)
        socket_io.wait_for_callbacks()

        # Send the joinProject event and receive the project infos
        socket_io.emit('joinProject', {'project_id': project_id}, set_project_infos)
        socket_io.wait_for_callbacks()

        # Disconnect from the socket if still connected
        if socket_io.connected:
            socket_io.disconnect()

        return project_infos
Exemple #30
0
def simulate_sa_alarm(alarm, delay, cont):
    cont += 1
    time.sleep(delay)
    cursor = connection.cursor()
    sql = "insert into alarms_alarmevents (alarm_id, triggered_time, value) " \
          "values (%s, %s, %s)"
    triggered_time = str(datetime.datetime.utcnow())
    cursor.execute(sql, [alarm.pk, str(triggered_time), 300])
    transaction.commit_unless_managed()
    cursor.execute("SELECT id FROM alarms_alarmevents WHERE "
                   "triggered_time = %s AND alarm_id = %s",
                   [triggered_time, alarm.pk])
    row = cursor.fetchone()
    alarm_event = row[0]

    socket = SocketIO('auditem.mx', 9999)
    socket.emit('alarm_trigger', {'alarm_event': alarm_event})

    print "alarm ", alarm.pk, "triggered at", triggered_time

    sql = "insert into alarms_alarmevents (alarm_id, triggered_time, value) " \
          "values (%s, %s, %s)"
    triggered_time = str(datetime.datetime.utcnow())
    cursor.execute(sql, [alarm.pk, str(triggered_time), 300])
    transaction.commit_unless_managed()
    cursor.execute("SELECT id FROM alarms_alarmevents WHERE "
                   "triggered_time = %s AND alarm_id = %s",
                   [triggered_time, alarm.pk])
    row = cursor.fetchone()
    alarm_event = row[0]

    socket.emit('alarm_trigger', {'alarm_event': alarm_event})

    SocketIO.disconnect(socket)

    print "alarm ", alarm.pk, "triggered at", triggered_time

    if cont < 60:
        simulate_sa_alarm(alarm, 30, cont)
    else:
        print "Simulation complete"
        return
Exemple #31
0
class YetiSocket:
    def __init__(self, host='localhost', port=5001, config_update_callback=None, manual_capture_callback=None):
            self._thread = threading.Thread(target=self._worker, args=(host, port, config_update_callback, manual_capture_callback))
            self._thread.daemon = True
            self._thread.start()


    def _worker(self, host, port, config_update_callback, manual_capture_callback):
            self.io = SocketIO(host, port)
            self.cam = self.io.define(LoggingNamespace, '/cam')

            if config_update_callback:
                self.cam.on('config_update', config_update_callback)

            if manual_capture_callback:
                self.cam.on('manual_capture', manual_capture_callback)

            self.io.wait()

    def alert(self, data):
        logger.info("Sending alert to server: %s" % data)
        self.cam.emit("alert", data)

    def config_updated(self, status):
        logger.info("Sending config updated result: %s" % status)
        self.cam.emit("config_updated", {"status":status})

    def manual_capture_result(self, result):
        logger.info("Sending manual capture result: %s" % result)
        self.cam.emit("manual_capture_result", {"result":result})

    def connect(self):
        self.cam.connect()

    def disconnect(self):
        self.cam.disconnect()
        self.io.disconnect()

    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_value, exc_tb):
        self.disconnect()
Exemple #32
0
class WsThread(threading.Thread):
    def __init__(self):
        super(WsThread, self).__init__()
        self.ready = False
        self.condition = threading.Condition()

    def _set_ready(self):
        self.condition.acquire()
        self.ready = True
        self.condition.notify_all()
        self.condition.release()

    def run(self):
        self.socketIO = SocketIO('192.168.1.10', 3000, params={'did': 10563})
        self.device_namespace = self.socketIO.define(Namespace, '/device')
        self._set_ready()
        self.socketIO.wait()

    def register_cmd_callbacks(self, fn):
        self.condition.acquire()
        while not self.ready:
            self.condition.wait()
        self.device_namespace.register_cmd_callbacks(fn)
        self.condition.release()

    def stop(self):
        self.condition.acquire()
        self.ready = False
        self.socketIO.disconnect()
        self.condition.release()

    def send(self, message):
        self.condition.acquire()
        while not self.ready:
            self.condition.wait()
        self.device_namespace.emit(message)
        self.condition.release()

    def __del__(self):
        self.stop()
def detectpeople(request):

    try:
        token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6Im9tLnBjcHJha2FzaEBnbWFpbC5jb20iLCJ1c2VybmFtZSI6InByYWthc2giLCJmaXJzdG5hbWUiOiJQcmFrYXNoIn0.j8WsE7aMrgyIA59gg84DDy3BnlFUaDl3q7Umw7jbN9o'
        g_url = 'http://api.giscle.ml'

        socketio = SocketIO(g_url, 80, LoggingNamespace)
        socketio.emit('authenticate', {'token': token})

        cam = cv2.VideoCapture("http://93.87.72.254:8090/mjpg/video.mjpg")

    except:
        print(
            "Error while making connection \nPlease check url and api key, authentaion error"
        )
        exit()

    frame_count = 1

    while True:
        global t
        t = time.time()
        ret, frame = cam.read()
        if not ret:
            continue
        frame = cv2.resize(frame, (900, 600))
        encoded, buffer = cv2.imencode('.jpg', frame)
        encoded_frame = base64.b64encode(buffer)
        encoded_frame = encoded_frame.decode('utf-8')
        socketio.emit('count_people', {'data': encoded_frame})
        socketio.on('response', extract_data)
        socketio.wait(0.0001)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    socketio.disconnect()
    cam.release()

    return HttpResponse("Detect people Counts")
Exemple #34
0
class WebLights(threading.Thread):
    class WebLightsNamespace(BaseNamespace):
        def on_connect(self):
            print '[Connected]'
            log.info("Connected to weblights")
    
        def on_dc_lights(self, status):
            log.info("dc_lights_update: " + str(status))
        def on_keep_alive(self, *args):
            log.debug("Received keep_alive")

    def run(self):
        log.info("Starting weblights")
        self.socketIO = SocketIO(
                cowtv_config["weblights"],
                Namespace=self.WebLightsNamespace)
        self.socketIO.wait()

    def toggle(self):
        self.socketIO.emit("toggle_lights")

    def disconnect(self):
        self.socketIO.disconnect()
Exemple #35
0
class TestChatbot(BaseTest):
    def _chat_callback(self, status):
        self._status = status

    def _chat_event(self, message):
        self._message = message

    def setUp(self):
        self._status = None
        self._message = None

        self.sio = SocketIO(HOST, PORT)
        self.sio.on(CHAT_EVENT, self._chat_event)

    def tearDown(self):
        self.sio.disconnect()

    def _test_chat(self, msg, response=None):
        # Send message with callback.
        self.sio.emit(CHAT_EVENT, msg, callback=self._chat_callback)
        # Wait for the callbacks/events triggering.
        self.sio.wait(CHAT_TIMEOUT)
        # Now check the callback and received response.
        self.assertEqual(True, self._status)
        self.assertEqual(unicode, type(self._message))
        self.assertGreater(len(self._message), 0)
        if response:
            print(self._message)
            self.assertTrue(self._message.startswith(response))

    def test_chat_hello(self):
        self._test_chat("Salut!")

    def test_chat_questions(self):
        tests = [("ce este aia inima?", "organ muscular cavitar situat in")]
        for question, answer in tests:
            self._test_chat(question, response=answer)
Exemple #36
0
class _WaldorfSio(mp.Process):
    """Handle client command in a separate process."""
    def __init__(self, cmd_queue, submit_queue):
        super(_WaldorfSio, self).__init__()
        self.daemon = True
        self.cmd_queue = cmd_queue
        self.submit_queue = submit_queue

    def setup(self):
        # Generate uid for client.
        self.uid = str(uuid.uuid4())
        self.system_info = get_system_info()
        self.cfg = self.cmd_queue[0].get()
        self.debug = self.cfg.debug
        self.setup_logger()
        self.result_q = [queue.Queue(), self.submit_queue[0]]
        self.rt = ResultThread(self)
        self.rt.start()

        # Collect information.
        info = {
            'uid': self.uid,
            'hostname': socket.gethostname(),
            'ver': waldorf.__version__,
            'ip': get_local_ip(),
            'os': self.system_info.os,
            'cpu_type': self.system_info.cpu_type,
            'cpu_count': self.system_info.cpu_count,
            'mem': self.system_info.mem
        }
        self.cookies = {'info': obj_encode(info)}

        # Connect to Waldorf master.
        self.sock = SocketIO(self.cfg.master_ip,
                             self.cfg.waldorf_port,
                             cookies=self.cookies)
        self.logger.debug('Connect to {}:{} with uid {}'.format(
            self.cfg.master_ip, self.cfg.waldorf_port, self.uid))
        self.client_ns = self.sock.define(Namespace, '/client')
        self.client_ns.setup(self)

        self.events = {}
        self.info = {}
        self.info['tasks'] = {}
        self._code = None

    def setup_logger(self):
        if self.debug >= 2:
            # Logging socketIO-client output.
            _cf = [
                '$GREEN[%(asctime)s]$RESET', '[%(name)s]',
                '$BLUE[%(filename)20s:%(funcName)15s:%(lineno)5d]$RESET',
                '[%(levelname)s]', ' $CYAN%(message)s$RESET'
            ]
            cformatter = ColoredFormatter('-'.join(_cf))

            logger = logging.getLogger('socketIO-client')
            logger.setLevel(logging.DEBUG)
            ch = logging.StreamHandler(sys.stdout)
            ch.setFormatter(cformatter)
            logger.addHandler(ch)
        if self.debug >= 1:
            # Logging Waldorf client.
            self.logger = init_logger('wd_client', get_path(relative_path='.'),
                                      (logging.DEBUG, logging.DEBUG))
        else:
            self.logger = DummyLogger()

    def put(self, r):
        self.cmd_queue[1].put(r)

    def on_echo(self):
        """Send echo message."""
        self.logger.debug('enter on_echo')
        self.info['echo_count'] = len(self.info['check_slave_resp'].keys()) + 1
        self.info['echo_resp'] = []
        self.events['echo'] = threading.Event()
        self.client_ns.emit(_WaldorfAPI.ECHO)
        time.sleep(0.01)
        self.events['echo'].wait()
        self.put(self.info['echo_resp'])
        self.logger.debug('leave on_echo')

    def on_check_ver(self):
        """Send check version message."""
        self.logger.debug('enter on_check_ver')
        self.events['check_ver'] = threading.Event()
        self.client_ns.emit(_WaldorfAPI.CHECK_VER, waldorf.__version__)
        time.sleep(0.01)
        self.events['check_ver'].wait()
        self.put(self.info['check_ver_resp'])
        self.logger.debug('leave on_check_ver')

    def on_check_slave(self):
        """Send check slave message."""
        self.logger.debug('enter on_check_slave')
        self.events['check_slave'] = threading.Event()
        self.client_ns.emit(_WaldorfAPI.CHECK_SLAVE)
        time.sleep(0.01)
        self.events['check_slave'].wait()
        self.put(len(self.info['check_slave_resp'].keys()))
        self.logger.debug(self.info['check_slave_resp'])
        assert len(self.info['check_slave_resp'].keys()) > 0
        self.logger.debug('leave on_check_slave')

    def on_get_env(self, name, pairs, suites, cfg):
        """Send get environment message.

        This method will wait until all responses are received.
        """
        self.logger.debug('enter on_get_env')
        args = (name, pairs, suites, cfg)
        args = obj_encode(args)
        self.events['get_env'] = threading.Event()
        self.client_ns.emit(_WaldorfAPI.GET_ENV, args)
        time.sleep(0.01)
        self.events['get_env'].wait()
        self.logger.debug(self.info['get_env_resp'])
        self.put(self.info['get_env_resp'])
        self.logger.debug('leave on_get_env')

    def on_reg_task(self, task_name, task_code, opts):
        """Send register task message.

        Send task code to master server.
        """
        self.logger.debug('enter on_reg_task')
        l = {}
        exec(task_code, {}, l)
        self._code = l[task_name]
        self.info['tasks'][task_name] = [self._code, opts]
        self.client_ns.emit(_WaldorfAPI.REG_TASK,
                            (self.uid, task_name, task_code, opts))
        self.put(0)
        self.logger.debug('leave on_reg_task')

    def on_freeze(self):
        """Send freeze message.

        Create new celery client and send freeze message.
        It will wait until all slaves are set up.
        """
        self.logger.debug('enter on_freeze')
        self.cfg.update()
        self.app_name = 'app-' + self.uid
        self.info['app'] = app = Celery(self.app_name,
                                        broker=self.cfg.celery_broker,
                                        backend=self.cfg.celery_backend)
        app.conf.task_default_queue = self.app_name
        app.conf.accept_content = ['json', 'pickle']
        app.conf.task_serializer = 'pickle'
        app.conf.result_serializer = 'pickle'
        app.conf.task_acks_late = True
        app.conf.worker_lost_wait = 60.0
        app.conf.result_expires = 1800
        self.info['task_handlers'] = {}
        for name, task in self.info['tasks'].items():
            self.info['task_handlers'][name] = app.task(**task[1])(task[0])
        self.info['freeze_count'] = len(self.info['check_slave_resp'].keys())
        self.info['freeze_resp'] = []
        self.events['freeze'] = threading.Event()
        self.client_ns.emit(_WaldorfAPI.FREEZE, self.uid)
        time.sleep(0.01)
        self.events['freeze'].wait()
        self.put(0)
        self.logger.debug('leave on_freeze')

    def on_submit(self, task_uid, task_name, args):
        """Send the job to celery broker and use queue to get the result."""
        self.info['tasks'][task_uid] = {}
        self.info['tasks'][task_uid]['retry_times'] = 0
        self.info['tasks'][task_uid]['info'] = (task_name, args)
        self.info['tasks'][task_uid]['submit_time'] = time.time()
        r = self.info['task_handlers'][task_name].apply_async(args=(args, ))
        self.result_q[0].put((task_uid, r))

    def on_map(self, task_name: str, args):
        """Use for loop to send jobs and get results.

        Notice: this method don't have task failure-restore mechanism.
        """
        self.logger.debug('enter on_map')
        num = len(args)
        self.logger.debug('num of task: {}'.format(num))
        task = self.info['task_handlers'][task_name]
        r = []
        if self.debug:
            pbar = tqdm.tqdm(total=num * 2 + 1, file=sys.stdout)
        else:
            pbar = Dummytqdm()
        for arg in args:
            r.append(task.apply_async(args=(arg, )))
            pbar.update()
        result = []
        for _r in r:
            result.append(
                _r.get(timeout=self.cfg.result_timeout,
                       interval=self.cfg.get_interval))
            pbar.update()
        self.put(result)
        pbar.update()
        pbar.close()
        self.logger.debug('leave on_map')

    def on_gen_git_c(self, info):
        """Generate git credential.

        Receive public key from server and encrypt information.
        """
        self.logger.debug('enter on_gen_git_c')
        self.events['gen_git_c'] = threading.Event()
        self.client_ns.emit(_WaldorfAPI.GEN_GIT_C)
        time.sleep(0.01)
        self.events['gen_git_c'].wait()
        info = pickle.dumps(info, -1)
        self._public_pem = self.info['gen_git_c_resp'].encode()
        rsa_key = RSA.importKey(self._public_pem)
        cipher = PKCS1_v1_5.new(rsa_key)
        cipher_text = base64.b64encode(cipher.encrypt(info))
        self.put(cipher_text)

    def on_clean_up(self):
        """Send clean up and exit message."""
        self.logger.debug('enter on_clean_up')
        self.client_ns.emit(_WaldorfAPI.CLEAN_UP, self.uid)
        self.client_ns.emit(_WaldorfAPI.EXIT, self.uid)
        self.result_q[0].put((0, _WaldorfAPI.CLEAN_UP))
        self.logger.debug('leave on_clean_up')

    def get_handler(self, api):
        """Just a way to automatically find handler method."""
        return self.__getattribute__('on_' + api)

    def run(self):
        self.setup()
        SockWaitThread(self).start()
        while True:
            try:
                cmd = self.cmd_queue[0].get()
                if cmd:
                    if cmd[1]:
                        self.get_handler(cmd[0])(*cmd[1])
                    else:
                        self.get_handler(cmd[0])()
                    if cmd[0] == _WaldorfAPI.CLEAN_UP:
                        break
            except KeyboardInterrupt:
                self.on_clean_up()
                break
            except Exception as e:
                self.on_clean_up()
                raise e
        self.sock.disconnect()
        self.logger.debug('loop end')
Exemple #37
0
class Communicator(object):
    """
    A communication manager that owns a socket.io client. The
    communicator offers access to a global scope provided by
    a server that the communicator connects to at instantiation
    time. Basic RPC calls are also implemented.
    """
    _RESULTS = dict()
    _UID = 0
    _LOCK = threading.Lock()
    _RPC_EXECUTE_COMMAND = "execute_command"
    _REGISTRY = dict()
    _COMMAND_REGISTRY = dict()

    def __init__(self,
                 port=8090,
                 host="localhost",
                 disconnect_callback=None,
                 logger=None,
                 network_debug=False,
                 event_processor=None):
        """
        Constructor. Rather than instantiating the Communicator directly,
        it is advised to make use of the get_or_create() classmethod as
        a factory constructor.

        :param int port: The port num to connect to. Default is 8090.
        :param str host: The host to connect to. Default is localhost.
        :param disconnect_callback: A callback to call if a disconnect
                                    message is received from the host.
        :param logger: A standard Python logger to use for network debug
                       logging.
        :param bool network_debug: Whether network debug logging is desired.
        :param event_processor: A callable that will be called during each
                                iteration of the response wait loop. An
                                example would be passing in the
                                QtGui.QApplication.processEvents callable,
                                which will force an iteration of the Qt
                                event loop during response wait periods,
                                which will stop Qt widgets from being
                                blocked from repainting.
        """
        self._port = port
        self._host = host
        self._network_debug = network_debug
        self._logger = logger or logging.getLogger(__name__)
        self._event_processor = event_processor
        self._response_logging_silenced = False

        self._io = SocketIO(host, port)
        self._io.on("return", self._handle_response)

        self._global_scope = None
        self._disconnect_callback = disconnect_callback

        if disconnect_callback:
            self._io.on("disconnect", disconnect_callback)

        self._get_global_scope()

    ##########################################################################################
    # constructor

    @classmethod
    def get_or_create(cls, identifier, *args, **kwargs):
        """
        A factory constructor that provides singleton instantiation
        behavior based on a given unique identifier. If an instance
        exists with the given identifier it will be returned,
        otherwise a new instance is constructed and returned after
        being recorded by the given identifier.

        :param identifier: Some hashable identifier to associate
                           the instantiated communicator with.
        :param int port: The port to connect to. Default is 8090.
        :param str host: The host to connect to. Default is localhost.
        :param disconnect_callback: A callback to call if a disconnect
                                    message is received from the host. 
        """
        if identifier in cls._REGISTRY:
            instance = cls._REGISTRY[identifier]
            instance.logger.debug("Reusing Communicator by id '%s'" %
                                  identifier)
        else:
            instance = cls(*args, **kwargs)
            instance._identifier = identifier
            cls._REGISTRY[identifier] = instance
            instance.logger.debug("New Communicator of id '%s'" % identifier)
        return instance

    ##########################################################################################
    # properties

    @property
    def event_processor(self):
        """
        The callable event processor that will be called between iterations
        of the RPC response wait loop.
        """
        return self._event_processor

    @event_processor.setter
    def event_processor(self, processor):
        self._event_processor = processor

    @property
    def host(self):
        """
        The host that was connected to.
        """
        return self._host

    @property
    def logger(self):
        """
        The standard Python logger used by the communicator.
        """
        return self._logger

    @logger.setter
    def logger(self, logger):
        self._logger = logger

    @property
    def network_debug(self):
        """
        Whether network debugging messages are logged.
        """
        return self._network_debug

    @network_debug.setter
    def network_debug(self, state):
        self._network_debug = bool(state)

    @property
    def port(self):
        """
        The port number connected to.
        """
        return self._port

    ##########################################################################################
    # context managers

    @contextlib.contextmanager
    def response_logging_silenced(self):
        """
        A context manager that will silence RPC command response logging
        on enter, and enable it on exit. This is useful if you're emitting
        an RPC command that you expect might fail, but you want to handle
        that failure without alerting a user via logging.
        """
        self._response_logging_silenced = True
        yield
        self._response_logging_silenced = False

    ##########################################################################################
    # RPC

    def disconnect(self):
        """
        Disconnects from the socket.io server.
        """
        self._io.disconnect()
        del self._REGISTRY[self._identifier]

    def ping(self):
        """
        Pings the host, testing whether the connection is still live.
        """
        self._io._ping()

    def process_new_messages(self,
                             wait=0.01,
                             single_loop=False,
                             process_events=True):
        """
        Processes new messages that have arrived but that have not been
        previously handled.

        :param float wait: How long to poll for new messages, in seconds.
        :param bool single_loop: If True, only a single check for messages
                                 will be made and the timeout duration will
                                 not be used. Default is False.
        :param bool process_events: If True and an event processor callable
                                    is registered with the communicator, it
                                    will be called at the end of the wait
                                    duration.
        """
        self.log_network_debug("Processing new messages, wait is %s" % wait)

        try:
            self._io._heartbeat_thread.hurry()
            self._io._transport.set_timeout(seconds=0.1)
            start = time.time()

            while wait >= (time.time() - start) or single_loop:
                try:
                    self._io._process_packets()
                except socketIO_client.exceptions.TimeoutError:
                    # Timeouts here are not a problem. It can be something
                    # as simple as the server being busy and not responding
                    # quickly enough, in which case subsequent attempts will
                    # go through without a problem.
                    self.log_network_debug(
                        "Timed out during _process_packets call. This is "
                        "likely not a problem if it only happens occasionally."
                    )
                else:
                    if single_loop:
                        break

                # Force an event loop iteration if we were provided with a
                # callable event processor.
                if self.event_processor and process_events:
                    self.event_processor()
        finally:
            self._io._heartbeat_thread.relax()
            self._io._transport.set_timeout()

        self.log_network_debug("New message processing complete.")

    def rpc_call(self, proxy_object, params=[], parent=None):
        """
        Executes a "call" RPC command.

        :param proxy_object: The proxy object to call via RPC.
        :param list params: The list of arguments to pass to the
                            callable when it is called.
        :param parent: The parent proxy object, if any. If given, the
                       callable will be called as a method of the
                       parent object. If a parent is not given, it
                       will be called as a function of the global
                       scope.

        :returns: The data returned by the callable when it is
                  called.
        """
        self.log_network_debug("Sending a call message using rpc_call...")

        if parent:
            params.insert(0, parent.uid)
            self.log_network_debug("Parent given, UID is %s" % parent.uid)
        else:
            self.log_network_debug("No parent given.")
            params.insert(0, None)

        return self.__run_rpc_command(
            method="call",
            proxy_object=proxy_object,
            params=params,
            wrapper_class=ProxyWrapper,
        )

    def rpc_eval(self, command):
        """
        Evaluates the given string command via RPC.

        :param str command: The command to execute.

        :returns: The data returned by the evaluated command.
        """
        self.log_network_debug("Sending an eval message using rpc_eval...")
        self.log_network_debug("Command is: %s" % command)

        return self.__run_rpc_command(
            method="eval",
            proxy_object=None,
            params=[command],
            wrapper_class=ProxyWrapper,
        )

    def rpc_get(self, proxy_object, property_name):
        """
        Gets the value of the given property for the given proxy
        proxy object.

        :param proxy_object: The proxy object to get the property
                             value from.
        :param str property_name: The name of the property to get.

        :returns: The value of the property of the remote object.
        """
        self.log_network_debug("Sending a get message using rpc_get...")
        self.log_network_debug("Getting property %s from object UID %s" %
                               (property_name, proxy_object.uid))

        return self.__run_rpc_command(
            method="get",
            proxy_object=proxy_object,
            params=[property_name],
            wrapper_class=ProxyWrapper,
            attach_parent=proxy_object,
        )

    def rpc_get_index(self, proxy_object, index):
        """
        Gets the value at the given index of the given proxy object.

        :param proxy_object: The proxy object to index into.
        :param int index: The index to get the value of.

        :returns: The value of the index of the remote object.
        """
        self.log_network_debug(
            "Sending a get_index message using rpc_get_index...")
        self.log_network_debug("Getting index %s of object UID %s" %
                               (index, proxy_object.uid))

        return self.__run_rpc_command(
            method="get_index",
            proxy_object=proxy_object,
            params=[index],
            wrapper_class=ProxyWrapper,
        )

    def rpc_new(self, class_name):
        """
        Instantiates a new remote object of the given class name.

        :param str class_name: The name of the class to instantiate.

        :returns: A proxy object pointing to the instantiated
                  remote object.
        """
        self.log_network_debug("Sending a 'new' message using rpc_new...")
        self.log_network_debug("Instantiating class %s" % class_name)

        return self.__run_rpc_command(
            method="new",
            proxy_object=None,
            params=[class_name],
            wrapper_class=ClassInstanceProxyWrapper,
        )

    def rpc_set(self, proxy_object, property_name, value):
        """
        Sets the given property to the given value on the given proxy
        object.

        :param proxy_object: The proxy object to set the property of.
        :param str property_name: The name of the property to set.
        :param value: The value to set the property to.
        """
        self.log_network_debug("Sending a set message using rpc_set...")
        self.log_network_debug("Setting property %s to %s for object UID %s" %
                               (property_name, value, proxy_object.uid))

        return self.__run_rpc_command(
            method="set",
            proxy_object=proxy_object,
            params=[property_name, value],
            wrapper_class=ProxyWrapper,
        )

    def wait(self, timeout=0.1, single_loop=False, process_events=True):
        """
        Triggers a wait and the processing of any messages already
        queued up or that arrive during the wait period.

        :param float timeout: The duration of time, in seconds, to
                              wait.
        :param bool single_loop: If True, only a single check for messages
                                 will be made and the timeout duration will
                                 not be used. Default is False.
        :param bool process_events: If True and an event processor callable
                                    is registered with the communicator, it
                                    will be called at the end of the wait
                                    duration.
        """
        self.log_network_debug("Triggering a wait of duration %s" % timeout)
        self.log_network_debug("single_loop is %s" % single_loop)
        self.log_network_debug("process_events is %s" % process_events)
        self.process_new_messages(
            wait=float(timeout),
            single_loop=single_loop,
            process_events=process_events,
        )

    ##########################################################################################
    # logging

    def log_network_debug(self, msg):
        """
        Logs a debug message if 'network_debug' is turned on.

        :param str msg: The log message.
        """
        if self.network_debug:
            self.logger.debug(msg)

    ##########################################################################################
    # internal methods

    def _get_global_scope(self):
        """
        Emits a message requesting that the remote global scope be
        introspected, wrapped, and returned as JSON data.
        """
        self.log_network_debug("Getting the remote global scope...")
        payload = self._get_payload("get_global_scope")
        self.log_network_debug("Payload: %s" % payload)

        self._io.emit(self._RPC_EXECUTE_COMMAND, payload)
        uid = payload["id"]
        results = self._wait_for_response(uid)

        self.log_network_debug("Raw data response: %s" % results)

        self._global_scope = ProxyScope(results, self)

    def _get_payload(self, method, proxy_object=None, params=[]):
        """
        Builds the payload dictionary to be sent via RPC.

        :param str method: The JSON-RPC method name to call.
        :param proxy_object: The proxy object to be included in the
                             payload.
        :param list params: The list of paramaters to be packaged.

        :returns: The payload dictionary, formatted for JSON-RPC
                  use.
        """
        payload = dict(
            id=self.__get_uid(),
            method=method,
            jsonrpc="2.0",
            params=[],
        )

        if proxy_object:
            payload["params"] = [proxy_object.serialized]

            if params:
                payload["params"].extend(self.__prepare_params(params))
        else:
            payload["params"] = self.__prepare_params(params)

        self.log_network_debug("Payload constructed: %s" % payload)

        return payload

    def _handle_response(self, response, *args):
        """
        Handles the response to an already-emitted message.

        :param str response: The JSON encoded message response.

        :returns: The decoded result data.
        """
        self.log_network_debug("Handling RPC response...")

        result = json.loads(response)
        uid = result["id"]
        self.log_network_debug("Response UID is %s" % uid)

        try:
            self._RESULTS[uid] = self._ensure_utf8(json.loads(
                result["result"]))
        except (TypeError, ValueError):
            self._RESULTS[uid] = self._ensure_utf8(result.get("result"))
        except KeyError:
            if not self._response_logging_silenced:
                self.logger.error("RPC command (UID=%s) failed!" % uid)
                self.logger.error("Failed command payload: %s" %
                                  self._COMMAND_REGISTRY[uid])
                self.logger.debug("Failure raw response: %s" % response)
                self.logger.debug("Failure results: %s" % result)
            raise RuntimeError("RPC command (UID=%s) failed!" % uid)

        self.log_network_debug("Processed response data: %s" %
                               self._RESULTS[uid])

    def _ensure_utf8(self, in_string):

        if isinstance(in_string, unicode):
            in_string = in_string.encode("utf-8")

        return in_string

    def _wait_for_response(self, uid):
        """
        Waits for the results of an RPC call.

        :param int uid: The unique id of the RPC call to wait for.

        :returns: The raw returned results data.
        """
        self.log_network_debug("Waiting for RPC response for UID %s..." % uid)

        while uid not in self._RESULTS:
            # If we were given an event processor, we can call that here. That
            # will be something like QApplication.processEvents, which will
            # force an iteration of the Qt event loop so that we're not
            # completely the UI thread here, even though we're blocking Python.
            if self.event_processor:
                self.event_processor()

            self.wait(single_loop=True, process_events=False)

        results = self._RESULTS[uid]
        del self._RESULTS[uid]

        self.log_network_debug("Results arrived for UID %s" % uid)
        return results

    ##########################################################################################
    # private methods

    def __get_uid(self):
        """
        Gets the next available unique id number.
        """
        with self._LOCK:
            self._UID += 1
            return self._UID

    def __prepare_params(self, params):
        """
        Prepares a list of paramaters to be emitted as part of an
        RPC call.

        :param list params: The list of paramaters to prepare.

        :returns: The list of prepared paramaters, fit for emission.
        """
        processed = []

        for param in params:
            # TODO: Probably handle all iterables.
            if isinstance(param, list):
                processed.extend(self.__prepare_params(param))
            elif isinstance(param, ProxyWrapper):
                processed.append(param.data)
            else:
                if isinstance(param,
                              basestring) and not isinstance(param, unicode):
                    # ensure the strings are unicode
                    param = param.decode("utf-8")
                processed.append(param)

        return processed

    def __run_rpc_command(self,
                          method,
                          proxy_object,
                          params,
                          wrapper_class,
                          attach_parent=None):
        """
        Emits the requested JSON-RPC method via socket.io and handles
        the returned result when it arrives.

        :param str method: The JSON-RPC method name to call.
        :param proxy_object: The proxy object to send.
        :param list params: The list of parameters to emit.
        :param wrapper_class: The class reference to use when
                              wrapping results.
        :param attach_parent: An optional parent object to associate
                              the returned data to.

        :returns: The wrapped results of the RPC call.
        """

        payload = self._get_payload(
            method=method,
            proxy_object=proxy_object,
            params=params,
        )

        self._COMMAND_REGISTRY[payload["id"]] = payload

        self._io.emit(self._RPC_EXECUTE_COMMAND, payload)
        results = self._wait_for_response(payload["id"])

        return wrapper_class(results, self, parent=attach_parent)

    ##########################################################################################
    # magic methods

    def __getattr__(self, name):
        try:
            return getattr(self._global_scope, name)
        except AttributeError:
            # If we were asked for something that's not in the global
            # scope, it's possible that it's a class that needs to be
            # instantiated.

            # TODO: This needs to be behavior that's custom to the given
            # environment we're dealing with. Right now, this behavior here
            # is handling a situation that arises in ExtendScript, but might
            # not even be appropriate for other flavors/versions of JS.

            # NOTE: I'm thinking we can do this sort of thing just with a
            # subclass. The base Communicator class can define the simpler
            # getattr, which assumes anything requested is available from
            # the global scope object. For Adobe, we can implement an
            # AdobeCommunicator subclass that reimplements getattr and
            # adds the below logic.
            instance = self.rpc_new(name)
            if isinstance(instance, ProxyWrapper):
                return instance
            else:
                raise
Exemple #38
0
class _Socket (object):

  def __init__(self, sdk):
    self._sdk = sdk
    self._socket = None

  def start (self, **auth):


    class Namespace (BaseNamespace):

      def on_broadcast (self, message):
        self.socket._sdk.network.on_broadcast(self.socket, message)

      def on_connect (self):
        self.socket._sdk.network.on_connect(self.socket)

      def on_disconnect (self):
        self.socket._sdk.network.on_disconnect(self.socket)

      def on_subscribed (self, message):
        self.socket._sdk.network.on_subscribed(self.socket, message)

    Namespace.socket = self

    params = { 'token': auth['token'] }
    self._socket = SocketIO(auth['network']['host'], Namespace=Namespace, params=params, wait_for_connection=False, hurry_interval_in_seconds=5)

  def stop (self):
    self._sdk.logger.debug('Disconnecting from network.')
    try:
      self._socket.disconnect()
      self._sdk.logger.debug('Disconnected from network')
    except:
      self._sdk.logger.warning('Failed to disconnect from network.')
      self._sdk.logger.debug('Failed to disconnect from network: %s', traceback.format_exc())

  def wait (self, seconds):
    if not self.is_connected:
      return time.sleep(seconds)
    try:
      self._socket.wait(seconds)
    except:
      self._sdk.logger.warning('Failed to wait for socket messages.')
      self._sdk.logger.debug('Failed to wait for socket messages: %s', traceback.format_exc())
      time.sleep(seconds)

  def emit (self, name, payload):
    if not self.is_connected:
      self._sdk.logger.debug('Failed to emit socket message: Device is offline.')
      return False
    try:
      self._sdk.logger.debug('Emitting socket message: %s,%s', name, payload)
      self._socket.emit(name, payload)
      return True
    except:
      self._sdk.logger.warning('Failed to emit socket message.')
      self._sdk.logger.debug('Failed to emit socket message: %s', traceback.format_exc())
      return False

  @property
  def is_connected (self):
    return self._socket and self._socket.connected
class App:

    debug = True
    host = 'watchlist.ageudum.com'
    port = 80
    defaultHertz = 2
    
    def __init__(self):
        
        try:
            self.socketIO = SocketIO(self.host, self.port, LoggingNamespace, False)
        except Exception as err:
            logger.error(err)
            tkMessageBox.showinfo("Error connecting to server.", "Could not connect to server.\nCheck internet connection or contact server admin with log.txt.")
            return

        self.root = Tk()
        self.root.wm_title("Rust Fleet Watchlist")
        self.root.minsize(width=250, height=425)
        self.root.attributes("-topmost", True)
        
        #Removing default tk icon until a better one is found
        #http://stackoverflow.com/questions/550050/removing-the-tk-icon-on-a-tkinter-window
        ICON = zlib.decompress(base64.b64decode('eJxjYGAEQgEBBiDJwZDBy'
        'sAgxsDAoAHEQCEGBQaIOAg4sDIgACMUj4JRMApGwQgF/ykEAFXxQRc='))
        _, ICON_PATH = tempfile.mkstemp()
        with open(ICON_PATH, 'wb') as icon_file:
            icon_file.write(ICON)
        self.root.iconbitmap(default=ICON_PATH)
        
        self.userName = StringVar(self.root, "")
        if os.path.exists('user.json'):
            with open('user.json') as dataFile:
                user = json.load(dataFile)
                self.userName.set(user['userName'])

        self.hertz = StringVar(self.root, self.defaultHertz)
          
        self.userNameLabel = Label(self.root, text="Username:"******"Current HP:")
        self.healthCalibrationInput = Entry(self.root, bd =5)
        
        self.thirstCalibrationLabel = Label(self.root, text="Current Thirst:")
        self.thirstCalibrationInput = Entry(self.root, bd =5)
        
        self.hungerCalibrationLabel = Label(self.root, text="Current Hunger:")
        self.hungerCalibrationInput = Entry(self.root, bd =5)
        
        self.calibrateButton = Button(self.root, text="Calibrate", command=self.onCalibrateButtonPress)
        
        self.frequencyLabel = Label(self.root, text="Update Frequency (Hertz):")
        self.frequencyInput = Entry(self.root, textvariable=self.hertz, bd =5)
        
        self.userNameLabel.pack()
        self.userNameInput.pack()
        
        self.healthCalibrationLabel.pack()
        self.healthCalibrationInput.pack()
        
        self.thirstCalibrationLabel.pack()
        self.thirstCalibrationInput.pack()
        
        self.hungerCalibrationLabel.pack()
        self.hungerCalibrationInput.pack()
        
        self.calibrateButton.pack()

        

        self.barDetector = BarDetector()
        #self.actionBarDetector = ActionBarDetector()
        if self.barDetector.calibrated:
            self.confLoadedLabel = Label(self.root, text="Previous Calibration Loaded")
            self.confLoadedLabel.pack()
        
        self.frequencyLabel.pack()
        self.frequencyInput.pack()        
        if self.debug:
            self.hpPanel = Label(self.root, image = None)
            self.hpPanel.pack()
            self.hpText = Label(self.root, text="HP")
            self.hpText.pack()
            self.thirstPanel = Label(self.root, image = None)
            self.thirstPanel.pack() 
            self.thirstText = Label(self.root, text="Thirst")
            self.thirstText.pack()
            self.hungerPanel = Label(self.root, image = None)
            self.hungerPanel.pack()
            self.hungerText = Label(self.root, text="Hunger")
            self.hungerText.pack()
            #self.actionBarPanel = Label(self.root, image = None)
            #self.actionBarPanel.pack()
        self.root.after(self.delay(), self.loop)
        self.root.protocol("WM_DELETE_WINDOW", self.quit)
        self.root.mainloop()
    
    def onCalibrateButtonPress(self):
        try:
            rustWindow = win32gui.FindWindow(None, 'Rust')
            if(rustWindow):
                self.barDetector.calibrate(rustWindow, self.healthCalibrationInput.get(), self.thirstCalibrationInput.get(), self.hungerCalibrationInput.get())
        except Exception as err:
            logger.error(err)
            
    def loop(self):
        try:
            self.hertz.set(self.frequencyInput.get())
            rustWindow = win32gui.GetForegroundWindow()
            if win32gui.GetWindowText(rustWindow) == 'Rust' and self.barDetector.calibrated and self.socketIO.connected:
                stats = self.barDetector.getStats(rustWindow)
                #self.actionBarDetector.getActionBarSlots(rustWindow)
                def showBar(value, barImage, imgPanel, textPanel, textPrefix):
                    uiImage = ImageTk.PhotoImage(barImage)
                    imgPanel.configure(image = uiImage)
                    imgPanel.image = uiImage
                    valueStr = textPrefix + str(value) + "%"
                    textPanel.configure(text = valueStr)
                if self.debug:
                    showBar(stats['health'], self.barDetector.hpBarImg, self.hpPanel, self.hpText, "HP: ")
                    showBar(stats['thirst'], self.barDetector.thirstBarImg, self.thirstPanel, self.thirstText, "Thirst: ")
                    showBar(stats['hunger'], self.barDetector.hungerBarImg, self.hungerPanel, self.hungerText, "Hunger: ")
                    #showBar('Actionbar', np.concatenate(self.actionBarDetector.actionBarSlotImages, axis=1), self.actionBarPanel, None, "Actionbar: ")
                self.generatePayload(stats)
        except Exception as err:
            logger.error(err)
        self.root.after(self.delay(), self.loop)
    
    def generatePayload(self, stats):
        stats['username'] = self.userNameInput.get()
        stats['bolt'] = False
        stats['AK'] = False
        stats['pistol'] = False
        stats['pipe'] = False
        self.socketIO.emit('playerupdate', stats)
        
    def quit(self):
        #write username to disk
        user = {}
        user['userName'] = self.userNameInput.get()
        with open('user.json', 'w') as dataFile:
            json.dump(user, dataFile)
        self.socketIO.disconnect()
        self.root.destroy()
        
    def delay(self):
        hertz = self.hertz.get()
        if len(hertz) == 0:
            hertz = self.defaultHertz
        return int(1000 / float(hertz))
Exemple #40
0
class Simulator:
    """Provides interface to an indoor simulation server"""

    BoxSpace = collections.namedtuple('BoxSpace', ['range', 'shape'])

    def __init__(self, params):
        params = edict(params)
        home = os.environ.get('HOME')
        common.add_localhost_to_noproxy()
        script_path = os.path.dirname(os.path.realpath(__file__))
        if 'SIM_PATH' not in params:
            params.SIM_PATH = os.environ.get('SIM_PATH', os.path.join(script_path, '../'))
        if 'NODE_BASE_URL' not in params:
            params.NODE_BASE_URL = os.environ.get('NODE_BASE_URL', os.path.join(home, 'work/'))
        if 'color_encoding' not in params:
            params.color_encoding = 'gray'
        if 'host' not in params:
            params.host = 'localhost'
        if 'port' not in params or params.port is None:
            params.port = common.get_random_port()
        if 'audio' not in params or not params.audio:
            params.audio = edict()
        if 'port' not in params.audio or params.audio.port is None:
            params.audio.port = common.get_random_port()
        if 'datapath' not in params.audio:
            params.audio.datapath = 'data/wav'    # where audio files are found
        if 'wallpath' not in params.audio:
            params.audio.wallpath = os.path.join(params.NODE_BASE_URL, 'suncg', 'wall')    # where scene wall files are found
        if 'width' not in params and 'resolution' in params:
            params.width = params.resolution[0]
            params.height = params.resolution[1]
        if 'sensors_config' not in params:
            params.sensors_config = '../config/sensors.yml'
        # TODO: Organize these encodings
        if params.get('roomtypes_file') is not None:
            self.roomTypes = LabelMapping(params['roomtypes_file'], 'roomType', 0)
        else:
            self.roomTypes = None
        if params.get('objecttypes_file') is not None:
            self.objectTypes = LabelMapping(params['objecttypes_file'], 'objectType', 0)
        else:
            self.objectTypes = None

        self.auto_start = params.auto_start if 'auto_start' in params else False
        self.start_time = None
        self.stats_counter = Counter()
        self.id = params.get('id', 'sim00')
        self._uuid = uuid.uuid4()
        self._rpcid = 0
        self._proc_sim = None
        self._proc_audio = None
        self._sio = None
        self._restarts = 0
        self._last_observation = None
        self.start_summary_info = None
        self.running = False
        self.killed = False
        self.params = params

        # Initialize logging
        if 'logdir' in params:
            self._logdir = params.logdir
        else:
            timestamp = datetime.now().strftime('%Y%m%d-%H%M%S-%f')
            self._logdir = './logs/' + timestamp
        self._logger = self._get_logger('simulator', propagate=True)
        self._output_dir = params.output_dir if 'output_dir' in params else self._logdir
        params.output_dir = os.path.abspath(self._output_dir)

        # Track what version we are
        stk_sim_path = os.path.dirname(os.path.abspath(__file__))
        stk_git_hash = sp.check_output(['git', 'rev-parse', '--short', 'HEAD'], universal_newlines=True,
                                       cwd=stk_sim_path).rstrip(),
        sim_git_hash = sp.check_output(['git', 'rev-parse', '--short', 'HEAD'], universal_newlines=True,
                                       cwd=params.SIM_PATH).rstrip(),
        info = {
            'sim_id': self.id,
            'machine': os.uname()[1],
            'sim_git_hash': sim_git_hash[0],
            'stk_git_hash': stk_git_hash[0]
        }
        self._logger.info(info)

        # Initialize sensors
        sensors_file = os.path.join(script_path, params.sensors_config)
        if sensors_file.endswith('.yml') or sensors_file.endswith('.yaml'):
            sensor_configs = yaml.load(open(sensors_file, 'r'))
        else:
            sensor_configs = json.load(open(sensors_file, 'r'))
        self._depth_noise_sims = {}
        self._sensors_by_name = {}
        for sensor_config in sensor_configs:
            # merge sensor configuration overrides
            if 'sensors' in params:
                for sensor_override in [x for x in params.sensors
                                        if 'name' in x and x['name'] == sensor_config['name']]:
                    sensor_config.update(sensor_override)
            sensor = edict(copy.copy(sensor_config))  # make copy so our noise_sim not in config parameters
            self._sensors_by_name[sensor['name']] = sensor
            if sensor.type == 'depth':
                if sensor.get('noise'):
                    noise_model = sensor.get('noise_model')
                    if noise_model is not None:
                        sensor['noise_sim'] = self._get_depth_noise_sim(noise_model)
                    else:
                        raise Exception('noise_model not specified for sensor ' + sensor.name)
                else:
                    sensor['noise_sim'] = None
        params.semantic_encodings = {}
        if self.roomTypes is not None:
            params.semantic_encodings['roomType'] = self.roomTypes.to_dict()
        if self.objectTypes is not None:
            params.semantic_encodings['objectType'] = self.objectTypes.to_dict()
        params.sensors = sensor_configs

        # Initialize agent config
        if 'agent_config' in params and params['agent_config']:
            cfg_id = params['agent_config']
            cfg_file = os.path.realpath(os.path.join(script_path, '../config/', cfg_id + '.yml'))
            with open(cfg_file, 'r') as f:
                agent_cfg = yaml.load(f)
            params.agent = agent_cfg

        # remove members that cannot be serialized and sent to simulator
        if 'nonserializable' in params:
            for nonserializable in params.nonserializable:
                if nonserializable in params:
                    del params[nonserializable]

    def __del__(self):
        if not self.killed:
            self.kill()

    def _get_logger(self, name, propagate=False):
        common.ensure_dir_exists(self._logdir)
        filename = os.path.join(self._logdir, name + '.log')
        logger = log.getLogger(self._uuid.hex + '.' + name)
        if len(logger.handlers) == 0:
            fh = log.FileHandler(filename)
            fh.setLevel(log.INFO)
            fh.setFormatter(log.Formatter(FORMAT))
            logger.addHandler(fh)              # output log messages to file
        logger.propagate = propagate           # don't propagate messages to root logger (keep just in file)
        return logger

    def _rpc(self, name, data=None, callback=None, seconds=1):
        self._rpcid = self._rpcid + 1
        rpc = RpcCall(self._sio, self._rpcid, self._logger)
        return rpc.call(name, data, callback, seconds, check_wait=lambda: self.running)

    def _get_depth_noise_sim(self, noise_model_spec):
        simkey = json.dumps(noise_model_spec)
        noise_sim = self._depth_noise_sims.get(simkey)

        if noise_sim is None:
            noise_type = noise_model_spec.get('type')
            if noise_type == 'simple':
                if noise_model_spec.noise[0] == 'gaussian':
                    noise_sim = DepthNoiseSim(near=noise_model_spec.clip[0], far=noise_model_spec.clip[1],
                                              mean=noise_model_spec.noise[1], sigma=noise_model_spec.noise[2])
                else:
                    raise ValueError('Unknown noise distribution ' + noise_model_spec.noise[0])
            elif noise_type == 'redwood':
                noise_model_file = Template(noise_model_spec.path).substitute({ "SIMDEPTH_DIR": simdepth_path })
                simkey = noise_type + ':' + noise_model_file
                noise_sim = RedwoodDepthNoiseSim(noise_model_file)
            else:
                raise ValueError('Unsupported noise type ' + noise_type)
            self._depth_noise_sims[simkey] = noise_sim
        return noise_sim

    def start_child_servers(self):
        if self.auto_start:
            if not self._proc_sim:
                script_path = os.path.dirname(os.path.realpath(__file__))
                path_sim = os.path.realpath(os.path.join(script_path, '../server/'))
                self._logger.info(self.id + ':Starting sim server at %s with port %d' % (path_sim + '/server.js', self.params.port))
                my_env = os.environ.copy()
                my_env['NODE_BASE_URL'] = self.params.NODE_BASE_URL

                simserver_cmd = ['node','--max-old-space-size=4096', path_sim + '/server.js',
                                 '-p', str(self.params.port)]
                if self.params.get('busywait', 0) > 0:
                    simserver_cmd.append('--busywait')
                    simserver_cmd.append(str(self.params.get('busywait')))
                if self.params.get('ping_timeout') is not None:
                    simserver_cmd.append('--ping_timeout')
                    simserver_cmd.append(str(self.params.get('ping_timeout')))
                if self.params.get('profile_cpu', False):
                    simserver_cmd.insert(1, '--prof')
                if self.params.get('debug_mem', False):
                    simserver_cmd.insert(1, '--expose-gc')
                self._proc_sim = BackgroundPopen('simserver', self._get_logger('simserver'),
                                                 out_handler=None, err_handler=None,
                                                 args=simserver_cmd,
                                                 #bufsize=0,
                                                 env=my_env, preexec_fn=os.setsid, cwd=path_sim)
                time.sleep(1)
            if not self._proc_audio and self.params.observations.audio:
                path_audio = os.path.join(self.params.SIM_PATH, 'r2sim')
                self._logger.info('Starting audio server at %s with port %d' % (path_audio, self.params.audio.port))

                r2sim_verbosity = 2 if self.params.audio.get('debug',False) else 1
                r2sim_cmd = ['bin/r2sim',
                             '-tcp_port', str(self.params.audio.port),
                             '-conf','config/r2sim.conf',
                             '-verbosity', str(r2sim_verbosity)]
                if self.params.audio.get('debug_memory', False):
                    r2sim_cmd = ['valgrind', '--leak-check=yes'] + r2sim_cmd
                self._proc_audio = BackgroundPopen('audioserver', self._get_logger('audioserver'),
                                                   out_handler=None, err_handler=None,
                                                   args=r2sim_cmd,
                                                   #bufsize=0,
                                                   preexec_fn=os.setsid, cwd=path_audio)
                time.sleep(1)
            if not self.check_status():
                return False
        if not self._sio:
            self._sio = SocketIO(self.params.host, self.params.port)
            self._sio.on('connect', self.on_connect)
            self._sio.on('disconnect', self.on_disconnect)
            self._sio.on('reconnect', self.on_reconnect)
        return True

    def restart_child_servers(self, randomize_ports=False, seconds=1):
        # Maybe something happened to our servers
        # Let's stop and restart!
        self._restarts += 1
        self._logger.info(self.id + ':Restart %d' % self._restarts)

        # FULL CLOSE
        # NOTE: set sio to none so it will be recreated again
        # Hypothetically, it should reconnected as long as simserver reuses the same port (but something goes wrong)
        self.close(seconds=seconds)
        self._sio = None

        # Partial close (not fully working)
        #self.running = False
        #self._rpc('close', seconds=seconds)  # Try to be good and tell other side we are closing

        # Stop servers
        self.stop_child_servers()

        # Restart servers
        if randomize_ports:
            # Only audio port need to be randomized (sio port is okay)
            self.params.audio.port = common.get_random_port()
        return self.start_child_servers()

    def restart(self, randomize_ports=False, seconds=1):
        self.restart_child_servers(randomize_ports, seconds)
        return self.start()

    def check_resources(self):
        resources_self = resource.getrusage(resource.RUSAGE_SELF)
        resources_children = resource.getrusage(resource.RUSAGE_CHILDREN)
        resources = { 'self': resources_self, 'children': resources_children }
        self._logger.info(pprint.pformat(resources))
        return resources

    def check_status(self):
        ok = True
        if self._proc_sim:
            rv = self._proc_sim.poll()
            if rv is not None:
                self._logger.info(self.id + ':sim server has exited with rv %d' % rv)
                self._proc_sim = None
                ok = False
        else:
            ok = False

        if self._proc_audio:
            rv = self._proc_audio.poll()
            if rv is not None:
                self._logger.info(self.id + ':audio simulator has exited with rv %d' % rv)
                self._proc_audio = None
                ok = False
        else:
            ok = not self.params.observations.audio

        return ok

    def start(self):
        """Starts the simulation. Returns summary of started configuration."""
        started = self.start_child_servers()
        if not started:
            self.running = False
            return False
        self.start_time = time.time()
        self.running = True
        self._rpc('start', self.params, self.on_started)
        return self.start_summary_info

    def init(self):
        """Initializes the simulation. Returns success."""
        started = self.start_child_servers()
        if not started:
            self.running = False
            return False
        return self._rpc('init', self.params, self.on_inited)

    def close(self, seconds=None):
        """Stops the simulation. Returns success."""
        self.start_summary_info = None
        res = self._rpc('close', seconds=seconds)
        self.running = False
        self._sio.disconnect()
        return res

    def seed(self, s):
        """Sets the random number seed for the simulator. Returns success."""
        return self._rpc('seed', s)

    def reset(self):
        """Resets the simulation. Returns summary of current configuration."""
        self._rpc('reset', callback=self.on_reset)
        return self.start_summary_info

    def move_to(self, pos=None, angle=None, tilt=None):
        """Move agent to position (x,y,z), facing direction with angle radians
        to +X axis, and with tilt radians from horizontal. Returns success."""
        return self._rpc('move_to', {'position': pos, 'angle': angle, 'tilt': tilt})

    def set_goal(self, goal):
        """Set agent goal. Returns success."""
        return self._rpc('set_goal', goal)

    def set_scene(self, id):
        """Sets the scene in which simulator will run. Returns success."""
        return self._rpc('configure', { 'scene': { 'fullId': id }})

    def configure(self, config):
        """Sets the simulator configuration. Returns success."""
        if not config:  # check for empty config
            return True
        return self._rpc('configure', config)

    def step(self, action, frame_skip):
        """Takes simulation step carrying out action frame_skip times"""
        if action is None:
            action = {}
        if type(action) is list:
            for a in action:
                a['frame_skip'] = frame_skip
        else:
            action['frame_skip'] = frame_skip
        return self._rpc('action', action, self.on_observation)

    def get_last_observation(self):
        return self._last_observation

    def get_scene_data(self):
        """Returns metadata about current scene: { id: scene_id, bbox: {min, max} }"""
        return self._rpc('get_scene_data')

    def get_action_trace(self):
        """Returns trace of actions in current session"""
        return self._rpc('get_action_trace')

    def get_observation_space(self):
        """Return observation space"""
        obs_meta = self._rpc('get_observation_metadata')['data']
        sensors = obs_meta.get('sensors')
        sensor_obs_space = {k: Simulator.BoxSpace(range=s.get('dataRange'), shape=s.get('shape')) for k, s in sensors.items()}
        meas = obs_meta.get('measurements')
        meas_obs_space = {k: Simulator.BoxSpace(range=s.get('dataRange'), shape=s.get('shape')) for k, s in meas.items()}
        return {'sensors': sensor_obs_space, 'measurements': meas_obs_space}

    def __process_color(self, name, rgb):
        """Converts rgb bytes to Image and reshapes"""
        frame = rgb['data']
        encoding = rgb.get('encoding')
        data = None
        image = None

        # RGB image
        mode = 'RGBA'
        if encoding == 'rgba':
            data = np.reshape(frame, rgb['shape'])
        elif encoding == 'gray':
            mode = 'L'
            data = np.reshape(frame, (rgb['shape'][0], rgb['shape'][1]))

        if self.params.get('save_png'):
            if image is None:
                image = Image.frombytes(mode,(data.shape[0], data.shape[1]),data)
            cnt = self.stats_counter['frames_received']
            image.save(os.path.join(self._output_dir, name + ('_%d.png' % cnt)))

        return {'image': image, 'data': data}

    def __process_depth(self, name, depth):
        """Converts depth bytes to Image and reshapes"""
        frame = depth['data']
        encoding = depth.get('encoding')
        data = None
        data_clean = None
        image = None

        # depths
        #self._logger.info('frame length %d', len(frame))
        #self._logger.info('shape %s', depth['shape'])
        mode = 'RGBA'
        if encoding == 'rgba':
            data = np.reshape(frame, depth['shape'])
        elif encoding == 'depth' or encoding == 'binned':
            #dims = (depth['shape'][0], depth['shape'][1])
            #self._logger.info(dims)
            data = np.reshape(frame, (depth['shape'][0], depth['shape'][1]))
            mode = 'L'
            # TODO: need to make sure in meters and is float32 for depth sensor noise simulation
            depth_sensor = self._sensors_by_name[name]
            if depth_sensor.noise_sim is not None:
                # Simulate noise
                data_clean = np.copy(data)  # TODO: Is this copying unnecessarily expensive, should there be a flag guarding against this?
                depth_sensor.noise_sim.simulate(data)

        if self.params.get('save_png'):
            if image is None:
                # self._logger.info('type is %s' % type(data))
                d = data.astype(np.float32)
                d = (d * (255.0 / np.max(d))).astype(np.uint8)
                image = Image.frombytes(mode,(d.shape[0], d.shape[1]),d)
            cnt = self.stats_counter['frames_received']
            image.save(os.path.join(self._output_dir, name + ('_%d.png' % cnt)))
        return {'image': image, 'data': data, 'data_clean': data_clean}

    def __process_camera_frame(self, name, f):
        """Converts generic camera based frame (assume to be rgba) bytes to Image and reshapes"""
        data = np.reshape(f['data'], f['shape'])
        data_viz = None
        if 'data_viz' in f:
            data_viz = np.reshape(f['data_viz'], f['shape'])

        image = None
        if self.params.get('save_png'):
            if image is None:
                imgd = data_viz if data_viz is not None else data
                image = Image.frombytes('RGBA',(imgd.shape[0], imgd.shape[1]),imgd)
            cnt = self.stats_counter['frames_received']
            image.save(os.path.join(self._output_dir, name + ('_%d.png' % cnt)))

        return {'image': image, 'data': data, 'data_viz': data_viz}

    def __process_audio(self, name, audio):
        """Saves audio """
        data = audio['data']
        sample_rate = audio.get('sampleRate')
        encoding = audio.get('encoding')
        # self._logger.info('Sampling rate is %d' % sample_rate)

        # TODO: Change save_png flag to more generic save sensor output flag
        if self.params.get('save_png'):
            wavfile.write(os.path.join(self._output_dir, name + '.wav'), sample_rate, data)
            np.savetxt(os.path.join(self._output_dir, name + '.wav.txt'), data)

        return {'data': data}

    def __process_force(self, name, force):
        data = force['data']
        # TODO: Change save_png flag to more generic save sensor output flag
        if self.params.get('save_png'):
            plt = common.bearing_plot(data)
            cnt = self.stats_counter['frames_received']
            plt.savefig(os.path.join(self._output_dir, name + ('_%d.png' % cnt)), dpi=25)
            plt.close()
        return {'data': data}

    def __process_observation(self, data):
        observation = data['observation']
        sensors = observation['sensors']
        if observation.get('map') is not None:
            converted = self.__process_camera_frame('map', observation['map'])
            observation['map']['data'] = converted['data']
        # Go over observations from sensors and process them
        for name, sensor_data in sensors.items():
            sensor_type = sensor_data.get('type')
            if sensor_type == 'color':
                converted_rgb = self.__process_color(name, sensor_data)
                sensor_data['data'] = converted_rgb['data']
            elif sensor_type == 'depth':
                converted_depth = self.__process_depth(name, sensor_data)
                sensor_data['data'] = converted_depth['data']
                sensor_data['data_clean'] = converted_depth['data_clean']
            elif sensor_type == 'audio':
                converted_audio = self.__process_audio(name, sensor_data)
                sensor_data['data'] = converted_audio['data']
            elif sensor_type == 'force':
                converted_force = self.__process_force(name, sensor_data)
                sensor_data['data'] = converted_force['data']
            else:
                if (len(sensor_data['shape']) == 3 and sensor_data['shape'][2] == 4):
                    # Frame from camera like sensor?
                    converted = self.__process_camera_frame(name, sensor_data)
                    sensor_data['data'] = converted['data']
                    sensor_data['data_viz'] = converted['data_viz']

    def __process_goal_observations(self, goal_observations):
        if goal_observations is not None:
            for i, obs in enumerate(goal_observations):
                self.__process_observation(obs)

    def on_observation(self, message):
        self.stats_counter.update(['frames_received'])
        data = message.get('data') if message is not None else None
        if data is not None:
            if 'observation' not in data:
                err_str = self.id + ':Received data message with no observation : ' + str(data)
                self._logger.error(err_str)
                raise Exception(err_str)
            self.__process_observation(data)
        else:
            self.stats_counter.update(['empty_frames_received'])
        self._last_observation = data  # save last observation
        return data

    def on_started(self, message):
        if message is None or message.get('status') == 'error':
            return False
        else:
            self.start_summary_info = message.get('data')
            self.__process_goal_observations(self.start_summary_info.get('goalObservations'))
            self.step({'name': 'idle'}, 1)  # take a first step to fill last observation
            #self._logger.info('started')
            return True

    def on_reset(self, message):
        if message is None or message.get('status') == 'error':
            return False
        else:
            self.start_summary_info = message.get('data')
            self.__process_goal_observations(self.start_summary_info.get('goalObservations'))
            self.step({'name': 'idle'}, 1)  # take a first step to fill last observation
            return True

    def on_inited(self, message):
        if message is None or message.get('status') == 'error':
            return False
        else:
            self._logger.info(self.id + ':inited')
            return True

    def on_connect(self):
        self._logger.info(self.id + ':connect')

    def on_disconnect(self):
        self._logger.info(self.id + ':disconnect')

    def on_reconnect(self):
        self._logger.info(self.id + ':reconnect')

    def flush_logs(self):
        if self._proc_sim:
            self._proc_sim.flush()
        if self._proc_audio:
            self._proc_audio.flush()
        if self._logger is not None:
            for handler in self._logger.handlers:
                handler.flush()

    def stop_child_servers(self):
        self._logger.info(self.id + ':Stopping child servers')
        if self._proc_sim:
            self._logger.info(self.id + ':Killing sim pid %d' % self._proc_sim.pid)
            try:
                os.killpg(os.getpgid(self._proc_sim.pid), signal.SIGTERM)
            except:
                self._logger.info(self.id + ':Error killing sim server')
            self._proc_sim.close()
            self._proc_sim = None
        if self._proc_audio:
            self._logger.info(self.id + ':Killing audio sim pid %d' % self._proc_audio.pid)
            try:
                os.killpg(os.getpgid(self._proc_audio.pid), signal.SIGTERM)
            except:
                self._logger.info(self.id + ':Error killing audio sim')
            self._proc_audio.close()
            self._proc_audio = None
        self._logger.info(self.id + ':Stopped child servers')

    def kill(self):
        self._logger.info(self.id + ':Stopping the simulator')
        self._logger.info(self.stats_counter)
        if self.running:
            self.close(seconds=1)
        self.stop_child_servers()
        self._logger.info(self.id + ':Simulator killed.')
        self.killed = True
class SocketResponse:
    """
    SocketResponse
    
    Class responsible for handling responses sent to the Socket.IO proxy server. This is used to
    send messages back to web clients that used the JavaScript Socket.IO client to make API requests.
    Clients are distinguished by a unique string, consisting of their API username and session ID.
    """
    def __init__(self):
        
        # Configuration / logger
        self.conf       = config.parse()
        self.log        = logger.create(__name__, self.conf.server.log)
        
        # SocketIO client / web socket parameters
        self.socket_io  = None
        self.web_socket = None
        
    def construct(self):
        """
        Construct the Socket.IO client for sending responses.
        """
        try:
            self.log.info('Opening SocketIO proxy connection: %s:%s' % (self.conf.socket.host, self.conf.socket.port))
            
            # Open the Socket.IO client connection
            self.socket_io = SocketIO(self.conf.socket.host, int(self.conf.socket.port))
            
            # Socket connection opened sucessfully
            self.log.info('Initialized SocketIO proxy connection')
            
        # Critical error when opening connection
        except Exception as e:
            self.log.info('Failed to initialize SocketIO proxy connection: %s' % e)
            return False
        
        # Return the constructed Socket.IO client
        return self
        
    def set(self, web_socket):
        """
        Set the web socket client attributes.
        """
        self.web_socket = web_socket
        
        # Return the web socket attributes
        return web_socket
        
    def disconnect(self):
        """
        Disconnect the Socket.IO client.
        """
        try:
            self.socket_io.disconnect()
            self.log.info('Closing SocketIO proxy connection')
        except:
            pass
        
    def broadcast(self, t, d={}):
        """
        Broadcast data to all web socket clients.
        """
        if self.socket_io:
            self.socket_io.emit('update', {'type': t, 'content': d})
        
    def loading(self, m=None):
        """
        Send a loading messages to a web socket client.
        """
        if self.web_socket and self.socket_io:
            self.socket_io.emit('update', { 'room': self.web_socket['room'], 'type': 'loading', 'content': m})
def ices_shutdown():
    global io, HOST, PORT, STATION, TOKEN
    io = SocketIO(HOST, PORT, Namespace)
    io.emit('shutdown', { 'station': STATION, 'token': TOKEN })
    io.wait(seconds=1)
    io.disconnect()
Exemple #43
0
class Node(object):
    """Node to handle incomming computation requests.

    The main steps this application follows: 1) retrieve (new) tasks
    from the central server, 2) kick-off docker algorithm containers
    based on this task and 3) retrieve the docker results and post
    them to the central server.

    TODO: read allowed repositories from the config file
    """
    def __init__(self, ctx):
        """ Initialize a new Node instance.

            Authenticates to the central server, setup encrpytion, a
            websocket connection, retrieving task that were posted while
            offline, preparing dataset for usage and finally setup a
            local proxy server.

            :param ctx: application context, see utils
        """
        self.log = logging.getLogger(logger_name(__name__))

        self.ctx = ctx
        self.config = ctx.config
        self.queue = queue.Queue()
        self._using_encryption = None

        # initialize Node connection to the server
        self.server_io = NodeClient(host=self.config.get('server_url'),
                                    port=self.config.get('port'),
                                    path=self.config.get('api_path'))

        self.log.info(f"Connecting server: {self.server_io.base_path}")

        # Authenticate with the server, obtaining a JSON Web Token.
        # Note that self.authenticate() blocks until it succeeds.
        self.log.debug("Authenticating")
        self.authenticate()

        # Setup encryption
        self.setup_encryption()

        # Thread for proxy server for algorithm containers, so they can
        # communicate with the central server.
        self.log.info("Setting up proxy server")
        t = Thread(target=self.__proxy_server_worker, daemon=True)
        t.start()

        # Create a long-lasting websocket connection.
        self.log.debug("Creating websocket connection with the server")
        self.connect_to_socket()

        # Check if new tasks were posted while offline.
        self.log.debug("Fetching tasks that were posted while offline")
        self.__sync_task_queue_with_server()

        # If we're in a 'regular' context, we'll copy the dataset to our data
        # dir and mount it in any algorithm container that's run; bind mounts
        # on a folder will work just fine.
        #
        # If we're running in dockerized mode we *cannot* bind mount a folder,
        # because the folder is in the container and not in the host. We'll
        # have to use a docker volume instead. This means:
        #  1. we need to know the name of the volume so we can pass it along
        #  2. need to have this volume mounted so we can copy files to it.
        #
        #  Ad 1: We'll use a default name that can be overridden by an
        #        environment variable.
        #  Ad 2: We'll expect `ctx.data_dir` to point to the right place. This
        #        is OK, since ctx will be a DockerNodeContext.
        #
        #  This also means that the volume will have to be created & mounted
        #  *before* this node is started, so we won't do anything with it here.

        # We'll create a subfolder in the data_dir. We need this subfolder so
        # we can easily mount it in the algorithm containers; the root folder
        # may contain the private key, which which we don't want to share.
        # We'll only do this if we're running outside docker, otherwise we
        # would create '/data' on the data volume.
        if not ctx.running_in_docker:
            task_dir = ctx.data_dir / 'data'
            os.makedirs(task_dir, exist_ok=True)

        else:
            task_dir = ctx.data_dir

        self.log.debug("Setting up the docker manager")
        self.__docker = DockerManager(
            allowed_images=self.config.get("allowed_images"),
            tasks_dir=task_dir,
            isolated_network_name=f"{ctx.docker_network_name}-net",
            node_name=ctx.name,
            data_volume_name=ctx.docker_volume_name,
        )

        # login to the registries
        self.__docker.login_to_registries(
            self.ctx.config.get("docker_registries", []))

        # If we're running in a docker container, database_uri would point
        # to a path on the *host* (since it's been read from the config
        # file). That's no good here. Therefore, we expect the CLI to set
        # the environment variable for us. This has the added bonus that we
        # can override the URI from the command line as well.
        default_uri = self.config['databases']['default']
        database_uri = os.environ.get('DATABASE_URI', default_uri)

        if Path(database_uri).exists():
            # We'll copy the file to the folder `data` in our task_dir.
            self.log.info(f'Copying {database_uri} to {task_dir}')
            shutil.copy(database_uri, task_dir)

            # Since we've copied the database to the folder 'data' in the root
            # of the volume: '/data/<database.csv>'. We'll just keep the
            # basename (i.e. filename + ext).
            database_uri = os.path.basename(database_uri)

        # Connect to the isolated algorithm network *only* if we're running in
        # a docker container.
        if ctx.running_in_docker:
            self.__docker.connect_to_isolated_network(
                ctx.docker_container_name,
                aliases=[cs.NODE_PROXY_SERVER_HOSTNAME])
            #self.__docker.connect_to_overlay_network(
            #    ctx.docker_container_name,
            #    aliases=[cs.NODE_PROXY_SERVER_HOSTNAME]
            #)

        # Let's keep it safe
        self.__docker.set_database_uri(database_uri)

        # Thread for sending results to the server when they come available.
        self.log.debug("Start thread for sending messages (results)")
        t = Thread(target=self.__speaking_worker, daemon=True)
        t.start()

        # listen forever for incoming messages, tasks are stored in
        # the queue.
        self.log.debug("Starting thread for incoming messages (tasks)")
        t = Thread(target=self.__listening_worker, daemon=True)
        t.start()

        self.log.info('Init complete')

    def __proxy_server_worker(self):
        """ Proxy algorithm container communcation.

            A proxy for communication between algorithms and central
            server.
        """
        # supply the proxy server with a destination (the central server)
        # we might want to not use enviroment vars
        os.environ["SERVER_URL"] = self.server_io.host
        os.environ["SERVER_PORT"] = self.server_io.port
        os.environ["SERVER_PATH"] = self.server_io.path

        if self.ctx.running_in_docker:
            # cs.NODE_PROXY_SERVER_HOSTNAME points to the name of the proxy
            # when running in the isolated docker network.
            default_proxy_host = cs.NODE_PROXY_SERVER_HOSTNAME
        else:
            # If we're running non-dockerized, assume that the proxy is
            # accessible from within the docker algorithm container on
            # host.docker.internal.
            default_proxy_host = 'host.docker.internal'

        # If PROXY_SERVER_HOST was set in the environment, it overrides our
        # value.
        proxy_host = os.environ.get("PROXY_SERVER_HOST", default_proxy_host)
        os.environ["PROXY_SERVER_HOST"] = proxy_host

        proxy_port = int(os.environ.get("PROXY_SERVER_PORT", 8080))

        # 'app' is defined in vantage6.node.proxy_server
        # app.debug = True
        app.config["SERVER_IO"] = self.server_io

        for try_number in range(5):
            self.log.info(
                f"Starting proxyserver at '{proxy_host}:{proxy_port}'")
            http_server = WSGIServer(('0.0.0.0', proxy_port), app)

            try:
                http_server.serve_forever()

            except OSError as e:
                self.log.debug(f'Error during attempt {try_number}')
                self.log.debug(f'{type(e)}: {e}')

                if e.errno == 48:
                    proxy_port = random.randint(2048, 16384)
                    self.log.critical(
                        f"Retrying with a different port: {proxy_port}")
                    os.environ['PROXY_SERVER_PORT'] = str(proxy_port)

                else:
                    raise

            except Exception as e:
                self.log.error('Proxyserver could not be started or crashed!')
                self.log.error(e)

    def __sync_task_queue_with_server(self):
        """ Get all unprocessed tasks from the server for this node."""
        assert self.server_io.cryptor, "Encrpytion has not been setup"

        # request open tasks from the server
        tasks = self.server_io.get_results(state="open", include_task=True)
        self.log.debug(tasks)
        for task in tasks:
            self.queue.put(task)

        self.log.info(f"received {self.queue._qsize()} tasks")

    def __start_task(self, taskresult):
        """Start a task.

            Start the docker image and notify the server that the task
            has been started.

            :param taskresult: an empty taskresult
        """
        task = taskresult['task']
        self.log.info("Starting task {id} - {name}".format(**task))

        # notify that we are processing this task
        self.server_io.set_task_start_time(taskresult["id"])

        token = self.server_io.request_token_for_container(
            task["id"], task["image"])
        token = token["container_token"]

        # create a temporary volume for each run_id
        # FIXME: why is docker_temporary_volume_name() in ctx???
        vol_name = self.ctx.docker_temporary_volume_name(task["run_id"])
        self.__docker.create_volume(vol_name)

        # For some reason, if the key 'input' consists of JSON, it is
        # automatically marshalled? This causes trouble, so we'll serialize it
        # again.
        # FIXME: should probably find & fix the root cause?
        if type(taskresult['input']) == dict:
            taskresult['input'] = json.dumps(taskresult['input'])

        # Run the container. This adds the created container/task to the list
        # __docker.active_tasks
        self.__docker.run(result_id=taskresult["id"],
                          image=task["image"],
                          docker_input=taskresult['input'],
                          tmp_vol_name=vol_name,
                          token=token)

    def __listening_worker(self):
        """ Listen for incoming (websocket) messages from the server.

            Runs in a separate thread. Received events are dispatched
            through the appropriate action_handler for a channel.
        """
        self.log.debug("listening for incoming messages")

        # FIXME: while True in combination with a wait() call that never exits
        #   makes joining the tread (to terminate) difficult?
        while True:
            # incoming messages are handled by the action_handler instance
            # which is attached when the socket connection was made. wait()
            # is blocks forever (if no time is specified).
            self.socketIO.wait()

    def __speaking_worker(self):
        """ Sending messages to central server.

            Routine that is in a seperate thread sending results
            to the server when they come available.

            TODO change to a single request, might need to reconsider
                the flow
        """
        self.log.debug("Waiting for results to send to the server")

        while True:
            results = self.__docker.get_result()

            # notify all of a crashed container
            if results.status_code:
                self.socket_tasks.emit('container_failed', self.server_io.id,
                                       results.status_code, results.result_id,
                                       self.server_io.collaboration_id)

            self.log.info(
                f"Sending result (id={results.result_id}) to the server!")

            # FIXME: why are we retrieving the result *again*? Shouldn't we
            # just store the task_id when retrieving the task the first time?
            response = self.server_io.request(f"result/{results.result_id}")
            task_id = response.get("task").get("id")

            if not task_id:
                self.log.error(f"task_id of result (id={results.result_id}) "
                               f"could not be retrieved")
                return

            response = self.server_io.request(f"task/{task_id}")
            initiator_id = response.get("initiator")

            if not initiator_id:
                self.log.error(
                    f"Initiator id from task (id={task_id})could not be "
                    f"retrieved")

            self.server_io.patch_results(
                id=results.result_id,
                initiator_id=initiator_id,
                result={
                    'result': results.data,
                    'log': results.logs,
                    'finished_at': datetime.datetime.now().isoformat(),
                })

    def authenticate(self):
        """ Authenticate to the central server

            Authenticate with the server using the api-key. If the
            server rejects for any reason we keep trying.
        """
        api_key = self.config.get("api_key")

        keep_trying = True
        while keep_trying:
            try:
                self.server_io.authenticate(api_key)

            except Exception as e:
                msg = 'Authentication failed. Retrying in 10 seconds!'
                self.log.warning(msg)
                self.log.debug(e)
                time.sleep(10)

            else:
                # This is only executed if try-block executed without error.
                keep_trying = False

        # At this point, we shoud be connnected.
        self.log.info(f"Node name: {self.server_io.name}")

    def private_key_filename(self):
        """Get the path to the private key."""

        # FIXME: Code duplication: vantage6/cli/node.py uses a lot of the same
        #   logic. Suggest moving this to ctx.get_private_key()
        filename = self.config['encryption']["private_key"]

        # filename may be set to an empty string
        if not filename:
            filename = 'private_key.pem'

        # If we're running dockerized, the location may have been overridden
        filename = os.environ.get('PRIVATE_KEY', filename)

        # If ctx.get_data_file() receives an absolute path, its returned as-is
        fullpath = Path(self.ctx.get_data_file(filename))

        return fullpath

    def setup_encryption(self):
        """Setup encryption ... or don't."""
        encrypted_collaboration = self.server_io.is_encrypted_collaboration()
        encrypted_node = self.config['encryption']["enabled"]

        if encrypted_collaboration != encrypted_node:
            # You can't force it if it just ain't right, you know?
            raise Exception("Expectations on encryption don't match!?")

        if encrypted_collaboration:
            self.log.warn('Enabling encryption!')
            private_key_file = self.private_key_filename()
            self.server_io.setup_encryption(private_key_file)

        else:
            self.log.warn('Disabling encryption!')
            self.server_io.setup_encryption(None)

    def connect_to_socket(self):
        """ Create long-lasting websocket connection with the server.

            The connection is used to receive status updates, such as
            new tasks.
        """

        self.socketIO = SocketIO(self.server_io.host,
                                 port=self.server_io.port,
                                 headers=self.server_io.headers,
                                 wait_for_connection=True)

        # define() returns the instantiated action_handler
        self.socket_tasks = self.socketIO.define(NodeTaskNamespace, '/tasks')
        self.socket_tasks.set_node_worker(self)

        # Log the outcome
        if self.socketIO.connected:
            msg = 'connected to host={host} on port={port}'
            msg = msg.format(host=self.server_io.host,
                             port=self.server_io.port)
            self.log.info(msg)

        else:
            msg = 'could *not* connect to {host} on port={port}'
            msg = msg.format(host=self.server_io.host,
                             port=self.server_io.port)
            self.log.critical(msg)

    def get_task_and_add_to_queue(self, task_id):
        """Fetches (open) task with task_id from the server.

            The `task_id` is delivered by the websocket-connection.
        """

        # fetch (open) result for the node with the task_id
        tasks = self.server_io.get_results(include_task=True,
                                           state='open',
                                           task_id=task_id)

        # in the current setup, only a single result for a single node
        # in a task exists.
        for task in tasks:
            self.queue.put(task)

    def run_forever(self):
        """Forever check self.queue for incoming tasks (and execute them)."""
        try:
            while True:
                # blocking untill a task comes available
                # timeout specified, else Keyboard interupts are ignored
                self.log.info("Waiting for new tasks....")

                while True:
                    try:
                        task = self.queue.get(timeout=1)
                        # if no item is returned, the Empty exception is
                        # triggered, thus break statement is not reached
                        break

                    except queue.Empty:
                        pass

                    except Exception as e:
                        self.log.debug(e)

                # if task comes available, attempt to execute it
                try:
                    self.__start_task(task)
                except Exception as e:
                    self.log.exception(e)

        except KeyboardInterrupt:
            self.log.debug("Caught a keyboard interupt, shutting down...")
            self.socketIO.disconnect()
            sys.exit()
Exemple #44
0
 def test_disconnect(self):
     socketIO = SocketIO('localhost', 8000)
     socketIO.disconnect()
     self.assertEqual(socketIO.connected, False)
class AtlasStream(object):

    EVENT_NAME_RESULTS = "atlas_result"
    EVENT_NAME_SUBSCRIBE = "atlas_subscribe"
    EVENT_NAME_ERROR = "atlas_error"

    # Remove the following list when deprecation time expires
    CHANNELS = {
        "result": "atlas_result",
        "probe": "atlas_probestatus",
        "error": "atlas_error",
    }
    # -------------------------------------------------------

    def __init__(self, debug=False, server=False, proxies=None, headers=None):
        """Initialize stream"""
        self.iosocket_server = "atlas-stream.ripe.net"
        self.iosocket_resource = "/stream/socket.io"
        self.socketIO = None
        self.debug = debug
        self.error_callback = None
        self.proxies = proxies or {}
        self.headers = headers or {}

        if not self.headers or not self.headers.get("User-Agent", None):
            user_agent = "RIPE ATLAS Cousteau v{0}".format(__version__)
            self.headers["User-Agent"] = user_agent

        if self.debug and server:
            self.iosocket_server = server

    def handle_error(self, error):
        if self.error_callback is not None:
            self.error_callback(error)
        else:
            print(error)

    def connect(self):
        """Initiate the channel we want to start streams from."""
        self.socketIO = SocketIO(
            host=self.iosocket_server,
            port=80,
            resource=self.iosocket_resource,
            proxies=self.proxies,
            headers=self.headers,
            transports=["websocket"],
            Namespace=AtlasNamespace,
        )

        self.socketIO.on(self.EVENT_NAME_ERROR, self.handle_error)

    def disconnect(self):
        """Exits the channel k shuts down connection."""
        self.socketIO.disconnect()
        self.socketIO.__exit__([])

    def unpack_results(self, callback, data):
        if isinstance(data, list):
            for result in data:
                callback(result)
        else:
            callback(data)

    def bind_channel(self, channel, callback):
        """Bind given channel with the given callback"""

        # Remove the following list when deprecation time expires
        if channel in self.CHANNELS:
            warning = (
                "The event name '{}' will soon be deprecated. Use "
                "the real event name '{}' instead."
            ).format(channel, self.CHANNELS[channel])

            self.handle_error(warning)
            channel = self.CHANNELS[channel]
        # -------------------------------------------------------

        if channel == self.EVENT_NAME_ERROR:
            self.error_callback = callback
        elif channel == self.EVENT_NAME_RESULTS:
            self.socketIO.on(channel, partial(self.unpack_results, callback))
        else:
            self.socketIO.on(channel, callback)

    def start_stream(self, stream_type, **stream_parameters):
        """Starts new stream for given type with given parameters"""
        if stream_type:
            self.subscribe(stream_type, **stream_parameters)
        else:
            self.handle_error("You need to set a stream type")

    def subscribe(self, stream_type, **parameters):
        """Subscribe to stream with give parameters."""
        parameters["stream_type"] = stream_type

        if (stream_type == "result") and ("buffering" not in parameters):
            parameters["buffering"] = True

        self.socketIO.emit(self.EVENT_NAME_SUBSCRIBE, parameters)

    def timeout(self, seconds=None):
        """
        Times out all streams after n seconds or wait forever if seconds is
        None
        """
        if seconds is None:
            self.socketIO.wait()
        else:
            self.socketIO.wait(seconds=seconds)
_id_symbols = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
def generate_id(length, symbols=_id_symbols):
    n = len(symbols)
    symbol_gen = (symbols[random.randrange(0, n)] for i in range(length))
    return ''.join(symbol_gen)

if len(sys.argv) == 1:
    print "Usage: agent.py <room_id>"
    sys.exit(1)
else:
    room_id = sys.argv[1]

user_name = 'INDRA'
user_id = generate_id(USER_ID_LEN)

socket = SocketIO('localhost', 3000)
sa_payload = {'userName': user_name,
              'room': room_id,
              'userId': user_id}
socket.on('message', on_message)
socket.on('userList', on_user_list)
socket.emit('subscribeAgent', sa_payload, ack_subscribe_agent)

try:
    socket.wait()
except KeyboardInterrupt:
    pass
print "Disconnecting..."
socket.emit('disconnect')
socket.disconnect()
Exemple #47
0
class SocketIoJsonInterface(object):
    def __init__(self,
                 url,
                 socketIONamespace,
                 events=None):
        if url.endswith('/'):
            # remove trailing slash
            url = url[:-1]
        self.url = url
        self.path = socketIONamespace
        self.events = events or {}

        self.socketIO = None
        self.reactorThread = None
        self.namespace = None
        self.nextMessageId = 0
        self.messageHandlers = {}
        self.lock = threading.Lock()


    def connect(self):
        with self.lock:
            if self._isConnected():
                raise ValueError("'connect' called when already connected")

        with self.lock:
            self.socketIO = SocketIO(self.url)
            self.reactorThread = threading.Thread(target=self.socketIO.wait)
            self.reactorThread.daemon = True
            self.namespace = self.socketIO.define(self._namespaceFactory, self.path)
            self.reactorThread.start()
        return self


    def close(self):
        with self.lock:
            if not self._isConnected():
                return
            reactorThread = self.reactorThread
            self.reactorThread = None
            self.socketIO.disconnect()
        reactorThread.join()


    def isConnected(self):
        with self.lock:
            return self._isConnected()


    def send(self, message, callback):
        with self.lock:
            self._raiseIfNotConnected()
            messageId = self.nextMessageId
            self.nextMessageId += 1
            self.messageHandlers[messageId] = callback

            def encoder(obj):
                if not isinstance(obj, dict) and hasattr(obj, 'toMemoizedJSON'):
                    return obj.toMemoizedJSON()
                return obj

            message['messageId'] = messageId
            self.namespace.emit('message', {'body': json.dumps(message, default=encoder)})


    def on(self, event, callback):
        if event in self.events:
            raise ValueError("Event handler for '%s' already exists" % event)
        self.events[event] = callback


    def _isConnected(self):
        return self.reactorThread is not None


    def _raiseIfNotConnected(self):
        if not self._isConnected():
            raise ValueError('Performing I/O on disconnected socket')

    def _namespaceFactory(self, *args, **kwargs):
        return Namespace(self._onConnected, *args, **kwargs)


    def _triggerEvent(self, event, *args, **kwargs):
        if event in self.events:
            self.events[event](*args, **kwargs)

    def _onConnected(self, namespace):
        self._triggerEvent('connect', None)
        namespace.on('response', self._on_message)
        namespace.on('disconnect', self._on_disconnect)

    def _on_message(self, payload):
        try:
            message = json.loads(payload)
        except:
            self._triggerEvent('invalid_message', payload)
            return

        messageId = message.get('messageId')
        if messageId is None:
            self._triggerEvent('special_message', message)
            return

        callback = self.messageHandlers.get(messageId)
        if callback is None:
            self._triggerEvent('unexpected_message', message)
            return

        if message.get('responseType') != 'SubscribeResponse':
            del self.messageHandlers[messageId]

        callback(message)


    def _on_disconnect(self):
        self._triggerEvent('disconnect')
class HttpReceiver(MessageReceiverInterface):
    """A class for receiving json/xml query results and passing them to its subscribers"""
    CONNECTION_CHECK_PERIOD = 10
    def __init__(self, others, protos, ip="127.0.0.1", port=3700, description=""):
        MessageReceiverInterface.__init__(self)
        self.localNetDescription = description
        self.serverIp = ip
        self.serverPort = port
        ## this is a dict of names to receivers
        ## like: 'sms' -> SmsReceiver_instance
        ## keys are used to match against osc requests
        self.allReceivers = others
        ## this is a dict of (ip,port) -> prototype
        ## like: (192.168.2.5, 8888) -> megavoice
        self.allPrototypes = protos
        ## this is a dict of (ip,port) -> prototype 
        ## for keeping track of prototypes that have been sent to server
        self.sentPrototypes = {}
        ## reg-exp pattern for finding hashtags in messages
        self.hashTagMatcher = re.compile(r"([#]\w+)")

    def _getLocationDict(self):
        return {
                'city':self.location['city'],
                'state':self.location['state'],
                'country':self.location['country'],
                'coordinates':self.location['coordinates']
                }
    ## server reply party !!!
    class localNetNamespace(BaseNamespace):
        pass

    def _onAddLocalNetSuccess(self, *args):
        self.addedToServer = True
        for arg in args:
            if('epoch' in arg):
                print "localNet was added to server"
                self.serverIsWaitingForMessagesSince = float(arg['epoch'])

    def _onAddPrototypeSuccess(self, *args):
        for arg in args:
            if('prototypeAddress' in arg):
                (pip,pport) = arg['prototypeAddress'].split(':')
                if((pip,int(pport)) in self.allPrototypes):
                    print self.allPrototypes[(pip,int(pport))]+" was added to server"
                    self.sentPrototypes[(pip,int(pport))] = self.allPrototypes[(pip,int(pport))]

    def _onRemovePrototypeSuccess(self, *args):
        for arg in args:
            if('prototypeAddress' in arg):
                (pip,pport) = arg['prototypeAddress'].split(':')
                if((pip,int(pport)) in self.sentPrototypes):
                    print self.sentPrototypes[(pip,int(pport))]+" was removed from server"
                    del self.sentPrototypes[(pip,int(pport))]

    def _onAddLocalNetMessageSuccess(self, *args):
        for arg in args:
            if('messageId' in arg):
                if((self.largestSentMessageId+1) == int(arg['messageId'])):
                    print "message "+str(int(arg['messageId']))+" was added to server"
                    self.largestSentMessageId += 1

    ## process message from server
    def _onAddServerMessage(self, *args):
        print "got message from server"
        for arg in args:
            mEpoch = float(arg['epoch']) if('epoch' in arg) else time()
            mText = arg['messageText'] if('messageText' in arg) else ""
            mPrototype = str(arg['prototype']) if('prototype' in arg) else ""
            mUser = str(arg['user']) if('user' in arg) else ""

            if(not mText is ""):
                ## send to all subscribers
                if(mPrototype is ""):
                    self.sendToAllSubscribers(mText)
                    mPrototype=self.subscriberList
                ## send to one subscriber
                else:
                    mPrototype = mPrototype.replace('[','').replace(']','').replace('u\'','').replace('\',',',')
                    mPrototype = mPrototype.split(',')
                    (ip,port) = (str(mPrototype[0]),int(mPrototype[1]))
                    if((ip,port) in self.subscriberList):
                        print "found prototype, sending to "+ip+":"+str(port)
                        self.sendToSubscriber(ip,port,mText)
                        mPrototype=[(ip,port)]
                    else:
                        print "didn't find prototype at "+ip+":"+str(port)+", so sending to all"
                        self.sendToAllSubscribers(mText)
                        mPrototype=self.subscriberList

                ## prepare to send to database (through queue due to threading)
                msgHashTags = []
                for ht in self.hashTagMatcher.findall(mText):
                    msgHashTags.append(str(ht))
                self.dbQ.put({'epoch':mEpoch,
                			  'dateTime':strftime("%Y/%m/%d %H:%M:%S", localtime(mEpoch)),
                			  'text':mText.encode('utf-8'),
                			  'receiver':'http',
                			  'hashTags':msgHashTags,
                			  'prototypes':mPrototype,
                			  'user':mUser});

    def _sendMessage(self, msg):
        prots = []
        for (i,p) in loads(msg.prototypes):
            ## make sure it's a real prototype, not an osc repeater
            if((str(i),int(p)) in self.allPrototypes):
                prots.append((str(i), int(p)))

        mInfo = {
                'name':self.location['name'],
                'location':self._getLocationDict(),
                'dateTime':msg.dateTime,
                'epoch':msg.epoch,
                'messageId':msg.id,
                'messageText':str(msg.text).decode('utf-8'),
                'hashTags':msg.hashTags,
                'user':msg.user,
                'receiver':msg.receiver,
                'prototypes':prots
                }
        print "sending message "+str(msg.id)+":"+str(msg.text).decode('utf-8')+" to server"
        self.localNetSocket.emit('addMessage', mInfo, self._onAddLocalNetMessageSuccess)

    def _attemptConnection(self):
    	self.lastConnectionAttempt = time()
    	## try to open socket and send localnet info
        try:
            self.socket = SocketIO(self.serverIp, self.serverPort)
        except SocketIOError:
            self.socketConnected = False
            print ("couldn't connect to web server at "+
                    self.serverIp+":"+str(self.serverPort))
        else:
            self.socketConnected = True
            self.localNetSocket = self.socket.define(self.localNetNamespace, '/localNet')
            self.localNetSocket.on('addMessage', self._onAddServerMessage)

    ## setup socket communication to server
    def setup(self, db, osc, loc):
        self.database = db
        self.oscClient = osc
        self.location = loc
        self.name = "http"
        self.socketConnected = False
        self.addedToServer = False
        self.largestSentMessageId = 0
        self.serverIsWaitingForMessagesSince = -100
        self.lastMessagesSent = time()
        self.lastConnectionAttempt = 0
        self.dbQ = Queue()

        return True

    def update(self):
        if(not self.socketConnected):
        	if(time()-self.lastConnectionAttempt > HttpReceiver.CONNECTION_CHECK_PERIOD):
        		self._attemptConnection()
        	return

        ## if local net not on web server, add to server
        if(not self.addedToServer):
            localNetInfo = {
                            'name':self.location['name'],
                            'location':self._getLocationDict(),
                            'localNetDescription':self.localNetDescription,
                            'receivers':self.allReceivers.keys(),
                            'hashTags':self.allReceivers['twitter'].hashTags
                            }
            print "adding localNet to server"
            self.localNetSocket.emit('addLocalNet', localNetInfo, self._onAddLocalNetSuccess)

        ## if server is waiting for messages since an epoch
        if(self.serverIsWaitingForMessagesSince > -1):
            mQuery = self.database.select()
            mQuery = mQuery.where(self.database.epoch > self.serverIsWaitingForMessagesSince).order_by(self.database.id)
            for m in mQuery.limit(1):
                self.largestSentMessageId = m.id-1
            for m in mQuery:
                self._sendMessage(m)
            self.lastMessagesSent = time()
            self.serverIsWaitingForMessagesSince = -1

        ## check for new prototypes
        addQ = Queue()
        for p in self.allPrototypes:
            if (not p in self.sentPrototypes):
                addQ.put(p)
                print "adding "+self.allPrototypes[p]+" to server"
        while (not addQ.empty()):
            p = addQ.get()
            (pip,pport) = p
            ## send prototype info to add it to server
            pInfo = {
                    'name':self.location['name'],
                    'location':self._getLocationDict(),
                    'prototypeName':self.allPrototypes[p],
                    'prototypeAddress':pip+":"+str(pport),
                    'prototypeDescription':"hello, I'm a prototype"
                    }
            self.localNetSocket.emit('addPrototype', pInfo, self._onAddPrototypeSuccess)

        ## check for disconnected prototypes
        delQ = Queue()
        for p in self.sentPrototypes:
            if (not p in self.allPrototypes):
                delQ.put(p)
                print "removing "+self.sentPrototypes[p]+" from server"
        while (not delQ.empty()):
            p = delQ.get()
            (pip,pport) = p
            ## send prototype info to remove it from server
            pInfo = {
                    'name':self.location['name'],
                    'location':self._getLocationDict(),
                    'prototypeName':self.sentPrototypes[p],
                    'prototypeAddress':pip+":"+str(pport)
                    }
            self.localNetSocket.emit('removePrototype', pInfo, self._onRemovePrototypeSuccess)

        ## send new messages to server
        if(time()-self.lastMessagesSent > 1.0):
            mQuery = self.database.select()
            for m in mQuery.where(self.database.id > self.largestSentMessageId).order_by(self.database.id):
                self._sendMessage(m)
            self.lastMessagesSent = time()

		## log onto local database
        while (not self.dbQ.empty()):
        	dbargs = self.dbQ.get()
        	self.database.create(epoch=dbargs['epoch'],
                                 dateTime=dbargs['dateTime'],
                                 text=dbargs['text'],
                                 receiver=dbargs['receiver'],
                                 hashTags=dumps(dbargs['hashTags']),
                                 prototypes=dumps(dbargs['prototypes']),
                                 user=dbargs['user'])

    ## end http receiver; disconnect socket
    def stop(self):
        if(self.socketConnected):
            self.socket.disconnect()
Exemple #49
0
def console(window, host='localhost', port=8088):
    """Main console function. Inits all other modules/classes as needed.
    
    window: curses wrapper window
    host: address of the server
    port: port the server can be found on
    
    Default host:port is localhost:8088.
    """
    # Initialize curses interface
    global cs 
    with cinchscreen.CinchScreen(window, log) as cs:

        # Establish server connection
        socket = SocketIO(host, port)
        listener = threading.Thread(target=listen_to_server, args=(socket,))
        listener.daemon = True
        listener.start()
        ns = socket.define(Namespace, '/cinch')
    
        # Test & initialize connection
        sleep(0.5)
        ns.emit('test', 'console')
    
    
        # Register commands.
        # commands - list of 3-string lists (name, regex, usage).
        for c in COMMANDS:
            cs.register_command(*c)
    
        # Listen to the console.
        try:
            while True:
                while cs.queue.empty():
                    sleep(0.1)
                cmd = cs.queue.get(timeout=0.2)
    
                # Process the command.
    
                # test
                if 'test' in cmd:
                    ns.emit('test', 'console')
                elif 'help' in cmd:
                    for command in COMMANDS:
                        output = command[0] + ': ' + command[2]
                        if 'v' in cmd['help']:
                            output += r' (regex: /' + command[1] + r'/)'
                        cs.write(output)
                elif 'nick' in cmd:
                    if cmd['nick'] == '':
                        cs.write(ns.nickname) #TODO RoomView
                    else:
                        ns.emit('nickname', cmd['nick'], ns.ackNickname)
                        #TODO status window update nick
                elif 'chat' in cmd:
                    ns.emit('chat', cmd['chat'])
                elif 'room' in cmd:
                    #if cmd['room'] == '':
                    #    ns.emit('createRoom', '')
                    #else:
                    try:
                        ai_requests = cmd['room'].split()
                        ai_req_output = {}
                        for request in ai_requests:
                            x = request.split(':')
                            ai_req_output[int(x[0])] = int(x[1])
                        ns.emit('createRoom', ai_req_output, ns.ackCreate)
                    except ValueError:
                        log.exception('room: arg from queue: %s', cmd['room'])
                        log.error('room: A problem occurred.')
                elif 'aig' in cmd:
                    # Quickstart a 3-ai game.
                    ns.emit('createRoom', {1:1,2:1,3:1}, ns.ackCreate)
                elif 'aig4' in cmd:
                    # Start a 4-ai game.
                    ns.emit('aiOnlyGame', cmd['aig4'].split(' '), ns.ack_aig4)
                elif 'lobby' in cmd:
                    # It is assumed the move to the lobby is successful on the
                    # server.
                    ns.emit('exit')
                elif 'join' in cmd:
                    try:
                        if hasattr(ns, 'rv'): # No RoomView = in lobby
                            cs.write('join: must be in lobby to join a room')
                        else:
                            tmp = cmd['join'].split()
                            room_num = int(tmp[0])
                            seat_num = int(tmp[1])
                            ns.emit('join', room_num, seat_num, ns.ackJoin)
                    except ValueError:
                        log.exception('join: arg from queue: %s', cmd['join'])
                        log.error('join: A problem occurred.')
                elif 'seat' in cmd:
                    if hasattr(ns, 'rv'):
                        log.info('seat: currently in room %s, seat %s',
                                 str(ns.rv.room), str(ns.rv.seat))
                    else:
                        log.info('seat: currently in lobby')
                elif 'ai' in cmd:
                    if cmd['ai'] == 'refresh':
                        ns.emit('aiList', ns.setAIInfo)
                    elif cmd['ai'] == 'list':
                        cs.write("Available AI agents:")
                        for ai in ns.ai_list:
                            cs.write(str(ai['id']) + ': ' + ai['name'] +
                                        ' - ' + ai['desc'])
                    else:
                        try:
                            raise ValueError
                        except ValueError:
                            log.exception("ai: couldn't handle arg %s", cmd['ai'])
                elif 'bid' in cmd:
                    if cmd['bid'].lower() in ['cinch', 'c']:
                        ns.emit('bid', 5)
                    elif cmd['bid'].lower() in ['pass', 'p']:
                        ns.emit('bid', 0)
                    else:
                        try:
                            ns.emit('bid', int(cmd['bid']))
                        except ValueError:
                            log.exception('bid: arg from queue: %s',
                                          cmd['bid'])
                            log.error('bid: A problem occurred.')
                elif 'play' in cmd:
                    try:
                        # Strict NS-style shorthand for now
                        #TODO develop better UI later
                        ivRANKS_SHORT = {x[1][0]:x[0] for x in cards.RANKS_MAP.items()}
                        ivSUITS_SHORT = {'C':0, 'D':1, 'H':2, 'S':3}
                        p_card = cards.Card(ivRANKS_SHORT[cmd['play'].upper()[0]],
                                            ivSUITS_SHORT[cmd['play'].upper()[1]])
                        ns.emit('play', p_card.encode())
                    except Exception:
                        log.exception('play: generic problem')
                elif 'hand' in cmd:
                    # Write current hand contents to console as well as dash.
                    if not hasattr(ns, 'rv'):
                        log.info("No hand - not in a game.")
                    else:
                        hand_str = ('Your hand: ' +
                                    ', '.join([str(card) for card in ns.rv.hand]))
                        cs.write(hand_str)
                        cs.update_dash('hand', [str(card) for card in ns.rv.hand])
                elif 'exit' in cmd:
                    raise SystemExit
                elif 'kill' in cmd:
                    ns.emit('killRoom', cmd['kill'], ns.ackKill)

        except KeyboardInterrupt:
            log.warning("C-c detected; exiting...")
        except SystemExit:
            log.warning("Exiting...")
    
        # Disconnect
        socket.disconnect()

def generate_id(length, symbols=_id_symbols):
    n = len(symbols)
    symbol_gen = (symbols[random.randrange(0, n)] for i in range(length))
    return ''.join(symbol_gen)


if len(sys.argv) == 1:
    print "Usage: agent.py <room_id>"
    sys.exit(1)
else:
    room_id = sys.argv[1]

user_name = 'INDRA'
user_id = generate_id(USER_ID_LEN)

socket = SocketIO('localhost', 3000)
sa_payload = {'userName': user_name, 'room': room_id, 'userId': user_id}
socket.on('message', on_message)
socket.on('userList', on_user_list)
socket.emit('subscribeAgent', sa_payload, ack_subscribe_agent)

try:
    socket.wait()
except KeyboardInterrupt:
    pass
print "Disconnecting..."
socket.emit('disconnect')
socket.disconnect()
Exemple #51
0
class BaseBot(object):

    def __init__(self, args):
        self.uuid = args.uuid
        self.socketIO = SocketIO(args.host, args.port)
        self.connect_events()
        self.socketIO.wait()

    def start(self):
        # Override this in your bot implementation
        print("Basebot has started. Now place some bets and observe the output.")

    def stop(self):
        print("Disconnecting...")
        self.socketIO.disconnect()

    def connect_events(self):
        self.socketIO.on('connect', self.on_connect)
        self.socketIO.on('disconnect', self.on_disconnect)
        self.socketIO.on('error', self.on_error)
        self.socketIO.on('joined', self.on_joined)
        self.socketIO.on('message', self.on_message)
        self.socketIO.on('reconnect', self.on_reconnect)
        self.socketIO.on('sessionstart', self.on_sessionstart)
        self.socketIO.on('sessionstate', self.on_sessionstate)
        self.socketIO.on('bet', self.on_bet)
        self.socketIO.on('payment', self.on_payment)
        self.socketIO.on('sessionstop', self.on_sessionstop)

    def on_connect(self, *args):
        print('Connected. Now subscribing to player channel %s' %(self.uuid))
        self.socketIO.emit('subscribe', self.uuid);

    def on_disconnect(self):
        print('Disconnect.')

    def on_reconnect(self, *args):
        print("Reconnect.")

    def on_error(self, name, message):
        print('Error: %s: %s' % (name, message))

    def on_joined(self, channel):
        print("Joined channel %s. Now starting bot." % channel)
        self.start()

    def on_message(self, channel, message):
        message = json.loads(message)
        print("on_message")
        print(json.dumps(message, sort_keys=True, indent=4, separators=(',', ': ')))

    def on_sessionstart(self, channel, message):
        message = json.loads(message)
        print("on_sessionstart")
        print(json.dumps(message, sort_keys=True, indent=4, separators=(',', ': ')))

    def on_sessionstate(self, channel, message):
        message = json.loads(message)
        print("on_sessionstate")
        print(json.dumps(message, sort_keys=True, indent=4, separators=(',', ': ')))

    def on_bet(self, channel, message):
        message = json.loads(message)
        print("on_bet")
        print(json.dumps(message, sort_keys=True, indent=4, separators=(',', ': ')))

    def on_payment(self, channel, message):
        message = json.loads(message)
        print("on_payment")
        print(json.dumps(message, sort_keys=True, indent=4, separators=(',', ': ')))

    def on_sessionstop(self, channel, message):
        message = json.loads(message)
        print("on_sessionstop")
        print(json.dumps(message, sort_keys=True, indent=4, separators=(',', ': ')))
Exemple #52
0
    return on_type_stream_started()


class P300Client(object):
    def __init__(self):
        results = []


if __name__ == '__main__':
    socket_client = SocketIO("localhost", 8001)
    socket_client.on("eeg_stream_created", on_stream_created)
    socket_client.on("marker_stream_created", on_stream_created)
    socket_client.on("ml_stream_created", on_stream_created)
    socket_client.on("eeg_stream_started", on_stream_created)
    socket_client.on("marker_stream_started", on_stream_created)
    socket_client.on("ml_stream_started", on_stream_created)
    socket_client.connect()
    socket_client.emit("create_eeg_stream")
    socket_client.emit("create_marker_stream")
    socket_client.emit(
        "create_ml_stream", {
            'classifier_path': 'classifer.pkl',
            'test_path': 'test_set.pkl',
            'analysis_time': 1,
            'event_time': 0.2,
            'train': True,
            'train_epochs': 120,
            'get_test': True,
        })
    socket_client.disconnect()
Exemple #53
0
class SocketService(threading.Thread, SentinelObject):

    def __init__(self, options, pingTimeout=1):
        threading.Thread.__init__(self)

        self.static_token = options['token']
        self.options = options  # saved for reconnect
        # self.__init_socket()
        self.commands = {}  # this will hold the possible commands from server
        self._stop = threading.Event()  # for stopping the thread, testing
        self.socket = None    
        self.socketIO = None  
    """  """
    def init(self):
        self.__init_socket()
    """  """
    def __init_socket(self):       
        token = jwt.encode({"name": self.options["camera-id"]}, 'secret')

        ip      = self.options["ip"]
        port    = self.options["port"]
        socket  = self.options["socket-id"]
        camera  = self.options["camera-id"] 

        self.socketIO   = SocketIO(ip, port,  params={'id': camera, 'token': token})      
        self.socket     = self.socketIO.define(SocketServiceNamespace, socket)
        self.logger.debug("Init socket: [%s]" % socket)   
    """  """
    def get_socket(self):
        return self.socket
    """  """
    def get_socketIO(self):
        return self.socketIO
    """  """
    def __apply_command(self, command, param=None):
        if command in self.commands:
            if param is None:
                self.commands[command]()
            else:
                self.commands[command](param)
    """  """
    def __handle_server_message(self, message):
        self.logger.debug("[%s] handle_server_message" % self.options["socket-id"])
        # todo key check
        self.logger.debug(message)
        if 'command' not in message:
            self.logger.error("Missing command key.")
            self.logger.error(message)
        else:
            print len(message)
            if len(message) < 2:
                self.__apply_command(message['command'])
            else:
                self.__apply_command(message['command'], message)
    """  """
    def disconnect(self):
        self.socketIO.disconnect(self.options["socket-id"])         
        # try:
        #     self.socketIO.disconnect(self.options["socket-id"])           
        # except  ConnectionError:
        #     self.logger.error(self.options["socket-id"] + " connection error")  
    """  """
    def send(self, id, msg):     
        try:
            self.connection_handler()
            self.socket.emit(id, msg)          
        except websocket.WebSocketConnectionClosedException:
            self.logger.debug("[%s] reconnecting ..." % self.options["socket-id"]) 
        except AttributeError, IndexError:
            self.logger.debug('Hiba történt az üzenet küldésekor')
        except ConnectionError:
            self.logger.debug('Kapcsolati hiba')
            self.__init_socket()
            self.socket.on(self.options["camera-id"], self.__handle_server_message)    
Exemple #54
0
class TestSocketIO(TestCase):

    def setUp(self):
        self.socketIO = SocketIO(HOST, PORT)
        self.called_on_response = False

    def tearDown(self):
        del self.socketIO

    def on_response(self, *args):
        self.called_on_response = True
        for arg in args:
            if isinstance(arg, dict):
                self.assertEqual(arg, PAYLOAD)
            else:
                self.assertEqual(arg, DATA)

    def is_connected(self, socketIO, connected):
        childThreads = [
            socketIO._rhythmicThread,
            socketIO._listenerThread,
        ]
        for childThread in childThreads:
            self.assertEqual(not connected, childThread.done.is_set())
        self.assertEqual(connected, socketIO.connected)

    def test_disconnect(self):
        'Terminate child threads after disconnect'
        self.is_connected(self.socketIO, True)
        self.socketIO.disconnect()
        self.is_connected(self.socketIO, False)
        # Use context manager
        with SocketIO(HOST, PORT) as self.socketIO:
            self.is_connected(self.socketIO, True)
        self.is_connected(self.socketIO, False)

    def test_message(self):
        'Message'
        self.socketIO.define(Namespace)
        self.socketIO.message()
        self.socketIO.wait(0.1)
        namespace = self.socketIO.get_namespace()
        self.assertEqual(namespace.response, 'message_response')

    def test_message_with_data(self):
        'Message with data'
        self.socketIO.define(Namespace)
        self.socketIO.message(DATA)
        self.socketIO.wait(0.1)
        namespace = self.socketIO.get_namespace()
        self.assertEqual(namespace.response, DATA)

    def test_message_with_payload(self):
        'Message with payload'
        self.socketIO.define(Namespace)
        self.socketIO.message(PAYLOAD)
        self.socketIO.wait(0.1)
        namespace = self.socketIO.get_namespace()
        self.assertEqual(namespace.response, PAYLOAD)

    def test_message_with_callback(self):
        'Message with callback'
        self.socketIO.message(callback=self.on_response)
        self.socketIO.wait_for_callbacks(seconds=0.1)
        self.assertEqual(self.called_on_response, True)

    def test_message_with_callback_with_data(self):
        'Message with callback with data'
        self.socketIO.message(DATA, self.on_response)
        self.socketIO.wait_for_callbacks(seconds=0.1)
        self.assertEqual(self.called_on_response, True)

    def test_emit(self):
        'Emit'
        self.socketIO.define(Namespace)
        self.socketIO.emit('emit')
        self.socketIO.wait(0.1)
        self.assertEqual(self.socketIO.get_namespace().argsByEvent, {
            'emit_response': (),
        })

    def test_emit_with_payload(self):
        'Emit with payload'
        self.socketIO.define(Namespace)
        self.socketIO.emit('emit_with_payload', PAYLOAD)
        self.socketIO.wait(0.1)
        self.assertEqual(self.socketIO.get_namespace().argsByEvent, {
            'emit_with_payload_response': (PAYLOAD,),
        })

    def test_emit_with_multiple_payloads(self):
        'Emit with multiple payloads'
        self.socketIO.define(Namespace)
        self.socketIO.emit('emit_with_multiple_payloads', PAYLOAD, PAYLOAD)
        self.socketIO.wait(0.1)
        self.assertEqual(self.socketIO.get_namespace().argsByEvent, {
            'emit_with_multiple_payloads_response': (PAYLOAD, PAYLOAD),
        })

    def test_emit_with_callback(self):
        'Emit with callback'
        self.socketIO.emit('emit_with_callback', self.on_response)
        self.socketIO.wait_for_callbacks(seconds=0.1)
        self.assertEqual(self.called_on_response, True)

    def test_emit_with_callback_with_payload(self):
        'Emit with callback with payload'
        self.socketIO.emit('emit_with_callback_with_payload',
                           self.on_response)
        self.socketIO.wait_for_callbacks(seconds=0.1)
        self.assertEqual(self.called_on_response, True)

    def test_emit_with_callback_with_multiple_payloads(self):
        'Emit with callback with multiple payloads'
        self.socketIO.emit('emit_with_callback_with_multiple_payloads',
                           self.on_response)
        self.socketIO.wait_for_callbacks(seconds=0.1)
        self.assertEqual(self.called_on_response, True)

    def test_emit_with_event(self):
        'Emit to trigger an event'
        self.socketIO.on('emit_with_event_response', self.on_response)
        self.socketIO.emit('emit_with_event', PAYLOAD)
        self.socketIO.wait_for_callbacks(0.1)
        self.assertEqual(self.called_on_response, True)

    def test_ack(self):
        'Trigger server callback'
        self.socketIO.define(Namespace)
        self.socketIO.emit('ack', PAYLOAD)
        self.socketIO.wait(0.1)
        self.assertEqual(self.socketIO.get_namespace().argsByEvent, {
            'ack_response': (PAYLOAD,),
            'ack_callback_response': (PAYLOAD,),
        })

    def test_namespaces(self):
        'Behave differently in different namespaces'
        mainNamespace = self.socketIO.define(Namespace)
        chatNamespace = self.socketIO.define(Namespace, '/chat')
        newsNamespace = self.socketIO.define(Namespace, '/news')
        newsNamespace.emit('emit_with_payload', PAYLOAD)
        self.socketIO.wait(0.1)
        self.assertEqual(mainNamespace.argsByEvent, {})
        self.assertEqual(chatNamespace.argsByEvent, {})
        self.assertEqual(newsNamespace.argsByEvent, {
            'emit_with_payload_response': (PAYLOAD,),
        })
class SocketIoJsonInterface(object):
    def __init__(self,
                 url,
                 socketIONamespace,
                 events=None,
                 version=None):
        if url.endswith('/'):
            # remove trailing slash
            url = url[:-1]
        self.url = url
        self.path = socketIONamespace
        self.events = events or {}
        self.version = version or pyfora.__version__

        self.socketIO = None
        self.reactorThread = None
        self.namespace = None
        self.nextMessageId = 0
        self.messageHandlers = {}
        self.lock = threading.Lock()
        self.connection_cv = threading.Condition(self.lock)
        self.connection_status = ConnectionStatus()


    def connect(self, timeout=None):
        timeout = timeout or 30.0
        with self.lock:
            if self._isConnected():
                raise ValueError("'connect' called when already connected")

        with self.lock:
            t0 = time.time()
            self.connection_status.status = ConnectionStatus.connecting
            while True:
                try:
                    self.socketIO = SocketIO(self.url, wait_for_connection=False)
                    break
                except (TimeoutError, ConnectionError):
                    if time.time() - t0 > timeout:
                        raise
                    time.sleep(0.5)

            self.reactorThread = threading.Thread(target=self.socketIO.wait)

            if isinstance(self.socketIO._transport_instance, WebsocketTransport):
                self.socketIO._transport_instance._connection.lock = threading.Lock()

            self.reactorThread.daemon = True
            self.namespace = self.socketIO.define(self._namespaceFactory, self.path)
            self.reactorThread.start()

            while self.connection_status.status == ConnectionStatus.connecting and \
                    (time.time() - t0 < timeout):
                self.connection_cv.wait(timeout)

        if self.connection_status.status == ConnectionStatus.connected:
            return self

        if self.connection_status.status == ConnectionStatus.connecting:
            message = "Connection timed out"
        else:
            message = self.connection_status.message
        raise pyfora.ConnectionError(message)


    def close(self):
        with self.lock:
            if not self._isConnected():
                return
            reactorThread = self.reactorThread
            self.reactorThread = None
            self.socketIO.disconnect()
        reactorThread.join()


    def isConnected(self):
        with self.lock:
            return self._isConnected()


    def send(self, message, callback):
        with self.lock:
            self._raiseIfNotConnected()
            messageId = self.nextMessageId
            self.nextMessageId += 1
            self.messageHandlers[messageId] = callback

            def encoder(obj):
                if not isinstance(obj, dict) and hasattr(obj, 'toMemoizedJSON'):
                    return obj.toMemoizedJSON()
                return obj

            message['messageId'] = messageId
            self.namespace.emit('message', {'body': json.dumps(message, default=encoder)})


    def on(self, event, callback):
        if event in self.events:
            raise ValueError("Event handler for '%s' already exists" % event)
        self.events[event] = callback


    def _isConnected(self):
        return self.connection_status.status in [ConnectionStatus.connecting,
                                                 ConnectionStatus.connected]


    def _raiseIfNotConnected(self):
        if not self._isConnected():
            raise ValueError('Performing I/O on disconnected socket')


    def _namespaceFactory(self, *args, **kwargs):
        return Namespace(self._onConnected, *args, **kwargs)


    def _triggerEvent(self, event, *args, **kwargs):
        if event in self.events:
            self.events[event](*args, **kwargs)


    def _onConnected(self, namespace):
        namespace.on('disconnect', self._on_disconnect)

        namespace.on('handshake', self._on_handshake)
        namespace.emit('handshake', {'version': self.version})


    def _on_handshake(self, handshake_response):
        with self.lock:
            if handshake_response == 'ok':
                self.connection_status.status = ConnectionStatus.connected
            else:
                self.connection_status.status = ConnectionStatus.disconnected
                self.connection_status.message = handshake_response
            self.connection_cv.notify()

        self.namespace.on('response', self._on_message)


    def _on_message(self, payload):
        def object_hook(obj):
            for k in obj:
                if isinstance(obj[k], unicode):
                    obj[k] = obj[k].encode("utf8")
            return obj
        try:
            message = json.loads(payload, object_hook=object_hook)
        except:
            self._triggerEvent('invalid_message', payload)
            return

        messageId = message.get('messageId')
        if messageId is None:
            self._triggerEvent('special_message', message)
            return

        callback = self.messageHandlers.get(messageId)
        if callback is None:
            self._triggerEvent('unexpected_message', message)
            return

        if message.get('responseType') != 'SubscribeResponse':
            del self.messageHandlers[messageId]

        callback(message)


    def _on_disconnect(self):
        callbacks = []
        with self.lock:
            self.connection_status.status = ConnectionStatus.disconnected
            self.connection_cv.notify()

            # respond to all pending messages with a failure
            callbacks = [
                (cb, self._disconnect_failure_message(messageId))
                for messageId, cb in self.messageHandlers.iteritems()
                ]
            self.messageHandlers.clear()

        self._triggerEvent('disconnect')

        for callback, message in callbacks:
            callback(message)

    def _disconnect_failure_message(self, messageId):
        return {
            "messageId": messageId,
            "responseType": "Failure",
            "message": "Disconnected from server"
            }
Exemple #56
0
class Telepat(object):
    def __init__(self, remote_url, sockets_url):
        self.token = ""
        self._mServerContexts = {}
        self._subscriptions = {}
        self.socketIO = None

        self.remote_url = remote_url
        self.sockets_url = sockets_url

        # Callbacks
        self.on_add_context = None
        self.on_update_context = None

        self.db = TelepatDB()

    def _start_ws(self):
        def on_socket_welcome(*args):
            response_data = args[0]
            self.token = response_data['sessionId']
            print("Received sessionId: {0}".format(self.token))
            self.token_event.set()

        def on_socket_message(*args):
            patch_data = args[0]
            if isinstance(patch_data, bytes):
                return
            if not "data" in patch_data:
                return

            patches = patch_data["data"]

            for ndict in patches["new"]:
                notification = TelepatTransportNotification()
                notification.notification_type = NOTIFICATION_TYPE_ADDED
                notification.value = ndict["value"]
                notification.subscription = ndict["subscription"]
                notification.guid = ndict["guid"]

                context = self.context_with_identifier(ndict["subscription"])
                if context:
                    self.process_notification(notification)
                    continue

                channel = self.channel_with_subscription(ndict["subscription"])
                channel.process_notification(notification)


            for ndict in patches["updated"]:
                notification = TelepatTransportNotification()
                notification.notification_type = NOTIFICATION_TYPE_UPDATED
                notification.path = ndict["path"]
                notification.value = ndict["value"]

                context = self.context_with_identifier(ndict["subscription"])
                if context:
                    self.process_notification(notification)
                    continue
                
                channel = self.channel_with_subscription(ndict["subscription"])
                channel.process_notification(notification)

            for ndict in patches["deleted"]:
                notification = TelepatTransportNotification()
                notification.notification_type = NOTIFICATION_TYPE_DELETED
                notification.path = ndict["path"]
                notification.value = None

                context = self.context_with_identifier(ndict["subscription"])
                if context:
                    self.process_notification(notification)
                    continue
                
                channel = self.channel_with_subscription(ndict["subscription"])
                channel.process_notification(notification)

            print("Received ws message: {0}".format(args[0]))

        self.socketIO = SocketIO(self.sockets_url, 80)
        self.socketIO.on('message', on_socket_message)
        self.socketIO.on('welcome', on_socket_welcome)
        self.socketIO.wait()

    def process_notification(self, notification):
        if notification.notification_type == NOTIFICATION_TYPE_ADDED:
            context = TelepatContext(notification.value)
            self._mServerContexts[context.id] = context
            if self.on_add_context:
                self.on_add_context(context, notification)

        elif notification.notification_type == NOTIFICATION_TYPE_UPDATED:
            path_components = notification.path.split("/")
            object_id = path_components[1]
            property_name = path_components[2]
            updated_context = self._mServerContexts[object_id]
            setattr(updated_context, property_name, notification.value)
            print("Calling on_update_context: {0}".format(self.on_update_context))
            if self.on_update_context:
                self.on_update_context(updated_context, notification)

        elif notification.notification_type == NOTIFICATION_TYPE_DELETED:
            pass

    @property
    def api_key(self):
        return httpmanager.api_key

    @api_key.setter
    def api_key(self, value):
        httpmanager.api_key = hashlib.sha256(value.encode()).hexdigest()
        
    @property
    def app_id(self):
        return httpmanager.app_id
        
    @app_id.setter
    def app_id(self, value):
        httpmanager.app_id = value
        device_id_key = "device_id_{0}".format(self.app_id)
        if self.db.get_operations_data(device_id_key):
            self.device_id = self.db.get_operations_data(device_id_key)
        else:
            self.device_id = ""

    @property
    def remote_url(self):
        return httpmanager.remote_url

    @remote_url.setter
    def remote_url(self, value):
        httpmanager.remote_url = value[:-1] if value.endswith("/") else value

    @property
    def device_id(self):
        return httpmanager.device_id

    @device_id.setter
    def device_id(self, value):
        httpmanager.device_id = value

    def context_map(self):
        return self._mServerContexts

    def context_with_identifier(self, identifier):
        for ctx_id in self._mServerContexts:
            if self._mServerContexts[ctx_id].context_identifier() == identifier:
                return self._mServerContexts[ctx_id]
        return None

    def register_subscription(self, channel):
        self._subscriptions[channel.subscription_identifier()] = channel

    def unregister_subscription(self, channel):
        del self._subscriptions[channel.subscription_identifier()]

    def channel_with_subscription(self, subscription_id):
        return self._subscriptions[subscription_id]

    def subscribe(self, context, model_name, object_type):
        channel = TelepatChannel(self, model_name, context)
        channel.object_type = object_type
        subscribe_response = channel.subscribe()
        return (channel, subscribe_response)

    def remove_subscription(self, channel):
        response = channel.unsubscribe()
        return TelepatResponse(response)

    def register_device(self, update=False):
        if self.socketIO:
            self.socketIO.disconnect()
            self.socketIO = None
        self.token_event = threading.Event()
        self.ws_thread = threading.Thread(target=self._start_ws)
        self.ws_thread.start()
        self.token_event.wait(15)
        if not self.token:
            if hasattr(self, "socketIO"):
                self.socketIO.disconnect()
            raise TelepatError('Websocket connection failed')
        params = {}
        info = {"os": platform.system(),
                "version": platform.release()
        }
        if not update: info["udid"] = str(uuid.uuid4())
        params["info"] = info
        params["volatile"] = {
            "type": "sockets",
            "token": self.token,
            "active": 1
        }
        response = httpmanager.post("/device/register", params, {})
        if response.status_code == 200:
            response_json = response.json()
            if "identifier" in response_json["content"]:
                device_id = response_json["content"]["identifier"]
                self.device_id = device_id
                self.db.set_operations_data("device_id_{0}".format(self.app_id), device_id)
        return response

    def login_admin(self, username, password):
        params = {
            "email": username,
            "password": password
        }
        response = httpmanager.post("/admin/login", params, {})
        if response.status_code == 200:
            httpmanager.bearer = response.json()["content"]["token"]
        return response

    def get_apps(self):
        response = httpmanager.get("/admin/apps", {}, {})
        return TelepatResponse(response)

    def get_schema(self):
        response = httpmanager.get("/admin/schema/all", {}, {})
        return TelepatResponse(response)

    def get_users(self):
        response = httpmanager.post("/admin/user/all", {}, {})
        return TelepatResponse(response)

    def get_all(self):
        response = httpmanager.get("/admin/contexts", {}, {})
        contexts_response = TelepatResponse(response)
        for context in contexts_response.getObjectOfType(TelepatContext):
            self._mServerContexts[context.id] = context
        return contexts_response

    def update_context(self, updated_context):
        context = self.context_map()[updated_context.id]
        return TelepatResponse(httpmanager.post("/admin/context/update", context.patch_against(updated_context), {}))
        
    def disconnect(self):
        if self.socketIO:
            self.socketIO.disconnect()
        self.db.close()
class BikeSocket:
    def __init__(self, server='dali.cs.kuleuven.be:8080'):
        """Constructor for BikeSocket"""

        self.host, self.port = server.split(':')
        self.port = int(self.port)
        try:
            self._socket = SocketIO(self.host, self.port,
                                    wait_for_connection=False)
            self._socket.on('server_message', self.on_server_response)

            # Create dedicated thread for socket callbacks
            print('Launching dedicated callback listener thread')
            self._message = None
            self._listener = Thread(target=self._socket.wait)
            # Daemonize so this thread doesn't lock up the program
            self._listener.daemon = True
            self._listener.start()

            # Testing server
            self._socket.emit('echo',
                              u'{1337:"\u0ca0_\u0ca0"}',
                              self.on_server_response)

            self._waiting = False
            starttime = clock()
            while not self._waiting:
                sleep(0.01)
                if clock() - starttime > 0.02:
                    break
            self._waiting = False
            self.connection = True
        except:
            self.connection = False

    def update_connection(self):
        """ Function to check if the connection is still there, 
        tries to establish connection if there is no connection """
        print("updating connection")
        if not self.connection:
            try:
                self._socket = SocketIO(self.host, self.port,
                                        wait_for_connection=False)
                self._socket.on('server_message', self.on_server_response)

                # Create dedicated thread for socket callbacks
                print('Launching dedicated callback listener thread')
                self._message = None
                self._listener = Thread(target=self._socket.wait)
                self._listener.daemon = True
                self._listener.start()

                # Testing server
                self._socket.emit('echo',
                                  u'{1337:"\u0ca0_\u0ca0"}',
                                  self.on_server_response)

                self._waiting = False
                starttime = clock()
                while not self._waiting:
                    sleep(0.01)
                    if clock() - starttime > 0.02:
                        self._waiting = False
                        return False
                self._waiting = False
                self.connection = True
                return True
            except:
                self.connection = False
                return False
        else:
            self._socket.emit('echo', u'{1337:"\u0ca0_\u0ca0"}',
                              self.on_server_response)
            self._waiting = False
            starttime = clock()
            while not self._waiting:
                sleep(0.01)
                if clock() - starttime > 0.02:
                    self._waiting = False
                    return False
            if self._waiting:
                self._waiting = False
                return True

    # Callback
    def on_server_response(self, *args):
        self._message = args
        self._waiting = True

    def start_batch(self, groupID='CW1A1', userID='r0451728'):
        """Tells the server to prepare for batch data
        Returns True if request was succesful, False otherwise"""
        self._waiting = False
        self._socket.emit('start',
                          dumps({'purpose': 'batch-sender',
                                 'groupID': groupID,
                                 'userID': userID}),
                          self.on_server_response)
        # self._waiting = False
        starttime = clock()
        while not self._waiting:
            sleep(0.01)
            if clock() - starttime > 0.02:
                self._waiting = False
                print(self._message)
                return False
        self._waiting = False
        print(self._message)
        succesfull = self._message[0].values()[0] == 200
        return succesfull

    def send_batch(self, tripData):
        """Sends batch data for trip.
        Precede with start_batch().
        Returns trip ID if succesfull"""
        self._waiting = False
        self._socket.emit('batch-tripdata',
                          dumps(tripData),
                          self.on_server_response)
        # self._waiting = False
        starttime = clock()
        while not self._waiting:
            sleep(0.01)
            if clock() - starttime > 1.00:
                self._waiting = False
                return False
        self._waiting = False
        print("server answer", self._message)
        return self._message[0]["_id"]

    def start_trip(self, groupID='CW1A1', userID='r0451728'):
        """Starts new realtime trip.
        Returns ID for trip if succesful"""
        self._waiting = False
        self._socket.emit('start',
                          dumps({'purpose': 'realtime-sender',
                                 'groupID': groupID,
                                 'userID': userID}),
                          self.on_server_response)
        # self._waiting = False
        starttime = clock()
        while not self._waiting:
            sleep(0.01)
            if clock() - starttime > 0.02:
                self._waiting = False
                return False
        self._waiting = False
        print(self._message[0]["message"])
        return self._message[0]["_id"]

    def send_data(self, _id, sensorData):
        """Sends data belonging to a certain trip"""
        self._waiting = False
        self._socket.emit('rt-sensordata',
                          dumps({'_id': _id,
                                 'sensorData': sensorData}),
                          self.on_server_response)
        # self._waiting = False
        starttime = clock()
        while not self._waiting:
            sleep(0.01)
            if clock() - starttime > 0.02:
                self._waiting = False
                return False
        self._waiting = False
        print(self._message)

    def end_trip(self, _id, metadata):
        """Ends the trip designated by _id"""
        self._waiting = False
        self._socket.emit('endBikeTrip',
                          dumps({'_id': _id,
                                 'meta': metadata}),
                          self.on_server_response)
        # self._waiting = False
        starttime = clock()
        while not self._waiting:
            sleep(0.01)
            if clock() - starttime > 0.02:
                self._waiting = False
                return False
        self._waiting = False
        print(self._message)

    def __del__(self):
        """Destructor: kills the callback listener"""
        self._listener._Thread__stop()
        self._socket.disconnect()
        sleep(1)
Exemple #58
0
#!/usr/bin/python
from socketIO_client import SocketIO, BaseNamespace
import traceback
# import logging
# logging.getLogger('socketIO-client').setLevel(logging.DEBUG)
# logging.basicConfig()

try:
    sio = SocketIO('localhost:5000')

    def on_msg(msg):
        pass

    sio.on('ris_rrc_list', on_msg)
    sio.wait()
except KeyboardInterrupt:
    sio.disconnect()
except Exception:
    traceback.print_exc()
Exemple #59
0
class AIBase(object):
    """Common features of all Cinch AI Agents.

    This provides an interface with the socketio server, handles known socket
    event messages, and includes common functions like checking play legality.

    When the agent receives indication that it is the active player, the play
    or bid methods are called, which must return the AI's desired play/bid.

    Attributes:
      room (int): The room number that the agent is in.
      pNum (int): The player number / seat number occupied by the agent.
      hand (list): The agent's hand of Card objects.
      gs (GS): The gamestate object used by the agent.
      name (str): The agent's name as identified in the model module.
      label (str): The label used to identify the agent in logs.
      socket (SocketIO): The socketio connection used to communicate with the
        main server.
      ns (BaseNamespace): The namespace used by the socket.

    """
    # ===============
    # Agent Management & Communications
    # ===============
    def __init__(self, targetRoom, targetSeat, ident):
        """Initialize AI.

        The AI agent connects to the server, joins a game, and prepares to
        receive game data.

        Args:
          targetRoom (int): Target game room number.
          targetSeat (int): Target seat within game room.
          ident (dict): AI identifying info, including data like version number
            and AI description. This is provided from the AI model module via
            the manager.

        """
        self.room = None
        self.pNum = None
        self.hand = []
        self.gs = GS()
        self.name = ident['name']
        self.label = self.name + "_" + str(targetSeat)

        self.setupSocket()
        self.ns.emit('nickname', self.label)
        self.join(targetRoom, targetSeat)
        self.pNum = targetSeat

    def __del__(self):
        """Cleanly shutdown AI agent."""
        self.stop()

    def ackJoin(self, *args):
        """Callback for request to join room.

        Args:
          *args (list): Confirmation data after joining room. If successful,
            this will be a 1-element list with a dict containing `roomNum`,
            `seatChart`, and `mySeat` keys. Otherwise, it will be an empty list
            because the request resulted in an error.

        """
        if len(args) == 0:
            # The agent will receive an 'err' event in this case.
            # TODO: look into intelligently handling this kind of error and
            # ensure it is not possible to sit in a bad seat.
            self.stop()
            return

        data = args[0]
        self.room = data['roomNum']

        if self.room != 0:  # Joining the lobby doesn't warrant any action
            self.pNum = data['mySeat']
            log.info("{2}_AI joined Game {0} Seat {1}".format(
                self.room, self.pNum, self.name))

    def on_err(self, msg):
        """Handle error event from server and log all data.

        Since some errors may be non-fatal, an error does not kill the agent.

        Args:
          msg (str): Error message.

        """
        log.error("err: {0}".format(msg))
        log.error("dump: {0} {1}".format(self.label, str(self.hand)))
        log.error("gs: {0}".format(self.gs))

    def handle_game_action(self, *args):
        """Combination handler for bid and play.

        This calls the agent's `bid` or `play` method as appropriate. If it is
        not the agent's turn, the `think` method is called instead. If the game
        is over, no actions are taken.

        This is also called when receiving `startData`.

        Args:
          *args (list): Data transmitted by server with bid or play event.

        """
        try:
            msg = args[0]
        except Exception as e:
            log.error("{0}: {1}".format(e.message, args))
            return

        self.applyUpdate(msg)

        if 'win' in msg:  # Game is over
            return

        if self.gs.activePlayer == self.pNum:
            if self.gs.mode == BID:
                self.bid()
            else:
                self.play()
        else:
            self.think()

    def setupSocket(self):
        """Create socket connection and configure namespace."""
        self.socket = SocketIO('127.0.0.1', SOCKETIO_PORT)
        self.ns = self.socket.define(BaseNamespace, SOCKETIO_NS)

        self.ns.on('err',       self.on_err)
        self.ns.on('bid',       self.handle_game_action)
        self.ns.on('play',      self.handle_game_action)
        self.ns.on('startData', self.handle_game_action)

    def applyUpdate(self, msg):
        """Update internal game information based on server message.

        Args:
          msg (dict): Message from server containing game state information
            and changes.

        """
        self.gs.activePlayer = msg['actvP']

        if 'win' in msg:
            self.stop()

        if 'playC' in msg:
            self.gs.cardsInPlay.append(cards.Card(msg['playC']))

        if 'sco' in msg:
            self.gs.score = msg['sco']

        if 'gp' in msg:
            self.gs.gp = msg['gp']

        if 'mp' in msg:
            self.gs.mp = msg['mp']

        if 'remP' in msg:
            self.gs.takenCards[msg['remP']].append(self.gs.cardsInPlay)
            self.gs.cardsInPlay = list()

        if 'dlr' in msg:
            self.gs.dealer = msg['dlr']

        if 'addC' in msg:
            self.hand = [cards.Card(num) for num in msg['addC']]
            self.gs.reset()

        if 'trp' in msg:
            self.gs.trump = msg['trp']

        if 'mode' in msg:
            self.gs.mode = msg['mode']

        if 'actor' in msg:
            self.gs.actor = msg['actor']

        if 'bid' in msg:
            self.gs.bidLog[msg['actor']] = msg['bid']
            if msg['bid'] > self.gs.highBid:
                self.gs.highBid = msg['bid']

    def join(self, room, seat):
        """Make request to join room.

        Args:
          room (int): Target room number
          seat (int): Target seat number

        """
        self.ns.emit('join', room, seat, self.ackJoin)

    def start(self):
        """Activate AI."""
        self.socket.wait()  # Blocks until self.stop()

    def stop(self):
        """Gracefully shutdown AI agent."""
        self.socket.disconnect()

        # TODO do any final cleanup (logging, etc)

    # ===============
    # Game Actions & Rules
    # ===============

    def send_bid(self, bid):
        """Send bid to server. Handle error response.

        TODO add callback to handle if an illegal bid was made; AIBase should
        provide failsafe methods.

        Args:
          bid (int): Bid amount (0-5, where PASS = 0)

        """
        if self.is_legal_bid(bid):
            pass
        elif bid == 0:  # Illegally tried to pass (stuck dealer)
            bid = 1
            log.error("Agent illegally tried to pass; adjusting bid to 1.")
        else:
            log.error("Agent made illegal bid of {0}; adjusting bid to PASS."
                      "".format(bid))
            bid = 0

        self.ns.emit('bid', bid)  # Transmit bid to server

        if bid > 0:
            log.info("{0} bids {1}".format(self.label, bid))
        else:
            log.info("{0} passes".format(self.label))

    def send_chat(self, chat_msg):
        """Send chat-style message to server (for debugging & hijinks).

        Args:
          chat_msg (str): Message to send via chat channels.

        """
        self.ns.emit('chat', chat_msg)

    def send_play(self, card):
        """Send proposed play to server and remove card from hand.

        If the AI sends an illegal play, there is no recovery.

        TODO: add callback to handle illegal play; AIBase should provide
        failsafe methods.

        Args:
          card (Card): Card object to play. It is assumed to have been checked
            for play legality by the caller.

        """
        card_val = card.code
        self.ns.emit('play', card_val)

        log.info("{0} plays {1}".format(self.label, str(card)))
        self.hand.remove(card)

    def is_legal_bid(self, bid):
        """Check if proposed bid is legal. Return boolean.

        Args:
          bid (int): Bid value (0=PASS, 5=CINCH).

        """
        if bid == 0:
            if self.pNum == self.gs.dealer and self.gs.highBid < 1:
                return False  # Stuck dealer, must not pass
            else:
                return True  # Always legal to pass otherwise
        elif bid < 0 or bid > 5:
            return False  # Bid out of bounds
        elif bid > self.gs.highBid:
            return True
        elif bid == 5 and self.pNum == self.gs.dealer:
            return True
        else:
            return False

    def is_legal_play(self, card):
        """Check if proposed play is legal. Return boolean.

        card (Card): Proposed play.

        """
        if len(self.gs.cardsInPlay) == 0:
            return True  # No restriction on what can be led

        if card.suit == self.gs.trump:
            return True  # Trump is always OK
        else:
            led = self.gs.cardsInPlay[0].suit
            if card.suit == led:
                return True  # Followed suit
            else:
                for c in self.hand:
                    if led == c.suit:
                        return False  # Could've followed suit but didn't

                return True  # Throwing off

    # ===============
    # Intelligence
    # ===============

    def bid(self):
        """Bidding logic. This is to be implemented within each agent.

        This gets called only when game mode == BID and self is active player.

        """
        raise NotImplementedError("bid() needs to be implemented in subclass.")

    def play(self):
        """Play logic. This is to be implemented within each agent.

        This gets called only when game mode == PLAY and self is active player.

        """
        raise NotImplementedError(
            "play() needs to be implemented in subclass.")

    def think(self):
        """Thinking logic, optionally implemented within each agent.

        This gets called after bids/plays but when this agent is not the active
        player (e.g. for pruning move trees after a card is played).

        """
        pass