Esempio n. 1
0
    def __init__(self, address='127.0.0.1', port=502, baud=19200, timeout_in_sec=1, databank=None):
        """Initialize Base Server and install modbus hooks

        Has two important instance variables:
            _server - an instance of a Modbus RTU or TCP server.
            _slaves - dictionary of ModbusClient slaves keyed by slave ID. (For TCP, this should be 1)

        :param address: Address of the Server (Not used in RTU). Defaults to 127.0.0.1
        :param port: Port of the Server (0 for RTU, defaults to 502 for TCP). For RTU, this MUST be set to 0.
        :param baud: Baudrate (Not used in TCP). Defaults to 19200
        :param timeout_in_sec: Timeout (Not used in RTU). Defaults to 1
        :param databank: (Not used in RTU)
        """

        if port == 0:
            server_serial = serial.Serial(
                address,
                baudrate=baud,
                bytesize=8,
                parity=serial.PARITY_EVEN,
                stopbits=1,
                xonxoff=0)
            self._server = RtuServer(server_serial)
        else:
            self._server = TcpServer(address=address, port=port, timeout_in_sec=timeout_in_sec, databank=databank)
            #  Begin Monkey Patch
            self._server._do_init = types.MethodType(_do_init, self._server)
            self._server._do_exit = types.MethodType(_do_exit, self._server)
            # End Monkey Patch

        self._slaves = dict()

        # Set up basic modbus hooks. These by default just log when they are getting called. To handle requests,
        #  subclasses of Server should overwrite the 'update' method, which is called by 'after'.
        self.install_hook('modbus.Server.before_handle_request', 'before')
        self.install_hook('modbus.Server.after_handle_request', 'after')
        self.install_hook('modbus.Slave.handle_write_multiple_registers_request', 'write_register')
        self.install_hook('modbus.Slave.handle_write_single_register_request', 'write_register')
        self.install_hook('modbus.Slave.handle_read_holding_registers_request', 'read_register')
        self.install_hook('modbus.Slave.handle_write_multiple_coils_request', 'write_coils')
        self.install_hook('modbus.Slave.handle_write_single_coil_request', 'write_coils')
def main():
    args = docopt(__doc__)
    server = TcpServer(port=int(args['--port']))
    slave = server.add_slave(1)

    slave.add_block(0, cst.ANALOG_INPUTS, 0, 100)
    log.info('Add analog inputs data block from register 0 to 99 on slave 1')
    slave.add_block(1, cst.DISCRETE_INPUTS, 0, 100)
    log.info('Add discrete inputs data block from register 0 to 99 on slave 1')
    slave.add_block(2, cst.COILS, 100, 100)
    log.info('Add coils data block from register 100 to 199 on slave 1')
    slave.add_block(3, cst.HOLDING_REGISTERS, 100, 100)
    log.info('Add holding registers block from register 100 to 199 on slave 1')

    server.start()
    log.info('TcpServer started listening at port {0}.'.format(args['--port']))

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        log.info('Received SIGINT. Exiting')
    finally:
        server.stop()
        log.info('TcpServer has stopped.')
Esempio n. 3
0
def main():
    """main"""

    #Connect to the slave
    if 'rtu' in sys.argv:
        server = RtuServer(serial.Serial(port=sys.argv[-1]))
    else:
        server = TcpServer(error_on_missing_slave=True)

    simu = MySimulator(server)

    try:
        LOGGER.info("'quit' for closing the server")
        simu.start()

    except Exception as excpt:
        print(excpt)

    finally:
        simu.close()
Esempio n. 4
0
def modbus_server():
    """ Yield an instance of modbus_tk.TcpServer. """
    modbus_server = TcpServer(port=0)

    slave = modbus_server.add_slave(1)

    slave.add_block(0, ANALOG_INPUTS, 0, 100)
    slave.set_values(0, 0, [1337, 2890])

    slave.add_block(1, DISCRETE_INPUTS, 0, 100)
    slave.set_values(1, 0, [1, 0])

    slave.add_block(2, COILS, 100, 100)
    slave.add_block(3, HOLDING_REGISTERS, 100, 100)

    modbus_server.start()

    yield modbus_server

    modbus_server.stop()
Esempio n. 5
0
    def __init__(self, mode, port, baud=None, hostname=None, verbose=None):
        self.rtu = None
        self.mode = mode
        if self.mode == 'rtu' and baud and port:
            self.rtu = serial.Serial(port=port, baudrate=baud)
            Simulator.__init__(self, ModbusRtuServer(self.rtu))
            # timeout is too fast for 19200 so increase a little bit
            self.server._serial.timeout *= 2
            self.server._serial.interCharTimeout *= 2
            LOGGER.info(
                'Initializing x modbus %s simulator: baud = %d port = %s parity = %s'
                % (self.mode, baud, port, self.rtu.parity))
            LOGGER.info('stop bits = %d xonxoff = %d' %
                        (self.rtu.stopbits, self.rtu.xonxoff))
        elif self.mode == 'tcp' and hostname and port:
            Simulator.__init__(self, TcpServer(address=hostname, port=port))
            LOGGER.info(
                'Initializing modbus %s simulator: addr = %s port = %s' %
                (self.mode, hostname, port))
        else:
            raise ModbusSimError('Unknown mode: %s' % (mode))

        self.server.set_verbose(True)
Esempio n. 6
0
                    
                    #execute a RPC command for changing the value
                    self._simu.set_values(1, "Cpu", i, (cpu_usage, ))
        except Exception, excpt:
            LOGGER.debug("SystemDataCollector error: %s", str(excpt))
        time.sleep(0.1)
        
