Пример #1
0
def display_remote_io(ip_address):
    '''
    display remote I/O information at the given IP address
    '''
    try:
        client = ModbusTcpClient(ip_address)
        client.write_coil(HW_CY_006, False)

        ip_holding_regs = client.read_holding_registers(HR_CI_006_CV, 6)

        client.write_registers(HW_CI_006_PV, ip_holding_regs.registers)
        cur_ip = format_modbus_ip_address(ip_holding_regs.registers[0],
                                          ip_holding_regs.registers[1])
        cur_gateway = format_modbus_ip_address(ip_holding_regs.registers[2],
                                               ip_holding_regs.registers[3])
        cur_subnet = format_modbus_ip_address(ip_holding_regs.registers[4],
                                              ip_holding_regs.registers[5])

        ip_holding_regs = client.read_holding_registers(HR_CI_009_CV, 4)
        cur_mac = format_mac(ip_holding_regs.registers)
        ip_holding_regs = client.read_holding_registers(HR_KI_003, 2)
        cur_version = format_version(ip_holding_regs.registers[0])

        print("{0} - {1}, version:{2}.{3}.{4} ".format(
            ip_address, device_type_name(ip_holding_regs.registers[1]),
            cur_version[1], cur_version[2], cur_version[3]),
              end='')
        print("gateway:{0}, subnet:{1} mac:{2}".format(cur_gateway, cur_subnet,
                                                       cur_mac))
        client.close()
    except ConnectionException:
        print("{0} - unavailable".format(ip_address))
Пример #2
0
class HeliosTCP(SmartPlugin):

    PLUGIN_VERSION = "1.0.2"
    MODBUS_SLAVE = 180
    PORT = 502
    START_REGISTER = 1

    _items = {}

    def __init__(self, sh):
        from bin.smarthome import VERSION
        if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5':
            self.logger = logging.getLogger(__name__)

        self._helios_ip = self.get_parameter_value('helios_ip')
        self._client = ModbusTcpClient(self._helios_ip)
        self.alive = False
        self._is_connected = False
        self._update_cycle = self.get_parameter_value('update_cycle')

    def run(self):
        """
        Run method for the plugin
        """
        self.logger.debug("Run method called")
        self._is_connected = self._client.connect()
        if not self._is_connected:
            self.logger.error(
                "Helios TCP: Failed to connect to Modbus Server at {0}".format(
                    self._helios_ip))
        self.scheduler_add('Helios TCP',
                           self._update_values,
                           cycle=self._update_cycle)
        self.alive = True

    def stop(self):
        """
        Stop method for the plugin
        """
        self.logger.debug("Stop method called")
        self.scheduler_remove('Helios TCP')
        self._client.close()
        self.alive = False

    def parse_item(self, item):
        if 'helios_tcp' in item.conf:
            varname = item.conf['helios_tcp']
            if varname in VARLIST.keys():
                self._items[varname] = item
                return self.update_item
            else:
                self.logger.warning(
                    "Helios TCP: Ignoring unknown variable '{0}'".format(
                        varname))

    def _update_values(self):
        for item in self._items:
            self._read_value(self._items[item])

    @staticmethod
    def _string_to_registers(instr: str):
        l = bytearray(instr, 'ascii')
        return [k[0] * 256 + k[1] for k in zip(l[::2], l[1::2])] + [0]

    def _read_value(self, item):
        try:
            var = item.conf['helios_tcp']
        except ValueError:
            return

        try:
            varprop = VARLIST[var]
        except KeyError:
            self.logger.error(
                "Helios TCP: Failed to find variable '{0}'".format(var))
            return

        # At first we write the variable name to read into the input registers:
        payload = self._string_to_registers(varprop['var'])
        request = self._client.write_registers(self.START_REGISTER,
                                               payload,
                                               unit=self.MODBUS_SLAVE)
        if request is None:
            self.logger.warning(
                "Helios TCP: Failed to send read request for variable '{0}'".
                format(var))
            return

        # Now we may read the holding registers:
        response = self._client.read_holding_registers(self.START_REGISTER,
                                                       varprop['length'],
                                                       unit=self.MODBUS_SLAVE)
        if response is None:
            self.logger.warning(
                "Helios TCP: Failed to send read response for variable '{0}'".
                format(var))
            return

        # Now we may dedocde the result
        # Note that we immediatly strip the varname from the result.
        result = response.encode().decode('ascii')[8:]
        result = list(result)

        # Remove trailing zeros:
        while result[-1] == '\x00':
            result.pop()

        result = ''.join(result)

        # Finally we may cast the result and return the obtained value:
        try:
            item(varprop["type"](result), self.get_shortname())
        except ValueError:
            self.logger.warning(
                "Helios TCP: Could not assign {0} to item {1}".format(
                    varprop["type"](result), item.id()))
            return

    def update_item(self, item, caller=None, source=None, dest=None):
        """
        Item has been updated

        This method is called, if the value of an item has been updated by SmartHomeNG.
        It should write the changed value out to the device (hardware/interface) that
        is managed by this plugin.

        :param item: item to be updated towards the plugin
        :param caller: if given it represents the callers name
        :param source: if given it represents the source
        :param dest: if given it represents the dest
        """
        if self.alive and caller != self.get_shortname():
            try:
                var = item.conf['helios_tcp']
            except ValueError:
                return

            newval = item()

            try:
                varprop = VARLIST[var]
            except KeyError:
                self.logger.error(
                    "Helios TCP: Failed to find variable '{0}'".format(var))
                return

            if not varprop["write"]:
                return

            if type(newval) != varprop["type"]:
                self.logger.error(
                    "Helios TCP: Type mismatch for variable '{0}'".format(var))
                return

            if newval < varprop["min"] or newval > varprop["max"]:
                self.logger.error(
                    "Helios TCP: Variable '{0}' out of bounds. The allowed range is [{1}, {2}]"
                    .format(var, varprop["min"], varprop["max"]))
                return

            if varprop["type"] == bool:
                payload_string = "{0}={1}".format(varprop["var"], int(newval))
            elif varprop["type"] == int:
                payload_string = "{0}={1}".format(varprop["var"], int(newval))
            elif varprop["type"] == float:
                payload_string = "{0}={1:.1f}".format(varprop["var"], newval)
            else:
                self.logger.error(
                    "Helios TCP: Type {0} of varible '{1}' not known".format(
                        varprop["type"], var))
                return

            payload = self._string_to_registers(payload_string)
            request = self._client.write_registers(self.START_REGISTER,
                                                   payload,
                                                   unit=self.MODBUS_SLAVE)
            if request is None:
                self.logger.warning(
                    "Helios TCP: Failed to send write request for variable '{0}'"
                    .format(var))
                return
