예제 #1
0
class BasicClass(object):
    def __init__(self):
        self.sd = ServiceDiscovery()

        rcomp = halremote.RemoteComponent('anddemo', debug=False)
        rcomp.no_create = True
        rcomp.newpin('button0', halremote.HAL_BIT, halremote.HAL_OUT)
        rcomp.newpin('button1', halremote.HAL_BIT, halremote.HAL_OUT)
        led_pin = rcomp.newpin('led', halremote.HAL_BIT, halremote.HAL_IN)
        led_pin.on_value_changed.append(self.led_pin_changed)
        led_pin.on_synced_changed.append(self.led_pin_synced)
        rcomp.on_connected_changed.append(self._connected)

        self.halrcomp = rcomp
        self.sd.register(rcomp)

    def led_pin_synced(self, synced):
        if synced:
            print("LED pin synced")

    def led_pin_changed(self, value):
        print('LED pin value changed: %s' % str(value))

    def _connected(self, connected):
        print('Remote component connected: %s' % str(connected))

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()
예제 #2
0
    def run(self):
        timeout = 2.0

        sd = ServiceDiscovery()
        halrcomp = halremote.RemoteComponent('anddemo')
        halrcomp.newpin('button0', halremote.HAL_BIT, halremote.HAL_OUT)
        halrcomp.newpin('button1', halremote.HAL_BIT, halremote.HAL_OUT)
        halrcomp.newpin('led', halremote.HAL_BIT, halremote.HAL_IN)
        sd.register(halrcomp)

        sd.start()
        print('waiting for component connected')
        assert halrcomp.wait_connected(timeout)
        print('component connected')
        print('stopping service discovery')
        sd.stop()
        print('completed')
예제 #3
0
class Logger(object):
    def __init__(self, debug=False):
        self._sd = ServiceDiscovery()

        log = application.ApplicationLog(debug=debug)
        log.log_level = application.log.RTAPI_MSG_DBG
        log.on_message_received.append(self._on_log_message_received)

        self._sd.register(log)

    @staticmethod
    def _on_log_message_received(msg):
        print(msg)

    def start(self):
        self._sd.start()

    def stop(self):
        self._sd.stop()
예제 #4
0
class MachinekitInterface(object):
    def __init__(self):
        self.sd = ServiceDiscovery(nameservers=['192.168.7.2'])

        rcomp = halremote.RemoteComponent('command-interface', debug=False)
        rcomp.no_create = False
        for i in range(MAX_AXES):
            rcomp.newpin('joint%i.position-cmd' % i, halremote.HAL_FLOAT,
                         halremote.HAL_OUT)
            rcomp.newpin('joint%i.position-fb' % i, halremote.HAL_FLOAT,
                         halremote.HAL_IN)
            rcomp.newpin('joint%i.enable' % i, halremote.HAL_BIT,
                         halremote.HAL_IO)
            rcomp.newpin('joint%i.position-max' % i, halremote.HAL_FLOAT,
                         halremote.HAL_IO)
            rcomp.newpin('joint%i.position-min' % i, halremote.HAL_FLOAT,
                         halremote.HAL_IO)
        rcomp.on_connected_changed.append(self._connected)

        self.halrcomp = rcomp
        self.sd.register(rcomp)

    def _connected(self, connected):
        print('Remote component connected: %s' % str(connected))

    def update_joint_values(self, data):
        if not self.halrcomp.connected:
            return
        pin = self.halrcomp.getpin('joint0.position-cmd')
        pin.set(data.get('Joint1', 0))

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()
예제 #5
0
class NeoPixelHal(object):
    """
    NeoPixel HAL Remote component.
    
    For docs on how to use the neopixel lib visit: https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel
    """

    WHITE = (255, 255, 255)
    RED = (255, 0, 0)
    BLUE = (0, 0, 255)
    OFF = (0, 0, 0)

    def __init__(self, com_pin=board.D18, num_pixels=16, debug=False):
        self.pixels = neopixel.NeoPixel(com_pin, num_pixels)
        self._connected = False
        self._enabled = False
        self._update_light()

        rcomp = halremote.RemoteComponent('neopixel', debug=debug)
        rcomp.no_create = True
        enable_pin = rcomp.newpin('enable', halremote.HAL_BIT,
                                  halremote.HAL_IN)
        enable_pin.on_value_changed.append(self._enable_pin_changed)
        mode_pin = rcomp.newpin('mode', halremote.HAL_U32, halremote.HAL_IN)
        mode_pin.on_value_changed.append(self._mode_pin_changed)
        rcomp.on_connected_changed.append(self._connected_changed)

        self.rcomp = rcomp
        self.sd = ServiceDiscovery(filter_=ServiceDiscoveryFilter(
            txt_records={b'uuid': MK_UUID}))
        self.sd.register(rcomp)

    def _standby_light(self):
        self.pixels.fill(self.OFF)
        color = tuple(
            map(lambda x: int(x * 0.01),
                (self.BLUE if self._connected else self.RED)))
        self.pixels[0] = color
        self.pixels[1] = color

    def _update_light(self):
        if self._enabled and self._connected:
            self.pixels.fill(self.RED)
        else:
            self._standby_light()

    def _enable_pin_changed(self, value):
        logger.debug(f'Enable pin changed: {value}')
        self._enabled = value
        self._update_light()

    def _mode_pin_changed(self, value):
        pass

    def _connected_changed(self, connected):
        logger.debug(f'Remote component connected: {connected}')
        self._connected = connected
        self._update_light()

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()

    def update(self):
        pass
