예제 #1
0
class ErrorBase(object):
    def __init__(self, debuglevel=0, debugname='Error Base'):
        self.debuglevel = debuglevel
        self.debugname = debugname
        self._error_string = ''
        self.on_error_string_changed = []

        # Error
        self._error_channel = ErrorSubscribe(debuglevel=debuglevel)
        self._error_channel.debugname = '%s - %s' % (self.debugname, 'error')
        self._error_channel.on_state_changed.append(self._error_channel_state_changed)
        self._error_channel.on_socket_message_received.append(
            self._error_channel_message_received
        )
        # more efficient to reuse protobuf messages
        self._error_rx = Container()

        # callbacks
        self.on_error_message_received = []
        self.on_state_changed = []

        # fsm
        self._fsm = Fysom(
            {
                'initial': 'down',
                'events': [
                    {'name': 'connect', 'src': 'down', 'dst': 'trying'},
                    {'name': 'error_up', 'src': 'trying', 'dst': 'up'},
                    {'name': 'disconnect', 'src': 'trying', 'dst': 'down'},
                    {'name': 'error_trying', 'src': 'up', 'dst': 'trying'},
                    {'name': 'disconnect', 'src': 'up', 'dst': 'down'},
                ],
            }
        )

        self._fsm.ondown = self._on_fsm_down
        self._fsm.onafterconnect = self._on_fsm_connect
        self._fsm.ontrying = self._on_fsm_trying
        self._fsm.onaftererror_up = self._on_fsm_error_up
        self._fsm.onafterdisconnect = self._on_fsm_disconnect
        self._fsm.onup = self._on_fsm_up
        self._fsm.onaftererror_trying = self._on_fsm_error_trying
        self._fsm.onenterup = self._on_fsm_up_entry
        self._fsm.onleaveup = self._on_fsm_up_exit

    def _on_fsm_down(self, _):
        if self.debuglevel > 0:
            print('[%s]: state DOWN' % self.debugname)
        for cb in self.on_state_changed:
            cb('down')
        return True

    def _on_fsm_connect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event CONNECT' % self.debugname)
        self.update_topics()
        self.start_error_channel()
        return True

    def _on_fsm_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: state TRYING' % self.debugname)
        for cb in self.on_state_changed:
            cb('trying')
        return True

    def _on_fsm_error_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: event ERROR UP' % self.debugname)
        return True

    def _on_fsm_disconnect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event DISCONNECT' % self.debugname)
        self.stop_error_channel()
        return True

    def _on_fsm_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP' % self.debugname)
        for cb in self.on_state_changed:
            cb('up')
        return True

    def _on_fsm_error_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: event ERROR TRYING' % self.debugname)
        return True

    def _on_fsm_up_entry(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP entry' % self.debugname)
        self.set_connected()
        return True

    def _on_fsm_up_exit(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP exit' % self.debugname)
        self.clear_connected()
        return True

    @property
    def error_string(self):
        return self._error_string

    @error_string.setter
    def error_string(self, string):
        if self._error_string is string:
            return
        self._error_string = string
        for cb in self.on_error_string_changed:
            cb(string)

    @property
    def error_uri(self):
        return self._error_channel.socket_uri

    @error_uri.setter
    def error_uri(self, value):
        self._error_channel.socket_uri = value

    def update_topics(self):
        print('WARNING: slot update topics unimplemented')

    def set_connected(self):
        print('WARNING: slot set connected unimplemented')

    def clear_connected(self):
        print('WARNING: slot clear connected unimplemented')

    def start(self):
        if self._fsm.isstate('down'):
            self._fsm.connect()

    def stop(self):
        if self._fsm.isstate('trying'):
            self._fsm.disconnect()
        elif self._fsm.isstate('up'):
            self._fsm.disconnect()

    def add_error_topic(self, name):
        self._error_channel.add_socket_topic(name)

    def remove_error_topic(self, name):
        self._error_channel.remove_socket_topic(name)

    def clear_error_topics(self):
        self._error_channel.clear_socket_topics()

    def start_error_channel(self):
        self._error_channel.start()

    def stop_error_channel(self):
        self._error_channel.stop()

    # process all messages received on error
    def _error_channel_message_received(self, identity, rx):

        # react to emc nml error message
        if rx.type == pb.MT_EMC_NML_ERROR:
            self.emc_nml_error_received(identity, rx)

        # react to emc nml text message
        elif rx.type == pb.MT_EMC_NML_TEXT:
            self.emc_nml_text_received(identity, rx)

        # react to emc nml display message
        elif rx.type == pb.MT_EMC_NML_DISPLAY:
            self.emc_nml_display_received(identity, rx)

        # react to emc operator text message
        elif rx.type == pb.MT_EMC_OPERATOR_TEXT:
            self.emc_operator_text_received(identity, rx)

        # react to emc operator error message
        elif rx.type == pb.MT_EMC_OPERATOR_ERROR:
            self.emc_operator_error_received(identity, rx)

        # react to emc operator display message
        elif rx.type == pb.MT_EMC_OPERATOR_DISPLAY:
            self.emc_operator_display_received(identity, rx)

        for cb in self.on_error_message_received:
            cb(identity, rx)

    def emc_nml_error_received(self, identity, rx):
        print('SLOT emc nml error unimplemented')

    def emc_nml_text_received(self, identity, rx):
        print('SLOT emc nml text unimplemented')

    def emc_nml_display_received(self, identity, rx):
        print('SLOT emc nml display unimplemented')

    def emc_operator_text_received(self, identity, rx):
        print('SLOT emc operator text unimplemented')

    def emc_operator_error_received(self, identity, rx):
        print('SLOT emc operator error unimplemented')

    def emc_operator_display_received(self, identity, rx):
        print('SLOT emc operator display unimplemented')

    def _error_channel_state_changed(self, state):

        if state == 'trying':
            if self._fsm.isstate('up'):
                self._fsm.error_trying()

        elif state == 'up':
            if self._fsm.isstate('trying'):
                self._fsm.error_up()
예제 #2
0
class LogServiceBase(object):
    def __init__(self, debuglevel=0, debugname='Log Service Base'):
        self.debuglevel = debuglevel
        self.debugname = debugname
        self._error_string = ''
        self.on_error_string_changed = []

        # Log
        self._log_channel = Publish(debuglevel=debuglevel)
        self._log_channel.debugname = '%s - %s' % (self.debugname, 'log')
        # more efficient to reuse protobuf messages
        self._log_tx = Container()

        # callbacks
        self.on_state_changed = []

        # fsm
        self._fsm = Fysom(
            {
                'initial': 'down',
                'events': [
                    {'name': 'connect', 'src': 'down', 'dst': 'up'},
                    {'name': 'disconnect', 'src': 'up', 'dst': 'down'},
                ],
            }
        )

        self._fsm.ondown = self._on_fsm_down
        self._fsm.onafterconnect = self._on_fsm_connect
        self._fsm.onup = self._on_fsm_up
        self._fsm.onafterdisconnect = self._on_fsm_disconnect

    def _on_fsm_down(self, _):
        if self.debuglevel > 0:
            print('[%s]: state DOWN' % self.debugname)
        for cb in self.on_state_changed:
            cb('down')
        return True

    def _on_fsm_connect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event CONNECT' % self.debugname)
        self.start_log_channel()
        return True

    def _on_fsm_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP' % self.debugname)
        for cb in self.on_state_changed:
            cb('up')
        return True

    def _on_fsm_disconnect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event DISCONNECT' % self.debugname)
        self.stop_log_channel()
        return True

    @property
    def error_string(self):
        return self._error_string

    @error_string.setter
    def error_string(self, string):
        if self._error_string is string:
            return
        self._error_string = string
        for cb in self.on_error_string_changed:
            cb(string)

    @property
    def log_uri(self):
        return self._log_channel.socket_uri

    @log_uri.setter
    def log_uri(self, value):
        self._log_channel.socket_uri = value

    @property
    def log_port(self):
        return self._log_channel.socket_port

    @property
    def log_dsn(self):
        return self._log_channel.socket_dsn

    def start(self):
        if self._fsm.isstate('down'):
            self._fsm.connect()

    def stop(self):
        if self._fsm.isstate('up'):
            self._fsm.disconnect()

    def add_log_topic(self, name):
        self._log_channel.add_socket_topic(name)

    def remove_log_topic(self, name):
        self._log_channel.remove_socket_topic(name)

    def clear_log_topics(self):
        self._log_channel.clear_socket_topics()

    def start_log_channel(self):
        self._log_channel.start()

    def stop_log_channel(self):
        self._log_channel.stop()

    def send_log_message(self, identity, msg_type, tx):
        self._log_channel.send_socket_message(identity.encode(), msg_type, tx)

    def send_log_message(self, identity, tx):
        ids = [identity.encode()]
        for receiver in ids:
            self.send_log_message(receiver, pb.MT_LOG_MESSAGE, tx)
예제 #3
0
class ErrorBase(object):
    def __init__(self, debuglevel=0, debugname='Error Base'):
        self.debuglevel = debuglevel
        self.debugname = debugname
        self._error_string = ''
        self.on_error_string_changed = []

        # Error
        self._error_channel = ErrorSubscribe(debuglevel=debuglevel)
        self._error_channel.debugname = '%s - %s' % (self.debugname, 'error')
        self._error_channel.on_state_changed.append(
            self._error_channel_state_changed)
        self._error_channel.on_socket_message_received.append(
            self._error_channel_message_received)
        # more efficient to reuse protobuf messages
        self._error_rx = Container()

        # callbacks
        self.on_error_message_received = []
        self.on_state_changed = []

        # fsm
        self._fsm = Fysom({
            'initial':
            'down',
            'events': [
                {
                    'name': 'connect',
                    'src': 'down',
                    'dst': 'trying'
                },
                {
                    'name': 'error_up',
                    'src': 'trying',
                    'dst': 'up'
                },
                {
                    'name': 'disconnect',
                    'src': 'trying',
                    'dst': 'down'
                },
                {
                    'name': 'error_trying',
                    'src': 'up',
                    'dst': 'trying'
                },
                {
                    'name': 'disconnect',
                    'src': 'up',
                    'dst': 'down'
                },
            ],
        })

        self._fsm.ondown = self._on_fsm_down
        self._fsm.onafterconnect = self._on_fsm_connect
        self._fsm.ontrying = self._on_fsm_trying
        self._fsm.onaftererror_up = self._on_fsm_error_up
        self._fsm.onafterdisconnect = self._on_fsm_disconnect
        self._fsm.onup = self._on_fsm_up
        self._fsm.onaftererror_trying = self._on_fsm_error_trying
        self._fsm.onleaveup = self._on_fsm_up_exit

    def _on_fsm_down(self, _):
        if self.debuglevel > 0:
            print('[%s]: state DOWN' % self.debugname)
        for cb in self.on_state_changed:
            cb('down')
        return True

    def _on_fsm_connect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event CONNECT' % self.debugname)
        self.update_topics()
        self.start_error_channel()
        return True

    def _on_fsm_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: state TRYING' % self.debugname)
        for cb in self.on_state_changed:
            cb('trying')
        return True

    def _on_fsm_error_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: event ERROR UP' % self.debugname)
        return True

    def _on_fsm_disconnect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event DISCONNECT' % self.debugname)
        self.stop_error_channel()
        return True

    def _on_fsm_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP entry' % self.debugname)
        self.set_connected()
        if self.debuglevel > 0:
            print('[%s]: state UP' % self.debugname)
        for cb in self.on_state_changed:
            cb('up')
        return True

    def _on_fsm_error_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: event ERROR TRYING' % self.debugname)
        return True

    def _on_fsm_up_exit(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP exit' % self.debugname)
        self.clear_connected()
        return True

    @property
    def error_string(self):
        return self._error_string

    @error_string.setter
    def error_string(self, string):
        if self._error_string is string:
            return
        self._error_string = string
        for cb in self.on_error_string_changed:
            cb(string)

    @property
    def error_uri(self):
        return self._error_channel.socket_uri

    @error_uri.setter
    def error_uri(self, value):
        self._error_channel.socket_uri = value

    def update_topics(self):
        print('WARNING: slot update topics unimplemented')

    def set_connected(self):
        print('WARNING: slot set connected unimplemented')

    def clear_connected(self):
        print('WARNING: slot clear connected unimplemented')

    def start(self):
        if self._fsm.isstate('down'):
            self._fsm.connect()

    def stop(self):
        if self._fsm.isstate('trying'):
            self._fsm.disconnect()
        elif self._fsm.isstate('up'):
            self._fsm.disconnect()

    def add_error_topic(self, name):
        self._error_channel.add_socket_topic(name)

    def remove_error_topic(self, name):
        self._error_channel.remove_socket_topic(name)

    def clear_error_topics(self):
        self._error_channel.clear_socket_topics()

    def start_error_channel(self):
        self._error_channel.start()

    def stop_error_channel(self):
        self._error_channel.stop()

    # process all messages received on error
    def _error_channel_message_received(self, identity, rx):

        # react to emc nml error message
        if rx.type == pb.MT_EMC_NML_ERROR:
            self.emc_nml_error_received(identity, rx)

        # react to emc nml text message
        elif rx.type == pb.MT_EMC_NML_TEXT:
            self.emc_nml_text_received(identity, rx)

        # react to emc nml display message
        elif rx.type == pb.MT_EMC_NML_DISPLAY:
            self.emc_nml_display_received(identity, rx)

        # react to emc operator text message
        elif rx.type == pb.MT_EMC_OPERATOR_TEXT:
            self.emc_operator_text_received(identity, rx)

        # react to emc operator error message
        elif rx.type == pb.MT_EMC_OPERATOR_ERROR:
            self.emc_operator_error_received(identity, rx)

        # react to emc operator display message
        elif rx.type == pb.MT_EMC_OPERATOR_DISPLAY:
            self.emc_operator_display_received(identity, rx)

        for cb in self.on_error_message_received:
            cb(identity, rx)

    def emc_nml_error_received(self, identity, rx):
        print('SLOT emc nml error unimplemented')

    def emc_nml_text_received(self, identity, rx):
        print('SLOT emc nml text unimplemented')

    def emc_nml_display_received(self, identity, rx):
        print('SLOT emc nml display unimplemented')

    def emc_operator_text_received(self, identity, rx):
        print('SLOT emc operator text unimplemented')

    def emc_operator_error_received(self, identity, rx):
        print('SLOT emc operator error unimplemented')

    def emc_operator_display_received(self, identity, rx):
        print('SLOT emc operator display unimplemented')

    def _error_channel_state_changed(self, state):

        if state == 'trying':
            if self._fsm.isstate('up'):
                self._fsm.error_trying()

        elif state == 'up':
            if self._fsm.isstate('trying'):
                self._fsm.error_up()
예제 #4
0
class RemoteComponentBase(object):
    def __init__(self, debuglevel=0, debugname='Remote Component Base'):
        self.debuglevel = debuglevel
        self.debugname = debugname
        self._error_string = ''
        self.on_error_string_changed = []

        # Halrcmd
        self._halrcmd_channel = RpcClient(debuglevel=debuglevel)
        self._halrcmd_channel.debugname = '%s - %s' % (self.debugname,
                                                       'halrcmd')
        self._halrcmd_channel.on_state_changed.append(
            self._halrcmd_channel_state_changed)
        self._halrcmd_channel.on_socket_message_received.append(
            self._halrcmd_channel_message_received)
        # more efficient to reuse protobuf messages
        self._halrcmd_rx = Container()
        self._halrcmd_tx = Container()

        # Halrcomp
        self._halrcomp_channel = HalrcompSubscribe(debuglevel=debuglevel)
        self._halrcomp_channel.debugname = '%s - %s' % (self.debugname,
                                                        'halrcomp')
        self._halrcomp_channel.on_state_changed.append(
            self._halrcomp_channel_state_changed)
        self._halrcomp_channel.on_socket_message_received.append(
            self._halrcomp_channel_message_received)
        # more efficient to reuse protobuf messages
        self._halrcomp_rx = Container()

        # callbacks
        self.on_halrcmd_message_received = []
        self.on_halrcomp_message_received = []
        self.on_state_changed = []

        # fsm
        self._fsm = Fysom({
            'initial':
            'down',
            'events': [
                {
                    'name': 'connect',
                    'src': 'down',
                    'dst': 'trying'
                },
                {
                    'name': 'halrcmd_up',
                    'src': 'trying',
                    'dst': 'bind'
                },
                {
                    'name': 'disconnect',
                    'src': 'trying',
                    'dst': 'down'
                },
                {
                    'name': 'halrcomp_bind_msg_sent',
                    'src': 'bind',
                    'dst': 'binding'
                },
                {
                    'name': 'no_bind',
                    'src': 'bind',
                    'dst': 'syncing'
                },
                {
                    'name': 'bind_confirmed',
                    'src': 'binding',
                    'dst': 'syncing'
                },
                {
                    'name': 'bind_rejected',
                    'src': 'binding',
                    'dst': 'error'
                },
                {
                    'name': 'halrcmd_trying',
                    'src': 'binding',
                    'dst': 'trying'
                },
                {
                    'name': 'disconnect',
                    'src': 'binding',
                    'dst': 'down'
                },
                {
                    'name': 'halrcmd_trying',
                    'src': 'syncing',
                    'dst': 'trying'
                },
                {
                    'name': 'halrcomp_up',
                    'src': 'syncing',
                    'dst': 'sync'
                },
                {
                    'name': 'sync_failed',
                    'src': 'syncing',
                    'dst': 'error'
                },
                {
                    'name': 'disconnect',
                    'src': 'syncing',
                    'dst': 'down'
                },
                {
                    'name': 'pins_synced',
                    'src': 'sync',
                    'dst': 'synced'
                },
                {
                    'name': 'halrcomp_trying',
                    'src': 'synced',
                    'dst': 'syncing'
                },
                {
                    'name': 'halrcmd_trying',
                    'src': 'synced',
                    'dst': 'trying'
                },
                {
                    'name': 'set_rejected',
                    'src': 'synced',
                    'dst': 'error'
                },
                {
                    'name': 'halrcomp_set_msg_sent',
                    'src': 'synced',
                    'dst': 'synced'
                },
                {
                    'name': 'disconnect',
                    'src': 'synced',
                    'dst': 'down'
                },
                {
                    'name': 'disconnect',
                    'src': 'error',
                    'dst': 'down'
                },
            ],
        })

        self._fsm.ondown = self._on_fsm_down
        self._fsm.onafterconnect = self._on_fsm_connect
        self._fsm.onleavedown = self._on_fsm_down_exit
        self._fsm.ontrying = self._on_fsm_trying
        self._fsm.onafterhalrcmd_up = self._on_fsm_halrcmd_up
        self._fsm.onafterdisconnect = self._on_fsm_disconnect
        self._fsm.onbind = self._on_fsm_bind
        self._fsm.onafterhalrcomp_bind_msg_sent = self._on_fsm_halrcomp_bind_msg_sent
        self._fsm.onafterno_bind = self._on_fsm_no_bind
        self._fsm.onbinding = self._on_fsm_binding
        self._fsm.onafterbind_confirmed = self._on_fsm_bind_confirmed
        self._fsm.onafterbind_rejected = self._on_fsm_bind_rejected
        self._fsm.onafterhalrcmd_trying = self._on_fsm_halrcmd_trying
        self._fsm.onsyncing = self._on_fsm_syncing
        self._fsm.onafterhalrcomp_up = self._on_fsm_halrcomp_up
        self._fsm.onaftersync_failed = self._on_fsm_sync_failed
        self._fsm.onsync = self._on_fsm_sync
        self._fsm.onafterpins_synced = self._on_fsm_pins_synced
        self._fsm.onsynced = self._on_fsm_synced
        self._fsm.onafterhalrcomp_trying = self._on_fsm_halrcomp_trying
        self._fsm.onafterset_rejected = self._on_fsm_set_rejected
        self._fsm.onafterhalrcomp_set_msg_sent = self._on_fsm_halrcomp_set_msg_sent
        self._fsm.onerror = self._on_fsm_error

    def _on_fsm_down(self, _):
        if self.debuglevel > 0:
            print('[%s]: state DOWN entry' % self.debugname)
        self.set_disconnected()
        if self.debuglevel > 0:
            print('[%s]: state DOWN' % self.debugname)
        for cb in self.on_state_changed:
            cb('down')
        return True

    def _on_fsm_connect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event CONNECT' % self.debugname)
        self.add_pins()
        self.start_halrcmd_channel()
        return True

    def _on_fsm_down_exit(self, _):
        if self.debuglevel > 0:
            print('[%s]: state DOWN exit' % self.debugname)
        self.set_connecting()
        return True

    def _on_fsm_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: state TRYING' % self.debugname)
        for cb in self.on_state_changed:
            cb('trying')
        return True

    def _on_fsm_halrcmd_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: event HALRCMD UP' % self.debugname)
        self.bind_component()
        return True

    def _on_fsm_disconnect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event DISCONNECT' % self.debugname)
        self.stop_halrcmd_channel()
        self.stop_halrcomp_channel()
        self.remove_pins()
        return True

    def _on_fsm_bind(self, _):
        if self.debuglevel > 0:
            print('[%s]: state BIND' % self.debugname)
        for cb in self.on_state_changed:
            cb('bind')
        return True

    def _on_fsm_halrcomp_bind_msg_sent(self, _):
        if self.debuglevel > 0:
            print('[%s]: event HALRCOMP BIND MSG SENT' % self.debugname)
        return True

    def _on_fsm_no_bind(self, _):
        if self.debuglevel > 0:
            print('[%s]: event NO BIND' % self.debugname)
        self.start_halrcomp_channel()
        return True

    def _on_fsm_binding(self, _):
        if self.debuglevel > 0:
            print('[%s]: state BINDING' % self.debugname)
        for cb in self.on_state_changed:
            cb('binding')
        return True

    def _on_fsm_bind_confirmed(self, _):
        if self.debuglevel > 0:
            print('[%s]: event BIND CONFIRMED' % self.debugname)
        self.start_halrcomp_channel()
        return True

    def _on_fsm_bind_rejected(self, _):
        if self.debuglevel > 0:
            print('[%s]: event BIND REJECTED' % self.debugname)
        self.stop_halrcmd_channel()
        return True

    def _on_fsm_halrcmd_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: event HALRCMD TRYING' % self.debugname)
        return True

    def _on_fsm_syncing(self, _):
        if self.debuglevel > 0:
            print('[%s]: state SYNCING' % self.debugname)
        for cb in self.on_state_changed:
            cb('syncing')
        return True

    def _on_fsm_halrcomp_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: event HALRCOMP UP' % self.debugname)
        return True

    def _on_fsm_sync_failed(self, _):
        if self.debuglevel > 0:
            print('[%s]: event SYNC FAILED' % self.debugname)
        self.stop_halrcomp_channel()
        self.stop_halrcmd_channel()
        return True

    def _on_fsm_sync(self, _):
        if self.debuglevel > 0:
            print('[%s]: state SYNC' % self.debugname)
        for cb in self.on_state_changed:
            cb('sync')
        return True

    def _on_fsm_pins_synced(self, _):
        if self.debuglevel > 0:
            print('[%s]: event PINS SYNCED' % self.debugname)
        return True

    def _on_fsm_synced(self, _):
        if self.debuglevel > 0:
            print('[%s]: state SYNCED entry' % self.debugname)
        self.set_connected()
        if self.debuglevel > 0:
            print('[%s]: state SYNCED' % self.debugname)
        for cb in self.on_state_changed:
            cb('synced')
        return True

    def _on_fsm_halrcomp_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: event HALRCOMP TRYING' % self.debugname)
        self.unsync_pins()
        self.set_timeout()
        return True

    def _on_fsm_set_rejected(self, _):
        if self.debuglevel > 0:
            print('[%s]: event SET REJECTED' % self.debugname)
        self.stop_halrcomp_channel()
        self.stop_halrcmd_channel()
        return True

    def _on_fsm_halrcomp_set_msg_sent(self, _):
        if self.debuglevel > 0:
            print('[%s]: event HALRCOMP SET MSG SENT' % self.debugname)
        return True

    def _on_fsm_error(self, _):
        if self.debuglevel > 0:
            print('[%s]: state ERROR entry' % self.debugname)
        self.set_error()
        if self.debuglevel > 0:
            print('[%s]: state ERROR' % self.debugname)
        for cb in self.on_state_changed:
            cb('error')
        return True

    @property
    def error_string(self):
        return self._error_string

    @error_string.setter
    def error_string(self, string):
        if self._error_string is string:
            return
        self._error_string = string
        for cb in self.on_error_string_changed:
            cb(string)

    @property
    def halrcmd_uri(self):
        return self._halrcmd_channel.socket_uri

    @halrcmd_uri.setter
    def halrcmd_uri(self, value):
        self._halrcmd_channel.socket_uri = value

    @property
    def halrcomp_uri(self):
        return self._halrcomp_channel.socket_uri

    @halrcomp_uri.setter
    def halrcomp_uri(self, value):
        self._halrcomp_channel.socket_uri = value

    def bind_component(self):
        print('WARNING: slot bind component unimplemented')

    def add_pins(self):
        print('WARNING: slot add pins unimplemented')

    def remove_pins(self):
        print('WARNING: slot remove pins unimplemented')

    def unsync_pins(self):
        print('WARNING: slot unsync pins unimplemented')

    def set_connected(self):
        print('WARNING: slot set connected unimplemented')

    def set_error(self):
        print('WARNING: slot set error unimplemented')

    def set_disconnected(self):
        print('WARNING: slot set disconnected unimplemented')

    def set_connecting(self):
        print('WARNING: slot set connecting unimplemented')

    def set_timeout(self):
        print('WARNING: slot set timeout unimplemented')

    def no_bind(self):
        if self._fsm.isstate('bind'):
            self._fsm.no_bind()

    def pins_synced(self):
        if self._fsm.isstate('sync'):
            self._fsm.pins_synced()

    def start(self):
        if self._fsm.isstate('down'):
            self._fsm.connect()

    def stop(self):
        if self._fsm.isstate('trying'):
            self._fsm.disconnect()
        elif self._fsm.isstate('binding'):
            self._fsm.disconnect()
        elif self._fsm.isstate('syncing'):
            self._fsm.disconnect()
        elif self._fsm.isstate('synced'):
            self._fsm.disconnect()
        elif self._fsm.isstate('error'):
            self._fsm.disconnect()

    def add_halrcomp_topic(self, name):
        self._halrcomp_channel.add_socket_topic(name)

    def remove_halrcomp_topic(self, name):
        self._halrcomp_channel.remove_socket_topic(name)

    def clear_halrcomp_topics(self):
        self._halrcomp_channel.clear_socket_topics()

    def start_halrcmd_channel(self):
        self._halrcmd_channel.start()

    def stop_halrcmd_channel(self):
        self._halrcmd_channel.stop()

    def start_halrcomp_channel(self):
        self._halrcomp_channel.start()

    def stop_halrcomp_channel(self):
        self._halrcomp_channel.stop()

    # process all messages received on halrcmd
    def _halrcmd_channel_message_received(self, rx):

        # react to halrcomp bind confirm message
        if rx.type == pb.MT_HALRCOMP_BIND_CONFIRM:
            if self._fsm.isstate('binding'):
                self._fsm.bind_confirmed()

        # react to halrcomp bind reject message
        elif rx.type == pb.MT_HALRCOMP_BIND_REJECT:
            # update error string with note
            self.error_string = ''
            for note in rx.note:
                self.error_string += note + '\n'
            if self._fsm.isstate('binding'):
                self._fsm.bind_rejected()

        # react to halrcomp set reject message
        elif rx.type == pb.MT_HALRCOMP_SET_REJECT:
            # update error string with note
            self.error_string = ''
            for note in rx.note:
                self.error_string += note + '\n'
            if self._fsm.isstate('synced'):
                self._fsm.set_rejected()

        for cb in self.on_halrcmd_message_received:
            cb(rx)

    # process all messages received on halrcomp
    def _halrcomp_channel_message_received(self, identity, rx):

        # react to halrcomp full update message
        if rx.type == pb.MT_HALRCOMP_FULL_UPDATE:
            self.halrcomp_full_update_received(identity, rx)

        # react to halrcomp incremental update message
        elif rx.type == pb.MT_HALRCOMP_INCREMENTAL_UPDATE:
            self.halrcomp_incremental_update_received(identity, rx)

        # react to halrcomp error message
        elif rx.type == pb.MT_HALRCOMP_ERROR:
            # update error string with note
            self.error_string = ''
            for note in rx.note:
                self.error_string += note + '\n'
            if self._fsm.isstate('syncing'):
                self._fsm.sync_failed()
            self.halrcomp_error_received(identity, rx)

        for cb in self.on_halrcomp_message_received:
            cb(identity, rx)

    def halrcomp_full_update_received(self, identity, rx):
        print('SLOT halrcomp full update unimplemented')

    def halrcomp_incremental_update_received(self, identity, rx):
        print('SLOT halrcomp incremental update unimplemented')

    def halrcomp_error_received(self, identity, rx):
        print('SLOT halrcomp error unimplemented')

    def send_halrcmd_message(self, msg_type, tx):
        self._halrcmd_channel.send_socket_message(msg_type, tx)

        if msg_type == pb.MT_HALRCOMP_BIND:
            if self._fsm.isstate('bind'):
                self._fsm.halrcomp_bind_msg_sent()

        elif msg_type == pb.MT_HALRCOMP_SET:
            if self._fsm.isstate('synced'):
                self._fsm.halrcomp_set_msg_sent()

    def send_halrcomp_bind(self, tx):
        self.send_halrcmd_message(pb.MT_HALRCOMP_BIND, tx)

    def send_halrcomp_set(self, tx):
        self.send_halrcmd_message(pb.MT_HALRCOMP_SET, tx)

    def _halrcmd_channel_state_changed(self, state):

        if state == 'trying':
            if self._fsm.isstate('syncing'):
                self._fsm.halrcmd_trying()
            elif self._fsm.isstate('synced'):
                self._fsm.halrcmd_trying()
            elif self._fsm.isstate('binding'):
                self._fsm.halrcmd_trying()

        elif state == 'up':
            if self._fsm.isstate('trying'):
                self._fsm.halrcmd_up()

    def _halrcomp_channel_state_changed(self, state):

        if state == 'trying':
            if self._fsm.isstate('synced'):
                self._fsm.halrcomp_trying()

        elif state == 'up':
            if self._fsm.isstate('syncing'):
                self._fsm.halrcomp_up()
예제 #5
0
class StatusBase(object):
    def __init__(self, debuglevel=0, debugname='Status Base'):
        self.debuglevel = debuglevel
        self.debugname = debugname
        self._error_string = ''
        self.on_error_string_changed = []

        # Status
        self._status_channel = StatusSubscribe(debuglevel=debuglevel)
        self._status_channel.debugname = '%s - %s' % (self.debugname, 'status')
        self._status_channel.on_state_changed.append(
            self._status_channel_state_changed)
        self._status_channel.on_socket_message_received.append(
            self._status_channel_message_received)
        # more efficient to reuse protobuf messages
        self._status_rx = Container()

        # callbacks
        self.on_status_message_received = []
        self.on_state_changed = []

        # fsm
        self._fsm = Fysom({
            'initial':
            'down',
            'events': [
                {
                    'name': 'connect',
                    'src': 'down',
                    'dst': 'trying'
                },
                {
                    'name': 'status_up',
                    'src': 'trying',
                    'dst': 'syncing'
                },
                {
                    'name': 'disconnect',
                    'src': 'trying',
                    'dst': 'down'
                },
                {
                    'name': 'channels_synced',
                    'src': 'syncing',
                    'dst': 'up'
                },
                {
                    'name': 'status_trying',
                    'src': 'syncing',
                    'dst': 'trying'
                },
                {
                    'name': 'disconnect',
                    'src': 'syncing',
                    'dst': 'down'
                },
                {
                    'name': 'status_trying',
                    'src': 'up',
                    'dst': 'trying'
                },
                {
                    'name': 'disconnect',
                    'src': 'up',
                    'dst': 'down'
                },
            ],
        })

        self._fsm.ondown = self._on_fsm_down
        self._fsm.onafterconnect = self._on_fsm_connect
        self._fsm.ontrying = self._on_fsm_trying
        self._fsm.onafterstatus_up = self._on_fsm_status_up
        self._fsm.onafterdisconnect = self._on_fsm_disconnect
        self._fsm.onsyncing = self._on_fsm_syncing
        self._fsm.onafterchannels_synced = self._on_fsm_channels_synced
        self._fsm.onafterstatus_trying = self._on_fsm_status_trying
        self._fsm.onup = self._on_fsm_up
        self._fsm.onleaveup = self._on_fsm_up_exit

    def _on_fsm_down(self, _):
        if self.debuglevel > 0:
            print('[%s]: state DOWN' % self.debugname)
        for cb in self.on_state_changed:
            cb('down')
        return True

    def _on_fsm_connect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event CONNECT' % self.debugname)
        self.update_topics()
        self.start_status_channel()
        return True

    def _on_fsm_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: state TRYING' % self.debugname)
        for cb in self.on_state_changed:
            cb('trying')
        return True

    def _on_fsm_status_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: event STATUS UP' % self.debugname)
        return True

    def _on_fsm_disconnect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event DISCONNECT' % self.debugname)
        self.stop_status_channel()
        return True

    def _on_fsm_syncing(self, _):
        if self.debuglevel > 0:
            print('[%s]: state SYNCING' % self.debugname)
        for cb in self.on_state_changed:
            cb('syncing')
        return True

    def _on_fsm_channels_synced(self, _):
        if self.debuglevel > 0:
            print('[%s]: event CHANNELS SYNCED' % self.debugname)
        return True

    def _on_fsm_status_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: event STATUS TRYING' % self.debugname)
        return True

    def _on_fsm_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP entry' % self.debugname)
        self.sync_status()
        if self.debuglevel > 0:
            print('[%s]: state UP' % self.debugname)
        for cb in self.on_state_changed:
            cb('up')
        return True

    def _on_fsm_up_exit(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP exit' % self.debugname)
        self.unsync_status()
        return True

    @property
    def error_string(self):
        return self._error_string

    @error_string.setter
    def error_string(self, string):
        if self._error_string is string:
            return
        self._error_string = string
        for cb in self.on_error_string_changed:
            cb(string)

    @property
    def status_uri(self):
        return self._status_channel.socket_uri

    @status_uri.setter
    def status_uri(self, value):
        self._status_channel.socket_uri = value

    def sync_status(self):
        print('WARNING: slot sync status unimplemented')

    def unsync_status(self):
        print('WARNING: slot unsync status unimplemented')

    def update_topics(self):
        print('WARNING: slot update topics unimplemented')

    def start(self):
        if self._fsm.isstate('down'):
            self._fsm.connect()

    def stop(self):
        if self._fsm.isstate('trying'):
            self._fsm.disconnect()
        elif self._fsm.isstate('up'):
            self._fsm.disconnect()

    def channels_synced(self):
        if self._fsm.isstate('syncing'):
            self._fsm.channels_synced()

    def add_status_topic(self, name):
        self._status_channel.add_socket_topic(name)

    def remove_status_topic(self, name):
        self._status_channel.remove_socket_topic(name)

    def clear_status_topics(self):
        self._status_channel.clear_socket_topics()

    def start_status_channel(self):
        self._status_channel.start()

    def stop_status_channel(self):
        self._status_channel.stop()

    # process all messages received on status
    def _status_channel_message_received(self, identity, rx):

        # react to emcstat full update message
        if rx.type == pb.MT_EMCSTAT_FULL_UPDATE:
            self.emcstat_full_update_received(identity, rx)

        # react to emcstat incremental update message
        elif rx.type == pb.MT_EMCSTAT_INCREMENTAL_UPDATE:
            self.emcstat_incremental_update_received(identity, rx)

        for cb in self.on_status_message_received:
            cb(identity, rx)

    def emcstat_full_update_received(self, identity, rx):
        print('SLOT emcstat full update unimplemented')

    def emcstat_incremental_update_received(self, identity, rx):
        print('SLOT emcstat incremental update unimplemented')

    def _status_channel_state_changed(self, state):

        if state == 'trying':
            if self._fsm.isstate('up'):
                self._fsm.status_trying()

        elif state == 'trying':
            if self._fsm.isstate('syncing'):
                self._fsm.status_trying()

        elif state == 'up':
            if self._fsm.isstate('trying'):
                self._fsm.status_up()
예제 #6
0
class CommandBase(object):
    def __init__(self, debuglevel=0, debugname='Command Base'):
        self.debuglevel = debuglevel
        self.debugname = debugname
        self._error_string = ''
        self.on_error_string_changed = []

        # Command
        self._command_channel = RpcClient(debuglevel=debuglevel)
        self._command_channel.debugname = '%s - %s' % (self.debugname,
                                                       'command')
        self._command_channel.on_state_changed.append(
            self._command_channel_state_changed)
        self._command_channel.on_socket_message_received.append(
            self._command_channel_message_received)
        # more efficient to reuse protobuf messages
        self._command_rx = Container()
        self._command_tx = Container()

        # callbacks
        self.on_command_message_received = []
        self.on_state_changed = []

        # fsm
        self._fsm = Fysom({
            'initial':
            'down',
            'events': [
                {
                    'name': 'connect',
                    'src': 'down',
                    'dst': 'trying'
                },
                {
                    'name': 'command_up',
                    'src': 'trying',
                    'dst': 'up'
                },
                {
                    'name': 'disconnect',
                    'src': 'trying',
                    'dst': 'down'
                },
                {
                    'name': 'command_trying',
                    'src': 'up',
                    'dst': 'trying'
                },
                {
                    'name': 'disconnect',
                    'src': 'up',
                    'dst': 'down'
                },
            ],
        })

        self._fsm.ondown = self._on_fsm_down
        self._fsm.onafterconnect = self._on_fsm_connect
        self._fsm.ontrying = self._on_fsm_trying
        self._fsm.onaftercommand_up = self._on_fsm_command_up
        self._fsm.onafterdisconnect = self._on_fsm_disconnect
        self._fsm.onup = self._on_fsm_up
        self._fsm.onaftercommand_trying = self._on_fsm_command_trying
        self._fsm.onleaveup = self._on_fsm_up_exit

    def _on_fsm_down(self, _):
        if self.debuglevel > 0:
            print('[%s]: state DOWN' % self.debugname)
        for cb in self.on_state_changed:
            cb('down')
        return True

    def _on_fsm_connect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event CONNECT' % self.debugname)
        self.start_command_channel()
        return True

    def _on_fsm_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: state TRYING' % self.debugname)
        for cb in self.on_state_changed:
            cb('trying')
        return True

    def _on_fsm_command_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: event COMMAND UP' % self.debugname)
        return True

    def _on_fsm_disconnect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event DISCONNECT' % self.debugname)
        self.stop_command_channel()
        self.clear_connected()
        return True

    def _on_fsm_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP entry' % self.debugname)
        self.set_connected()
        if self.debuglevel > 0:
            print('[%s]: state UP' % self.debugname)
        for cb in self.on_state_changed:
            cb('up')
        return True

    def _on_fsm_command_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: event COMMAND TRYING' % self.debugname)
        return True

    def _on_fsm_up_exit(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP exit' % self.debugname)
        self.clear_connected()
        return True

    @property
    def error_string(self):
        return self._error_string

    @error_string.setter
    def error_string(self, string):
        if self._error_string is string:
            return
        self._error_string = string
        for cb in self.on_error_string_changed:
            cb(string)

    @property
    def command_uri(self):
        return self._command_channel.socket_uri

    @command_uri.setter
    def command_uri(self, value):
        self._command_channel.socket_uri = value

    def set_connected(self):
        print('WARNING: slot set connected unimplemented')

    def clear_connected(self):
        print('WARNING: slot clear connected unimplemented')

    def start(self):
        if self._fsm.isstate('down'):
            self._fsm.connect()

    def stop(self):
        if self._fsm.isstate('trying'):
            self._fsm.disconnect()
        elif self._fsm.isstate('up'):
            self._fsm.disconnect()

    def start_command_channel(self):
        self._command_channel.start()

    def stop_command_channel(self):
        self._command_channel.stop()

    # process all messages received on command
    def _command_channel_message_received(self, rx):

        # react to emccmd executed message
        if rx.type == pb.MT_EMCCMD_EXECUTED:
            self.emccmd_executed_received(rx)

        # react to emccmd completed message
        elif rx.type == pb.MT_EMCCMD_COMPLETED:
            self.emccmd_completed_received(rx)

        # react to error message
        elif rx.type == pb.MT_ERROR:
            # update error string with note
            self.error_string = ''
            for note in rx.note:
                self.error_string += note + '\n'

        for cb in self.on_command_message_received:
            cb(rx)

    def emccmd_executed_received(self, rx):
        print('SLOT emccmd executed unimplemented')

    def emccmd_completed_received(self, rx):
        print('SLOT emccmd completed unimplemented')

    def send_command_message(self, msg_type, tx):
        self._command_channel.send_socket_message(msg_type, tx)

    def send_emc_task_abort(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_ABORT, tx)

    def send_emc_task_plan_run(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_RUN, tx)

    def send_emc_task_plan_pause(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_PAUSE, tx)

    def send_emc_task_plan_step(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_STEP, tx)

    def send_emc_task_plan_resume(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_RESUME, tx)

    def send_emc_set_debug(self, tx):
        self.send_command_message(pb.MT_EMC_SET_DEBUG, tx)

    def send_emc_coolant_flood_on(self, tx):
        self.send_command_message(pb.MT_EMC_COOLANT_FLOOD_ON, tx)

    def send_emc_coolant_flood_off(self, tx):
        self.send_command_message(pb.MT_EMC_COOLANT_FLOOD_OFF, tx)

    def send_emc_axis_home(self, tx):
        self.send_command_message(pb.MT_EMC_AXIS_HOME, tx)

    def send_emc_axis_jog(self, tx):
        self.send_command_message(pb.MT_EMC_AXIS_JOG, tx)

    def send_emc_axis_abort(self, tx):
        self.send_command_message(pb.MT_EMC_AXIS_ABORT, tx)

    def send_emc_axis_incr_jog(self, tx):
        self.send_command_message(pb.MT_EMC_AXIS_INCR_JOG, tx)

    def send_emc_tool_load_tool_table(self, tx):
        self.send_command_message(pb.MT_EMC_TOOL_LOAD_TOOL_TABLE, tx)

    def send_emc_tool_update_tool_table(self, tx):
        self.send_command_message(pb.MT_EMC_TOOL_UPDATE_TOOL_TABLE, tx)

    def send_emc_task_plan_execute(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_EXECUTE, tx)

    def send_emc_coolant_mist_on(self, tx):
        self.send_command_message(pb.MT_EMC_COOLANT_MIST_ON, tx)

    def send_emc_coolant_mist_off(self, tx):
        self.send_command_message(pb.MT_EMC_COOLANT_MIST_OFF, tx)

    def send_emc_task_plan_init(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_INIT, tx)

    def send_emc_task_plan_open(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_OPEN, tx)

    def send_emc_task_plan_set_optional_stop(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_SET_OPTIONAL_STOP, tx)

    def send_emc_task_plan_set_block_delete(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_PLAN_SET_BLOCK_DELETE, tx)

    def send_emc_task_set_mode(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_SET_MODE, tx)

    def send_emc_task_set_state(self, tx):
        self.send_command_message(pb.MT_EMC_TASK_SET_STATE, tx)

    def send_emc_traj_set_so_enable(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_SO_ENABLE, tx)

    def send_emc_traj_set_fh_enable(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_FH_ENABLE, tx)

    def send_emc_traj_set_fo_enable(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_FO_ENABLE, tx)

    def send_emc_traj_set_max_velocity(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_MAX_VELOCITY, tx)

    def send_emc_traj_set_mode(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_MODE, tx)

    def send_emc_traj_set_scale(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_SCALE, tx)

    def send_emc_traj_set_rapid_scale(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_RAPID_SCALE, tx)

    def send_emc_traj_set_spindle_scale(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_SPINDLE_SCALE, tx)

    def send_emc_traj_set_teleop_enable(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_TELEOP_ENABLE, tx)

    def send_emc_traj_set_teleop_vector(self, tx):
        self.send_command_message(pb.MT_EMC_TRAJ_SET_TELEOP_VECTOR, tx)

    def send_emc_tool_set_offset(self, tx):
        self.send_command_message(pb.MT_EMC_TOOL_SET_OFFSET, tx)

    def send_emc_axis_override_limits(self, tx):
        self.send_command_message(pb.MT_EMC_AXIS_OVERRIDE_LIMITS, tx)

    def send_emc_spindle_constant(self, tx):
        self.send_command_message(pb.MT_EMC_SPINDLE_CONSTANT, tx)

    def send_emc_spindle_decrease(self, tx):
        self.send_command_message(pb.MT_EMC_SPINDLE_DECREASE, tx)

    def send_emc_spindle_increase(self, tx):
        self.send_command_message(pb.MT_EMC_SPINDLE_INCREASE, tx)

    def send_emc_spindle_off(self, tx):
        self.send_command_message(pb.MT_EMC_SPINDLE_OFF, tx)

    def send_emc_spindle_on(self, tx):
        self.send_command_message(pb.MT_EMC_SPINDLE_ON, tx)

    def send_emc_spindle_brake_engage(self, tx):
        self.send_command_message(pb.MT_EMC_SPINDLE_BRAKE_ENGAGE, tx)

    def send_emc_spindle_brake_release(self, tx):
        self.send_command_message(pb.MT_EMC_SPINDLE_BRAKE_RELEASE, tx)

    def send_emc_motion_set_aout(self, tx):
        self.send_command_message(pb.MT_EMC_MOTION_SET_AOUT, tx)

    def send_emc_motion_set_dout(self, tx):
        self.send_command_message(pb.MT_EMC_MOTION_SET_DOUT, tx)

    def send_emc_motion_adaptive(self, tx):
        self.send_command_message(pb.MT_EMC_MOTION_ADAPTIVE, tx)

    def send_emc_axis_set_max_position_limit(self, tx):
        self.send_command_message(pb.MT_EMC_AXIS_SET_MAX_POSITION_LIMIT, tx)

    def send_emc_axis_set_min_position_limit(self, tx):
        self.send_command_message(pb.MT_EMC_AXIS_SET_MIN_POSITION_LIMIT, tx)

    def send_emc_axis_unhome(self, tx):
        self.send_command_message(pb.MT_EMC_AXIS_UNHOME, tx)

    def send_shutdown(self, tx):
        self.send_command_message(pb.MT_SHUTDOWN, tx)

    def _command_channel_state_changed(self, state):

        if state == 'trying':
            if self._fsm.isstate('up'):
                self._fsm.command_trying()

        elif state == 'up':
            if self._fsm.isstate('trying'):
                self._fsm.command_up()
예제 #7
0
class LogBase(object):
    def __init__(self, debuglevel=0, debugname='Log Base'):
        self.debuglevel = debuglevel
        self.debugname = debugname
        self._error_string = ''
        self.on_error_string_changed = []

        # Log
        self._log_channel = SimpleSubscribe(debuglevel=debuglevel)
        self._log_channel.debugname = '%s - %s' % (self.debugname, 'log')
        self._log_channel.on_state_changed.append(
            self._log_channel_state_changed)
        self._log_channel.on_socket_message_received.append(
            self._log_channel_message_received)
        # more efficient to reuse protobuf messages
        self._log_rx = Container()

        # callbacks
        self.on_log_message_received = []
        self.on_state_changed = []

        # fsm
        self._fsm = Fysom({
            'initial':
            'down',
            'events': [
                {
                    'name': 'connect',
                    'src': 'down',
                    'dst': 'trying'
                },
                {
                    'name': 'log_up',
                    'src': 'trying',
                    'dst': 'up'
                },
                {
                    'name': 'disconnect',
                    'src': 'trying',
                    'dst': 'down'
                },
                {
                    'name': 'disconnect',
                    'src': 'up',
                    'dst': 'down'
                },
            ],
        })

        self._fsm.ondown = self._on_fsm_down
        self._fsm.onafterconnect = self._on_fsm_connect
        self._fsm.ontrying = self._on_fsm_trying
        self._fsm.onafterlog_up = self._on_fsm_log_up
        self._fsm.onafterdisconnect = self._on_fsm_disconnect
        self._fsm.onup = self._on_fsm_up
        self._fsm.onleaveup = self._on_fsm_up_exit

    def _on_fsm_down(self, _):
        if self.debuglevel > 0:
            print('[%s]: state DOWN' % self.debugname)
        for cb in self.on_state_changed:
            cb('down')
        return True

    def _on_fsm_connect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event CONNECT' % self.debugname)
        self.update_topics()
        self.start_log_channel()
        return True

    def _on_fsm_trying(self, _):
        if self.debuglevel > 0:
            print('[%s]: state TRYING' % self.debugname)
        for cb in self.on_state_changed:
            cb('trying')
        return True

    def _on_fsm_log_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: event LOG UP' % self.debugname)
        return True

    def _on_fsm_disconnect(self, _):
        if self.debuglevel > 0:
            print('[%s]: event DISCONNECT' % self.debugname)
        self.stop_log_channel()
        return True

    def _on_fsm_up(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP entry' % self.debugname)
        self.set_connected()
        if self.debuglevel > 0:
            print('[%s]: state UP' % self.debugname)
        for cb in self.on_state_changed:
            cb('up')
        return True

    def _on_fsm_up_exit(self, _):
        if self.debuglevel > 0:
            print('[%s]: state UP exit' % self.debugname)
        self.clear_connected()
        return True

    @property
    def error_string(self):
        return self._error_string

    @error_string.setter
    def error_string(self, string):
        if self._error_string is string:
            return
        self._error_string = string
        for cb in self.on_error_string_changed:
            cb(string)

    @property
    def log_uri(self):
        return self._log_channel.socket_uri

    @log_uri.setter
    def log_uri(self, value):
        self._log_channel.socket_uri = value

    def update_topics(self):
        print('WARNING: slot update topics unimplemented')

    def set_connected(self):
        print('WARNING: slot set connected unimplemented')

    def clear_connected(self):
        print('WARNING: slot clear connected unimplemented')

    def start(self):
        if self._fsm.isstate('down'):
            self._fsm.connect()

    def stop(self):
        if self._fsm.isstate('trying'):
            self._fsm.disconnect()
        elif self._fsm.isstate('up'):
            self._fsm.disconnect()

    def add_log_topic(self, name):
        self._log_channel.add_socket_topic(name)

    def remove_log_topic(self, name):
        self._log_channel.remove_socket_topic(name)

    def clear_log_topics(self):
        self._log_channel.clear_socket_topics()

    def start_log_channel(self):
        self._log_channel.start()

    def stop_log_channel(self):
        self._log_channel.stop()

    # process all messages received on log
    def _log_channel_message_received(self, identity, rx):

        # react to log message message
        if rx.type == pb.MT_LOG_MESSAGE:
            self.log_message_received(identity, rx)

        for cb in self.on_log_message_received:
            cb(identity, rx)

    def log_message_received(self, identity, rx):
        print('SLOT log message unimplemented')

    def _log_channel_state_changed(self, state):

        if state == 'up':
            if self._fsm.isstate('trying'):
                self._fsm.log_up()
예제 #8
0
class hsmsHandler(EventProducer):
    """Baseclass for creating Host/Equipment models. This layer contains the HSMS functionality. Inherit from this class and override required functions.

    :param address: IP address of remote host
    :type address: string
    :param port: TCP port of remote host
    :type port: integer
    :param active: Is the connection active (*True*) or passive (*False*)
    :type active: boolean
    :param session_id: session / device ID to use for connection
    :type session_id: integer
    :param name: Name of the underlying configuration
    :type name: string
    :param event_handler: object for event handling
    :type event_handler: :class:`secsgem.common.EventHandler`
    :param custom_connection_handler: object for connection handling (ie multi server)
    :type custom_connection_handler: :class:`secsgem.hsmsConnections.HsmsMultiPassiveServer`

    **Example**::

        import secsgem

        def S1F1Handler(connection, packet):
            print "S1F1 received"

        def onConnect(event, data):
            print "Connected"

        client = secsgem.hsmsHandler("10.211.55.33", 5000, True, 0, "test", eventHandler=secsgem.EventHandler(events={'RemoteConnected': onConnect}))
        client.registerCallback(1, 1, S1F1Handler)

        client.enable()

        time.sleep(3)

        client.disable()

    """
    def __init__(self, address, port, active, session_id, name, event_handler=None, custom_connection_handler=None):
        EventProducer.__init__(self, event_handler)

        self.logger = logging.getLogger(self.__module__ + "." + self.__class__.__name__)

        self.address = address
        self.port = port
        self.active = active
        self.sessionID = session_id
        self.name = name

        self.connected = False

        # repeating linktest variables
        self.linktestTimer = None
        self.linktestTimeout = 30

        # event and packet queues
        self.eventQueue = []
        self.packetQueue = []

        # hsms connection state fsm
        self.connectionState = Fysom({
            'initial': 'NOT_CONNECTED',
            'events': [
                {'name': 'connect', 'src': 'NOT_CONNECTED', 'dst': 'CONNECTED'},
                {'name': 'disconnect', 'src': ['CONNECTED', 'NOT_SELECTED', 'SELECTED'], 'dst': 'NOT_CONNECTED'},
                {'name': 'select', 'src': 'NOT_SELECTED', 'dst': 'SELECTED'},
                {'name': 'deselect', 'src': 'SELECTED', 'dst': 'NOT_SELECTED'},
                {'name': 'timeoutT7', 'src': 'NOT_SELECTED', 'dst': 'NOT_CONNECTED'},
            ],
            'callbacks': {
                'onNOT_SELECTED': self._on_state_connect,
                'onNOT_CONNECTED': self._on_state_disconnect,
                'onSELECTED': self._on_state_select,
            },
            'autoforward': [
                {'src': 'CONNECTED', 'dst': 'NOT_SELECTED'}
            ]
        })

        # setup connection
        if self.active:
            if custom_connection_handler is None:
                self.connection = HsmsActiveConnection(self.address, self.port, self.sessionID, self)
            else:
                self.connection = custom_connection_handler.create_connection(self.address, self.port, self.sessionID, self)
        else:
            if custom_connection_handler is None:
                self.connection = HsmsPassiveConnection(self.address, self.port, self.sessionID, self)
            else:
                self.connection = custom_connection_handler.create_connection(self.address, self.port, self.sessionID, self)

    def _on_state_connect(self, data):
        """Connection state model got event connect

        :param data: event attributes
        :type data: object
        """
        # start linktest timer
        self.linktestTimer = threading.Timer(self.linktestTimeout, self._on_linktest_timer)
        self.linktestTimer.start()

        # start select process if connection is active
        if self.active:
            system_id = self.sendSelectReq()
            self.waitforSelectRsp(system_id)

    def _on_state_disconnect(self, data):
        """Connection state model got event disconnect

        :param data: event attributes
        :type data: object
        """
        # stop linktest timer
        if self.linktestTimer:
            self.linktestTimer.cancel()

        self.linktestTimer = None

    def _on_state_select(self, data):
        """Connection state model got event select

        :param data: event attributes
        :type data: object
        """
        # send event
        self.fireEvent('HsmsSelected', {'connection': self})

        # notify hsms handler of selection
        if hasattr(self, '_onHsmsSelect') and callable(getattr(self, '_onHsmsSelect')):
            self._onHsmsSelect()

    def _on_linktest_timer(self):
        """Linktest time timed out, so send linktest request"""
        # send linktest request and wait for response
        system_id = self.sendLinktestReq()
        self.waitforLinktestRsp(system_id)

        # restart the timer
        self.linktestTimer = threading.Timer(self.linktestTimeout, self._on_linktest_timer)
        self.linktestTimer.start()

    def on_connection_established(self):
        """Connection was established"""
        # update connection state
        self.connected = True

        self.connectionState.connect()

        self.fireEvent("HsmsConnected", {'connection': self})

    def on_before_connection_closed(self):
        """Connection is about to be closed"""
        # send separate request
        self.sendSeparateReq()

    def on_connection_closed(self):
        """Connection was closed"""
        # update connection state
        self.connected = False
        self.connectionState.disconnect()

        self.fireEvent("HsmsDisconnected", {'connection': self})

    def _queuePacket(self, packet):
        """Add packet to event queue

        :param packet: received data packet
        :type packet: :class:`secsgem.hsmsPackets.hsmsPacket`
        """
        # add to event queue
        self.packetQueue.append(packet)

        # notify all that new event arrived
        for event in self.eventQueue:
            event.set()

    def on_connection_packet_received(self, packet):
        """Packet received by connection

        :param packet: received data packet
        :type packet: :class:`secsgem.hsmsPackets.hsmsPacket`
        """
        if packet.header.sType > 0:
            self.logger.info("< %s\n  %s", packet, hsmsSTypes[packet.header.sType])

            # check if it is a select request
            if packet.header.sType == 0x01:
                # if we are disconnecting send reject else send response
                if self.connection.disconnecting:
                    self.sendRejectRsp(packet.header.system, packet.header.sType, 4)
                else:
                    self.sendSelectRsp(packet.header.system)

                    # update connection state
                    self.connectionState.select()

            # check if it is a select response
            elif packet.header.sType == 0x02:
                # update connection state
                self.connectionState.select()

                # queue packet to notify waiting threads
                self._queuePacket(packet)

            # check if it is a deselect request
            elif packet.header.sType == 0x03:
                # if we are disconnecting send reject else send response
                if self.connection.disconnecting:
                    self.sendRejectRsp(packet.header.system, packet.header.sType, 4)
                else:
                    self.sendDeselectRsp(packet.header.system)
                    # update connection state
                    self.connectionState.deselect()

            elif packet.header.sType == 0x04:
                # update connection state
                self.connectionState.deselect()

                # queue packet to notify waiting threads
                self._queuePacket(packet)

            # check if it is a linktest request
            elif packet.header.sType == 0x05:
                # if we are disconnecting send reject else send response
                if self.connection.disconnecting:
                    self.sendRejectRsp(packet.header.system, packet.header.sType, 4)
                else:
                    self.sendLinktestRsp(packet.header.system)

            else:
                # queue packet if not handeled
                self._queuePacket(packet)
        else:
            if not self.connectionState.isstate("SELECTED"):
                self.logger.info("< %s", packet)
                self.logger.warning("received message when not selected")
                self.connection.send_packet(hsmsPacket(hsmsRejectReqHeader(packet.header.system, packet.header.sType, 4)))

                return True

            # redirect packet to hsms handler
            if hasattr(self, '_onHsmsPacketReceived') and callable(getattr(self, '_onHsmsPacketReceived')):
                self._onHsmsPacketReceived(packet)
            else:
                self.logger.info("< %s", packet)

    def _serializeData(self):
        """Returns data for serialization

        :returns: data to serialize for this object
        :rtype: dict
        """
        return {'address': self.address, 'port': self.port, 'active': self.active, 'sessionID': self.sessionID, 'name': self.name, 'connected': self.connected}

    def enable(self):
        """Enables the connection"""
        self.connection.enable()

    def disable(self):
        """Disables the connection"""
        self.connection.disable()

    def waitforStreamFunction(self, stream, function, is_control=False):
        """Wait for an incoming stream and function and return the receive data

        :param stream: number of stream to wait for
        :type stream: integer
        :param function: number of function to wait for
        :type function: integer
        :param is_control: is it a control packet
        :type is_control: bool
        :returns: Packet that was received
        :rtype: :class:`secsgem.hsmsPackets.hsmsPacket`
        """
        if is_control:
            # setup timeout to T6
            timeout = time.time() + self.connection.T6
        else:
            # setup timeout to T3
            timeout = time.time() + self.connection.T3

        # setup event for new item in queue
        event = threading.Event()
        self.eventQueue.append(event)

        found_packet = None

        while found_packet is None:
            for packet in self.packetQueue:
                if (packet.header.stream == stream) and (packet.header.function == function):
                    self.packetQueue.remove(packet)
                    found_packet = packet
                    break

            if found_packet is None:
                if event.wait(1):
                    event.clear()
                elif not self.connected or self.connection.disconnecting or time.time() > timeout:
                    return None

        self.eventQueue.remove(event)

        return found_packet

    def sendStreamFunction(self, packet):
        """Send the packet and wait for the response

        :param packet: packet to be sent
        :type packet: :class:`secsgem.secsFunctionBase.secsStreamFunction`
        """
        out_packet = hsmsPacket(hsmsStreamFunctionHeader(self.connection.get_next_system_counter(), packet.stream, packet.function, True, self.sessionID), packet.encode())
        self.connection.send_packet(out_packet)

    def waitforSystem(self, system, is_control=False):
        """Wait for an message with supplied system

        :param system: number of system to wait for
        :type system: integer
        :returns: Packet that was received
        :rtype: :class:`secsgem.hsmsPackets.hsmsPacket`
        """
        if not self.connected:
            self.logger.warning("handler not connected waiting for response for system {0}".format(system))
            return None

        if is_control:
            # setup timeout to T6
            timeout = time.time() + self.connection.T6
        else:
            # setup timeout to T3
            timeout = time.time() + self.connection.T3

        event = threading.Event()
        self.eventQueue.append(event)

        found_packet = None

        while found_packet is None:
            for packet in self.packetQueue:
                if packet.header.system == system:
                    self.packetQueue.remove(packet)
                    found_packet = packet
                    break

            if found_packet is None:
                if event.wait(1):
                    event.clear()
                elif not self.connected or self.connection.disconnecting or time.time() > timeout:
                    self.logger.warning("response for system {0} not received within timeout".format(system))
                    return None

        self.eventQueue.remove(event)

        return found_packet

    def sendAndWaitForResponse(self, packet):
        """Send the packet and wait for the response

        :param packet: packet to be sent
        :type packet: :class:`secsgem.secsFunctionBase.secsStreamFunction`
        :returns: Packet that was received
        :rtype: :class:`secsgem.hsmsPackets.hsmsPacket`
        """
        out_packet = hsmsPacket(hsmsStreamFunctionHeader(self.connection.get_next_system_counter(), packet.stream, packet.function, True, self.sessionID), packet.encode())
        self.connection.send_packet(out_packet)

        return self.waitforSystem(out_packet.header.system, (packet.stream == 0))

    def sendResponse(self, function, system):
        """Send response function for system

        :param function: function to be sent
        :type function: :class:`secsgem.secsFunctionBase.secsStreamFunction`
        :param system: system to reply to
        :type system: integer
        """
        out_packet = hsmsPacket(hsmsStreamFunctionHeader(system, function.stream, function.function, False, self.sessionID), function.encode())
        self.connection.send_packet(out_packet)

    def sendSelectReq(self):
        """Send a Select Request to the remote host

        :returns: System of the sent request
        :rtype: integer
        """
        system_id = self.connection.get_next_system_counter()

        packet = hsmsPacket(hsmsSelectReqHeader(system_id))
        self.connection.send_packet(packet)

        return system_id

    def sendSelectRsp(self, system_id):
        """Send a Select Response to the remote host

        :param system_id: System of the request to reply for
        :type system_id: integer
        """
        packet = hsmsPacket(hsmsSelectRspHeader(system_id))
        self.connection.send_packet(packet)

    def waitforSelectRsp(self, system_id):
        """Wait for an incoming Select Response

        :param system_id: System of the request to reply for
        :type system_id: integer
        :returns: Packet that was received
        :rtype: :class:`secsgem.hsmsPackets.hsmsPacket`
        """
        result = self.waitforSystem(system_id, True)

        return result

    def sendLinktestReq(self):
        """Send a Linktest Request to the remote host

        :returns: System of the sent request
        :rtype: integer
        """
        system_id = self.connection.get_next_system_counter()

        packet = hsmsPacket(hsmsLinktestReqHeader(system_id))
        self.connection.send_packet(packet)

        return system_id

    def sendLinktestRsp(self, system_id):
        """Send a Linktest Response to the remote host

        :param system_id: System of the request to reply for
        :type system_id: integer
        """
        packet = hsmsPacket(hsmsLinktestRspHeader(system_id))
        self.connection.send_packet(packet)

    def waitforLinktestRsp(self, system_id):
        """Wait for an incoming Linktest Response

        :param system_id: System of the request to reply for
        :type system_id: integer
        :returns: Packet that was received
        :rtype: :class:`secsgem.hsmsPackets.hsmsPacket`
        """
        return self.waitforSystem(system_id, True)

    def sendDeselectReq(self):
        """Send a Deselect Request to the remote host

        :returns: System of the sent request
        :rtype: integer
        """
        system_id = self.connection.get_next_system_counter()

        packet = hsmsPacket(hsmsDeselectReqHeader(system_id))
        self.connection.send_packet(packet)

        return system_id

    def sendDeselectRsp(self, system_id):
        """Send a Deselect Response to the remote host

        :param system_id: System of the request to reply for
        :type system_id: integer
        """
        packet = hsmsPacket(hsmsDeselectRspHeader(system_id))
        self.connection.send_packet(packet)

    def waitforDeselectRsp(self, system_id):
        """Wait for an incoming Deselect Response

        :param system_id: System of the request to reply for
        :type system_id: integer
        :returns: Packet that was received
        :rtype: :class:`secsgem.hsmsPackets.hsmsPacket`
        """
        result = self.waitforSystem(system_id, True)

        return result

    def sendRejectRsp(self, system_id, s_type, reason):
        """Send a Reject Response to the remote host

        :param system_id: System of the request to reply for
        :type system_id: integer
        :param s_type: s_type of rejected message
        :type s_type: integer
        :param reason: reason for rejection
        :type reason: integer
        """
        packet = hsmsPacket(hsmsRejectReqHeader(system_id, s_type, reason))
        self.connection.send_packet(packet)

    def sendSeparateReq(self):
        """Send a Separate Request to the remote host"""
        system_id = self.connection.get_next_system_counter()

        packet = hsmsPacket(hsmsSeparateReqHeader(system_id))
        self.connection.send_packet(packet)

        return system_id