Пример #1
0
    def offline_jianmo(self,
                       shujulujing,
                       moxinglujingqianzhui,
                       timestamp=0,
                       send=send):
        """Start building model for offline data

        Arguments:
            shujulujing {str} -- The offline data
            moxinglujingqianzhui {str} -- The prefix of model path, '.mat' will be added for real mpdel path

        Keyword Arguments:
            timestamp {int} -- [description] (default: {0})
            send {func} -- Sending method (default: {send})

        Returns:
            {int} -- 0 means success, 1 means fail
        """
        send(real_time_reply.OK())

        # The state should be 'Idle'
        if self.check_state('Idle', 'offline_jianmo', send=send) == 1:
            return 1

        # Check {shujulujing}
        if not os.path.exists(shujulujing):
            onerror(runtime_error.FileError, shujulujing, send=send)
            return 1

        # Try to mkdir and check of [moxinglujingqianzhui]
        try:
            mkdir(os.path.dirname(moxinglujingqianzhui))
        except:
            onerror(runtime_error.FileError, moxinglujingqianzhui, send=send)
            return 1

        # Workload
        moxinglujing = f'{moxinglujingqianzhui}.mat'

        # todo: Building a model
        self.latest_jianmo_send = send
        self.latest_shujulujing = shujulujing
        self.latest_moxinglujing = moxinglujing
        try:
            self.send_backend(
                dict(cmd='jianmo',
                     moxinglujing=moxinglujing,
                     shujulujing=shujulujing))
        except:
            logger.info('Fail on sending jianmo request to backend.')

        # If not USE_BACKEND,****************************************
        # use response_jianmo
        if not USE_BACKEND:
            self.response_jianmo(zhunquelv="1.0", timestamp=0, send=send)

        logger.debug('Building model.')
        logger.info('Building model.')

        return 0
Пример #2
0
    def response_jianmo(self, zhunquelv, timestamp=0, send=send):
        moxinglujing = self.latest_moxinglujing
        shujulujing = self.latest_shujulujing

        self.latest_jianmo_send(
            dict(mode='Offline',
                 cmd='zhunquelv',
                 moxinglujing=moxinglujing,
                 zhunquelv=zhunquelv,
                 timestamp=time.time()))

        if not USE_BACKEND:
            print('-' * 80)
            print(moxinglujing)
            with open(moxinglujing, 'w') as f:
                f.writelines(['Fake model.'])

        logger.debug(
            f'Built model based on {shujulujing}, model has been saved in {moxinglujing}.'
        )
        logger.info(
            f'Built model based on {shujulujing}, model has been saved in {moxinglujing}.'
        )

        pass
Пример #3
0
    def offline_jieshucaiji(self, timestamp=0, send=send):
        """Stop offline collection

        Keyword Arguments:
            timestamp {int} -- [description] (default: {0})
            send {func} -- Sending method (default: {send})

        Returns:
            {int} -- 0 means success, 1 means fail
        """
        send(real_time_reply.OK())

        # The state should be 'Offline'
        if self.check_state('Offline', 'offline_jieshucaiji', send=send) == 1:
            return 1

        # workload
        self.state = 'Idle'

        # Stop backend
        try:
            self.send_backend(dict(cmd='jieshucaiji'))
        except:
            logger.info('Fail to stop offline recording in backend.')
            traceback.print_exc()

        if not USE_BACKEND:
            with open(self._shujulujing, 'w') as f:
                f.writelines(['Fake data.'])

        logger.debug('Stopped offline collection.')
        return 0
Пример #4
0
 def starts(self):
     """ Start serving """
     self.server.listen(1)
     t = threading.Thread(target=self.maintain_clients, name='TCP server')
     t.setDaemon(True)
     t.start()
     logger.info(f'TCP Server started.')