예제 #6
0
class TerminalUI(object):
    def __init__(self, uuid, use_curses, debug=False):
        sd_filter = ServiceDiscoveryFilter(txt_records={'uuid': uuid})
        self.sd = ServiceDiscovery(filter_=sd_filter)

        halrcomp = halremote.component('test')
        halrcomp.debug = debug
        halrcomp.newpin("coolant-iocontrol", halremote.HAL_BIT, halremote.HAL_IN)
        halrcomp.newpin("coolant", halremote.HAL_BIT, halremote.HAL_OUT)
        self.halrcomp = halrcomp
        self.sd.register(halrcomp)

        halrcomp2 = halremote.RemoteComponent(name='test2', debug=debug)
        halrcomp2.newpin("coolant-iocontrol", halremote.HAL_BIT, halremote.HAL_IN)
        halrcomp2.newpin("coolant", halremote.HAL_BIT, halremote.HAL_OUT)
        self.halrcomp2 = halrcomp2
        self.sd.register(halrcomp2)

        self.status = ApplicationStatus(debug=debug)
        self.status.on_synced_changed.append(self._on_status_synced)
        self.sd.register(self.status)
        self.command = ApplicationCommand(debug=debug)
        self.sd.register(self.command)
        self.error = ApplicationError(debug=debug)
        self.sd.register(self.error)
        self.fileservice = ApplicationFile(debug=debug)
        self.fileservice.local_file_path = 'test.ngc'
        self.fileservice.local_path = './ngc/'
        self.fileservice.remote_path = '/home/xy/'
        self.fileservice.remote_file_path = '/home/xy/test.ngc'
        self.fileservice.on_ready_changed.append(self._on_fileservice_ready)
        self.sd.register(self.fileservice)

        self.timer = None
        self.timer_interval = 0.1

        self.use_curses = use_curses
        if not self.use_curses:
            return

        self.messages = []

        self.screen = curses.initscr()
        self.screen.keypad(True)
        self.dro_window = curses.newwin(10, 40, 1, 2)
        self.status_window = curses.newwin(10, 40, 1, 44)
        self.command_window = curses.newwin(10, 40, 1, 86)
        self.connection_window = curses.newwin(10, 80, 12, 2)
        self.error_window = curses.newwin(20, 120, 12, 84)
        self.file_window = curses.newwin(10, 80, 1, 108)
        curses.noecho()
        curses.cbreak()

    def _on_status_synced(self, synced):
        if synced:
            self.timer = threading.Timer(self.timer_interval, self.status_timer_tick)
            self.timer.start()
        else:
            if self.timer:
                self.timer.cancel()
                self.timer = None

    def _on_fileservice_ready(self, ready):
        if ready:
            print('fileservice ready')
            self.fileservice.refresh_files()
            self.fileservice.wait_completed()
            print(self.fileservice.file_list)
            self.fileservice.remove_file('test.ngc')
            self.fileservice.wait_completed()

    def status_timer_tick(self):
        # print(
        #     'stat: {}, cmd: {}, err: {}'.format(
        #         self.status.synced, self.command.connected, self.error.connected
        #     )
        # )
        if self.use_curses:
            self.update_screen()
        self.timer = threading.Timer(self.timer_interval, self.status_timer_tick)
        self.timer.start()

    def toggle_pin(self):
        self.halrcomp['coolant'] = not self.halrcomp['coolant']
        return True

    def update_screen(self):
        con = self.connection_window
        con.clear()
        con.border(0)
        con.addstr(1, 2, 'Connection')
        con.addstr(
            3, 4, 'Status: %s %s' % (str(self.status.synced), self.status.status_uri)
        )
        con.addstr(
            4,
            4,
            'Command: %s %s' % (str(self.command.connected), self.command.command_uri),
        )
        con.addstr(
            5, 4, 'Error: %s %s' % (str(self.error.connected), self.error.error_uri)
        )
        con.refresh()

        if not self.status.synced or not self.command.connected:
            return

        dro = self.dro_window
        dro.clear()
        dro.border(0)
        dro.addstr(1, 2, "DRO")
        for i, n in enumerate(['x', 'y', 'z']):  # range(self.status.config.axes):
            pos = str(getattr(self.status.motion.position, n))
            dro.addstr(3 + i, 4, '%s: %s' % (n, pos))
        dro.refresh()

        status = self.status_window
        status.clear()
        status.border(0)
        status.addstr(1, 2, 'Status')
        status.addstr(
            3,
            4,
            'Estop: %s'
            % str(self.status.task.task_state == application.EMC_TASK_STATE_ESTOP),
        )
        status.addstr(
            4,
            4,
            'Power: %s'
            % str(self.status.task.task_state == application.EMC_TASK_STATE_ON),
        )
        status.refresh()

        cmd = self.command_window
        cmd.clear()
        cmd.border(0)
        cmd.addstr(1, 2, 'Command')
        cmd.addstr(3, 4, 'Estop - F1')
        cmd.addstr(4, 4, 'Power - F2')
        cmd.refresh()

        error = self.error_window
        error.clear()
        error.border(0)
        error.addstr(1, 2, 'Notifications')
        self.messages += self.error.get_messages()
        pos = 0
        for message in self.messages:
            # msg_type = str(message['type'])
            for note in message['notes']:
                error.addstr(3 + pos, 4, str(note))
                pos += 1
        error.refresh()

        win = self.file_window
        win.clear()
        win.border(0)
        win.addstr(1, 2, 'File')
        win.addstr(3, 4, 'Status: %s' % self.fileservice.transfer_state)
        win.addstr(4, 4, 'Progress: %f' % self.fileservice.progress)
        win.refresh()

        self.screen.nodelay(True)
        c = self.screen.getch()
        if c == curses.KEY_F1:
            if self.status.task.task_state == application.EMC_TASK_STATE_ESTOP:
                ticket = self.command.set_task_state(
                    application.EMC_TASK_STATE_ESTOP_RESET
                )
                self.command.wait_completed(ticket=ticket, timeout=0.2)
            else:
                self.command.set_task_state(application.EMC_TASK_STATE_ESTOP)
                self.command.wait_completed(timeout=0.2)
        elif c == curses.KEY_F2:
            if self.status.task.task_state == application.EMC_TASK_STATE_ON:
                self.command.set_task_state(application.EMC_TASK_STATE_OFF)
            else:
                self.command.set_task_state(application.EMC_TASK_STATE_ON)
        elif c == curses.KEY_F3:
            self.fileservice.start_upload()

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()

        if self.timer:
            self.timer.cancel()

        if self.use_curses:
            curses.endwin()