if __name__ == "__main__":
    #create the object for getting CPU data
    data_collector = SystemDataCollector(5) 
    #create the thread in charge of calling the data collector
    system_monitor = WorkerThread(data_collector.collect)
    
    #create the modbus TCP simulator and one slave 
    #and one block of analog inputs
    simu = Simulator(TcpServer())
    slave = simu.server.add_slave(1)
    slave.add_block("Cpu", ANALOG_INPUTS, 0, 10)
    
    try:
        LOGGER.info("'quit' for closing the server")
        
        #start the data collect
        system_monitor.start()
        
        #start the simulator! will block until quit command is received
        simu.start()
            
    except Exception, excpt:
        print excpt
            
Esempio n. 7
0
class Server (object):
    """Base Modbus Server.

    Basic Modbus Server that implements both RTU and TCP. For setting up an RTU server, make sure 'port' is configured
    to 0.  Basic hooks are set up here, so that when subclassing this class, only minimal functions (namely update)
    need to be overwritten.

    A Server can have multiple slaves, although TCP protocol only allows for one (RTU allows for multiple slaves).
    In this instance, the slave id should be set to 1.

    This class is mostly used for testing to simulate a modbus server that we would see in the field.
    """
    def __init__(self, address='127.0.0.1', port=502, baud=19200, timeout_in_sec=1, databank=None):
        """Initialize Base Server and install modbus hooks

        Has two important instance variables:
            _server - an instance of a Modbus RTU or TCP server.
            _slaves - dictionary of ModbusClient slaves keyed by slave ID. (For TCP, this should be 1)

        :param address: Address of the Server (Not used in RTU). Defaults to 127.0.0.1
        :param port: Port of the Server (0 for RTU, defaults to 502 for TCP). For RTU, this MUST be set to 0.
        :param baud: Baudrate (Not used in TCP). Defaults to 19200
        :param timeout_in_sec: Timeout (Not used in RTU). Defaults to 1
        :param databank: (Not used in RTU)
        """

        if port == 0:
            server_serial = serial.Serial(
                address,
                baudrate=baud,
                bytesize=8,
                parity=serial.PARITY_EVEN,
                stopbits=1,
                xonxoff=0)
            self._server = RtuServer(server_serial)
        else:
            self._server = TcpServer(address=address, port=port, timeout_in_sec=timeout_in_sec, databank=databank)
            #  Begin Monkey Patch
            self._server._do_init = types.MethodType(_do_init, self._server)
            self._server._do_exit = types.MethodType(_do_exit, self._server)
            # End Monkey Patch

        self._slaves = dict()

        # Set up basic modbus hooks. These by default just log when they are getting called. To handle requests,
        #  subclasses of Server should overwrite the 'update' method, which is called by 'after'.
        self.install_hook('modbus.Server.before_handle_request', 'before')
        self.install_hook('modbus.Server.after_handle_request', 'after')
        self.install_hook('modbus.Slave.handle_write_multiple_registers_request', 'write_register')
        self.install_hook('modbus.Slave.handle_write_single_register_request', 'write_register')
        self.install_hook('modbus.Slave.handle_read_holding_registers_request', 'read_register')
        self.install_hook('modbus.Slave.handle_write_multiple_coils_request', 'write_coils')
        self.install_hook('modbus.Slave.handle_write_single_coil_request', 'write_coils')

    def define_slave(self, slave_id, client_class, unsigned=True):
        """Add a Modbus Client Slave.

        :param slave_id: Slave ID. This must be 1 for Modbus TCP.
        :param client_class: Subclass of modbus.Client. This class holds all the register definitions.
        :param unsigned: Boolean indicating whether or not values are signed or unsigned.
        :return: Slave instance.
        """
        self._slaves[slave_id] = client_class
        slave = self._server.add_slave(slave_id, unsigned=unsigned)
        slave.klass = client_class
        if not issubclass(client_class, Client):
            raise TypeError("client_class must be subclass of {0}".format(Client))

        for request in client_class().requests():
            # logger.info("Adding [%s], %s, %s, %s", request.name, request.table, request.address, request.count)
            slave.add_block(request.name, request.table, request.address, request.count)
        return slave

    @classmethod
    def install_hook(cls, hook_name, method):
        """Helper method for installing hooks. This is necessary to ensure child methods are called if implemented."""
        install_hook(hook_name, getattr(cls, method))

    def set_values(self, slave_id, field, values):
        slave = self._server.get_slave(slave_id)
        slave_class = self._slaves[slave_id]
        request = slave_class().get_request(field)
        slave.set_values(request.name, field.address, values)

    ##################
    # Server Methods #
    ##################

    def start(self):
        self._server.start()

    def stop(self):
        self._server.stop()

    def is_alive(self):
        return self._server._thread.isAlive()

    def set_verbose(self, on=True):
        self._server.set_verbose(on)

    ######################
    # Basic Modbus Hooks #
    ######################

    @staticmethod
    def before(args):
        server, request = args
        # logger.debug("Before: {0}-{1}".format(server, request))

    @classmethod
    def after(cls, args):
        server, response = args
        # logger.debug("After: {0}-{1}".format(server, response))
        cls.update(args)

    @staticmethod
    def update(args):
        pass

    @staticmethod
    def write_register(args):
        slave, request_pdu = args
        # logger.debug("Writing: {0}-{1}".format(slave, request_pdu))

    @staticmethod
    def read_register(args):
        slave, request_pdu = args
        # logger.debug("Reading: {0}-{1}".format(slave, request_pdu))

    @staticmethod
    def write_coils(args):
        slave, request_pdu = args