Пример #5
0
    def query(self, chixushijian, zhenshibiaoqian, timestamp=0, send=send):
        """Answer for query package during ONLINE collection

        Arguments:
            chixushijian {float} -- Duration of the latest motion
            zhenshibiaoqian {str} -- True label of motion (image or actural motion)

        Keyword Arguments:
            timestamp {int} -- [description] (default: {0})
            send {func} -- Sending method (default: {send})

        Returns:
            {int} -- 0 for success, 1 for fail
        """
        send(real_time_reply.OK())

        # The state should be 'Online'
        if self.check_state('Online', 'query', send=send) == 1:
            return 1

        # Workload
        # Save the [send] as [latest_query_send],
        # the query result will be send through it
        self.latest_query_send = send
        self.latest_zhenshibiaoqian = zhenshibiaoqian
        try:
            self.send_backend(dict(cmd='query'))
        except:
            logger.info(f'Fail to send query request to backend.')

        # If not USE_BACKEND,****************************************
        # simulation response_query
        if not USE_BACKEND:
            # Use fix latency for message recognizeable
            time.sleep(0.1)
            self.response_query(zhenshibiaoqian, timestamp=0, send=send)

        # # Guess label, always return '2' for now
        # # todo: Estimate label from real data
        # logger.debug('Estimating label.')
        # gujibiaoqian = '2'
        # # Send back Query result
        # send(dict(mode='QueryReply',
        #           gujibiaoqian=gujibiaoqian,
        #           timestamp=time.time()))

        # # Send UI a motion order,
        # # if estimated and real label are both '2'
        # if all([gujibiaoqian == '2',
        #         zhenshibiaoqian == '2']):
        #     self.send_UI(dict(mode='Online',
        #                       cmd='kaishiyundong',
        #                       timestamp=time.time()))

        # logger.debug('Responded to query package')
        return 0
Пример #6
0
 def maintain_clients(self):
     """ Maintain clients pool. """
     while True:
         # Wait for new client
         c, a = self.new_client()
         # New client instance
         client = Client(client=c, address=a)
         # Add new client into client pool
         self.clientpool.append(client)
         logger.info(f'New client accepted {a}')
Пример #7
0
    def state(self, s):
        """Safe switch STATE into [s]

        Arguments:
            s {str} -- The name of new state, one from ['Idle', 'Busy', 'Online', 'Offline']
        """
        assert (s in ['Idle', 'Busy', 'Online', 'Offline'])
        if not s == self._state:
            self._state = s
            logger.info(f'State switched to {s}.')
            logger.debug(f'State switched to {s}.')
Пример #8
0
    def online_jieshucaiji(self, timestamp=0, send=send):
        """Stop online collection

        Keyword Arguments:
            timestamp {int} -- [description] (default: {0})
            send {func} -- Sending method. (default: {send})

        Returns:
            {int} -- 0 for success, 1 for fail
        """
        send(real_time_reply.OK())

        # The state should be 'Online'
        if self.check_state('Online', 'online_jieshucaiji', send=send) == 1:
            return 1

        # Workload

        # Stop backend
        try:
            self.send_backend(dict(cmd='jieshucaiji'))
        except:
            logger.info('Fail to stop offline recording in backend.')
            traceback.print_exc()

        if not USE_BACKEND:
            with open(self._shujulujing, 'w') as f:
                f.writelines(['Fake online data.'])

        # Calculate accuracy
        try:
            zhunquelv = self.accuracy()
            logger.debug(f'Accuracy is {zhunquelv}, labels are {self.labels}.')
        except:
            logger.debug(
                f'Accuracy can not be calculated, labels are {self.labels}')
            raise ValueError(
                f'Accuracy can not be calculated, labels are {self.labels}')

        # Send accuracy back to UI as remembered
        send(
            dict(
                mode='Online',
                cmd='zhunquelv',
                zhunquelv=str(zhunquelv),  # Covert accuracy into {str}
                moxinglujing=self.moxinglujing,
                shujulujing=self.shujulujing,
                timestamp=time.time()))
        self.state = 'Idle'

        logger.debug('Stopped online collection.')
        return 0