예제 #7
0
class TerminalUI(object):
    def __init__(self, uuid, use_curses, debug=False):
        sd_filter = ServiceDiscoveryFilter(txt_records={'uuid': uuid})
        self.sd = ServiceDiscovery(filter_=sd_filter)

        halrcomp = halremote.component('test')
        halrcomp.debug = debug
        halrcomp.newpin("coolant-iocontrol", halremote.HAL_BIT, halremote.HAL_IN)
        halrcomp.newpin("coolant", halremote.HAL_BIT, halremote.HAL_OUT)
        self.halrcomp = halrcomp
        self.sd.register(halrcomp)

        halrcomp2 = halremote.RemoteComponent(name='test2', debug=debug)
        halrcomp2.newpin("coolant-iocontrol", halremote.HAL_BIT, halremote.HAL_IN)
        halrcomp2.newpin("coolant", halremote.HAL_BIT, halremote.HAL_OUT)
        self.halrcomp2 = halrcomp2
        self.sd.register(halrcomp2)

        self.status = ApplicationStatus(debug=debug)
        self.status.on_synced_changed.append(self._on_status_synced)
        self.sd.register(self.status)
        self.command = ApplicationCommand(debug=debug)
        self.sd.register(self.command)
        self.error = ApplicationError(debug=debug)
        self.sd.register(self.error)
        self.fileservice = ApplicationFile(debug=debug)
        self.fileservice.local_file_path = 'test.ngc'
        self.fileservice.local_path = './ngc/'
        self.fileservice.remote_path = '/home/xy/'
        self.fileservice.remote_file_path = '/home/xy/test.ngc'
        self.fileservice.on_ready_changed.append(self._on_fileservice_ready)
        self.sd.register(self.fileservice)

        self.timer = None
        self.timer_interval = 0.1

        self.use_curses = use_curses
        if not self.use_curses:
            return

        self.messages = []

        self.screen = curses.initscr()
        self.screen.keypad(True)
        self.dro_window = curses.newwin(10, 40, 1, 2)
        self.status_window = curses.newwin(10, 40, 1, 44)
        self.command_window = curses.newwin(10, 40, 1, 86)
        self.connection_window = curses.newwin(10, 80, 12, 2)
        self.error_window = curses.newwin(20, 120, 12, 84)
        self.file_window = curses.newwin(10, 80, 1, 108)
        curses.noecho()
        curses.cbreak()

    def _on_status_synced(self, synced):
        if synced:
            self.timer = threading.Timer(self.timer_interval, self.status_timer_tick)
            self.timer.start()
        else:
            if self.timer:
                self.timer.cancel()
                self.timer = None

    def _on_fileservice_ready(self, ready):
        if ready:
            print('fileservice ready')
            self.fileservice.refresh_files()
            self.fileservice.wait_completed()
            print(self.fileservice.file_list)
            self.fileservice.remove_file('test.ngc')
            self.fileservice.wait_completed()

    def status_timer_tick(self):
        # if self.status.synced:
        # print('flood %s' % self.status.io.flood)
        if self.use_curses:
            self.update_screen()
        self.timer = threading.Timer(self.timer_interval, self.status_timer_tick)
        self.timer.start()

    def toggle_pin(self):
        self.halrcomp['coolant'] = not self.halrcomp['coolant']
        return True

    def update_screen(self):
        con = self.connection_window
        con.clear()
        con.border(0)
        con.addstr(1, 2, 'Connection')
        con.addstr(
            3, 4, 'Status: %s %s' % (str(self.status.synced), self.status.status_uri)
        )
        con.addstr(
            4,
            4,
            'Command: %s %s' % (str(self.command.connected), self.command.command_uri),
        )
        con.addstr(
            5, 4, 'Error: %s %s' % (str(self.error.connected), self.error.error_uri)
        )
        con.refresh()

        if not self.status.synced or not self.command.connected:
            return

        dro = self.dro_window
        dro.clear()
        dro.border(0)
        dro.addstr(1, 2, "DRO")
        for i, n in enumerate(['x', 'y', 'z']):  # range(self.status.config.axes):
            pos = str(getattr(self.status.motion.position, n))
            dro.addstr(3 + i, 4, '%s: %s' % (n, pos))
        dro.refresh()

        status = self.status_window
        status.clear()
        status.border(0)
        status.addstr(1, 2, 'Status')
        status.addstr(
            3,
            4,
            'Estop: %s'
            % str(self.status.task.task_state == application.EMC_TASK_STATE_ESTOP),
        )
        status.addstr(
            4,
            4,
            'Power: %s'
            % str(self.status.task.task_state == application.EMC_TASK_STATE_ON),
        )
        status.refresh()

        cmd = self.command_window
        cmd.clear()
        cmd.border(0)
        cmd.addstr(1, 2, 'Command')
        cmd.addstr(3, 4, 'Estop - F1')
        cmd.addstr(4, 4, 'Power - F2')
        cmd.refresh()

        error = self.error_window
        error.clear()
        error.border(0)
        error.addstr(1, 2, 'Notifications')
        self.messages += self.error.get_messages()
        pos = 0
        for message in self.messages:
            # msg_type = str(message['type'])
            for note in message['notes']:
                error.addstr(3 + pos, 4, str(note))
                pos += 1
        error.refresh()

        win = self.file_window
        win.clear()
        win.border(0)
        win.addstr(1, 2, 'File')
        win.addstr(3, 4, 'Status: %s' % self.fileservice.transfer_state)
        win.addstr(4, 4, 'Progress: %f' % self.fileservice.progress)
        win.refresh()

        self.screen.nodelay(True)
        c = self.screen.getch()
        if c == curses.KEY_F1:
            if self.status.task.task_state == application.EMC_TASK_STATE_ESTOP:
                ticket = self.command.set_task_state(
                    application.EMC_TASK_STATE_ESTOP_RESET
                )
                self.command.wait_completed(ticket=ticket, timeout=0.2)
            else:
                self.command.set_task_state(application.EMC_TASK_STATE_ESTOP)
                self.command.wait_completed(timeout=0.2)
        elif c == curses.KEY_F2:
            if self.status.task.task_state == application.EMC_TASK_STATE_ON:
                self.command.set_task_state(application.EMC_TASK_STATE_OFF)
            else:
                self.command.set_task_state(application.EMC_TASK_STATE_ON)
        elif c == curses.KEY_F3:
            self.fileservice.start_upload()

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()

        if self.timer:
            self.timer.cancel()

        if self.use_curses:
            curses.endwin()