Пример #3
0
def main():            
	registersPerPage = 256
	RPMPageNumber = 4
	RPMRegisterOffset = 6
	DCCurrentPageNumber = 4
	DCCurrentStartOffset = 204
	DCCurrentEndOffset = 205
	STOP     =  35700;    # 10001011(H8B,D139) 01110100(H74,116)  # -29836 (35700)
	STOPC    =  29835;    # 01110100(H74,D116) 10001011(H8B,D139) #  29835
	AUTO     =  35701;    # 10001011(H8B,D139) 01110101(H75,D117) # -29835 (35701)
	AUTOC    =  29834;    # 01110100(H74,D116) 10001010(H8A,D138) #  29834
	MANUAL   =  35702;    # 10001011(H8B,D139) 01110110(H76,D118) # -29834 (35702)
	MANUALC  =  29833;    # 01110100(H74,D116) 10001001(H89,D137) #  29833
	AUTOM    =  35704;    # 10001011(H8B,D139) 01111000(H78,D120) # -29832 (35704)
	AUTOMC   =  29831;    # 01110100(H74,D116) 10000111(H87,D135) #  29831
	START    =  35705;    # 10001011(H8B,D139) 01111001(H79,D121) # -29831 (35705)
	STARTC   =  29830;    # 01110100(H74,D116) 10000110(H87,D134) #  29830
	RESETAL  =  35734;    # 10001011(H8B,D139) 10010110(H96,D150) # -35734 (35734)
	#RESETALC =  29801;    # 
	#RESETA2  =  35734;    # 10001011(H8B,D139) 10010110(H96,D150) #  (35734)
	#RESETA2C =  29828;
	#RESETAT  = -29801;    # 10001011(H8B,D139) 10010110(H96,D150) # -35734 (35734)
	#RESETATC =  29800;    
	MODE_STOP          = 0; #Stop mode
	MODE_AUTO          = 1; #Auto mode
	MODE_MANUAL        = 2; #Manual mode
	MODE_TEST          = 3; #Test on load mode
	MODE_AUTO_MRESTORE = 4; #Auto with manual restore mode/Prohibit Return
	MODE_USER_CONFIG   = 5; #User configuration mode
	MODE_TEST_OFF_LOAD = 6; #Test off load mode

	host = sys.argv[1]
	print(host)
	client = ModbusClient(str(host), port=502)
	client.connect()
	time.sleep(0.1)

	rm = client.write_registers(4104, [MANUAL,MANUALC])
	print("Change DSE to MANUAL mode, starting engine in 5 seconds...")

	x = 4
	while x>=1:
		time.sleep(1)
		print(str(x))
		x-=1

	rq = client.write_registers(4104, [START,STARTC])
	time.sleep(3)
	print("Starting engine, proceding to read RPM and DC current")
	time.sleep(1)

	x = 1
	while x==1:
		time.sleep(0.01)
		register = registersPerPage * RPMPageNumber + RPMRegisterOffset
		global RPMRegister
		RPMRegister  = sync_client_read(register)
		register = registersPerPage * DCCurrentPageNumber + DCCurrentEndOffset
		global DCRegister
		DCRegister = sync_client_read(register)
		DCRegister = float(DCRegister)
		x = 0
		os.system('sudo python3 readings.py')

	while 1==1:
		time.sleep(0.01)
		register = registersPerPage * RPMPageNumber + RPMRegisterOffset
		RPMRegister  = sync_client_read(register)
		register = registersPerPage * DCCurrentPageNumber + DCCurrentEndOffset
		DCregister  = sync_client_read(register)
		DCRegister  = float(DCRegister)
Пример #4
0
a = 1
client = ModbusTcpClient('10.181.5.35', port=502)

rq = client.write_coil(1, True)
rr = client.read_coils(1, 1)
assert (rq.function_code < 0x80)  # test that we are not an error
assert (rr.bits[0] == True)  # test the expected value
#result = client.read_coils(0,1)
"""arguments = {
    'read_address':    1,
    'read_count':      8,
    'write_address':   1,
    'write_registers': [20]*8,"""