Пример #9
0
    def offline_kaishicaiji(self, shujulujingqianzhui, timestamp=0, send=send):
        """Start offline collection

        Arguments:
            shujulujingqianzhui {str} -- The prefix of data path, '.cnt' will be added for real data path

        Keyword Arguments:
            timestamp {int} -- [description] (default: {0})
            send {func} -- Sending method (default: {send})

        Returns:
            {int} -- 0 for success, 1 for fail
        """
        # Send OK means I has got everything in need,
        # but not guartee that all the things are correct,
        # if incorrect, I will reply Error in further
        send(real_time_reply.OK())

        # The state should be 'Idle'
        self.force_Idle()
        if self.check_state('Idle', 'offline_kaishicaiji', send=send) == 1:
            return 1

        # Try to mkdir and check of [shujulujingqianzhui] dir
        try:
            mkdir(os.path.dirname(shujulujingqianzhui))
        except:
            onerror(runtime_error.FileError, shujulujingqianzhui, send=send)
            return 1

        # Workload
        self.get_ready(state='Offline')
        path = f'{shujulujingqianzhui}.mat'

        if not USE_BACKEND:
            self._shujulujing = path

        try:
            self.send_backend(
                dict(cmd='kaishicaiji', mat_path=path, model_path='[empty]'))
        except:
            logger.info('Fail to start offline recording in backend.')
            traceback.print_exc()

        # Start self.record function as separate daemon threading
        # t = threading.Thread(target=self.record, args=(path,))
        # t.setDaemon(True)
        # t.start()

        logger.debug('Started offline collection.')
        return 0
Пример #10
0
    def __init__(self, ip=IP, port=PORT):
        """Default init

        Keyword Arguments:
            ip {str} -- Legal IP address, like 'localhost' or '127.0.0.1' (default: {IP})
            port {int} -- Legal port, like 65535 (default: {PORT})
        """
        # Init server
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.bind((ip, port))
        logger.info(f'TCP Server is parepared listening on {ip}:{port}')
        # self.server.listen(1)
        # Init clients pool
        self._clientpool = []
Пример #11
0
    def send(self, msg, encoding='utf-8'):
        """Send [msg] to connected TCP Client

        Arguments:
            msg {str} -- [description]
        """
        # Dumps dict
        if isinstance(msg, dict):
            msg = json.dumps(msg, ensure_ascii=False).encode(encoding)

        # Encode str
        if isinstance(msg, str):
            msg = msg.encode(encoding)

        # Send
        self.client.sendall(msg)
        logger.info(f'Sent {msg} to {self.address}')
        logger.debug(f'Sent {msg} to {self.address}')
Пример #12
0
    def force_Idle(self):
        """Force State to Idle, used for kaishicaiji by-force.
        """
        if self.state == 'Idle':
            return 0

        msg = f'Current state is {self.state}, setting it to Idle by-force.'
        logger.info(msg)
        logger.debug(msg)

        # Stop backend
        logger.debug('Send jieshucaiji to backend.')
        try:
            self.send_backend(dict(cmd='jieshucaiji'))
        except:
            logger.info('Fail to stop offline recording in backend.')
            traceback.print_exc()

        # workload
        self.state = 'Idle'
Пример #13
0
    def response_query(self, gujibiaoqian, timestamp=0, send=send):
        self.latest_query_send(
            dict(mode='QueryReply',
                 gujibiaoqian=gujibiaoqian,
                 timestamp=time.time()))

        zhenshibiaoqian = self.latest_zhenshibiaoqian
        if all([gujibiaoqian == '1', zhenshibiaoqian == '1']):
            self.send_UI(
                dict(mode='Online', cmd='kaishiyundong',
                     timestamp=time.time()))

        self.labels.append((gujibiaoqian, zhenshibiaoqian))
        logger.info(
            f'Estimated label: {gujibiaoqian}, True label: {zhenshibiaoqian}')
        logger.debug(
            f'Estimated label: {gujibiaoqian}, True label: {zhenshibiaoqian}')
        logger.debug(f'Labels is {self.labels}')

        pass
Пример #14
0
    def get_ready(self,
                  state='Idle',
                  moxinglujing=None,
                  shujulujing=None,
                  send_UI=send):
        """Get ready for comming operation,
        switch STATE into 'Idle',
        empty LABELS,
        when STATE is switch into 'Online', make sure it has a valid send_UI.

        Keyword Arguments:
            state {str} -- Witch STATE will be set. (default: {'Idle'})
            moxinglujing {str} -- The path of model. (default: {None})
            shujulujing {str} -- The path of data. (default: {None})
            send_UI {func} -- Method of send_ui, means send to UI TCP client, to tell UI something when income TCP client may not be UI. (default: {send})
        """

        self.state = state
        self._labels = []
        self.moxinglujing = moxinglujing
        self.shujulujing = shujulujing
        self.send_UI = send_UI
        logger.info(f'Worker is ready to go, {state}.')