예제 #8
0
class IPCServer:
    def __init__(self, uuid, debug=True):
        self.debug = debug
        self.threads = []
        self.shutdown = threading.Event()
        sd_filter = ServiceDiscoveryFilter(txt_records={'uuid': uuid})
        self.sd = ServiceDiscovery(filter_=sd_filter)
        self.status = ApplicationStatus()
        self.command = ApplicationCommand()
        self.sd.register(self.status)
        self.sd.register(self.command)

        # create ipc sockets
        context = zmq.Context()
        context.linger = 0
        self.context = context
        # self.pubSocket = context.socket(zmq.PUB)
        # self.pubSocket.bind('ipc://machinetalk-server.ipc')
        # self.pubDsname = self.pubSocket.get_string(zmq.LAST_ENDPOINT, encoding='utf-8')
        # if self.debug:
        #     print('bound PUB socket to %s' % self.pubDsname)
        self.zmqSocket = context.socket(zmq.ROUTER)
        self.zmqSocket.bind('ipc://machinetalk-server.ipc')
        self.zmqDsname = self.zmqSocket.get_string(zmq.LAST_ENDPOINT,
                                                   encoding='utf-8')
        if self.debug:
            print('bound ROUTER socket to %s' % self.zmqDsname)
        self.zmqLock = threading.Lock()

        self._tx = Message()
        self._rx = Message()

        self.threads.append(threading.Thread(target=self.socket_worker))
        for thread in self.threads:
            thread.start()

    def send_msg(self, identity, msg_type):
        with self.zmqLock:
            self._tx.type = msg_type
            txBuffer = self._tx.SerializeToString()
            self.zmqSocket.send_multipart([identity, txBuffer], zmq.NOBLOCK)
            self._tx.Clear()

    def socket_worker(self):
        poll = zmq.Poller()
        poll.register(self.zmqSocket, zmq.POLLIN)

        while not self.shutdown.is_set():
            s = dict(poll.poll(200))
            if self.zmqSocket in s and s[self.zmqSocket] == zmq.POLLIN:
                self.process_msg(self.zmqSocket)

    def process_msg(self, socket):
        (identity, message) = socket.recv_multipart()
        self._rx.ParseFromString(message)

        if self.debug:
            print("process message called, id: %s" % identity)
            print(str(self._rx))

        if self._rx.type == IPC_POSITION:
            self._tx.x = (self.status.motion.position.x -
                          self.status.motion.g5x_offset.x -
                          self.status.motion.g92_offset.x -
                          self.status.io.tool_offset.x)
            self._tx.y = (self.status.motion.position.y -
                          self.status.motion.g5x_offset.y -
                          self.status.motion.g92_offset.y -
                          self.status.io.tool_offset.y)
            self.send_msg(identity, IPC_POSITION)

        elif self._rx.type == IPC_JOG:
            self.command.set_task_mode(application.EMC_TASK_MODE_MANUAL)
            self.command.jog(self._rx.jog_type, self._rx.axis,
                             self._rx.velocity, self._rx.distance)

        elif self._rx.type == IPC_CONNECTED:
            self._tx.connected = self.status.synced and self.command.connected
            self.send_msg(identity, IPC_CONNECTED)

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()
        self.shutdown.set()
        for thread in self.threads:
            thread.join()
        self.threads = []