while a < 4:
    rq = client.write_registers(0, [0] * 15)
    rq2 = client.write_registers(
        1000, [241] * 100)  #Startadresse, skrevet verdi, antall registre
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)
    client.write_coil(0, True)
    client.write_coil(1, True)
    client.write_coil(2, False)
    client.write_coil(3, True)
    #t.sleep(0.5)

    result = client.read_coils(0, 1000)
    result2 = client.read_coils(1000, 1000)
    #rr = client.read_input_registers(1,8)
    print(result.bits[0])
    print(result.bits[1])
Пример #5
0
 
from pymodbus3.client.sync import ModbusTcpClient  
 
        # instead of this

       # 192.168.1.22:502
        #PLC Mod Bus Regs 40001-40100
        
        
 #40096-40100     monnth day hour .....  
#Reg 2 Bytes --> not 4 bytes     
 


plc_client = ModbusTcpClient('192.168.1.22')
# result =client.read_holding_registers(0,5,unit=0X01) 
# print (str(result))
try:
    for x in range(5,6):
        result = plc_client.write_registers( 9,[int(x)  ],unit=0X01) 
        result = plc_client.write_registers(40007,[int(x) ],unit=0X01) 
        result = plc_client.write_registers(40010,[int(1)],unit=0X01) 
 
    print (str(result))
except Exception as e:
    print("error sending data to plc " + str(e))
 