Пример #15
0
    def __init__(self, client, address, onclose=None):
        """Start [client] for listening at [address],
        [onclose] is a function that will be called when client is closed.

        Arguments:
            client {Client instance} -- The connected TCP Client
            address {str} -- Address str

        Keyword Arguments:
            onclose {func} -- Method will be called when client is closed (default: {None})
        """
        # Setup client and onclose handler
        self.client = client
        self.address = address
        if onclose is None:
            self.onclose = self.default_onclose
        else:
            self.onclose = onclose
        # Start listening
        t = threading.Thread(target=self.listening)
        t.setDaemon(True)
        t.start()
        logger.info(f'New client started {address}')
Пример #16
0
 def __init__(self, ip=IP, port=PORT):
     self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     self.server.bind((ip, port))
     logger.info(f'TCP Server is ready to listen on {ip}:{port}')
Пример #17
0
    def start(self):
        """TCP server starts,
        now it serves forever,
        if it is disconnected, it will start a new listening immediately.
        """

        while True:
            try:
                self.server.listen(1)
                logger.info(f'TCP Server starts listening.')

                # Accept in comming connection
                client, address = self.server.accept()
                logger.info(
                    f'New connection is established: {address}:{client}')

                # Say hi...........
                # client.sendall(b'hello')

                # Intending I am a EEG device,
                # and I am serving.
                interval = 0.1
                passed_time = 0
                states = ['rest', 'imag', 'rest', 'imag']
                idx = 0
                t = time.time()
                print(states[idx])

                # Whether the data slice contains a trigger on head
                self.new_switch = True

                while True:
                    # Make up bits according to [state] and [interval]
                    bits = make_up_package(
                        self.make_signal(state=states[idx], interval=interval))

                    # Send bits
                    client.sendall(bits)

                    time.sleep(interval - (time.time() - t) % interval)
                    # Update passed_time
                    passed_time += interval

                    # The state will be updated every 5 seconds
                    if passed_time > 5:
                        # Every time we update idx,
                        # new_switch should be set
                        self.new_switch = True

                        # Update idx
                        idx += 1
                        idx %= len(states)
                        print(states[idx])

                        # Reset passed_time
                        passed_time = 0
            except ConnectionAbortedError:
                continue
            except KeyboardInterrupt:
                break

        client.close()
Пример #18
0
import numpy as np
import time
import os
import sys
import struct
import socket

print(__file__)  # noqa
sys.path.append(os.path.dirname(__file__))  # noqa

from local_profile import IP, PORT, BUF_SIZE, NUM_CHANNEL, SFREQ, logger

logger.info('---- New Session ----')


def make_up_package(floats):
    """Make up Dry EEG device package

    Arguments:
        floats {list} -- List of float values, the values will be sent as simulation of an EEG device

    Returns:
        bits {bytes} -- Well formulated bytes to simulate an EEG device
    """

    # Fixed stuffs
    # 0-1-2-3-4
    _token = b'@ABCD'

    # 5
    _type = chr(1).encode()