예제 #9
0
class TestClass(object):
    def __init__(self, debug=False):
        self.debug = debug
        context = zmq.Context()
        context.linger = 0
        self.context = context

        self.sd = ServiceDiscovery()
        services = ['launchercmd', 'halrcmd', 'command', 'config']
        for name in services:
            service = Service(type_=name)
            self.sd.register(service)
            service.on_ready_changed.append(
                partial(self.service_ready, service=service)
            )

        self._tx = Container()
        self._rx = Container()

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()

    def service_ready(self, ready, service):
        if ready:
            self.send_broken(service.name, service.uri)
            self.send_broker_msg(service.name, service.uri)

    def send_broken(self, name, dsn):
        socket = self.context.socket(zmq.DEALER)
        socket.setsockopt(zmq.LINGER, 0)
        socket.setsockopt(zmq.RCVTIMEO, 1000)
        if self.debug:
            print('connecting to %s' % dsn)
        socket.connect(dsn)
        bogus = 'random_string'
        if self.debug:
            print('sending bogus string %s' % bogus)
        socket.send(bogus)
        answer = ''
        try:
            answer = socket.recv()
        except zmq.error.Again as e:
            print('test failed, answer timed out %s' % name)
            return
        self._rx.ParseFromString(answer)
        if self.debug:
            print('received answer %s' % self._rx)
        if self._rx.type == MT_ERROR:
            print('test successfull, %s handles broken messages' % name)
        else:
            print('test failed, %s does not handle broken messages' % name)

    def send_broker_msg(self, name, dsn):
        frontend = self.context.socket(zmq.ROUTER)
        backend = self.context.socket(zmq.DEALER)
        backend.setsockopt(zmq.IDENTITY, 'broker')
        socket = self.context.socket(zmq.DEALER)
        socket.setsockopt(zmq.IDENTITY, 'client')
        if self.debug:
            print('connecting backend to %s' % dsn)
        backend.connect(dsn)
        ipc = 'ipc://broker'
        if self.debug:
            print('connecting frontend to %s' % ipc)
        frontend.bind(ipc)
        if self.debug:
            print('connecting socket to %s' % ipc)
        socket.connect(ipc)
        if self.debug:
            print('sending ping via socket')
        self._tx.Clear()
        self._tx.type = MT_PING
        socket.send(self._tx.SerializeToString())
        if self.debug:
            print('receiving with broker:')
        recv = frontend.recv_multipart()
        if self.debug:
            print(recv)
            print('forwarding to host')
        backend.send_multipart(recv)
        if self.debug:
            print('receiving with backend:')
        recv = backend.recv_multipart()
        if self.debug:
            print(recv)
            print('sending data to frontend:')
        frontend.send_multipart(recv)
        if self.debug:
            print('receiving data with socket:')
        recv = socket.recv()
        self._rx.ParseFromString(recv)
        if self.debug:
            print(self._rx)
        if self._rx.type == MT_PING_ACKNOWLEDGE:
            print('test successfull, %s handles multiple ids' % name)
        else:
            print('test failed, %s does not correctly handle multiple ids' % name)