plc_client.close()
Пример #6
0
class COMx(MAQ20Module):
    """
    COM Module:
    Takes care of the communication backend and provides functions that read the COMx register map.
    """
    def __init__(self, ip_address, port):
        if ip_address is not None or port is not None:
            if MODBUS_BACKEND == PYMODBUS3:
                self._client = ModbusTcpClient(ip_address, port=port)
            if MODBUS_BACKEND == UMODBUS:
                self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self._sock.settimeout(2)  # seconds
                self._sock.connect((ip_address, port))
        super(COMx, self).__init__(com=self, registration_number=0)

    def read_register(self, address):
        """
        Low level register access.
        Performs a modbus read register request to the MAQ20
        :param address: requested address
        :return: int - [-32767, 32767]
        """
        return self.read_registers(address, 1)[0]

    def read_registers(self, address, number_of_registers):
        """
        Low level register access.
        Performs a modbus read registers request to the MAQ20
        :param address: starting address.
        :param number_of_registers: number of registers to be read in sequence.
        :return: list(int) [-32767, 32767]
        """
        if MODBUS_BACKEND == PYMODBUS3:
            result = self._client.read_holding_registers(
                address=address, count=number_of_registers)
            # converts the returned values to signed.
            try:
                return [
                    unsigned16_to_signed16(value) for value in result.registers
                ]
            except AttributeError:
                return None
        if MODBUS_BACKEND == UMODBUS:
            message = tcp.read_holding_registers(0, address,
                                                 number_of_registers)
            result = tcp.send_message(message, self._sock)
            return [unsigned16_to_signed16(value) for value in result]

    def write_register(self, address, value):
        """
        Low level register access.
        Performs a modbus write register request to the MAQ20
        :param address: starting address.
        :param value: int [-32767, 32767] or a str of size 1
        :return: modbus response.
        """
        if type(value) is str:
            value = ord(value[0])
        value = signed16_to_unsigned16(value)
        if MODBUS_BACKEND == PYMODBUS3:
            return self._client.write_register(address, value)
        if MODBUS_BACKEND == UMODBUS:
            message = tcp.write_single_register(slave_id=0,
                                                address=address,
                                                value=value)
            return tcp.send_message(message, self._sock)

    def write_registers(self, address, values=None):
        """
        Low level register access.
        Performs a modbus write registers request to the MAQ20
        :param address: starting address.
        :param values: list(int) [-32767, 32767] or a str
        :return: modbus response.
        """
        ints = []
        if type(values) is str:
            for c in values:
                ints.append(ord(c))
        else:
            ints = [signed16_to_unsigned16(x) for x in values]
        if MODBUS_BACKEND == PYMODBUS3:
            return self._client.write_registers(address, ints)
        if MODBUS_BACKEND == UMODBUS:
            message = tcp.write_multiple_registers(slave_id=0,
                                                   starting_address=address,
                                                   values=ints)
            return tcp.send_message(message, self._sock)

    def read_ip_address(self):
        return self._com.read_registers(50, 4)

    def write_ip_address(self, ip_address):
        if type(ip_address) is str:
            first = ip_address.partition('.')
            second = first[2].partition('.')
            third = second[2].partition('.')
            numbers = [first[0], second[0], third[0], third[2]]
            numbers = [int(number) for number in numbers]
            return self.write_registers(50, numbers)
        elif type(ip_address) is list:
            return self.write_registers(50, ip_address)
        return None

    def read_ethernet_subnet_mask(self):
        return self._com.read_registers(55, 4)

    def write_ethernet_subnet_mask(self, mask):
        if type(mask) is str:
            first = mask.partition('.')
            second = first[2].partition('.')
            third = second[2].partition('.')
            numbers = [first[0], second[0], third[0], third[2]]
            numbers = [int(number) for number in numbers]
            return self.write_registers(55, numbers)
        elif type(mask) is list:
            return self.write_registers(55, mask)
        return None

    def read_serial_port_baud(self) -> int:
        return {
            0: 1200,
            1: 2400,
            2: 4800,
            3: 9600,
            4: 19200,
            5: 38400,
            6: 57600,
            7: 115200,
            8: 230400,
            9: 460800,
            10: 921600
        }[self._com.read_register(60)]

    def write_serial_port_baud(self, baud):
        if baud > 10:
            baud = {
                1200: 0,
                2400: 1,
                4800: 2,
                9600: 3,
                19200: 4,
                38400: 5,
                57600: 6,
                115200: 7,
                230400: 8,
                460800: 9,
                921600: 10
            }[baud]
        return self.write_register(60, baud)

    def read_serial_port_parity(self) -> str:
        return {0: 'None', 1: 'Odd', 2: 'Even'}[self._com.read_register(65)]

    def write_serial_port_parity(self, parity):
        if type(parity) is str:
            parity = parity.lower()
            parity = {'none': 0, 'odd': 1, 'even': 2}[parity]
        self.write_register(65, parity)

    def read_rs485_type(self):
        return {0: '4-wire', 1: '2-wire'}[self.read_register(66)]

    def write_rs485_type(self, rs485_type):
        if type(rs485_type) is str:
            if rs485_type[0] == '4':
                rs485_type = 0
            elif rs485_type[1] == '2':
                rs485_type = 1
            else:
                return None
        return self.write_register(66, rs485_type)

    def read_termination(self):
        return {0: False, 1: True}[self.read_register(67)]

    def write_termination(self, termination):
        if type(termination) is str:
            if termination[0] == 'D' or termination[0] == 'd':
                termination = 0
            elif termination[0] == 'E' or termination[0] == 'e':
                termination = 1
            else:
                return None
        if type(termination) is bool:
            termination = {False: 0, True: 1}[termination]
        return self.write_register(67, termination)

    def read_slave_id(self):
        return self.read_register(68)

    def write_slave_id(self, slave_id):
        return self.write_register(68, slave_id)

    def write_save_port_and_server_settings(self):
        """Saves the com port and file server information into the COM's EEPROM memory.
        Note: Changes apply after power cycle."""
        return self.write_register(70, 1)

    def read_file_server_username(self) -> str:
        return response_to_string(self.read_registers(71, 10))

    def write_file_server_username(self, username):
        if type(username) is not str:
            return False
        else:
            return self.write_registers(71, username)

    def read_file_server_password(self):
        return response_to_string(self.read_registers(81, 10))

    def write_file_server_password(self, password):
        if type(password) is not str:
            return False
        else:
            return self.write_registers(81, password)

    def read_file_server_anonymous_login(self):
        return self.read_register(91)

    def write_file_server_anonymous_login(self, input_value):
        return self.write_register(91, input_value)

    #######################
    # Module Configuration.
    #######################

    def read_module_status(self):
        return self.read_registers(100, 24)

    def write_module_status(self, input_value):
        # TODO: Write this function.
        pass

    def read_ethernet_port_present(self):
        return self.read_register(130)

    def read_usb_port_present(self):
        return self.read_register(131)

    def read_rs485_port_present(self):
        return self.read_register(132)

    def read_rs232_port_present(self):
        return self.read_register(133)

    def read_can_port_present(self):
        return self.read_register(134)

    ###############################
    # Registration and Data Logger.
    ###############################

    # TODO: Decide how to handle manual registration.

    def auto_registration(self, enable):
        """
        Enables or disables auto registration.
        :param enable: Boolean
        :return: response from modbus backend.
        """
        result = None
        if enable is True:
            result = self.write_register(1020, 1)  # enable auto registration
        elif enable is False:
            result = self.write_register(1020, 0)  # disable auto registration
            # """This for loop """
            # for i in range(24):
            #     self.write_register(1022, i+1)
        return result

    def delete_registration_numbers(self, numbers):
        if numbers == "all":
            for i in range(24):
                self.write_register(1022, i + 1)
        try:
            for number in numbers:
                self.write_register(1022, number)
        except TypeError:
            self.write_register(1022, number)
        return True

    def register_module(self, serial_number, registration_number):
        pass

    # SD CARD

    def read_log_file_name(self):
        return utils.response_to_string(self.read_registers(1100, 11))

    def write_log_file_name(self, name: str):
        return self.write_registers(1100, name) if len(name) < 12 else False

    def read_log_start_address_1(self):
        """
        Default = 2000 (Start Address of I/O Module in Slot 1.  Data for this module is at Start Address 3000)
        :return: int
        """
        return self.read_register(1120)

    def write_log_start_address_1(self, value):
        """
        Default = 2000 (Start Address of I/O Module in Slot 1.  Data for this module is at Start Address 3000)
        :return: modbus response.
        """
        return self.write_register(1120, value)

    def read_number_of_registers_to_log_1(self):
        """
        Number of Registers to Log starting at Log Start Address 1.  Maximum = 100, Default = 8
        :return: int
        """
        return self.read_register(1121)

    def write_number_of_registers_to_log_1(self, value):
        """
        Number of Registers to Log starting at Log Start Address 1.  Maximum = 100, Default = 8
        :param value: number to write
        :return: modbus response
        """
        return self.write_register(1121, value)

    def read_log_start_address_2(self):
        """
        Default = 4000 (Start Address of I/O Module in Slot 2.  Data for this module is at Start Address 5000)
        :return: int
        """
        return self.read_register(1122)

    def write_log_start_address_2(self, value):
        """
        Default = 4000 (Start Address of I/O Module in Slot 2.  Data for this module is at Start Address 5000)
        :return: modbus response.
        """
        return self.write_register(1122, value)

    def read_number_of_registers_to_log_2(self):
        """
        Number of Registers to Log starting at Log Start Address 2.  Maximum = 100, Default = 8
        :return: int
        """
        return self.read_register(1123)

    def write_number_of_registers_to_log_2(self, value):
        """
        Number of Registers to Log starting at Log Start Address 2.  Maximum = 100, Default = 8
        :param value: number to write
        :return: modbus response
        """
        return self.write_register(1123, value)

    def read_log_start_address_3(self):
        """
        Default = 6000 (Start Address of I/O Module in Slot 3.  Data for this module is at Start Address 7000)
        :return: int
        """
        return self.read_register(1124)

    def write_log_start_address_3(self, value):
        """
        Default = 6000 (Start Address of I/O Module in Slot 3.  Data for this module is at Start Address 7000)
        :return: modbus response.
        """
        return self.write_register(1124, value)

    def read_number_of_registers_to_log_3(self):
        """
        Number of Registers to Log starting at Log Start Address 3.  Maximum = 100, Default = 8
        :return: int
        """
        return self.read_register(1125)

    def write_number_of_registers_to_log_3(self, value):
        """
        Number of Registers to Log starting at Log Start Address 3.  Maximum = 100, Default = 8
        :param value: number to write
        :return: modbus response
        """
        return self.write_register(1125, value)

    def read_log_start_address_4(self):
        """
        Default = 8000 (Start Address of I/O Module in Slot 4.  Data for this module is at Start Address 9000)
        :return: int
        """
        return self.read_register(1126)

    def write_log_start_address_4(self, value):
        """
        Default = 8000 (Start Address of I/O Module in Slot 4.  Data for this module is at Start Address 9000)
        :return: modbus response.
        """
        return self.write_register(1126, value)

    def read_number_of_registers_to_log_4(self):
        """
        Number of Registers to Log starting at Log Start Address 4.  Maximum = 100, Default = 8
        :return: int
        """
        return self.read_register(1127)

    def write_number_of_registers_to_log_4(self, value):
        """
        Number of Registers to Log starting at Log Start Address 4.  Maximum = 100, Default = 8
        :param value: number to write
        :return: modbus response
        """
        return self.write_register(1127, value)

    def read_log_interval(self):
        return utils.int16_to_int32(self.read_registers(1130, 2))

    def write_log_interval(self, value):
        return self.write_registers(1130, utils.int32_to_int16s(value))

    def read_log_number_of_samples(self):
        return utils.int16_to_int32(self.read_registers(1132, 2))

    def write_log_number_of_samples(self, value):
        return self.write_registers(1132, utils.int32_to_int16s(value))

    def read_log_enable(self):
        return self.read_register(1140)

    def write_log_enable(self, enable):
        return self.write_register(1140, enable)

    def read_card_available(self):
        return self.read_register(1150)

    def read_total_space(self):
        return utils.int16_to_int32(self.read_registers(1151, 2))

    def read_free_space(self):
        return utils.int16_to_int32(self.read_registers(1153, 2))

    #############################
    # Module RTC and Temperature.
    #############################

    def read_second(self):
        """0-59"""
        return self.read_register(1200)

    def write_second(self, second):
        """0-59"""
        return self.write_register(1200, second)

    def read_minute(self):
        """0-59"""
        return self.read_register(1201)

    def write_minute(self, minute):
        """0-59"""
        return self.write_register(1201, minute)

    def read_hour(self):
        """0-23"""
        return self.read_register(1202)

    def write_hour(self, hour):
        """0-23"""
        return self.write_register(1202, hour)

    def read_day(self):
        """1-7, 1 = Sunday"""
        return self.read_register(1203)

    def write_day(self, day):
        """1-7, 1 = Sunday"""
        return self.write_register(1203, day)

    def read_date(self):
        """1-31"""
        return self.read_register(1204)

    def write_date(self, date):
        """1-31"""
        return self.write_register(1204, date)

    def read_month(self):
        """1-12"""
        return self.read_register(1205)

    def write_month(self, month):
        """1-12"""
        return self.write_register(1205, month)

    def read_year(self):
        """0-99"""
        return self.read_register(1206)

    def write_year(self, year):
        """0-99"""
        return self.write_register(1206, year)

    def read_internal_temperature_sensor(self):
        """0-59, Degree C"""
        return self.read_register(1210)

    ######################
    # PID Loop Controllers
    ######################
    # TODO: Implement the write functions for PID loop controllers.
    # TODO: Document write functions.

    def read_pid_id(self):
        """
        Unique instance ID of Controller
        :return: 0 to 31
        """
        return self.read_register(1300)

    def write_pid_id(self, input_id):
        """
        Unique instance ID of Controller
        :return: modbus response
        """
        return self.write_register(1300,
                                   input_id) if 0 <= input_id <= 31 else False

    def read_pid_enable(self):
        """
        Enable/Disable Controller
        :return: 0 or 1
        """
        return self.read_register(1301)

    def write_pid_enable(self, enable):
        """
        Enable/Disable Controller
        :return: modbus response
        """
        return self.write_register(1301, enable)

    def read_pid_name(self):
        """
        PID Controller name, 10 characters max.
        :return: string of length 10
        """
        return response_to_string(self.read_registers(1310, 10))

    def write_pid_name(self, name):
        """
        PID Controller name, 10 characters max.
        :return: modbus response
        """
        return self.write_registers(1310, name)

    def read_pid_description(self):
        """
        PID Controller Description, 10 characters max.
        :return: string of length 10
        """
        return response_to_string(self.read_registers(1330, 10))

    def write_pid_description(self, description):
        """
        PID Controller Description, 10 characters max.
        :return: string of length 10
        """
        return self.write_registers(1330, description)

    def read_pid_engineering_units(self):
        """
        Engineering Units (EU) chosen for the Controller, 5 characters max.
        :return: string of length 5
        """
        return response_to_string(self.read_registers(1350, 5))

    def write_pid_engineering_units(self, engineering_units):
        """
        Engineering Units (EU) chosen for the Controller, 5 characters max.
        :return: string of length 5
        """
        return self.write_registers(1350, engineering_units)

    def read_pid_pv_range_unit(self):
        """
        Units chosen for Process Variable.  5 characters max.  Standard unit = "%".
        :return: string of length 5
        """
        return response_to_string(self.read_registers(1355, 5))

    def write_pid_pv_range_unit(self, pv_range_unit):
        """
        Units chosen for Process Variable.  5 characters max.  Standard unit = "%".
        :return: string of length 5
        """
        return self.write_registers(1355, pv_range_unit)

    def read_pid_co_range_unit(self):
        """
        Units chosen for Control Output.  5 characters max.  Standard unit = "%".
        :return: string of length 5
        """
        return response_to_string(self.read_registers(1360, 5))

    def write_pid_co_range_unit(self, co_range_unit):
        """
        Units chosen for Control Output.  5 characters max.  Standard unit = "%".
        :return: string of length 5
        """
        return self.write_registers(1360, co_range_unit)

    def read_pid_pv_modbus_address(self):
        """
        System Address where Process Variable is obtained from.
        :return: 0 to 65,535
        """
        return self.read_register(1366)

    def read_pid_co_modbus_address(self):
        """
        System Address where Control Output is sent to.
        :return: 0 to 65,535
        """
        return self.read_register(1367)

    def read_pid_pv_count_maximum(self):
        """
        Process Variable maximum count value.  MSB at Address 1368, LSB at Address 1369.
        :return: 0 to 2^32-1
        """
        return int16_to_int32(self.read_registers(1368, 2))

    def write_pid_pv_count_maximum(self, pv_count_maximum):
        """
        Process Variable maximum count value.  MSB at Address 1368, LSB at Address 1369.
        :return: 0 to 2^32-1
        """
        return self.write_registers(1368, int32_to_int16s(pv_count_maximum))

    def read_pid_pv_count_minimum(self):
        """
        Process Variable minimum count value.  MSB at Address 1370, LSB at Address 1371.
        :return: 0 to 2^32-1
        """
        return int16_to_int32(self.read_registers(1370, 2))

    def write_pid_pv_count_minimum(self, pv_count_minimum):
        """
        Process Variable minimum count value.  MSB at Address 1370, LSB at Address 1371.
        :return: 0 to 2^32-1
        """
        return self.write_registers(1370, int32_to_int16s(pv_count_minimum))

    def read_pid_co_count_maximum(self):
        """
        Control Output maximum count value.  MSB at Address 1372, LSB at Address 1373.
        :return: 0 to 2^32-1
        """
        return int16_to_int32(self.read_registers(1372, 2))

    def write_pid_co_count_maximum(self, co_count_maximum):
        """
        Control Output maximum count value.  MSB at Address 1372, LSB at Address 1373.
        :return: 0 to 2^32-1
        """
        return self.write_registers(1372, int32_to_int16s(co_count_maximum))

    def read_pid_co_count_minimum(self):
        """
        Control Output minimum count value.  MSB at Address 1374, LSB at Address 1375.
        :return: 0 to 2^32-1
        """
        return int16_to_int32(self.read_registers(1374, 2))

    def write_pid_co_count_minimum(self, co_count_minimum):
        """
        Control Output minimum count value.  MSB at Address 1374, LSB at Address 1375.
        :return: 0 to 2^32-1
        """
        return self.write_registers(1374, int32_to_int16s(co_count_minimum))

    def read_pid_pv_range_maximum(self):
        """
        Process Variable Range maximum value.  Integer part at Address 1376, fractional part at Address 1377.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1376, 2))

    def write_pid_pv_range_maximum(self, pv_range_maximum):
        """
        Process Variable Range maximum value.  Integer part at Address 1376, fractional part at Address 1377.
        :return: float type number
        """
        return self.write_registers(1376, float_to_ints(pv_range_maximum))

    def read_pid_pv_range_minimum(self):
        """
        Process Variable Range minimum value.  Integer part at Address 1378, fractional part at Address 1379.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1378, 2))

    def write_pid_pv_range_minimum(self, pv_range_minimum):
        """
        Process Variable Range minimum value.  Integer part at Address 1378, fractional part at Address 1379.
        :return: float type number
        """
        return self.write_registers(1378, float_to_ints(pv_range_minimum))

    def read_pid_co_range_maximum(self):
        """
        Control Output Range maximum value.  Integer part at Address 1380, fractional part at Address 1381.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1380, 2))

    def write_pid_co_range_maximum(self, co_range_maximum):
        """
        Control Output Range maximum value.  Integer part at Address 1380, fractional part at Address 1381.
        :return: float type number
        """
        return self.write_registers(1380, float_to_ints(co_range_maximum))

    def read_pid_co_range_minimum(self):
        """
        Control Output Range minimum value.  Integer part at Address 1382, fractional part at Address 1383.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1382, 2))

    def write_pid_co_range_minimum(self, co_range_minimum):
        """
        Control Output Range minimum value.  Integer part at Address 1382, fractional part at Address 1383.
        :return: float type number
        """
        return self.write_registers(1382, float_to_ints(co_range_minimum))

    def read_pid_algorithm(self):
        """
        PID Control Algorithm.  0 = Noninteractive, 1 = Parallel
        :return: string
        """
        return {0: "Noninteractive", 1: "Parallel"}[self.read_register(1386)]

    def write_pid_algorithm(self, algorithm):
        """
        PID Control Algorithm.  0 = Noninteractive, 1 = Parallel
        :return: string
        """
        return self.read_register(1386)  # TODO: Finish this.

    def read_pid_control_direction(self):
        """
        Control Direction.  0 = Reverse Acting, 1 = Direct Acting
        :return: string
        """
        return {
            0: "Reverse Acting",
            1: "Direct Acting"
        }[self.read_register(1387)]

    def read_pid_setpoint_action(self):
        """
        Setpoint Action.  0 = Proportional & Derivative on Error, 1 = Proportional on Error / Derivative on PV,
        2 = Proportional & Derivative on PV.
        :return: string
        """
        return {
            0: "Proportional & Derivative on Error",
            1: "Proportional on Error / Derivative on PV",
            2: "Proportional & Derivative on PV",
        }[self.read_register(1388)]

    def write_pid_setpoint_action(self, setpoint_action):
        """
        Setpoint Action.  0 = Proportional & Derivative on Error, 1 = Proportional on Error / Derivative on PV,
        2 = Proportional & Derivative on PV.
        :return: string
        """
        return self.read_register(1388)

    def read_pid_mode(self):
        """
        Operational Mode.  0 = Manual, 1 = Automatic
        :return: string
        """
        return {0: "Manual", 1: "Automatic"}[self.read_register(1389)]

    def read_pid_output_type(self):
        """
        Control Output Signal Type.  0 = Voltage, 1 = Current, 2 = Discrete Output (PWM)
        :return: string
        """
        return {
            0: "Voltage",
            1: "Current",
            2: "Discrete Output (PWM)"
        }[self.read_register(1390)]

    def read_pid_setpoint(self):
        """
        Setpoint.
        Integer part at Address 1396, fractional part at Address 1397.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1396, 2))

    def read_pid_process_variable(self):
        """
        Process Variable.
        Integer part at Address 1398, fractional part at Address 1399.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1398, 2))

    def read_pid_control_output(self):
        """
        Control Output.
        Integer part at Address 1400, fractional part at Address 1401.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1400, 2))

    def read_pid_pv_maximum(self):
        """
        Process Variable maximum value.
        Integer part at Address 1402, fractional part at Address 1403.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1402, 2))

    def read_pid_pv_minimum(self):
        """
        Process Variable minimum value.
        Integer part at Address 1404, fractional part at Address 1405.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1404, 2))

    def read_pid_co_maximum(self):
        """
        Control Output maximum value.
        Integer part at Address 1406, fractional part at Address 1407.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1406, 2))

    def read_pid_co_minimum(self):
        """
        Control Output minimum value.
        Integer part at Address 1408, fractional part at Address 1409.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1408, 2))

    def read_pid_kc(self):
        """
        Controller Gain (%/%).
        Integer part at Address 1410, fractional part at Address 1411.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1410, 2))

    def read_pid_ti(self):
        """
        Integral Time (minutes).
        Integer part at Address 1412, fractional part at Address 1413.  Fractional part is in 10,000ths of a second.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1412, 2))

    def read_pid_td(self):
        """
        Derivative Time (minutes).
        Integer part at Address 1414, fractional part at Address 1415.  Fractional part is in 10,000ths of a second.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1414, 2))

    def read_pid_scan_time(self):
        """
        PID Controller Update Rate (seconds).
        Integer part at Address 1416, fractional part at Address 1417.  This value is fixed at 1s.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1416, 2))

    def read_pid_co_high_clamp(self):
        """
        Controller Output upper limit (%).
        Integer part at Address 1418, fractional part at Address 1419.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1418, 2))

    def read_pid_co_low_clamp(self):
        """
        Controller Output lower limit (%).
        Integer part at Address 1420, fractional part at Address 1421.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1420, 2))

    def read_pid_pv_tracking(self):
        """
        Track Process Variable in Manual Mode. 0 = Do Not Track PV, 1 = Track PV
        :return: string
        """
        return {0: "Do Not Track PV", 1: "Track PV"}[self.read_register(1422)]

    def read_pid_gap_width(self):
        """
        Gap around setpoint (Engineering Units).
        Integer part at Address 1423, fractional part at Address 1424.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1423, 2))

    def read_pid_gap_multiplier(self):
        """
        Gain multiplier inside Gap.
        Integer part at Address 1425, fractional part at Address 1426.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1425, 2))

    def read_pid_filter_time_constant(self):
        """
        PV Filter Time Constant (minutes).
        Integer part at Address 1427, fractional part at Address 1428. Fractional part is in 10,000ths of a second.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1427, 2))

    def read_pid_active_alarm(self):
        """
        Indicates which alarm condition is active. 0 = Low-Low, 1 = Low, 2 = None, 3 = High-High, 4 = High.
        :return: string
        """
        return {
            0: "Low-Low",
            1: "Low",
            2: "None",
            3: "High-High",
            4: "High",
        }[self.read_register(1441)]

    def read_pid_alarm_deadband(self):
        """
        Deadband or Hysteresis.  Adds to low limits, subtracts from high limits.
        Integer part at Address 1442, fractional part at Address 1443.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1442, 2))

    def read_pid_high_high_alarm_limit(self):
        """
        High-High Alarm Limit (Engineering Units). Integer part at Address 1444, fractional part at Address 1445.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1444, 2))

    def read_pid_high_alarm_limit(self):
        """
        High Alarm Limit (Engineering Units). Integer part at Address 1446, fractional part at Address 1447.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1446, 2))

    def read_pid_low_alarm_limit(self):
        """
        Low Alarm Limit (Engineering Units). Integer part at Address 1448, fractional part at Address 1449.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1448, 2))

    def read_pid_low_low_alarm_limit(self):
        """
        Low-Low Alarm Limit (Engineering Units). Integer part at Address 1450, fractional part at Address 1451.
        :return: float type number
        """
        return ints_to_float(self.read_registers(1450, 2))

    ###################
    # Helper Functions.
    ###################

    def ftp_settings(self) -> str:
        # TODO: Document this function.
        result = "Username: "******"\n"
        result += "Password: "******"\n"
        result += "Anonymous Login: "******"Enabled"
        elif anonymous_login == 0:
            result += "Disabled"
        return result

    def __del__(self):
        if MODBUS_BACKEND == PYMODBUS3:
            self._client.close()
        if MODBUS_BACKEND == UMODBUS:
            self._sock.close()