Пример #19
0
    def online_kaishicaiji(self,
                           moxinglujing,
                           shujulujingqianzhui,
                           timestamp=0,
                           send=send):
        """Start Online collection

        Arguments:
            moxinglujing {str} -- The path of model, it should be an existing path
            shujulujingqianzhui {str} -- The prefix of data path, '.cnt' will be added in real data path

        Keyword Arguments:
            timestamp {int} -- [description] (default: {0})
            send {func} -- Sending method (default: {send})

        Returns:
            {int} -- 0 for success, 1 for fail
        """
        send(real_time_reply.OK())

        # Check moxinglujing
        if not os.path.exists(os.path.dirname(moxinglujing)):
            onerror(runtime_error.FileError, moxinglujing, send=send)
            return 1

        # Try to mkdir and check of {shujulujingqianzhui}
        try:
            mkdir(os.path.dirname(shujulujingqianzhui))
        except:
            onerror(runtime_error.FileError, shujulujingqianzhui, send=send)
            return 1

        # The state should be 'Idle'
        self.force_Idle()
        if self.check_state('Idle', 'online_kaishicaiji', send=send) == 1:
            return 1

        # Workload
        path = f'{shujulujingqianzhui}.mat'

        if not USE_BACKEND:
            self._shujulujing = path

        # Remember Send-to-UI method,
        # as Start online collection can only be triggered by UI.
        self.get_ready(state='Online',
                       moxinglujing=moxinglujing,
                       shujulujing=path,
                       send_UI=send)

        try:
            self.send_backend(
                dict(cmd='kaishicaiji', mat_path=path,
                     model_path=moxinglujing))
        except:
            logger.info('Fail to start online recording in backend.')
            traceback.print_exc()

        # Start daemon thread for data collection and start it
        # t = threading.Thread(target=self.record, args=(path, moxinglujing))
        # t.setDaemon(True)
        # t.start()

        logger.debug('Started online collection.')
        return 0
Пример #20
0
    def listening(self):
        """ Listen and handling incoming message """
        while True:
            try:
                # Get data
                data = self.client.recv(BUF_SIZE)
                logger.info(f'Received {data}, from {self.address}')
                logger.debug(
                    '{dash} New data received {dash}'.format(dash='-' * 8))
                logger.debug(f'Received {data}, from {self.address}')

                # If empty package received, it means the client to be closed.
                assert (not data == b'')

                # Parse data using JSON format,
                # Decode data
                try:
                    decoded_data = data.decode('utf-8')
                except:
                    logger.info(f'{data} can not be decoded.')
                    logger.debug(f'{data} can not be decoded.')
                    continue

                # send ParseError if parsing is failed
                try:
                    D = json.loads(decoded_data)
                except:
                    logger.debug(
                        f'{decoded_data} can not be loaded by JSON, try linked expection.'
                    )
                    try:
                        split = decoded_data.split('}{')

                        D = list()
                        for s in split:
                            if not s.startswith('{'):
                                s = '{' + s
                            if not s.endswith('}'):
                                s = s + '}'
                            D.append(json.loads(s))
                        logger.debug(f'Link exception success: {D}.')
                    except:
                        logger.error(
                            f'{decoded_data} can not be loaded by JSON')
                        logger.error('{}'.format(traceback.format_exc()))
                        self.send(
                            real_time_reply.ParseError(detail=decoded_data))
                        continue
                # print(D)

                # Deal with D
                if isinstance(D, list):
                    for d in D:
                        self.deal(d)
                else:
                    self.deal(D)

            except Exception:
                traceback.print_exc()
                logger.debug(traceback.format_exc())
                # Close the client
                self.client.close()
                # Stop listening
                break

        # Run onclose function
        self.onclose()
        logger.info(f'Connection closed {self.client}.')
Пример #21
0
 def accept_backend(self, timestamp=0, send=send):
     self.send_backend = send
     logger.info('Backend connection established.')
     pass
Пример #22
0
import socket
import threading
import traceback

print(__file__)  # noqa
sys.path.append(os.path.dirname(__file__))  # noqa

from worker import Worker
from local_profile import IP, PORT, BUF_SIZE
from local_profile import logger, RealtimeReply, RuntimeError
from local_profile import USE_BACKEND, IP_EEG_DEVICE, PORT_EEG_DEVICE
from backend_toolbox import new_backend
import local_profile
CurrentDirectory = os.path.dirname(local_profile.__file__)

logger.info('---- New Session ----')
logger.info('---- Version 2020-05-29 ----')

# Worker instance
worker = Worker()
# Real-time reply instance
real_time_reply = RealtimeReply()
# runtime error instance
runtime_error = RuntimeError()


def reg_timestamp(timestamp, tmp=time.time()):
    """Regularize time stamp and rescale it into time.time()

    Arguments:
        timestamp {object} -- Input time stamp.