예제 #10
0
class TestClass(object):
    def __init__(self, debug=False):
        self.debug = debug
        context = zmq.Context()
        context.linger = 0
        self.context = context

        self.sd = ServiceDiscovery()
        services = ['launchercmd', 'halrcmd', 'command', 'config']
        for name in services:
            service = Service(type_=name)
            self.sd.register(service)
            service.on_ready_changed.append(
                partial(self.service_ready, service=service))

        self._tx = Container()
        self._rx = Container()

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()

    def service_ready(self, ready, service):
        if ready:
            self.send_broken(service.name, service.uri)
            self.send_broker_msg(service.name, service.uri)

    def send_broken(self, name, dsn):
        socket = self.context.socket(zmq.DEALER)
        socket.setsockopt(zmq.LINGER, 0)
        socket.setsockopt(zmq.RCVTIMEO, 1000)
        if self.debug:
            print('connecting to %s' % dsn)
        socket.connect(dsn)
        bogus = 'random_string'
        if self.debug:
            print('sending bogus string %s' % bogus)
        socket.send(bogus)
        answer = ''
        try:
            answer = socket.recv()
        except zmq.error.Again as e:
            print('test failed, answer timed out %s' % name)
            return
        self._rx.ParseFromString(answer)
        if self.debug:
            print('received answer %s' % self._rx)
        if self._rx.type == MT_ERROR:
            print('test successfull, %s handles broken messages' % name)
        else:
            print('test failed, %s does not handle broken messages' % name)

    def send_broker_msg(self, name, dsn):
        frontend = self.context.socket(zmq.ROUTER)
        backend = self.context.socket(zmq.DEALER)
        backend.setsockopt(zmq.IDENTITY, 'broker')
        socket = self.context.socket(zmq.DEALER)
        socket.setsockopt(zmq.IDENTITY, 'client')
        if self.debug:
            print('connecting backend to %s' % dsn)
        backend.connect(dsn)
        ipc = 'ipc://broker'
        if self.debug:
            print('connecting frontend to %s' % ipc)
        frontend.bind(ipc)
        if self.debug:
            print('connecting socket to %s' % ipc)
        socket.connect(ipc)
        if self.debug:
            print('sending ping via socket')
        self._tx.Clear()
        self._tx.type = MT_PING
        socket.send(self._tx.SerializeToString())
        if self.debug:
            print('receiving with broker:')
        recv = frontend.recv_multipart()
        if self.debug:
            print(recv)
            print('forwarding to host')
        backend.send_multipart(recv)
        if self.debug:
            print('receiving with backend:')
        recv = backend.recv_multipart()
        if self.debug:
            print(recv)
            print('sending data to frontend:')
        frontend.send_multipart(recv)
        if self.debug:
            print('receiving data with socket:')
        recv = socket.recv()
        self._rx.ParseFromString(recv)
        if self.debug:
            print(self._rx)
        if self._rx.type == MT_PING_ACKNOWLEDGE:
            print('test successfull, %s handles multiple ids' % name)
        else:
            print('test failed, %s does not correctly handle multiple ids' %
                  name)