Пример #7
0
from pymodbus3.client.sync import ModbusTcpClient

# instead of this

# 192.168.1.22:502
#PLC Mod Bus Regs 40001-40100

#40096-40100     monnth day hour .....
#Reg 2 Bytes --> not 4 bytes

client = ModbusTcpClient('192.168.1.22')
result = client.read_holding_registers(0, 5, unit=0X01)
print(str(result))
result = client.write_registers(0, [300, 305], unit=0X01)
print(str(result))

client.close()
Пример #8
0
def main():
    registersPerPage = 256
    RPMPageNumber = 4
    RPMRegisterOffset = 6
    DCCurrentPageNumber = 4
    DCCurrentStartOffset = 204
    DCCurrentEndOffset = 205
    STOP = 35700
    # 10001011(H8B,D139) 01110100(H74,116)  # -29836 (35700)
    STOPC = 29835
    # 01110100(H74,D116) 10001011(H8B,D139) #  29835
    AUTO = 35701
    # 10001011(H8B,D139) 01110101(H75,D117) # -29835 (35701)
    AUTOC = 29834
    # 01110100(H74,D116) 10001010(H8A,D138) #  29834
    MANUAL = 35702
    # 10001011(H8B,D139) 01110110(H76,D118) # -29834 (35702)
    MANUALC = 29833
    # 01110100(H74,D116) 10001001(H89,D137) #  29833
    AUTOM = 35704
    # 10001011(H8B,D139) 01111000(H78,D120) # -29832 (35704)
    AUTOMC = 29831
    # 01110100(H74,D116) 10000111(H87,D135) #  29831
    START = 35705
    # 10001011(H8B,D139) 01111001(H79,D121) # -29831 (35705)
    STARTC = 29830
    # 01110100(H74,D116) 10000110(H87,D134) #  29830
    RESETAL = 35734
    # 10001011(H8B,D139) 10010110(H96,D150) # -35734 (35734)
    #RESETALC =  29801;    #
    #RESETA2  =  35734;    # 10001011(H8B,D139) 10010110(H96,D150) #  (35734)
    #RESETA2C =  29828;
    #RESETAT  = -29801;    # 10001011(H8B,D139) 10010110(H96,D150) # -35734 (35734)
    #RESETATC =  29800;
    MODE_STOP = 0
    #Stop mode
    MODE_AUTO = 1
    #Auto mode
    MODE_MANUAL = 2
    #Manual mode
    MODE_TEST = 3
    #Test on load mode
    MODE_AUTO_MRESTORE = 4
    #Auto with manual restore mode/Prohibit Return
    MODE_USER_CONFIG = 5
    #User configuration mode
    MODE_TEST_OFF_LOAD = 6
    #Test off load mode

    host = sys.argv[1]
    print(host)
    client = ModbusClient(str(host), port=502)
    client.connect()
    time.sleep(0.1)

    rm = client.write_registers(4104, [MANUAL, MANUALC])
    print("Change DSE to MANUAL mode, starting engine in 5 seconds...")

    x = 4
    while x >= 1:
        time.sleep(1)
        print(str(x))
        x -= 1

    rq = client.write_registers(4104, [START, STARTC])
    time.sleep(3)
    print("Starting engine, proceding to read RPM and DC current")
    time.sleep(1)

    x = 1
    while x == 1:
        time.sleep(0.01)
        register = registersPerPage * RPMPageNumber + RPMRegisterOffset
        global RPMRegister
        RPMRegister = sync_client_read(register)
        register = registersPerPage * DCCurrentPageNumber + DCCurrentEndOffset
        global DCRegister
        DCRegister = sync_client_read(register)
        DCRegister = float(DCRegister)
        x = 0
        os.system('sudo python3 readings.py')

    while 1 == 1:
        time.sleep(0.01)
        register = registersPerPage * RPMPageNumber + RPMRegisterOffset
        RPMRegister = sync_client_read(register)
        register = registersPerPage * DCCurrentPageNumber + DCCurrentEndOffset
        DCregister = sync_client_read(register)
        DCRegister = float(DCRegister)