예제 #11
0
class IPCServer:
    def __init__(self, uuid, debug=True):
        self.debug = debug
        self.threads = []
        self.shutdown = threading.Event()
        sd_filter = ServiceDiscoveryFilter(txt_records={'uuid': uuid})
        self.sd = ServiceDiscovery(filter_=sd_filter)
        self.status = ApplicationStatus()
        self.command = ApplicationCommand()
        self.sd.register(self.status)
        self.sd.register(self.command)

        # create ipc sockets
        context = zmq.Context()
        context.linger = 0
        self.context = context
        # self.pubSocket = context.socket(zmq.PUB)
        # self.pubSocket.bind('ipc://machinetalk-server.ipc')
        # self.pubDsname = self.pubSocket.get_string(zmq.LAST_ENDPOINT, encoding='utf-8')
        # if self.debug:
        #     print('bound PUB socket to %s' % self.pubDsname)
        self.zmqSocket = context.socket(zmq.ROUTER)
        self.zmqSocket.bind('ipc://machinetalk-server.ipc')
        self.zmqDsname = self.zmqSocket.get_string(zmq.LAST_ENDPOINT, encoding='utf-8')
        if self.debug:
            print('bound ROUTER socket to %s' % self.zmqDsname)
        self.zmqLock = threading.Lock()

        self._tx = Message()
        self._rx = Message()

        self.threads.append(threading.Thread(target=self.socket_worker))
        for thread in self.threads:
            thread.start()

    def send_msg(self, identity, msg_type):
        with self.zmqLock:
            self._tx.type = msg_type
            txBuffer = self._tx.SerializeToString()
            self.zmqSocket.send_multipart([identity, txBuffer], zmq.NOBLOCK)
            self._tx.Clear()

    def socket_worker(self):
        poll = zmq.Poller()
        poll.register(self.zmqSocket, zmq.POLLIN)

        while not self.shutdown.is_set():
            s = dict(poll.poll(200))
            if self.zmqSocket in s and s[self.zmqSocket] == zmq.POLLIN:
                self.process_msg(self.zmqSocket)

    def process_msg(self, socket):
        (identity, message) = socket.recv_multipart()
        self._rx.ParseFromString(message)

        if self.debug:
            print("process message called, id: %s" % identity)
            print(str(self._rx))

        if self._rx.type == IPC_POSITION:
            self._tx.x = (
                self.status.motion.position.x
                - self.status.motion.g5x_offset.x
                - self.status.motion.g92_offset.x
                - self.status.io.tool_offset.x
            )
            self._tx.y = (
                self.status.motion.position.y
                - self.status.motion.g5x_offset.y
                - self.status.motion.g92_offset.y
                - self.status.io.tool_offset.y
            )
            self.send_msg(identity, IPC_POSITION)

        elif self._rx.type == IPC_JOG:
            self.command.set_task_mode(application.EMC_TASK_MODE_MANUAL)
            self.command.jog(
                self._rx.jog_type, self._rx.axis, self._rx.velocity, self._rx.distance
            )

        elif self._rx.type == IPC_CONNECTED:
            self._tx.connected = self.status.synced and self.command.connected
            self.send_msg(identity, IPC_CONNECTED)

    def start(self):
        self.sd.start()

    def stop(self):
        self.sd.stop()
        self.shutdown.set()
        for thread in self.threads:
            thread.join()
        self.threads = []