class TestClientServer(unittest.TestCase):
    def setUp(self):
        # modbus server
        self.server = ModbusServer(port=5020, no_block=True)
        self.server.start()
        # modbus client
        self.client = ModbusClient(port=5020)
        self.client.open()

    def tearDown(self):
        self.client.close()

    def test_read_and_write(self):
        # word space
        self.assertEqual(self.client.read_holding_registers(0), [0],
                         'Default value is 0 when server start')
        self.assertEqual(self.client.read_input_registers(0), [0],
                         'Default value is 0 when server start')
        # single read/write
        self.assertEqual(self.client.write_single_register(0, 0xffff), True)
        self.assertEqual(self.client.read_input_registers(0), [0xffff])
        # multi-write at max size
        words_l = [randint(0, 0xffff)] * 0x7b
        self.assertEqual(self.client.write_multiple_registers(0, words_l),
                         True)
        self.assertEqual(self.client.read_holding_registers(0, len(words_l)),
                         words_l)
        self.assertEqual(self.client.read_input_registers(0, len(words_l)),
                         words_l)
        # write over sized
        words_l = [randint(0, 0xffff)] * 0x7c
        self.assertEqual(self.client.write_multiple_registers(0, words_l),
                         None)
        # bit space
        self.assertEqual(self.client.read_coils(0), [False],
                         'Default value is False when server start')
        self.assertEqual(self.client.read_discrete_inputs(0), [False],
                         'Default value is False when server start')
        # single read/write
        self.assertEqual(self.client.write_single_coil(0, True), True)
        self.assertEqual(self.client.read_coils(0), [True])
        self.assertEqual(self.client.read_discrete_inputs(0), [True])
        # multi-write at min size
        bits_l = [getrandbits(1)] * 0x1
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), True)
        self.assertEqual(self.client.read_coils(0, len(bits_l)), bits_l)
        self.assertEqual(self.client.read_discrete_inputs(0, len(bits_l)),
                         bits_l)
        # multi-write at max size
        bits_l = [getrandbits(1)] * 0x7b0
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), True)
        self.assertEqual(self.client.read_coils(0, len(bits_l)), bits_l)
        self.assertEqual(self.client.read_discrete_inputs(0, len(bits_l)),
                         bits_l)
        # multi-write over sized
        bits_l = [getrandbits(1)] * 0x7b1
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), None)
Exemplo n.º 2
0
class TestClientServer(unittest.TestCase):

    def setUp(self):
        # modbus server
        self.server = ModbusServer(port=5020, no_block=True)
        self.server.start()
        # modbus client
        self.client = ModbusClient(port=5020)
        self.client.open()

    def tearDown(self):
        self.client.close()

    def test_read_and_write(self):
        # word space
        self.assertEqual(self.client.read_holding_registers(0), [0], 'Default value is 0 when server start')
        self.assertEqual(self.client.read_input_registers(0), [0], 'Default value is 0 when server start')
        # single read/write
        self.assertEqual(self.client.write_single_register(0, 0xffff), True)
        self.assertEqual(self.client.read_input_registers(0), [0xffff])
        # multi-write at max size
        words_l = [randint(0, 0xffff)] * 0x7b
        self.assertEqual(self.client.write_multiple_registers(0, words_l), True)
        self.assertEqual(self.client.read_holding_registers(0, len(words_l)), words_l)
        self.assertEqual(self.client.read_input_registers(0, len(words_l)), words_l)
        # write over sized
        words_l = [randint(0, 0xffff)] * 0x7c
        self.assertEqual(self.client.write_multiple_registers(0, words_l), None)
        # bit space
        self.assertEqual(self.client.read_coils(0), [False], 'Default value is False when server start')
        self.assertEqual(self.client.read_discrete_inputs(0), [False], 'Default value is False when server start')
        # single read/write
        self.assertEqual(self.client.write_single_coil(0, True), True)
        self.assertEqual(self.client.read_coils(0), [True])
        self.assertEqual(self.client.read_discrete_inputs(0), [True])
        # multi-write at min size
        bits_l = [getrandbits(1)] * 0x1
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), True)
        self.assertEqual(self.client.read_coils(0, len(bits_l)), bits_l)
        self.assertEqual(self.client.read_discrete_inputs(0, len(bits_l)), bits_l)
        # multi-write at max size
        bits_l = [getrandbits(1)] * 0x7b0
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), True)
        self.assertEqual(self.client.read_coils(0, len(bits_l)), bits_l)
        self.assertEqual(self.client.read_discrete_inputs(0, len(bits_l)), bits_l)
        # multi-write over sized
        bits_l = [getrandbits(1)] * 0x7b1
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), None)
Exemplo n.º 3
0
 def read_all_tags(self):
     try:
         c = ModbusClient(host="192.168.2.11", port=502, debug=False)
         c.open()
         
         for name, tag in self.tag_db.items():
             mb0 = tag['modbus_start'] -1
             mb1 = tag['modbus_stop'] -1
             size = 1+mb1-mb0
             #print(name, mb0, mb1, size)
             #print(tag)
             if 0 <= mb0 < 100000:
                 val = c.read_coils(mb0)[0]
             elif 100000 <= mb0 < 200000:
                 val = c.read_discrete_inputs(mb0-100000)[0]
             elif 300000 <= mb0 < 400000:
                 val = c.read_input_registers(mb0-300000,  size)
                 if size == 1: val = val[0]
                 elif size == 2:
                     val = utils.word_list_to_long(val, big_endian=False)[0]
             elif 400000 <= mb0 < 500000:
                 val = c.read_holding_registers(mb0-400000,  size )
                 if size == 1: val = val[0]
                 elif size == 2:
                     val = utils.word_list_to_long(val, big_endian=False)[0]
             
             if tag['dtype'] == 'float32':
                 val = utils.decode_ieee(val)
             
             #print(name, val)
             self.settings[name] = val
                 
     except Exception as err:
         print("Error in read_all_tags", err)
         c.close()        
Exemplo n.º 4
0
def read_valid_registers(target_ip, port, reg):
    result = False
    print(f'\n=====Polling remote server for {reg}:=====')
    for i in range(start_reg, end_reg):
        client = ModbusClient(host=target_ip,
                              port=port,
                              auto_open=True,
                              auto_close=True,
                              timeout=10)
        if reg == "hold":
            data = client.read_holding_registers(i, 1)
        if reg == "input":
            data = client.read_input_registers(i, 1)
        if reg == "discrete":
            data = client.read_discrete_inputs(i, 1)
        if reg == "coil":
            data = client.read_coils(i, 1)
        if data:
            result = True
            print(f'\nValid Registers {reg} detected at {i} with value {data}')
        client.close()
        print('/', end='')
        sleep(0.1)


#	return valid_list,data_list,permission_list
    if result != True:
        print(f'\n No Valid Registers detected in specified range')
Exemplo n.º 5
0
def read(ip):

    # Initialize modbus
    c = ModbusClient(host=ip, port=502, auto_open=True, timeout=0.1)

    # Read the outputs (Returns None if timeout)
    return(c.read_coils(16, 6))
Exemplo n.º 6
0
class Pebl:
    def __init__(self, ip, system, port=502):
        self.c = ModbusClient(host=ip, port=502, auto_open=True)
        self.c.host(ip)
        self.c.port(port)
        self.c.open()
        self.system = system
        print("opened")

    def run(self):
        return_values = []
        data_points = csv_json_alarms(self.system)
        for data_point in data_points:
            print(data_point)
            if data_point['type'] == 'COIL':
                value = self.c.read_coils(int(data_point['address']))
                print(value)
                name = data_point['alarm']
                return_values.append({'name': name, 'value': value})

        f = open('data.json', 'w')
        f.write(json.dumps(return_values))
        f.close()

    def run_manual(self):
        return_values = []
        data_points = csv_json_alarms(self.system)
        for data_point in data_points:
            print(data_point)
            if data_point['type'] == 'COIL':
                value = self.c.read_coils(int(data_point['address']))
                name = data_point['alarm']
                if data_point['trigger'] == 'NC':
                    if not value[0]:
                        return_values.append({'name': name, 'value': 'OK'})
                    else:
                        return_values.append({'name': name, 'value': 'ALARM'})
                elif data_point['trigger'] == 'NO':
                    if value[0]:
                        return_values.append({'name': name, 'value': 'ALARM'})
                    else:
                        return_values.append({'name': name, 'value': 'OK'})
        return return_values
Exemplo n.º 7
0
    def connect_nexus_machine(self):
        c = ModbusClient()
        c.host("192.168.0.147")
        c.port(502)
        c.open()
        input_register = c.read_coils(0, 16)
        while True:
            if input_register:

                self.lineEditIP.setText(str(input_register))

            else:
                print("read error")
            time.sleep(5)
Exemplo n.º 8
0
def read_valid_registers(ip_addr,port,reg):
	valid_list=[]
	data_list=[]
	permission_list=[]
	client=ModbusClient(host=ip_addr,port=port,auto_open=True,auto_close=True,timeout=10)
	for i in tqdm(range(1,500)):
		if reg == "hold":
			data=client.read_holding_registers(i,1)
		if reg == "input":
			data=client.read_input_registers(i,1)
		if reg == "discrete":
			data=client.read_discrete_inputs(i,1)
		if reg == "coil":
			data=client.read_coils(i,1)
		if data:
				valid_list.append(i)
				data_list.append(data[0])
				permission_list.append("Read")
	client.close()
	return valid_list,data_list,permission_list
Exemplo n.º 9
0
def monitor_register(target_ip, port, address, delay, reg):
    while True:
        client = ModbusClient(host=target_ip,
                              port=port,
                              auto_open=True,
                              auto_close=True,
                              timeout=1)
        if reg == "Holding":
            data = client.read_holding_registers(address, 1)
        if reg == "Input":
            data = client.read_input_registers(address, 1)
        if reg == "Discrete":
            data = client.read_discrete_inputs(address, 1)
        if reg == "Coil":
            data = client.read_coils(address, 1)
        if data:
            print(f'{reg} register at address {address} has value {data}')
        #print ('.', end='')
        client.close()
        sleep(delay)
Exemplo n.º 10
0
def write_single_coil(target_ip, port, target_reg, value):
    client = ModbusClient(host=target_ip,
                          port=port,
                          auto_open=True,
                          auto_close=True,
                          timeout=10)
    result = client.write_single_coil(int(target_reg),
                                      int(value))  # Writing to coil
    client.close()
    sleep(0.1)
    client = ModbusClient(host=target_ip,
                          port=port,
                          auto_open=True,
                          auto_close=True,
                          timeout=10)
    data = client.read_coils(int(target_reg), 1)  # Reading the coil state
    if result == True:
        print(f'Write to coil {target_reg} successful! \nCurrent value:{data}')
    else:
        print('Write operation failed')
    client.close()
Exemplo n.º 11
0
    def get(self, uid):
        try:
            # Get alert details from database by ip
            try:
                alert_document = self.DB['devices_aggregated'].find_one(
                    {'device._id': ObjectId(uid)})
                if alert_document == None:
                    return ({'found': False})
                alert_document['found'] = True
            except:
                return ({'found': False})

            ip = alert_document['device']['ip']
            c = ModbusClient(host=ip, port=502, auto_open=True, timeout=1)

            try:
                bits = c.read_coils(16, 6)
                alert_document["online"] = True
                alert_document["all_clear"] = bits[0]
                alert_document["emergency"] = bits[1]
                alert_document["lightning"] = bits[2]
                alert_document["a"] = bits[3]
                alert_document["b"] = bits[4]
                alert_document["c"] = bits[5]

            except:
                alert_document["online"] = False
                alert_document["all_clear"] = False
                alert_document["emergency"] = False
                alert_document["lightning"] = False
                alert_document["a"] = False
                alert_document["b"] = False
                alert_document["c"] = False

            return (jsonify(json.loads(dumps(alert_document))))
        except:
            return (Response('{"success": false}',
                             status=500,
                             mimetype='application/json'))
Exemplo n.º 12
0
def pollModbus(
        ip: str
    ) -> list:
    '''
    Get output states via modbus over IP
    '''
    # Setup modbus connection
    try:
        c = ModbusClient(host=ip, port=502, auto_open=True, timeout=1)
    except:
        c = False

    if c:
        # Read Modbus outputs
        bits = c.read_coils(16, 6)
    else:
        bits = False
        
    # If there is a response
    if bits:
        # Set output states
        return([bits[0], bits[1], bits[2], bits[3], bits[4], bits[5]])
    else:
        return([])
Exemplo n.º 13
0
# TCP auto connect on first modbus request
#c = ModbusClient(host="localhost", port=502, auto_open=True)

# TCP auto connect on modbus request, close after it
#c = ModbusClient(host="127.0.0.1", auto_open=True, auto_close=True)

c = ModbusClient()
c.host("192.168.58.10")
c.port(502)
# managing TCP sessions with call to c.open()/c.close()
c.open()

# to debug the communication
#c.debug(True)
inputRegD = c.read_discrete_inputs(0, 16)
coil = c.read_coils(0, 16)
read_holding = c.read_holding_registers(0, 2)
inputReg = c.read_input_registers(0, 2)

while True:
    if inputRegD:
        #print(regs)
        #print(type(regs))
        #print(type(coil))
        x = inputRegD[5]
        print("Read Input: " + str(inputRegD))
        print("Read Coils: " + str(coil))
        print("Holding Register: " + str(read_holding))
        print("Read Input Register: " + str(inputReg))

    else:
Exemplo n.º 14
0
import time

SERVER_HOST = "192.168.181.76"
SERVER_PORT = 502

c = ModbusClient()

# uncomment this line to see debug message
#c.debug(True)

# define modbus server host, port
c.host(SERVER_HOST)
c.port(SERVER_PORT)

while True:
    # open or reconnect TCP to server
    if not c.is_open():
        if not c.open():
            print("unable to connect to "+SERVER_HOST+":"+str(SERVER_PORT))

    # if open() is ok, read coils (modbus function 0x01)
    if c.is_open():
        # read 10 bits at address 0, store result in regs list
        bits = c.read_coils(43, 14)
        # if success display registers
        if bits:
            print("bit ad #43 to 56: "+str(bits))

    # sleep 2s before next polling
    time.sleep(2)
Exemplo n.º 15
0
class AmpSwitch(object):
    def __init__(self, host, port=502, switches=(), debug=False):
        """ """

        self.host = host
        self.port = port
        self.debug = debug
        self.switches = switches

        self.dev = None

        self.connect()

    def __str__(self):
        return "AmpSwitch(host=%s, port=%s, dev=%s>" % (self.host,
                                                        self.port,
                                                        self.dev)
    def setDebug(self, state):
        self.debug = state
        self.connect()
        
    def close(self):
        if self.dev is not None:
            self.dev.close()
            self.dev = None

    def connect(self):
        """ (re-) establish a connection to the device. """

        if self.dev is None:
            self.dev = ModbusClient()
            self.dev.debug(self.debug)
            self.dev.host(self.host)
            self.dev.port(self.port)

        if self.dev.is_open():
            return True

        ret = self.dev.open()
        if not ret:
            raise RuntimeError("failed to connect to %s:%s" % (self.host,
                                                               self.port))

        return True

    def readCoils(self):
        """ Return the state of all our switches. """

        self.connect()

        regs = self.dev.read_coils(0, 16)
        return regs

    def setCoils(self, on=(), off=()):
        """Turn on and off a given set of switches. 

        Argunents
        ---------

        on, off : list-like, or a single integer.

        Notes:
        ------

        The off set is executed first. . There is a command to change
        all switchees at once, but I have not made it work yet.

        """
        self.connect()

        if isinstance(on, int):
            on = on,
        if isinstance(off, int):
            off = off,

        regs0 = self.readCoils()
        regs1 = regs0[:]
        for c in off:
            ret = self.dev.write_single_coil(c, False)
            regs1[c] = False
        for c in on:
            ret = self.dev.write_single_coil(c, True)
            regs1[c] = True
        
        # ret = self.dev.write_multiple_registers(0, regs1)
        ret = self.readCoils()
        return ret

    def chooseCoil(self, n):
        return self.setCoils(on=n, off=list(range(16)))
Exemplo n.º 16
0
def get_points(conn, devices):
    for device in devices:
        try:
            cur = conn.cursor()
            #Get IP Address and port from database
            cur.execute("SELECT ip, port FROM device WHERE devID = ?",
                        (device, ))
            request = cur.fetchone()
            ip = request[0]
            port = request[1]

            client = ModbusClient()
            client.host(ip)
            client.port(port)

            client_connected = True
            if (client.is_open() == False):
                if (client.open() == False):
                    print("Unable to connect to " + ip + ":" + str(port))
                    client_connected = False

            if (client_connected == True):
                cur.execute(
                    "SELECT name, address, type, pointID, mult_factor FROM device_points WHERE devID = ? AND deleted = 0",
                    (device, ))
                rows = cur.fetchall()

                for row in rows:
                    if (row[2] == "dig_in"):
                        req = client.read_discrete_inputs(int(row[1]), 1)

                        datetime_str = datetime.now().strftime(
                            "%Y-%m-%d %H:%M:%S.%f")
                        point_ID = row[3]
                        value = req[0] * row[4]
                        print(datetime_str + " | " + str(point_ID) + " | " +
                              str(value))
                        cur.execute("INSERT INTO point_data VALUES (?, ?, ?)",
                                    (datetime_str, point_ID, value))
                        #print("Value for point " + row[0] + ": " + str(req) + datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))

                    if (row[2] == "dig_out"):
                        req = client.read_coils(int(row[1]), 1)

                        datetime_str = datetime.now().strftime(
                            "%Y-%m-%d %H:%M:%S.%f")
                        point_ID = row[3]
                        value = req[0] * row[4]
                        error_code = 0
                        print(datetime_str + " | " + str(point_ID) + " | " +
                              str(value))
                        cur.execute("INSERT INTO point_data VALUES (?, ?, ?)",
                                    (datetime_str, point_ID, value))
                        #print("Value for point " + row[0] + ": " + str(req) + datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))

                    if (row[2] == "an_in"):
                        req = client.read_input_registers(int(row[1]), 1)

                        datetime_str = datetime.now().strftime(
                            "%Y-%m-%d %H:%M:%S.%f")
                        point_ID = row[3]
                        value = req[0] * row[4]
                        error_code = 0
                        print(datetime_str + " | " + str(point_ID) + " | " +
                              str(value))
                        cur.execute("INSERT INTO point_data VALUES (?, ?, ?)",
                                    (datetime_str, point_ID, value))
                        #print("Value for point " + row[0] + ": " + str(req) + datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))

                    if (row[2] == "an_out"):
                        req = client.read_holding_registers(int(row[1]), 1)

                        datetime_str = datetime.now().strftime(
                            "%Y-%m-%d %H:%M:%S.%f")
                        point_ID = row[3]
                        value = req[0] * row[4]
                        error_code = 0
                        print(datetime_str + " | " + str(point_ID) + " | " +
                              str(value))
                        cur.execute("INSERT INTO point_data VALUES (?, ?, ?)",
                                    (datetime_str, point_ID, value))
                        #print("Value for point " + row[0] + ": " + str(req) + datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))

                print("\n")
                conn.commit()
                cur.close()
                client.close()

        except Error as e:
            print(e)
            conn.close()
            database = "./database/SCADADB.db"
            conn = create_connection(database)
Exemplo n.º 17
0
class ET7000:
    ranges = {
        0x00: {
            'min': -0.015,
            'max': 0.015,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0x01: {
            'min': -0.05,
            'max': 0.05,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0x02: {
            'min': -0.1,
            'max': 0.1,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0x03: {
            'min': -0.5,
            'max': 0.5,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0x04: {
            'min': -1.,
            'max': 1.,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0x05: {
            'min': -2.5,
            'max': 2.5,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0x06: {
            'min': -20.0e-3,
            'max': 20.0e-3,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'A'
        },
        0x07: {
            'units': 'A',
            'min': 4.0e-3,
            'min_code': 0x0000,
            'max_code': 0xffff,
            'max': 20.0e-3
        },
        0x08: {
            'units': 'V',
            'min': -10.,
            'max': 10.,
            'min_code': 0x8000,
            'max_code': 0x7fff,
        },
        0x09: {
            'units': 'V',
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'min': -5.,
            'max': 5.
        },
        0x0A: {
            'units': 'V',
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'min': -1.,
            'max': 1.
        },
        0x0B: {
            'units': 'V',
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'min': -.5,
            'max': .5
        },
        0x0C: {
            'units': 'V',
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'min': -.15,
            'max': .15
        },
        0x0D: {
            'min': -20.0e-3,
            'max': 20.0e-3,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'A'
        },
        0x0E: {
            'units': 'degC',
            'min_code': 0xdca2,
            'max_code': 0x7fff,
            'min': -210.0,
            'max': 760.0
        },
        0x0F: {
            'units': 'degC',
            'min_code': 0xe6d0,
            'max_code': 0x7fff,
            'min': -270.0,
            'max': 1372.0
        },
        0x10: {
            'units': 'degC',
            'min_code': 0xa99a,
            'max_code': 0x7fff,
            'min': -270.0,
            'max': 400.0
        },
        0x11: {
            'units': 'degC',
            'min_code': 0xdd71,
            'max_code': 0x7fff,
            'min': -270.0,
            'max': 1000.0
        },
        0x12: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 1768.0
        },
        0x13: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 1768.0
        },
        0x14: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 1820.0
        },
        0x15: {
            'units': 'degC',
            'min_code': 0xe56b,
            'max_code': 0x7fff,
            'min': -270.0,
            'max': 1300.0
        },
        0x16: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 2320.0
        },
        0x17: {
            'units': 'degC',
            'min_code': 0xe000,
            'max_code': 0x7fff,
            'min': -200.0,
            'max': 800.0
        },
        0x18: {
            'units': 'degC',
            'min_code': 0x8000,
            'max_code': 0x4000,
            'min': -200.0,
            'max': 100.0
        },
        0x19: {
            'units': 'degC',
            'min_code': 0xe38e,
            'max_code': 0xffff,
            'min': -200.0,
            'max': 900.0
        },
        0x1A: {
            'min': 0.0,
            'max': 20.0e-3,
            'min_code': 0x0000,
            'max_code': 0xffff,
            'units': 'A'
        },
        0x20: {
            'units': 'degC',
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'min': -100.0,
            'max': 100.0
        },
        0x21: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 100.0
        },
        0x22: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 200.0
        },
        0x23: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 600.0
        },
        0x24: {
            'units': 'degC',
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'min': -100.0,
            'max': 100.0
        },
        0x25: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 100.0
        },
        0x26: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 200.0
        },
        0x27: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 600.0
        },
        0x28: {
            'units': 'degC',
            'min_code': 0x999a,
            'max_code': 0x7fff,
            'min': -80.0,
            'max': 100.0
        },
        0x29: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 100.0
        },
        0x2A: {
            'units': 'degC',
            'min_code': 0xd556,
            'max_code': 0x7fff,
            'min': -200.0,
            'max': 600.0
        },
        0x2B: {
            'units': 'degC',
            'min_code': 0xeeef,
            'max_code': 0x7fff,
            'min': -20.0,
            'max': 150.0
        },
        0x2C: {
            'units': 'degC',
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 200.0
        },
        0x2D: {
            'units': 'degC',
            'min_code': 0xeeef,
            'max_code': 0x7fff,
            'min': -20.0,
            'max': 150.0
        },
        0x2E: {
            'units': 'degC',
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'min': -200.0,
            'max': 200.0
        },
        0x2F: {
            'units': 'degC',
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'min': -200.0,
            'max': 200.0
        },
        0x80: {
            'units': 'degC',
            'min_code': 0xd556,
            'max_code': 0x7fff,
            'min': -200.0,
            'max': 600.0
        },
        0x81: {
            'units': 'degC',
            'min_code': 0xd556,
            'max_code': 0x7fff,
            'min': -200.0,
            'max': 600.0
        },
        0x82: {
            'units': 'degC',
            'min_code': 0xd556,
            'max_code': 0x7fff,
            'min': -50.0,
            'max': 150.0
        },
        0x83: {
            'min_code': 0xd556,
            'max_code': 0x7fff,
            'units': 'degC',
            'min': -60.0,
            'max': 180.0
        },
        0x30: {
            'min_code': 0x0000,
            'max_code': 0xffff,
            'min': 0.0,
            'max': 20.0e-3,
            'units': 'A'
        },
        0x31: {
            'min_code': 0x0000,
            'max_code': 0xffff,
            'min': 4.0e-3,
            'max': 20.0e-3,
            'units': 'A'
        },
        0x32: {
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'min': 0.0,
            'max': 10.0,
            'units': 'V'
        },
        0x33: {
            'min': -10.0,
            'max': 10.0,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0x34: {
            'min': 0.0,
            'max': 5.0,
            'min_code': 0x0000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0x35: {
            'min': -5.0,
            'max': 5.0,
            'min_code': 0x8000,
            'max_code': 0x7fff,
            'units': 'V'
        },
        0xff: {
            'min': 0,
            'max': 0xffff,
            'min_code': 0x0000,
            'max_code': 0xffff,
            'units': '?'
        }
    }
    devices = {0x7015: {}, 0x7016: {}, 0x7018: {}, 0x7060: {}, 0x7026: {}}

    @staticmethod
    def range(r):
        if r in ET7000.ranges:
            return (ET7000.ranges[r])
        return ET7000.ranges[0xff]

    # default conversion from quanta to real units
    @staticmethod
    def convert(b, amin, amax):
        b = float(b)
        # обрабатывается 2 случая - минимум нулевой или больше 0
        if amin >= 0 and amax > 0:
            return amin + (amax - amin) * b / 0xffff
        # и минимум  и максимум разного знака
        if amin < 0 and amax > 0:
            range = max(-amin, amax)
            if b <= 0x7fff:
                return range * b / 0x7fff
            else:
                return range * (0x8000 - b) / 0x8000
        # в других случаях ошибка
        return float('nan')

    @staticmethod
    def ai_convert_function(r):
        v_min = 0
        v_max = 0xffff
        c_min = 0
        c_max = 0xffff
        try:
            v_min = ET7000.ranges[r]['min']
            v_max = ET7000.ranges[r]['max']
            c_min = ET7000.ranges[r]['min_code']
            c_max = ET7000.ranges[r]['max_code']
        except:
            pass
        if c_min < c_max:
            k = (v_max - v_min) / (c_max - c_min)
            b = v_min - k * c_min
            return lambda x: k * x + b
        k_max = v_max / c_max
        k_min = v_min / (0x10000 - c_min)
        #return lambda x: (x < 0x8000) * k_max * x + (x >= 0x8000) *  k_min * (0x10000 - x)
        return lambda x: k_max * x if x < 0x8000 else k_min * (0x10000 - x)

    @staticmethod
    def ao_convert_function(r):
        v_min = 0
        v_max = 0xffff
        c_min = 0
        c_max = 0xffff
        try:
            v_min = ET7000.ranges[r]['min']
            v_max = ET7000.ranges[r]['max']
            c_min = ET7000.ranges[r]['min_code']
            c_max = ET7000.ranges[r]['max_code']
        except:
            pass
        #print(hex(r), v_min, v_max, c_min, c_max)
        if c_min < c_max:
            k = (c_max - c_min) / (v_max - v_min)
            b = c_min - k * v_min
            return lambda x: int(k * x + b)
        k_max = c_max / v_max
        k_min = (0xffff - c_min) / v_min
        #return lambda x: int((x >= 0) * k_max * x + (x < 0) * (0xffff - k_min * x))
        return lambda x: int(k_max * x) if (x >= 0) else int(0xffff - k_min * x
                                                             )

    @staticmethod
    def convert_to_raw(v, amin, amax):
        v = float(v)
        # обрабатывается 2 случая - минимум нулевой или больше 0
        if amin >= 0 and amax > 0:
            return int((v - amin) / (amax - amin) * 0xffff)
        # и минимум  и максимум разного знака
        if amin < 0 and amax > 0:
            if v >= 0.0:
                return int(v * 0x7fff / amax)
            else:
                return int(0x8000 - v / amax * 0x7fff)
        # в других случаях ошибка
        return 0

    def __init__(self, host, port=502, timeout=0.15, logger=None):
        self.host = host
        self.port = port
        # logger confid
        if logger is None:
            logger = logging.getLogger(__name__)
        self.logger = logger
        # default device type
        self._name = 0
        self.type = '0000'
        # default ai
        self.AI_n = 0
        self.AI_masks = []
        self.AI_ranges = []
        self.AI_min = []
        self.AI_max = []
        self.AI_units = []
        self.AI_raw = []
        self.AI_values = []
        # default ao
        self.AO_n = 0
        self.AO_masks = []
        self.AO_ranges = []
        self.AO_min = []
        self.AO_max = []
        self.AO_units = []
        self.AO_raw = []
        self.AO_values = []
        self.AO_write_raw = []
        self.AO_write_values = []
        self.AO_write_result = False
        # default di
        self.DI_n = 0
        self.DI_values = []
        # default do
        self.DO_n = 0
        self.DO_values = []
        # modbus client
        self._client = ModbusClient(host,
                                    port,
                                    auto_open=True,
                                    auto_close=True,
                                    timeout=timeout)
        status = self._client.open()
        if not status:
            self.logger.error('ET7000 device at %s is offline' % host)
            return
        # read module name
        self._name = self.read_module_name()
        self.type = hex(self._name).replace('0x', '')
        if self._name not in ET7000.devices:
            self.logger.warning(
                'ET7000 device type %s probably not supported' %
                hex(self._name))
        # ai
        self.AI_n = self.read_AI_n()
        self.AI_masks = [False] * self.AI_n
        self.AI_ranges = [0xff] * self.AI_n
        self.AI_raw = [0] * self.AI_n
        self.AI_values = [float('nan')] * self.AI_n
        self.AI_units = [''] * self.AI_n
        self.read_AI_masks()
        self.read_AI_ranges()
        self.AI_convert = [lambda x: x] * self.AI_n
        for n in range(self.AI_n):
            r = self.AI_ranges[n]
            self.AI_units[n] = ET7000.ranges[r]['units']
            self.AI_convert[n] = ET7000.ai_convert_function(r)
        # ao
        self.AO_n = self.read_AO_n()
        self.AO_masks = [True] * self.AO_n
        self.read_AO_masks()
        self.AO_ranges = [0xff] * self.AO_n
        self.AO_raw = [0] * self.AO_n
        self.AO_values = [float('nan')] * self.AO_n
        self.AO_write_values = [float('nan')] * self.AO_n
        self.AO_units = [''] * self.AO_n
        self.AO_write = [0] * self.AO_n
        self.AO_write_raw = [0] * self.AO_n
        self.read_AO_ranges()
        self.AO_convert = [lambda x: x] * self.AI_n
        self.AO_convert_write = [lambda x: 0] * self.AI_n
        for n in range(self.AO_n):
            r = self.AO_ranges[n]
            self.AO_units[n] = ET7000.ranges[r]['units']
            self.AO_convert[n] = ET7000.ai_convert_function(
                r)  # !!! ai_convert for reading
            self.AO_convert_write[n] = ET7000.ao_convert_function(
                r)  # !!! ao_convert for writing
        # di
        self.DI_n = self.read_DI_n()
        self.DI_values = [False] * self.DI_n
        # do
        self.DO_n = self.read_DO_n()
        self.DO_values = [False] * self.DO_n
        self.DO_write = [False] * self.DO_n

    def read_module_name(self):
        regs = self._client.read_holding_registers(559, 1)
        if regs and regs[0] != 0:
            return regs[0]
        regs = self._client.read_holding_registers(260, 1)
        if regs:
            return regs[0]
        return 0

    # AI functions
    def read_AI_n(self):
        regs = self._client.read_input_registers(320, 1)
        if regs and regs[0] != 0:
            return regs[0]
        regs = self._client.read_input_registers(120, 1)
        if regs:
            return regs[0]
        return 0

    def read_AI_masks(self):
        coils = self._client.read_coils(595, self.AI_n)
        if coils and len(coils) == self.AI_n:
            self.AI_masks = coils
        return coils

    def read_AI_ranges(self):
        regs = self._client.read_holding_registers(427, self.AI_n)
        if regs and len(regs) == self.AI_n:
            self.AI_ranges = regs
        return regs

    def read_AI_raw(self, channel=None):
        if channel is None:
            n = self.AI_n
            channel = 0
        else:
            n = 1
        regs = self._client.read_input_registers(0 + channel, n)
        if regs and len(regs) == n:
            self.AI_raw[channel:channel + n] = regs
        if n == 1:
            return regs[0]
        return regs

    def convert_AI(self):
        for k in range(self.AI_n):
            if self.AI_masks[k]:
                self.AI_values[k] = self.AI_convert[k](self.AI_raw[k])
            else:
                self.AI_values[k] = float('nan')
        return self.AI_values

    def read_AI(self, channel=None):
        if channel is None:
            self.read_AI_raw()
            self.convert_AI()
            return self.AI_values
        return self.read_AI_channel(channel)

    def read_AI_channel(self, k: int):
        v = float('nan')
        if self.AI_masks[k]:
            regs = self._client.read_input_registers(0 + k, 1)
            if regs:
                self.AI_raw[k] = regs[0]
                v = self.AI_convert[k](regs[0])
        self.AI_values[k] = v
        return v

    # AO functions
    def read_AO_n(self):
        regs = self._client.read_input_registers(330, 1)
        if regs and regs[0] != 0:
            return regs[0]
        regs = self._client.read_input_registers(130, 1)
        if regs:
            return regs[0]
        return 0

    def read_AO_masks(self):
        return self.AO_masks

    def read_AO_ranges(self):
        regs = self._client.read_holding_registers(459, self.AO_n)
        if regs and len(regs) == self.AO_n:
            self.AO_ranges = regs
        return regs

    def read_AO_raw(self, channel=None):
        if channel is None:
            n = self.AO_n
            channel = 0
        else:
            n = 1
        regs = self._client.read_holding_registers(0 + channel, n)
        if regs and len(regs) == n:
            self.AO_raw[channel:channel + n] = regs
        if n == 1:
            return regs[0]
        return regs

    def write_AO_raw(self, regs):
        result = self._client.write_multiple_registers(0, regs)
        self.AO_write_result = result
        if len(regs) == self.AO_n:
            self.AO_write_raw = regs
        return result

    def convert_AO(self):
        raw = self.AO_raw
        for k in range(self.AO_n):
            self.AO_values[k] = self.AO_convert[k](raw[k])
        return self.AO_values

    def convert_to_raw_AO(self, values=None):
        if values is None:
            values = self.AO_write_values
        answer = []
        for k in range(len(values)):
            answer.append(self.AO_convert_write[k](values[k]))
        return answer

    def read_AO(self):
        self.AO_raw = self.read_AO_raw()
        self.convert_AO()
        return self.AO_values

    def read_AO_channel(self, k: int):
        v = float('nan')
        if self.AO_masks[k]:
            regs = self._client.read_holding_registers(0 + k, 1)
            if regs:
                v = self.AO_convert[k](regs[0])
                self.AO_values[k] = v
        return v

    def write_AO(self, values):
        self.AO_write_values = values
        regs = ET7000.convert_to_raw_AO(values)
        result = self.write_AO_raw(regs)
        return result

    def write_AO_channel(self, k: int, value):
        raw = self.AO_convert_write[k](value)
        result = self._client.write_single_register(0 + k, raw)
        self.AO_write_result = result
        if result:
            self.AO_write_values[k] = value
            self.AO_write_raw[k] = raw
            pass
        return result

    # DI functions
    def read_DI_n(self):
        regs = self._client.read_input_registers(300, 1)
        if regs and regs[0] != 0:
            return regs[0]
        regs = self._client.read_input_registers(100, 1)
        if regs:
            return regs[0]
        return 0

    def read_DI(self):
        regs = self._client.read_discrete_inputs(0, self.DI_n)
        if regs:
            self.DI_values = regs
        return self.DI_values

    def read_DI_channel(self, k: int):
        reg = self._client.read_discrete_inputs(0 + k, 1)
        if reg:
            self.DI_values[k] = reg[0]
            return reg[0]
        return None

    # DO functions
    def read_DO_n(self):
        self.DO_time = time.time()
        regs = self._client.read_input_registers(310, 1)
        if regs and regs[0] != 0:
            return regs[0]
        regs = self._client.read_input_registers(110, 1)
        if regs:
            return regs[0]
        return 0

    def read_DO(self):
        regs = self._client.read_coils(0, self.DI_n)
        if regs:
            self.DI_values = regs
        return self.DI_values

    def read_DO_channel(self, k: int):
        reg = self._client.read_coils(0 + k, 1)
        if reg:
            self.DO_values[k] = reg[0]
            return reg[0]
        return None

    def write_DO(self, values):
        self.DO_write = values
        self.DO_write_result = self._client.write_multiple_coils(0, values)
        return self.DO_write_result

    def write_DO_channel(self, k: int, value: bool):
        result = self._client.write_single_coil(0 + k, value)
        self.DO_write_result = result
        if result:
            self.DO_write[k] = value
        return result
Exemplo n.º 18
0
from pyModbusTCP.client import ModbusClient
import time

try:
    c = ModbusClient(host="localhost", port=502)

except ValueError:
    print("Error with host or port parameters")

while (1):
    if not c.is_open():
        if not c.open():
            print("unable to connect to ")
    if c.is_open():
        hreg = c.read_holding_registers(0, 10)
        creg = c.read_coils(0, 5)

    if hreg:
        print("Holding registers 0 to 9:" + str(hreg))

    if creg:
        print("Coil registers 0 to 4:" + str(creg))
        time.sleep(1)

# uncomment this line to see debug message
# c.debug(True)

# while True:
# # open or reconnect TCP to server
# if not c.is_open():
# if not c.open():
Exemplo n.º 19
0
SERVER_HOST = "localhost"
SERVER_PORT = 502

c = ModbusClient()

# uncomment this line to see debug message
#c.debug(True)

# define modbus server host, port
c.host(SERVER_HOST)
c.port(SERVER_PORT)

while True:
    # open or reconnect TCP to server
    if not c.is_open():
        if not c.open():
            print("unable to connect to " + SERVER_HOST + ":" +
                  str(SERVER_PORT))

    # if open() is ok, read coils (modbus function 0x01)
    if c.is_open():
        # read 10 bits at address 0, store result in regs list
        bits = c.read_coils(0, 10)
        # if success display registers
        if bits:
            print("bit ad #0 to 9: " + str(bits))

    # sleep 2s before next polling
    time.sleep(2)
Exemplo n.º 20
0
                  str(SERVER_PORT))

    # if open() is ok, read coils (modbus function 0x01)
    if c.is_open():
        if is_ok == False:
            is_ok = c.write_single_coil(ADDRESS_WR, toggle)

            if is_ok:
                print("bit #" + str(ADDRESS_WR) + ": write to " + str(toggle))

            else:
                print("bit #" + str(ADDRESS_WR) + ": unable to write " +
                      str(toggle))
            time.sleep(0.5)
        # read 10 bits at address 0, store result in regs list
        bits = c.read_coils(ADDRESS_START, LENGHT)

        # if success display registers
        if bits:
            print(is_ok)
            print("bit from M{} to M{} : ".format(
                ADDRESS_START - 2000, ADDRESS_START + LENGHT - 2001) +
                  str(bits))
            if bits[0] == False:
                is_ok = False
            bit_no = ADDRESS_START
            for i in bits:

                print('Bit M{} - {}'.format(bit_no - 2000, i))
                bit_no += 1
Exemplo n.º 21
0
    # if open() is ok, write coils (modbus function 0x01)
    if c.is_open():
        # write 4 bits in modbus address 0 to 3
        print("")
        print("write bits")
        print("----------")
        print("")
        for addr in range(4):
            is_ok = c.write_single_coil(addr, toggle)
            if is_ok:
                print("bit #" + str(addr) + ": write to " + str(toggle))
            else:
                print("bit #" + str(addr) + ": unable to write " + str(toggle))
            time.sleep(0.5)

        time.sleep(1)

        print("")
        print("read bits")
        print("---------")
        print("")
        bits = c.read_coils(0, 4)
        if bits:
            print("bits #0 to 3: " + str(bits))
        else:
            print("unable to read")

    toggle = not toggle
    # sleep 2s before next polling
    time.sleep(2)
Exemplo n.º 22
0
class LightController():
    """Class to control lights of a single controller"""

    toggle_time = config.toggle_time

    def __init__(self, host):
        self.client = ModbusClient(host=host, auto_open=True, auto_close=False)
        #self.client.debug(True)
        logger.info("Connecting to %s", self.client.host())

        status = self.check_status()
        if status & 1<<15:
            # Watchdog ellapsed, try to reset
            logger.info("Resetting watchdog")
            self.client.write_single_register(0x1121, 0xbecf)
            self.client.write_single_register(0x1121, 0xaffe)

        # Disable the watchdog, if enabled
        watchdog_timeout = self.client.read_holding_registers(0x1120)[0]
        if watchdog_timeout > 0:
            logger.debug("Watchdog timeout: %d", watchdog_timeout)
            logger.info("Disabling watchdog")
            self.client.write_single_register(0x1120, 0)

        (self.num_outputs, self.num_inputs) = self.client.read_holding_registers(0x1012, 2)
        logger.info("Number of outputs: %d", self.num_outputs)
        logger.info("Number of inputs: %d", self.num_inputs)
        self.client.close()
        # We use auto close for all subsequent calls after initialization
        self.client.auto_close(True)

    def check_status(self):
        """Read buscoupler status from the module"""
        buscoupler_status = self.client.read_holding_registers(0x100c)[0]
        if buscoupler_status & 1<<0:
            logger.error("Bus terminal error")
        if buscoupler_status & 1<<1:
            logger.error("Bus coupler configuration error")
        if buscoupler_status & 1<<15:
            logger.error("Fieldbus error, watchdog timer elapsed")
        return buscoupler_status

    def inputs(self):
        """Read input status from module"""
        inputs = self.client.read_discrete_inputs(0, self.num_inputs)
        logger.debug("Inputs: %s", "".join(map(lambda c: '1' if c else '0', inputs)))
        return inputs

    def outputs(self):
        """Read output status from module"""
        coils = self.client.read_coils(0, self.num_outputs)
        logger.debug("Outputs: %s", "".join(map(lambda c: '1' if c else '0', coils)))
        return coils

    def toggle(self, bit_addr):
        """Toggle a impulse relay connected to a single output"""
        logger.info("Toggling %d on %s", bit_addr, self.client.host())
        self.client.auto_close(False)
        self.client.write_single_coil(bit_addr, True)
        logger.debug("On %d", bit_addr)
        time.sleep(self.toggle_time)
        self.client.write_single_coil(bit_addr, False)
        logger.debug("Off %d", bit_addr)
        self.client.close()
        self.client.auto_close(True)
Exemplo n.º 23
0
    # if open() is ok, write coils (modbus function 0x01)
    if c.is_open():
        # write 4 bits in modbus address 0 to 3
        print("")
        print("write bits")
        print("----------")
        print("")
        for addr in range(8192, 8198):
            is_ok = c.write_single_coil(addr, toggle)
            if is_ok:
                print("bit #" + str(addr) + ": write to " + str(toggle))
            else:
                print("bit #" + str(addr) + ": unable to write " + str(toggle))
            time.sleep(0.5)

        time.sleep(1)

        print("")
        print("read bits")
        print("---------")
        print("")
        bits = c.read_coils(8192, 6)
        if bits:
            print("bits #8193 to 8196: " + str(bits))
        else:
            print("unable to read")

    toggle = not toggle
    # sleep 2s before next polling
    time.sleep(2)
Exemplo n.º 24
0
class ClienteMODBUS():
    """
    Classe Cliente MODBUS
    """
    def __init__(self,
                 server_ip,
                 porta,
                 device_id=1,
                 scan_time=0.1,
                 valor=0,
                 dbpath="C:\database.db"):
        """
        Construtor
        """
        self._scan_time = scan_time
        self._server_ip = server_ip
        self._device_id = device_id
        self._port = porta
        self._cliente = ModbusClient(host=server_ip,
                                     port=porta,
                                     unit_id=device_id)

        self._dbpath = dbpath
        self._valor = valor
        self._con = sqlite3.connect(self._dbpath)
        self._cursor = self._con.cursor()

    def atendimento(self):
        """
        Método para atendimento do usuário
        """
        try:
            self._cliente.open()
            print('\n\033[33m --> Cliente Modbus conectado..\033[m\n')

        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

        try:
            atendimento = True
            while atendimento:
                print('-' * 100)
                print('\033[34mCliente Modbus\033[m'.center(100))
                print('-' * 100)
                sel = input(
                    "Qual serviço? \n1- Leitura \n2- Escrita \n3- Configuração \n4- Sair \nNº Serviço: "
                )
                if sel == '1':
                    self.createTable()
                    self.createTableF01()
                    self.createTableF02()
                    self.createTableF03()
                    self.createTableF04()
                    print('\nQual tipo de dado deseja ler?')
                    print(
                        "1- Coil Status \n2- Input Status \n3- Holding Register \n4- Input Register"
                    )
                    while True:
                        tipo = int(input("Type: "))
                        if tipo > 4:
                            print('\033[31mDigite um tipo válido..\033[m')
                            sleep(0.5)
                        else:
                            break

                    if tipo == 3 or tipo == 4:
                        while True:
                            val = int(
                                input(
                                    "\n1- Decimal \n2- Floating Point \n3- Float Swapped \nLeitura: "
                                ))
                            if val > 3:
                                print('\033[31mDigite um tipo válido..\033[m')
                                sleep(0.5)
                            else:
                                break
                        if val == 1:  #valores decimais
                            addr = int(input(f'\nAddress: '))
                            leng = int(input(f'Length: '))
                            nvezes = input('Quantidade de leituras: ')
                            print('\nComeçando leitura Decimal..\n')
                            sleep(0.5)
                            try:
                                for i in range(0, int(nvezes)):
                                    print(f'\033[33mLeitura {i+1}:\033[m',
                                          end='')
                                    print(
                                        self.lerDado(int(tipo), int(addr),
                                                     leng))
                                    sleep(self._scan_time)
                                print(
                                    '\nValores lidos e inseridos no DB com sucesso!!\n'
                                )
                                sleep(0.5)
                            except Exception as e:
                                print('\033[31mERRO: ', e.args, '\033[m')
                                try:
                                    sleep(0.5)
                                    print(
                                        '\033[33m\nTentando novamente..\033[m')
                                    if not self._cliente.is_open():
                                        self._cliente.open()
                                    sleep(0.5)
                                    for i in range(0, int(nvezes)):
                                        print(
                                            f'\033[33mLeitura {i + 1}:\033[m',
                                            end='')
                                        print(
                                            self.lerDado(
                                                int(tipo), int(addr), leng))
                                        sleep(self._scan_time)
                                    print(
                                        '\nValores lidos e inseridos no DB com sucesso!!\n'
                                    )
                                    sleep(0.5)
                                except Exception as e:
                                    print('\033[31mERRO: ', e.args, '\033[m')
                                    print(
                                        '\nO Cliente não conseguiu receber uma resposta.. \nVoltando ao menu..\n\n'
                                    )
                                    sleep(1.5)

                        elif val == 2:  #valores FLOAT
                            addr = input(f'\nAddress: ')
                            leng = int(input(f'Length: '))
                            nvezes = input('Quantidade de leituras: ')
                            print('\nComeçando leitura FLOAT..\n')
                            sleep(0.5)
                            try:
                                for i in range(0, int(nvezes)):
                                    print(f'\033[33mLeitura {i + 1}:\033[m',
                                          end='')
                                    print(
                                        self.lerDadoFloat(
                                            int(tipo), int(addr), leng))
                                    sleep(self._scan_time)
                                print(
                                    '\nValores lidos e inseridos no DB com sucesso!!\n'
                                )
                                sleep(0.5)
                            except Exception as e:
                                print('\033[31mERRO: ', e.args, '\033[m\n')
                                print(
                                    'O Cliente não conseguiu receber uma resposta.. \nVoltando ao menu..\n\n'
                                )
                                sleep(1.5)

                        elif val == 3:  #valores FLOAT SWAPPED
                            addr = input(f'\nAddress: ')
                            leng = int(input(f'Length: '))
                            nvezes = input('Quantidade de leituras: ')
                            print('\nComeçando leitura FLOAT SWAPPED..\n')
                            sleep(0.5)
                            try:
                                for i in range(0, int(nvezes)):
                                    print(f'\033[33mLeitura {i + 1}:\033[m',
                                          end='')
                                    print(
                                        self.lerDadoFloatSwapped(
                                            int(tipo), int(addr), leng))
                                    sleep(self._scan_time)
                                print(
                                    '\nValores lidos e inseridos no DB com sucesso!!\n'
                                )
                                sleep(0.5)
                            except Exception as e:
                                print('\033[31mERRO: ', e.args, '\033[m\n')
                                print(
                                    'O Cliente não conseguiu receber uma resposta.. \nVoltando ao menu..\n\n'
                                )
                                sleep(1.5)

                        else:
                            print('\033[31mSeleção inválida..\033[m\n')
                            sleep(0.7)

                    else:
                        addr = input(f'\nAddress: ')
                        leng = int(input(f'Length: '))
                        nvezes = input('Quantidade de leituras: ')
                        print('\nComeçando leitura..\n')
                        sleep(0.5)
                        try:
                            for i in range(0, int(nvezes)):
                                print(f'\033[33mLeitura {i + 1}:\033[m',
                                      end='')
                                print(self.lerDado(int(tipo), int(addr), leng))
                                sleep(self._scan_time)
                            print(
                                '\nValores lidos e inseridos no DB com sucesso!!\n'
                            )
                            sleep(0.5)
                        except Exception as e:
                            print('\033[31mERRO: ', e.args, '\033[m\n')
                            print(
                                'O Cliente não conseguiu receber uma resposta.. \nVoltando ao menu..\n\n'
                            )
                            sleep(1.5)

                elif sel == '2':
                    print(
                        '\nQual tipo de dado deseja escrever? \n1- Coil Status \n2- Holding Register'
                    )
                    while True:
                        tipo = int(input("Tipo: "))
                        if tipo > 2:
                            print('\033[31mDigite um tipo válido..\033[m')
                            sleep(0.5)
                        else:
                            break
                    addr = input(f'Digite o endereço: ')
                    valor = int(input(f'Digite o valor que deseja escrever: '))
                    try:
                        print('\nEscrevendo..')
                        sleep(0.5)
                        self.escreveDado(int(tipo), int(addr), valor)
                    except Exception as e:
                        print('\033[31mERRO: ', e.args, '\033[m')
                        print(
                            '\nO Cliente não conseguiu escrever.. \nVoltando ao menu..\n\n'
                        )
                        sleep(1.5)

                elif sel == '3':
                    print('')
                    print('-' * 100)
                    print('Configurações de Leitura'.center(100))
                    print(
                        f'\n\033[32m->\033[m Configuração atual: - IP Addrs: \033[35m{self._server_ip}\033[m - TCP Port: \033[35m{self._port}\033[m - Device ID: \033[35m{self._device_id}\033[m - Scan_Time: \033[35m{self._scan_time}\033[ms'
                    )
                    print(
                        '\nQual tipo de configuração deseja fazer? \n1- Endereço IP \n2- Porta TCP \n3- Device ID \n4- ScanTime \n5- Voltar'
                    )
                    config = int(input("Configuração: "))
                    if config == 1:
                        ipserv = str(input(' Novo endereço IP: '))
                        try:
                            self._cliente.close()
                            self._server_ip = ipserv
                            self._cliente = ModbusClient(host=self._server_ip)
                            self._cliente.open()
                            print(
                                f'\nServer IP alterado para {ipserv} com sucesso!!\n'
                            )
                            sleep(0.5)
                        except Exception as e:
                            print('\033[31mERRO: ', e.args, '\033[m')
                            print(
                                '\nNão foi possível alterar o endereço IP.. \nVoltando ao menu..\n\n'
                            )
                            sleep(0.5)
                    elif config == 2:
                        porttcp = input(' Nova porta TCP: ')
                        try:
                            self._cliente.close()
                            self._port = int(porttcp)
                            self._cliente = ModbusClient(port=self._port)
                            self._cliente.open()
                            print(
                                f'\nTCP port alterado para {porttcp} com sucesso!!\n'
                            )
                            sleep(0.5)
                        except Exception as e:
                            print('\033[31mERRO: ', e.args, '\033[m')
                            print(
                                '\nNão foi possível alterar a porta.. \nVoltando ao menu..\n\n'
                            )
                            sleep(0.5)
                    elif config == 3:
                        while True:
                            iddevice = input(' Novo device ID: ')
                            if 0 <= int(iddevice) < 256:
                                break
                            else:
                                print(
                                    '\033[31mDevice ID deve ser um número inteiro entre 0 e 256.\033[m',
                                    end='')
                                sleep(0.5)
                        try:
                            self._cliente.close()
                            self._device_id = int(iddevice)
                            self._cliente = ModbusClient(
                                unit_id=self._device_id)
                            self._cliente.open()
                            print(
                                f'\nDevice ID alterado para {iddevice} com sucesso!!\n'
                            )
                            sleep(0.5)
                        except Exception as e:
                            print('\033[31mERRO: ', e.args, '\033[m')
                            print(
                                '\nNão foi possível alterar o ID do device.. \nVoltando ao menu..\n\n'
                            )
                            sleep(0.5)
                    elif config == 4:
                        scant = input(' Novo tempo de varredura [s]: ')
                        try:
                            self._scan_time = float(scant)
                            print(
                                f'\nScan_time alterado para {scant}s com sucesso!!\n'
                            )
                        except Exception as e:
                            print('\033[31mERRO: ', e.args, '\033[m')
                            print(
                                '\nNão foi possível alterar o tempo de varredura.. \nVoltando ao menu..\n\n'
                            )
                            sleep(0.5)
                    elif config == 5:
                        print('\nVoltando ao menu inicial..\n')
                        sleep(0.5)
                    else:
                        print('\033[31mSeleção inválida..\033[m\n')
                        sleep(0.7)

                elif sel == '4':
                    sleep(0.2)
                    print('\n\033[32mFechando sistema..\033[m')
                    sleep(0.5)
                    self._cliente.close()
                    atendimento = False

                else:
                    print('\033[31mSeleção inválida..\033[m\n')
                    sleep(0.7)
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def createTable(self):
        """
        Método que cria a tabela para armazenamento dos dados, caso ela não exista
        """
        try:
            sql_str = f"""
            CREATE TABLE IF NOT EXISTS pointValues (
                ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Address TEXT, Type TEXT, Display TEXT, Value REAL, TimeStamp1 TEXT NOT NULL)
                """
            self._cursor.execute(sql_str)
            self._con.commit()
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def inserirDB(self, addrs, tipo, disp, value):
        """
        Método para inserção dos dados no DB
        """
        try:
            date = str(
                datetime.datetime.fromtimestamp(int(
                    time.time())).strftime("%Y-%m-%d %H:%M:%S"))
            str_values = f"'{addrs}', {tipo}, {disp}, {value}, '{date}'"
            sql_str = f'INSERT INTO pointValues (Address, Type, Display, Value, TimeStamp1) VALUES ({str_values})'
            self._cursor.execute(sql_str)
            self._con.commit()
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def createTableF01(self):
        """
        Método que cria a tabela para armazenamento dos dados, caso ela não exista
        """
        try:
            sql_str = f"""
            CREATE TABLE IF NOT EXISTS pointValuesF01 (
                ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Address TEXT, Type TEXT, Display TEXT, Value REAL, TimeStamp1 TEXT NOT NULL)
                """
            self._cursor.execute(sql_str)
            self._con.commit()
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def createTableF02(self):
        """
        Método que cria a tabela para armazenamento dos dados, caso ela não exista
        """
        try:
            sql_str = f"""
            CREATE TABLE IF NOT EXISTS pointValuesF02 (
                ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Address TEXT, Type TEXT, Display TEXT, Value REAL, TimeStamp1 TEXT NOT NULL)
                """
            self._cursor.execute(sql_str)
            self._con.commit()
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def createTableF03(self):
        """
        Método que cria a tabela para armazenamento dos dados, caso ela não exista
        """
        try:
            sql_str = f"""
            CREATE TABLE IF NOT EXISTS pointValuesF03 (
                ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Address TEXT, Type TEXT, Display TEXT, Value REAL, TimeStamp1 TEXT NOT NULL)
                """
            self._cursor.execute(sql_str)
            self._con.commit()
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def createTableF04(self):
        """
        Método que cria a tabela para armazenamento dos dados, caso ela não exista
        """
        try:
            sql_str = f"""
            CREATE TABLE IF NOT EXISTS pointValuesF04 (
                ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Address TEXT, Type TEXT, Display TEXT, Value REAL, TimeStamp1 TEXT NOT NULL)
                """
            self._cursor.execute(sql_str)
            self._con.commit()
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def inserirDBF0(self, addrs, tipo, disp, value):
        """
        Método para inserção dos dados no DB
        """
        try:
            if tipo == "'F01-CoilStatus'":
                date = str(
                    datetime.datetime.fromtimestamp(int(
                        time.time())).strftime("%Y-%m-%d %H:%M:%S"))
                str_values = f"'{addrs}', {tipo}, {disp}, {value}, '{date}'"
                sql_str = f'INSERT INTO pointValuesF01 (Address, Type, Display, Value, TimeStamp1) VALUES ({str_values})'
                self._cursor.execute(sql_str)
                self._con.commit()
            elif tipo == "'F02-InputStatus'":
                date = str(
                    datetime.datetime.fromtimestamp(int(
                        time.time())).strftime("%Y-%m-%d %H:%M:%S"))
                str_values = f"'{addrs}', {tipo}, {disp}, {value}, '{date}'"
                sql_str = f'INSERT INTO pointValuesF02 (Address, Type, Display, Value, TimeStamp1) VALUES ({str_values})'
                self._cursor.execute(sql_str)
                self._con.commit()
            elif tipo == "'F03-HoldingRegister'":
                date = str(
                    datetime.datetime.fromtimestamp(int(
                        time.time())).strftime("%Y-%m-%d %H:%M:%S"))
                str_values = f"'{addrs}', {tipo}, {disp}, {value}, '{date}'"
                sql_str = f'INSERT INTO pointValuesF03 (Address, Type, Display, Value, TimeStamp1) VALUES ({str_values})'
                self._cursor.execute(sql_str)
                self._con.commit()
            elif tipo == "'F04-InputRegister'":
                date = str(
                    datetime.datetime.fromtimestamp(int(
                        time.time())).strftime("%Y-%m-%d %H:%M:%S"))
                str_values = f"'{addrs}', {tipo}, {disp}, {value}, '{date}'"
                sql_str = f'INSERT INTO pointValuesF04 (Address, Type, Display, Value, TimeStamp1) VALUES ({str_values})'
                self._cursor.execute(sql_str)
                self._con.commit()
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def inserirDBFP(self, addrs, tipo, disp, value):
        """
        Método para inserção dos dados no DB
        """
        try:
            if tipo == "'F03-HoldingRegister'":
                date = str(
                    datetime.datetime.fromtimestamp(int(
                        time.time())).strftime("%Y-%m-%d %H:%M:%S"))
                str_values = f"'{addrs}', {tipo}, {disp}, {value}, '{date}'"
                sql_str = f'INSERT INTO pointValuesF03 (Address, Type, Display, Value, TimeStamp1) VALUES ({str_values})'
                self._cursor.execute(sql_str)
                self._con.commit()
            elif tipo == "'F04-InputRegister'":
                date = str(
                    datetime.datetime.fromtimestamp(int(
                        time.time())).strftime("%Y-%m-%d %H:%M:%S"))
                str_values = f"'{addrs}', {tipo}, {disp}, {value}, '{date}'"
                sql_str = f'INSERT INTO pointValuesF04 (Address, Type, Display, Value, TimeStamp1) VALUES ({str_values})'
                self._cursor.execute(sql_str)
                self._con.commit()
            else:
                print(
                    "Erro ao inserir no DB com Floating Point e Float Swapped!!"
                )
        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')

    def lerDado(self, tipo, addr, leng=1):
        """
        Método para leitura MODBUS
        """
        if tipo == 1:
            co = self._cliente.read_coils(addr - 1, leng)
            ic = 0
            while ic <= leng:
                if ic == leng:
                    break
                else:
                    value = co[0 + ic]
                    ic += 1
                    # print(value)
                    if value == True:
                        value = 1
                    else:
                        value = 0
                    ende = str(addr + ic - 1).zfill(5)
                    self.inserirDB(addrs=str(ende),
                                   tipo="'F01-CoilStatus'",
                                   disp="'Booleano'",
                                   value=value)
                    self.inserirDBF0(addrs=str(ende),
                                     tipo="'F01-CoilStatus'",
                                     disp="'Booleano'",
                                     value=value)
            return co

        elif tipo == 2:
            di = self._cliente.read_discrete_inputs(addr - 1, leng)
            idi = 0
            while idi <= leng:
                if idi == leng:
                    break
                else:
                    value = di[0 + idi]
                    idi += 1
                    # print(value)
                    self.inserirDB(addrs=(10000 + addr + idi - 1),
                                   tipo="'F02-InputStatus'",
                                   disp="'Booleano'",
                                   value=value)
                    self.inserirDBF0(addrs=(10000 + addr + idi - 1),
                                     tipo="'F02-InputStatus'",
                                     disp="'Booleano'",
                                     value=value)
            return di

        elif tipo == 3:
            hr = self._cliente.read_holding_registers(addr - 1, leng)
            ihr = 0
            while ihr <= leng:
                if ihr == leng:
                    break
                else:
                    value = hr[0 + ihr]
                    ihr += 1
                    # print(value)
                    self.inserirDB(addrs=(40000 + addr + ihr - 1),
                                   tipo="'F03-HoldingRegister'",
                                   disp="'Decimal'",
                                   value=value)
                    self.inserirDBF0(addrs=(40000 + addr + ihr - 1),
                                     tipo="'F03-HoldingRegister'",
                                     disp="'Decimal'",
                                     value=value)
            return hr

        elif tipo == 4:
            ir = self._cliente.read_input_registers(addr - 1, leng)
            iir = 0
            while iir <= leng:
                if iir == leng:
                    break
                else:
                    value = ir[0 + iir]
                    iir += 1
                    # print(value)
                    self.inserirDB(addrs=(30000 + addr + iir - 1),
                                   tipo="'F04-InputRegister'",
                                   disp="'Decimal'",
                                   value=value)
                    self.inserirDBF0(addrs=(30000 + addr + iir - 1),
                                     tipo="'F04-InputRegister'",
                                     disp="'Decimal'",
                                     value=value)
            return ir

        else:
            print('Tipo de leitura inválido..')

    def lerDadoFloat(self, tipo, addr, leng):
        """
        Método para leitura FLOAT MODBUS
        """
        i = 0
        g = 0
        e1 = []
        listfloat = []
        while i < leng:
            if tipo == 3:
                i1 = self._cliente.read_holding_registers(addr - 1 + g, 2)
                tipore = "'F03-HoldingRegister'"
                ende = 40000
            elif tipo == 4:
                i1 = self._cliente.read_input_registers(addr - 1 + g, 2)
                tipore = "'F04-InputRegister'"
                ende = 30000
            else:
                print('Tipo inválido..')
            for x in i1:
                x = bin(x).lstrip("0b")
                e1.insert(0 + g, x)
            i += 1
            g += 2
        e = 0
        while e <= leng:
            e2 = ''
            for x in e1:
                e2 = str(f'{e2}{x.rjust(16, "0")} ')
            e += 1
        b2 = str(f'{e2}')
        e3 = b2.split()
        y = 0
        while y < len(e3):
            ieee = f'{e3[0+y]}{e3[1+y]}'
            sign = int(ieee[0])
            expo = str(ieee[1:9])
            expodec = 0
            expopot = 7
            for i in range(8):
                expodec = expodec + (int(expo[i]) * (2**expopot))
                expopot -= 1
            mant = str(ieee[9:])
            mantdec = 0
            mantpot = -1
            for i in range(23):
                mantdec = mantdec + (int(mant[i]) * (2**mantpot))
                mantpot -= 1
            value = ((-1)**sign) * (1 + mantdec) * 2**(expodec - 127)
            # print(f'{round(value, 3)}')
            listfloat.append(round(value, 3))
            y += 2
            self.inserirDB(addrs=(ende + addr + y - 2),
                           tipo=tipore,
                           disp="'Floating Point'",
                           value=round(value, 3))
            self.inserirDBFP(addrs=(ende + addr + y - 2),
                             tipo=tipore,
                             disp="'Floating Point'",
                             value=round(value, 3))
        return listfloat

    def lerDadoFloatSwapped(self, tipo, addr, leng):
        """
        Método para leitura FLOAT SWAPPED MODBUS
        """
        i = 0
        g = 0
        e1 = []
        listfloatsp = []
        while i < leng:
            if tipo == 3:
                i1 = self._cliente.read_holding_registers(addr - 1 + g, 2)
                tipore = "'F03-HoldingRegister'"
                ende = 40000
            elif tipo == 4:
                i1 = self._cliente.read_input_registers(addr - 1 + g, 2)
                tipore = "'F04-InputRegister'"
                ende = 30000
            else:
                print('Tipo inválido..')
            i2 = i1[::-1]
            for x in i2:
                x = bin(x).lstrip("0b")
                e1.insert(0 + g, x)
            i += 1
            g += 2
        e = 0
        while e <= leng:
            e2 = ''
            for x in e1:
                e2 = str(f'{e2}{x.rjust(16, "0")} ')
            e += 1
        b2 = str(f'{e2}')
        e3 = b2.split()
        y = 0
        while y < len(e3):
            ieee = f'{e3[0+y]}{e3[1+y]}'
            sign = int(ieee[0])
            expo = str(ieee[1:9])
            expodec = 0
            expopot = 7
            for i in range(8):
                expodec = expodec + (int(expo[i]) * (2**expopot))
                expopot -= 1
            mant = str(ieee[9:])
            mantdec = 0
            mantpot = -1
            for i in range(23):
                mantdec = mantdec + (int(mant[i]) * (2**mantpot))
                mantpot -= 1
            value = ((-1)**sign) * (1 + mantdec) * 2**(expodec - 127)
            # print(f'{round(value, 3)}')
            listfloatsp.append(round(value, 3))
            y += 2
            self.inserirDB(addrs=(ende + addr + y - 2),
                           tipo=tipore,
                           disp="'Float (Swapped)'",
                           value=round(value, 3))
            self.inserirDBFP(addrs=(ende + addr + y - 2),
                             tipo=tipore,
                             disp="'Float (Swapped)'",
                             value=round(value, 3))
        return listfloatsp

    def escreveDado(self, tipo, addr, valor):
        """
        Método para escrita MODBUS
        """
        try:
            if tipo == 1:
                print(
                    f'\033[33mValor {valor} escrito no endereço {addr}\033[m\n'
                )
                return self._cliente.write_single_coil(addr - 1, valor)
            elif tipo == 2:
                print(
                    f'\033[33mValor {valor} escrito no endereço {addr}\033[m\n'
                )
                return self._cliente.write_single_register(addr - 1, valor)
            else:
                print('Tipo de escrita inválido..\n')

        except Exception as e:
            print('\033[31mERRO: ', e.args, '\033[m')
Exemplo n.º 25
0
host_client = "192.168.1.220"
c = ModbusClient()
if not c.host(host_client):
    print("host error")
if not c.port(502):
    print("port error")

# Автоматическое соединение TCP по запросу Modbus, закрытие после него\TCP auto connect on modbus request, close after it
c = ModbusClient(host=host_client, auto_open=True, auto_close=True)

while True:
    if c.is_open():
        #    считываем регистры установки\read setup registers
        in_regs_read = c.read_input_registers(0, 51)
        hl_regs_read = c.read_holding_registers(0, 3)
        coil_regs_read = c.read_coils(0, 25)
        dis_in_regs = c.read_discrete_inputs(0, 72)
        #       присвоить переменным значение\assign variables a value
        CL_POWER, CL_TIMER, CL_WEEK, CL_Boost_MODE, CL_FPLC_MODE, CL_IntRH_CTRL, CL_ExtRH_CTRL, CL_IntCO2_CTRL, CL_ExtCO2_CTRL, CL_IntPM2_5_CTRL, CL_ExtPM2_5_CTRL, CL_IntVOC_CTRL, CL_ExtVOC_CTRL, CL_BoostSWITCH_CTRL, CL_FplcSWITCH_CTRL, CL_FireALARM_CTRL, CL_10V_SENSOR_CTRL, CL_RESET_FILTER_TIMER, CL_RESET_ALARM, CL_RESTORE_FACTORY, CL_CLOUD_CTRL, CL_MinSuAirOutTEMP_CTRL, CL_WaterPRESS_CTRL, CL_WaterFLOW_CTRL, CL_WaterHeaterAutoRestart = coil_regs_read
        IR_CurSelTEMP, IR_CurTEMP_SuAirIn, IR_CurTEMP_SuAirOut, IR_CurTEMP_ExAirIn, IR_CurTEMP_ExAirOut, unknown6in, unknown7in, IR_CurTEMP_Ext, IR_CurTEMP_Water, IR_CurVBAT, IR_CurRH_Int, IR_CurRH_Ext, IR_CurCO2_Int, IR_CurCO2_Ext, IR_CurPM2_5_Int, IR_CurPM2_5_Ext, IR_CurVOC_Int, IR_CurVOC_Ext, IR_Cur10V_SENSOR, IR_CurSuAirFLOW, IR_CurExAirFLOW, IR_CurSuPRESS, IR_CurExPRESS, IR_SuRPM, IR_ExRPM, unknown26in, IR_CurTIMER_TIME, unknown28in, IR_CurFILTER_TIMER, unknown30in, IR_TotalWorkingTime, IR_StateFILTER, IR_CurWeekSpeed, IR_CurWeekSetTemp, unknown35in, unknown36in, IR_VerMAIN_FMW, IR_DeviceTYPE, IR_ALARM, IR_RH_U, IR_CO2_U, IR_PM2_5_U, IR_VOC_U, IR_PreHeater_U, IR_MainHeater_U, IR_BPS_ROTOR_U, IR_KKB_U, IR_ReturnWater_U, IR_SuAirOutSetTemp, IR_WaterStandbySetTemp, IR_WaterStartSetTemp = in_regs_read
        DI_CurBoostSWITCH, DI_CurFplcSWITCH, DI_CurFireALARM, DI_StatusRH, DI_StatusCO2, DI_StatusPM2_5, DI_StatusVOC, DI_StatusHEATER, DI_StatusCOOLER, DI_StatusFanBLOWING, DI_CurPreHeaterThermostat, DI_CurMainHeaterThermostat, DI_CurSuFilterPRESS, DI_CurExFilterPRESS, DI_CurWaterPRESS, DI_CurWaterFLOW, DI_CurSuFanPRESS, DI_CurExFanPRESS, DI_WaterPreheatingStatus, DI_AlarmCODE0, DI_AlarmCODE1, DI_AlarmCODE2, DI_AlarmCODE3, DI_AlarmCODE4, DI_AlarmCODE5, DI_AlarmCODE6, DI_AlarmCODE7, DI_AlarmCODE8, DI_AlarmCODE9, DI_AlarmCODE10, DI_AlarmCODE11, DI_AlarmCODE12, DI_AlarmCODE13, DI_AlarmCODE14, DI_AlarmCODE15, DI_AlarmCODE16, DI_AlarmCODE17, DI_AlarmCODE18, DI_AlarmCODE19, DI_AlarmCODE20, DI_AlarmCODE21, DI_AlarmCODE22, DI_AlarmCODE23, DI_AlarmCODE24, DI_AlarmCODE25, DI_AlarmCODE26, DI_AlarmCODE27, DI_AlarmCODE28, DI_AlarmCODE29, DI_AlarmCODE30, DI_AlarmCODE31, DI_AlarmCODE32, DI_AlarmCODE33, DI_AlarmCODE34, DI_AlarmCODE35, DI_AlarmCODE36, DI_AlarmCODE37, DI_AlarmCODE38, DI_AlarmCODE39, DI_AlarmCODE40, DI_AlarmCODE41, DI_AlarmCODE42, DI_AlarmCODE43, DI_AlarmCODE44, DI_AlarmCODE45, DI_AlarmCODE46, DI_AlarmCODE47, DI_AlarmCODE48, DI_AlarmCODE49, DI_AlarmCODE50, DI_AlarmCODE51, DI_AlarmCODE52 = dis_in_regs
        HR_VENTILATION_MODE, HR_MaxSPEED_MODE, HR_SPEED_MODE = hl_regs_read
        print("Время", real_time)
        print("Время", type(real_time))
        #          тест списков :)
        #        print("количество значений списка переменних", len(other))
        print("количество значений списка регистров", type(hl_regs_read))
        print(CL_POWER)
        print(IR_CurSelTEMP)
        print(DI_StatusHEATER)
        print(HR_SPEED_MODE)
Exemplo n.º 26
0
    # if open() is ok, write coils (modbus function 0x01)
    if c.is_open():
        # write 4 bits in modbus address 0 to 3
        print("")
        print("write bits")
        print("----------")
        print("")
        for addr in range(4):
            is_ok = c.write_single_coil(addr, toggle)
            if is_ok:
                print("bit #" + str(addr) + ": write to " + str(toggle))
            else:
                print("bit #" + str(addr) + ": unable to write " + str(toggle))
            time.sleep(0.5)

        time.sleep(1)

        print("")
        print("read bits")
        print("---------")
        print("")
        bits = c.read_coils(0, 4)
        if bits:
            print("bits #0 to 3: "+str(bits))
        else:
            print("unable to read")

    toggle = not toggle
    # sleep 2s before next polling
    time.sleep(2)
Exemplo n.º 27
0
client = ModbusClient("192.168.0.124", 502)
client.open()
print("Connected to Modbus!")

Cap = cv2.VideoCapture(1, cv2.CAP_DSHOW)     # Initialize camera
window = Kuka.init_GUI()                     # Initialize GUI
calibrate_thread = threading.Thread(target=calibration)  # Declare a thread to run the calibration function
calibrate_thread.start()                                 # Start the thread

# Main loop
while True:
    color, x, y, = 0, 0, 0  # Set x, y, and color variables to zero

    # read from modbus
    try:
        yellow = client.read_coils(10)[0]
        green = client.read_coils(11)[0]
        red = client.read_coils(12)[0]
        blue = client.read_coils(13)[0]
    except TypeError:
        print("Modbus Error")
        yellow, green, red, blue = False, False, False, False
        pass

    print(yellow, green, red, blue)
    ret, frame = Cap.read()                         # Read from camera
    blur = cv2.GaussianBlur(frame, (25, 25), 10)    # Blur the image
    hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)     # make a HSV version of the blurred image
    Kuka.show_cal_screen(hsv, frame, thresholds)    # Show the calibration screen

Exemplo n.º 28
0
class modbusTCP_Slave:
    # Working Modes
    RESULT_MODE__RETURN_ALL_VALUES__RAW = 0
    RESULT_MODE__RETURN_ALL_VALUES__FORMATTED = 1
    RESULT_MODE__RETURN_ONLY_NEW_VALUES__RAW = 2
    RESULT_MODE__RETURN_ONLY_NEW_VALUES__FORMATTED = 3

    def __init__(self, _jsonFile, _resultMode=0):

        # JSON object with the information of the Modbus Master device
        self.deviceHost = _jsonFile["host"]
        self.devicePort = _jsonFile["port"]
        self.deviceData = _jsonFile["data"]

        # Result Mode
        self.resultMode = int(_resultMode)

        # For Polling Process
        self.deviceData_LastValues = ""
        self.deviceData_CurrentValues = ""

    # Connect with Modbus Server
    def SetupPollingProcess(self):

        # Initialize deviceData values
        for data_point in self.deviceData:
            data_point["value"] = 0

        try:
            # Create Client
            self.client = ModbusClient()
            self.client.host(self.deviceHost)
            self.client.port(self.devicePort)
            self.client.unit_id(1)
        except ValueError as e:
            # Problems accessing Modbus Server
            return -1

        # Initialize copies of data
        self.deviceData_LastValues = copy.deepcopy(self.deviceData)
        self.deviceData_CurrentValues = copy.deepcopy(self.deviceData)

        # Setup process OK
        return 0

    # Poll data from Modbus Master device
    def PollDataFromDevice(self):

        # Open or reconnect TCP to server
        if not self.client.is_open():
            if not self.client.open():
                return -1

        if self.client.is_open():
            # Go through data and act correspondingly
            for data_point in self.deviceData_CurrentValues:
                addr = data_point["address"]
                if data_point["type"] == "coil":
                    read_data = self.client.read_coils(addr, 1)
                    if read_data != None:
                        data_point["value"] = read_data

                elif data_point["type"] == "register":
                    read_data = self.client.read_holding_registers(addr, 1)
                    if read_data != None:
                        data_point["value"] = read_data

            ### Process Data and return it depending on Working Mode
            #   RESULT_MODE__RETURN_ALL_VALUES__RAW ==> 0
            #   RESULT_MODE__RETURN_ALL_VALUES__FORMATTED ==> 0
            #   RESULT_MODE__RETURN_ONLY_NEW_VALUES__RAW ==> 0
            #   RESULT_MODE__RETURN_ONLY_NEW_VALUES__FORMATTED ==> 0
            ##################################################################
            if (self.resultMode == self.RESULT_MODE__RETURN_ALL_VALUES__RAW):
                # All data - RAW
                return self.deviceData_CurrentValues
            elif (self.resultMode ==
                  self.RESULT_MODE__RETURN_ALL_VALUES__FORMATTED):
                # All data - FORMATTED
                return self.__formatDataValue(self.deviceData_CurrentValues)
            else:
                # Check for new values
                newValues = self.__checkForNewValues(
                    self.deviceData_LastValues, self.deviceData_CurrentValues)

                # Copy of the latest received data
                self.deviceData_LastValues = copy.deepcopy(
                    self.deviceData_CurrentValues)

                # Process new values, if there is any
                if (newValues != []):
                    # RAW or FORMATTED?
                    if (self.resultMode ==
                            self.RESULT_MODE__RETURN_ONLY_NEW_VALUES__RAW):
                        return newValues
                    elif (self.resultMode ==
                          self.RESULT_MODE__RETURN_ONLY_NEW_VALUES__FORMATTED):
                        return self.__formatDataValue(newValues)
                else:
                    return []

    # Format RAW data according to this template
    # [ 07/16/20 @ 12:48:06 - 126 ] ---> localhost @ Port: 11503 ==> Value: False from     coil at address: 1520
    def __formatDataValue(self, values):

        # Prepare timestamp
        temp = datetime.datetime.now()
        x = temp.strftime("%x")
        y = temp.strftime("%X")
        z = temp.strftime("%f")
        timestamp = "[ " + x + " @ " + y + " - " + z[:3] + " ]"

        result = []

        for data_point in values:

            # Prepare value
            value = str(data_point["value"][0]).rjust(5)

            # Format information
            formattedValue = (str(timestamp) + " ---> " +
                              str(self.deviceHost) + " @ Port: " +
                              str(self.devicePort) + " ==> Value: " + value +
                              " from " + (data_point["type"]).rjust(8) +
                              " at address: " + str(data_point["address"]))

            result.append(formattedValue)

        return result

    # Check if latest polled data is new
    # Only new data will be taken into account
    def __checkForNewValues(self, lastValues, currentValues):
        # Temp array
        newValues = []

        for current_DP in currentValues:
            # Check if the value changed
            for last_DP in lastValues:
                if (last_DP["type"] == current_DP["type"]) and (
                        last_DP["address"] == current_DP["address"]) and (
                            last_DP["value"] != current_DP["value"]):
                    # --- New value
                    newValues.append(current_DP)

        return newValues
Exemplo n.º 29
0
class ModbusTCPSensor(OMPluginBase):
    """
    Get sensor values form modbus
    """

    name = 'modbusTCPSensor'
    version = '1.0.18'
    interfaces = [('config', '1.0')]

    config_description = [{
        'name': 'modbus_server_ip',
        'type': 'str',
        'description': 'IP or hostname of the ModBus server.'
    }, {
        'name':
        'modbus_port',
        'type':
        'int',
        'description':
        'Port of the ModBus server. Default: 502'
    }, {
        'name': 'debug',
        'type': 'int',
        'description': 'Turn on debugging (0 = off, 1 = on)'
    }, {
        'name':
        'sample_rate',
        'type':
        'int',
        'description':
        'How frequent (every x seconds) to fetch the sensor data, Default: 60'
    }, {
        'name':
        'sensors',
        'type':
        'section',
        'description':
        'OM sensor ID (e.g. 4), a sensor type and a Modbus Address',
        'repeat':
        True,
        'min':
        0,
        'content': [{
            'name': 'sensor_id',
            'type': 'int'
        }, {
            'name':
            'sensor_type',
            'type':
            'enum',
            'choices':
            ['temperature', 'humidity', 'brightness', 'validation_bit']
        }, {
            'name': 'modbus_address',
            'type': 'int'
        }, {
            'name': 'modbus_register_length',
            'type': 'int'
        }]
    }, {
        'name':
        'bits',
        'type':
        'section',
        'description':
        'OM validation bit ID (e.g. 4), and a Modbus Coil Address',
        'repeat':
        True,
        'min':
        0,
        'content': [{
            'name': 'validation_bit_id',
            'type': 'int'
        }, {
            'name': 'modbus_coil_address',
            'type': 'int'
        }]
    }]

    default_config = {'modbus_port': 502, 'sample_rate': 60}

    def __init__(self, webinterface, logger):
        super(ModbusTCPSensor, self).__init__(webinterface, logger)
        self.logger('Starting ModbusTCPSensor plugin...')

        self._config = self.read_config(ModbusTCPSensor.default_config)
        self._config_checker = PluginConfigChecker(
            ModbusTCPSensor.config_description)

        py_modbus_tcp_egg = '/opt/openmotics/python/plugins/modbusTCPSensor/pyModbusTCP-0.1.7-py2.7.egg'
        if py_modbus_tcp_egg not in sys.path:
            sys.path.insert(0, py_modbus_tcp_egg)

        self._client = None
        self._samples = []
        self._save_times = {}
        self._read_config()

        self.logger("Started ModbusTCPSensor plugin")

    def _read_config(self):
        self._ip = self._config.get('modbus_server_ip')
        self._port = self._config.get(
            'modbus_port', ModbusTCPSensor.default_config['modbus_port'])
        self._debug = self._config.get('debug', 0) == 1
        self._sample_rate = self._config.get(
            'sample_rate', ModbusTCPSensor.default_config['sample_rate'])
        self._sensors = []
        # Load Sensors
        for sensor in self._config.get('sensors', []):
            if 0 <= sensor['sensor_id'] < 32:
                self._sensors.append(sensor)
        # Load Validation bits
        self._validation_bits = []
        for validation_bit in self._config.get('bits', []):
            if 0 <= validation_bit['validation_bit_id'] < 256:
                self._validation_bits.append(validation_bit)
        self._enabled = len(self._sensors) > 0

        try:
            from pyModbusTCP.client import ModbusClient
            self._client = ModbusClient(self._ip,
                                        self._port,
                                        auto_open=True,
                                        auto_close=True)
            self._client.open()
            self._enabled = self._enabled & True
        except Exception as ex:
            self.logger('Error connecting to Modbus server: {0}'.format(ex))

        self.logger('ModbusTCPSensor is {0}'.format(
            'enabled' if self._enabled else 'disabled'))

    @background_task
    def run(self):
        while True:
            try:
                if not self._enabled or self._client is None:
                    time.sleep(5)
                    continue
                # Process all configured sensors
                self.process_sensors()
                # Process all validation bits
                self.process_validation_bits()

                time.sleep(self._sample_rate)
            except Exception as ex:
                self.logger('Could not process sensor values: {0}'.format(ex))
                time.sleep(15)

    def clamp_sensor(self, value, sensor_type):
        clamping = {
            'temperature': [-32, 95.5, 1],
            'humidity': [0, 100, 1],
            'brightness': [0, 100, 0]
        }
        return round(
            max(clamping[sensor_type][0], min(value,
                                              clamping[sensor_type][1])),
            clamping[sensor_type][2])

    def process_sensors(self):
        om_sensors = {}
        for sensor in self._sensors:
            registers = self._client.read_holding_registers(
                sensor['modbus_address'], sensor['modbus_register_length'])
            if registers is None:
                continue
            sensor_value = struct.unpack(
                '>f',
                struct.pack('BBBB', registers[1] >> 8, registers[1] & 255,
                            registers[0] >> 8, registers[0] & 255))[0]
            if not om_sensors.get(sensor['sensor_id']):
                om_sensors[sensor['sensor_id']] = {
                    'temperature': None,
                    'humidity': None,
                    'brightness': None
                }

            sensor_value = self.clamp_sensor(sensor_value,
                                             sensor['sensor_type'])

            om_sensors[sensor['sensor_id']][
                sensor['sensor_type']] = sensor_value
        if self._debug == 1:
            self.logger('The sensors values are: {0}'.format(om_sensors))

        for sensor_id, values in om_sensors.iteritems():
            result = json.loads(
                self.webinterface.set_virtual_sensor(sensor_id, **values))
            if result['success'] is False:
                self.logger(
                    'Error when updating virtual sensor {0}: {1}'.format(
                        sensor_id, result['msg']))

    def process_validation_bits(self):
        for validation_bit in self._validation_bits:
            bit = self._client.read_coils(
                validation_bit['modbus_coil_address'], 1)

            if bit is None or len(bit) != 1:
                if self._debug == 1:
                    self.logger('Failed to read bit {0}, bit is {1}'.format(
                        validation_bit['validation_bit_id'], bit))
                continue
            result = json.loads(
                self.webinterface.do_basic_action(
                    None, 237 if bit[0] else 238,
                    validation_bit['validation_bit_id']))
            if result['success'] is False:
                self.logger('Failed to set bit {0} to {1}'.format(
                    validation_bit['validation_bit_id'], 1 if bit[0] else 0))
            else:
                if self._debug == 1:
                    self.logger('Successfully set bit {0} to {1}'.format(
                        validation_bit['validation_bit_id'],
                        1 if bit[0] else 0))

    @om_expose
    def get_config_description(self):
        return json.dumps(ModbusTCPSensor.config_description)

    @om_expose
    def get_config(self):
        return json.dumps(self._config)

    @om_expose
    def set_config(self, config):
        config = json.loads(config)
        for key in config:
            if isinstance(config[key], six.string_types):
                config[key] = str(config[key])
        self._config_checker.check_config(config)
        self.write_config(config)
        self._config = config
        self._read_config()
        return json.dumps({'success': True})
Exemplo n.º 30
0
class TestClientServer(unittest.TestCase):
    port = 5020

    def setUp(self):
        # modbus server
        self.server = ModbusServer(port=TestClientServer.port, no_block=True)
        self.server.start()
        # modbus client
        self.client = ModbusClient(port=TestClientServer.port)
        self.client.open()
        # to prevent address taken errors
        TestClientServer.port += 1

    def tearDown(self):
        self.client.close()

    @repeat
    def test_word_init(self):
        # word space
        self.assertEqual(self.client.read_holding_registers(0), [0],
                         'Default value is 0 when server start')
        self.assertEqual(self.client.read_input_registers(0), [0],
                         'Default value is 0 when server start')

    @repeat
    def test_word_single(self):
        # single read/write
        self.assertEqual(self.client.write_single_register(0, 0xffff), True)
        self.assertEqual(self.client.read_input_registers(0), [0xffff])

    @repeat
    def test_word_multi(self):
        # multi-write at max size
        words_l = [randint(0, 0xffff)] * 0x7b
        self.assertEqual(self.client.write_multiple_registers(0, words_l),
                         True)
        self.assertEqual(self.client.read_holding_registers(0, len(words_l)),
                         words_l)
        self.assertEqual(self.client.read_input_registers(0, len(words_l)),
                         words_l)

    @repeat
    def test_word_oversize(self):
        # write over sized
        words_l = [randint(0, 0xffff)] * 0x7c
        self.assertEqual(self.client.write_multiple_registers(0, words_l),
                         None)

    @repeat
    def test_bit_init(self):
        # bit space
        self.assertEqual(self.client.read_coils(0), [False],
                         'Default value is False when server start')
        self.assertEqual(self.client.read_discrete_inputs(0), [False],
                         'Default value is False when server start')

    @repeat
    def test_bit_single(self):
        # single read/write
        self.assertEqual(self.client.write_single_coil(0, True), True)
        self.assertEqual(self.client.read_coils(0), [True])
        self.assertEqual(self.client.read_discrete_inputs(0), [True])

    @repeat
    def test_bit_multi_min(self):
        # multi-write at min size
        bits_l = [getrandbits(1)] * 0x1
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), True)
        self.assertEqual(self.client.read_coils(0, len(bits_l)), bits_l)
        self.assertEqual(self.client.read_discrete_inputs(0, len(bits_l)),
                         bits_l)

    @repeat
    def test_bit_multi_max(self):
        # multi-write at max size
        bits_l = [getrandbits(1)] * 0x7b0
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), True)
        self.assertEqual(self.client.read_coils(0, len(bits_l)), bits_l)
        self.assertEqual(self.client.read_discrete_inputs(0, len(bits_l)),
                         bits_l)

    @repeat
    def test_bit_multi_oversize(self):
        # multi-write over sized
        bits_l = [getrandbits(1)] * 0x7b1
        self.assertEqual(self.client.write_multiple_coils(0, bits_l), None)
Exemplo n.º 31
0
# define o cliente
c = ModbusClient()

# debug do cliente
#c.debug(True)

# ip/porta do servidor modbus (para se conectar)
c.host("10.13.110.215")
c.port(502)

while True:
    # para abrir a conexao TCP com o servidor
    if not c.is_open():
        if not c.open():
            print ("unable to connect")
    
    # read_coils() para leitura de dados vindo do servidor/supervisorio
    on = c.read_coils(6)

    # se a conexao estabelecida, entao escreve (write coils (modbus function 0x01))
    if c.is_open():
        
        c.write_single_coil(v1, valvula1)
        c.write_single_coil(v2, valvula2)

        c.write_single_register(n1, nivel1)
        c.write_single_register(n2, nivel2)
        
        # ... logica de codigo a implementar de acordo com a aplicacao a ser desenvolvida
Exemplo n.º 32
0
    def onHeartbeat(self):
        Domoticz.Debug("onHeartbeat called")

        try:
            client = ModbusClient(host=self.TCP_IP,
                                  port=int(self.TCP_PORT),
                                  unit_id=int(1),
                                  auto_open=True,
                                  auto_close=True,
                                  timeout=2)
        except:
            Domoticz.Error("Can not connect to Modbus TCP/IP: " + self.TCP_IP +
                           ":" + self.TCP_PORT)

        try:
            c207 = BinaryPayloadDecoder.fromRegisters(
                client.read_coils(207, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            c211 = BinaryPayloadDecoder.fromRegisters(
                client.read_coils(211, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            c902 = BinaryPayloadDecoder.fromRegisters(
                client.read_coils(902, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            c1200 = BinaryPayloadDecoder.fromRegisters(
                client.read_coils(1200, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            #Domoticz.Debug("Modbus response: v='" + str(i201) + "'")
        except:
            Domoticz.Error(
                "Modbus TCP/IP communication error (input registers). Check it out!"
            )

        try:
            i200 = BinaryPayloadDecoder.fromRegisters(
                client.read_input_registers(200, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            i201 = BinaryPayloadDecoder.fromRegisters(
                client.read_input_registers(201, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            i203 = BinaryPayloadDecoder.fromRegisters(
                client.read_input_registers(203, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            i204 = BinaryPayloadDecoder.fromRegisters(
                client.read_input_registers(204, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            i205 = BinaryPayloadDecoder.fromRegisters(
                client.read_input_registers(205, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            i206 = BinaryPayloadDecoder.fromRegisters(
                client.read_input_registers(206, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            #Domoticz.Debug("Modbus response: v='" + str(i201) + "'")
        except:
            Domoticz.Error(
                "Modbus TCP/IP communication error (input registers). Check it out!"
            )

        try:
            d200 = BinaryPayloadDecoder.fromRegisters(
                client.read_discrete_inputs(200, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            d201 = BinaryPayloadDecoder.fromRegisters(
                client.read_discrete_inputs(201, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            d202 = BinaryPayloadDecoder.fromRegisters(
                client.read_discrete_inputs(202, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            d203 = BinaryPayloadDecoder.fromRegisters(
                client.read_discrete_inputs(203, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            #Domoticz.Debug("Modbus response: v='" + str(i201) + "'")
        except:
            Domoticz.Error(
                "Modbus TCP/IP communication error (discrete inputs). Check it out!"
            )

        try:
            v1000 = BinaryPayloadDecoder.fromRegisters(
                client.read_holding_registers(1000, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            v1001 = BinaryPayloadDecoder.fromRegisters(
                client.read_holding_registers(1001, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            #v1008 = BinaryPayloadDecoder.fromRegisters(client.read_holding_registers(1008, 1), byteorder=Endian.Big, wordorder=Endian.Big).decode_16bit_int()
            #v1009 = BinaryPayloadDecoder.fromRegisters(client.read_holding_registers(1009, 1), byteorder=Endian.Big, wordorder=Endian.Big).decode_16bit_int()
            #v1012 = BinaryPayloadDecoder.fromRegisters(client.read_holding_registers(1012, 1), byteorder=Endian.Big, wordorder=Endian.Big).decode_16bit_int()
            #v1013 = BinaryPayloadDecoder.fromRegisters(client.read_holding_registers(1013, 1), byteorder=Endian.Big, wordorder=Endian.Big).decode_16bit_int()
            v1015 = BinaryPayloadDecoder.fromRegisters(
                client.read_holding_registers(1015, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            v1016 = BinaryPayloadDecoder.fromRegisters(
                client.read_holding_registers(1016, 1),
                byteorder=Endian.Big,
                wordorder=Endian.Big).decode_16bit_int()
            #Domoticz.Debug("Modbus response: v='" + str(v1015) + "'")
        except:
            Domoticz.Error(
                "Modbus TCP/IP communication error (holding registers). Check it out!"
            )

        # == Temperatures
        Devices[self.uTU1].Update(0, str(i200 / 10))
        Devices[self.uTU2].Update(0, str(i201 / 10))
        Devices[self.uTEa].Update(0, str(i203 / 10))
        Devices[self.uTEb].Update(0, str(i204 / 10))

        # == IN1 & IN2
        # I00205 Stav vstupu IN1 (0-10V): Analogový vstup: U= DATA/1000, Kontaktní vstup: rozepnuto ~ 3350 až 3450, sepnuto ~ do 20
        # I00206 Stav vstupu IN2 (0-10V): Analogový vstup: U= DATA/1000, Kontaktní vstup: rozepnuto ~ 3350 až 3450, sepnuto ~ do 20
        # kontakt: Statuses: Open: nValue = 1, Closed: nValue = 0
        if self.uIN1 in Devices:
            if self.atreaIN1type == "Contact":
                Devices[self.uIN1].Update(int(not (i205 <= 50)), "")
            elif Devices[self.uIN1].Type == 81:
                # Humidity_status can be one of:
                # 0=Normal      45~50, 55~60
                # 1=Comfortable 50~55
                # 2=Dry         <45
                # 3=Wet         >60
                if i205 < 4500: humstat = 2
                elif i205 > 6000: humstat = 3
                elif i205 >= 5000 and i205 <= 5500: humstat = 1
                else: humstat = 0
                Devices[self.uIN1].Update(int(i205 / 100), str(humstat))
            else:
                Devices[self.uIN1].Update(int(i205 / 100), str(i205 / 100))
        if self.uIN2 in Devices:
            if self.atreaIN2type == "Contact":
                Devices[self.uIN2].Update(int(not (i206 <= 50)), "")
            elif Devices[self.uIN2].Type == 81:
                if i206 < 4500: humstat = 2
                elif i206 > 6000: humstat = 3
                elif i206 >= 5000 and i206 <= 5500: humstat = 1
                else: humstat = 0
                Devices[self.uIN2].Update(int(i206 / 100), str(humstat))
            else:
                Devices[self.uIN2].Update(int(i206 / 100), str(i206 / 100))

        # == D1 & D2 & D3 & D4
        # D00200 Stav vstupu D1 : 0/1 : Vypnuto/Zapnuto
        # D00201 Stav vstupu D2 : 0/1 : Vypnuto/Zapnuto
        # D00202 Stav vstupu D3 : 0/1 : Vypnuto/Zapnuto
        # D00203 Stav vstupu D4 : 0/1 : Vypnuto/Zapnuto
        if self.uD1 in Devices: Devices[self.uD1].Update(int(d200 == 1), "")
        if self.uD2 in Devices: Devices[self.uD2].Update(int(d201 == 1), "")
        if self.uD3 in Devices: Devices[self.uD3].Update(int(d202 == 1), "")
        if self.uD4 in Devices: Devices[self.uD4].Update(int(d203 == 1), "")

        # == ZVT
        # C00207 0 = ZVT
        if self.uZVT in Devices: Devices[self.uZVT].Update(int(c207 == 0), "")

        # == Bypass
        # C00211 1 = Bypass flap
        if self.uBypass in Devices:
            Devices[self.uBypass].Update(int(c211 == 1), "")

        # == Heating season
        # C01200 1 = heating, 0 = non-heating
        if self.uHeatingSeason in Devices:
            Devices[self.uHeatingSeason].Update(int(c1200 == 1), "")

        # == Nightly Cooling
        # C00902 0 = recuperation, 1 = cooling
        if self.uNightlyCooling in Devices:
            Devices[self.uNightlyCooling].Update(int(c902 == 1), "")

        # == ControlMode
        if v1015 == 2 or v1016 == 2:
            Devices[self.uControlMode].Update(1, str(30))
        elif v1015 == 1 or v1016 == 1:
            Devices[self.uControlMode].Update(0, str(10))
        else:
            Devices[self.uControlMode].Update(0, str(20))

        # == PowerReq
        # H01009 Nastavení požadovaného výkonu, pokud H01016=1,   0 = Vyp, 12=12%,..., 100 = 100%
        # H01013 Nastavení požadovaného výkonu, pokud H01016=0/2, 0 = Vyp, 12=12%,..., 100 = 100%
        #if (v1016 == 1):   Devices[self.uPowerReq].Update(int(int(v1009) >= 10), str(self._powerPercentToDomoticzValue(v1009)))
        #elif (v1016 == 2): Devices[self.uPowerReq].Update(int(int(v1013) >= 10), str(self._powerPercentToDomoticzValue(v1013)))
        #elif (v1016 == 0): Devices[self.uPowerReq].Update(int(int(v1001) >= 10), str(self._powerPercentToDomoticzValue(v1001)))

        # == PowerCur
        # "0|60|90|120|150|180|240|300"
        Devices[self.uPowerCur].Update(
            int(int(v1001) >= 10),
            str(self._powerPercentToDomoticzValue(v1001)))

        # == ModeReq                                                  "Vypnuto |    Periodické větrání |    Větrání"
        # H01008 Nastavení požadovaného režimu, pokud H01015=1,                 0 = Periodické větrání, 1 = Větrání
        # H01012 Nastavení požadovaného režimu, pokud H01015= 0/2, 0 = Vypnuto, 1 = Periodické větrání, 2 = Větrání
        #if (v1015 == 1):
        #    if v1008 == 0:   Devices[self.uModeReq].Update(1, str(10))
        #    elif v1008 == 1: Devices[self.uModeReq].Update(1, str(20))
        #elif (v1015 == 2):
        #    if v1012 == 0:   Devices[self.uModeReq].Update(1, str(10))
        #    elif v1012 == 1: Devices[self.uModeReq].Update(1, str(20))
        #elif (v1015 == 0):
        #    if v1000 == 0:   Devices[self.uModeReq].Update(1, str(10))
        #    elif v1000 == 1: Devices[self.uModeReq].Update(1, str(20))

        # == ModeCur
        # "|Periodické větrání|Větrání|Čidlo vlhkosti|IN2|D1|D2|Koupelny+WC|Odsavač kuchyň|Náběh|Doběh|Odmrazování rekuperátoru"
        if (v1000 == 0):
            Devices[self.uModeCur].Update(int(int(v1001) >= 10), str(10))
        elif (v1000 == 1):
            Devices[self.uModeCur].Update(int(int(v1001) >= 10), str(20))
        elif (v1000 == 10):
            Devices[self.uModeCur].Update(1, str(30))
        elif (v1000 == 11):
            Devices[self.uModeCur].Update(1, str(40))
        elif (v1000 == 12):
            Devices[self.uModeCur].Update(1, str(50))
        elif (v1000 == 13):
            Devices[self.uModeCur].Update(1, str(60))
        elif (v1000 == 14):
            Devices[self.uModeCur].Update(1, str(70))
        elif (v1000 == 15):
            Devices[self.uModeCur].Update(1, str(80))
        elif (v1000 == 20):
            Devices[self.uModeCur].Update(1, str(90))
        elif (v1000 == 21):
            Devices[self.uModeCur].Update(1, str(100))
        elif (v1000 == 22):
            Devices[self.uModeCur].Update(1, str(110))

        # == Filter alarm from XML via HTTP
        try:
            bChangedFilter = True
            timeOfChange = 0
            xml = xmltodict.parse(
                requests.get("http://" + str(self.TCP_IP) +
                             "/config/alarms.xml").content)
            for i in xml['root']['errors']['i']:
                if int(i['@i']) == 100:
                    bChangedFilter = int(i['@p']) == 1
                    timeOfChange = i['@t']
            dtOfChange = datetime.fromtimestamp(int(timeOfChange))

            if bChangedFilter:
                Devices[self.uAlarmFilter].Update(
                    1,
                    self._("Filter last changed") + ": " + str(dtOfChange))
            else:
                Devices[self.uAlarmFilter].Update(
                    4,
                    self._("Filter to change since") + ": " + str(dtOfChange))
        except:
            Domoticz.Error(
                "Failed to get or process XML via HTML to get state of filter alarm."
            )

        return
Exemplo n.º 33
0
class Device():
    def __init__(self, host, port, timeout, byteorder=BE):       
        # big_endian        :   Byte order of the device memory structure
        #                       True  >>  big endian
        #                       False >>  little endian
        if byteorder == BE:
            self.big_endian=True
        else:
            self.big_endian=False
        
        self.dev = ModbusClient()
        self.dev.host(host)
        self.dev.port(port)
        self.dev.timeout(timeout)
        self.dev.open()
        #self.dev.debug = True

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ READ METHODS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    #Method to read binary variable
    def read_bits(self, VarNameList, AddressList, functioncode=2):
        # Arguments:
        # VarNameList       :   list of variable name
        # AddressList       :   list of variable register address in decimal (relative address)
        # functioncode      :   functioncode for modbus reading operation
        #                       1 >> for Discrete Output (Coils)
        #                       2 >> for Discrete Input
        # Return            :   dictionary of variable name and its value
        
        self.values = []
        if functioncode == 1:
            for address in AddressList:
                self.values.extend(self.dev.read_coils(address[0], len(address)))
        elif functioncode == 2:
            for address in AddressList:
                self.values.extend(self.dev.read_discrete_inputs(address[0], len(address)))    
        self.Result = dict(zip(VarNameList, self.values))
        return self.Result

    #Method to read INT16 or UINT16 variable
    def read_INT16(self, VarNameList, AddressList, MultiplierList, signed=False, roundto=3, functioncode=3):
        # Arguments:
        # VarNameList       :   list of variable name
        # AddressList       :   list of variable register address in decimal (relative address)
        # MultiplierList    :   list of multiplier
        # roundto           :   number of digits after decimal point
        #                       any positive integer number >> to limit the number of digits after decimal point
        #                       None                        >> to disable
        # signed            :   True  >> for signed values
        #                       False >> for unsigned values
        # functioncode      :   functioncode for modbus reading operation
        #                       3 >> for Holding Register
        #                       4 >> for Input Register
        # Return            :   dictionary of variable name and its value
        
        self.values = []

        if functioncode == 3:
            for address in AddressList:
                self.values.extend(self.dev.read_holding_registers(address[0],len(address)))
        elif functioncode == 4:
            for address in AddressList:
                self.values.extend(self.dev.read_input_registers(address[0],len(address)))
        
        if signed:
            self.values = UINT16toINT16(self.values)
        
        for i in range(0, len(self.values)):
            self.values[i] = round(self.values[i]*MultiplierList[i],roundto)

        self.Result = dict(zip(VarNameList, self.values))
        return self.Result


    #Method to read INT32 or UINT32 variable
    def read_INT32(self, VarNameList, AddressList, MultiplierList, signed=False, roundto=3, functioncode=3):
        # Arguments:
        # VarNameList       :   list of variable name
        # AddressList       :   list of variable register address in decimal (relative address)
        # MultiplierList    :   list of multiplier
        # roundto           :   number of digits after decimal point
        #                       any positive integer number >> to limit the number of digits after decimal point
        #                       None                        >> to disable
        # signed            :   True  >> for signed values
        #                       False >> for unsigned values
        # functioncode      :   functioncode for modbus reading operation
        #                       3 >> for Holding Register
        #                       4 >> for Input Register
        # Return            :   dictionary of variable name and its value

        self.values = []

        if functioncode == 3:
            for address in AddressList:
                self.values.extend(self.dev.read_holding_registers(address[0],len(address)))
        elif functioncode == 4:
            for address in AddressList:
                self.values.extend(self.dev.read_input_registers(address[0],len(address)))

        self.values = UINT16toINT32(self.values, self.big_endian, signed)
        for i in range(0, len(self.values)):
            self.values[i] = round(self.values[i]*MultiplierList[i], roundto)

        self.Result = dict(zip(VarNameList, self.values))
        return self.Result
    
    #Method to read INT64 or UINT64 variable
    def read_INT64(self, VarNameList, AddressList, MultiplierList, signed=False, roundto=3, functioncode=3):
        # Arguments:
        # VarNameList       :   list of variable name
        # AddressList       :   list of variable register address in decimal (relative address)
        # MultiplierList    :   list of multiplier
        # roundto           :   number of digits after decimal point
        #                       any positive integer number >> to limit the number of digits after decimal point
        #                       None                        >> to disable
        # signed            :   True  >> for signed values
        #                       False >> for unsigned values
        # functioncode      :   functioncode for modbus reading operation
        #                       3 >> for Holding Register
        #                       4 >> for Input Register
        # Return            :   dictionary of variable name and its value
        
        self.values = []

        if functioncode == 3:
            for address in AddressList:
                self.values.extend(self.dev.read_holding_registers(address[0],len(address)))
        elif functioncode == 4:
            for address in AddressList:
                self.values.extend(self.dev.read_input_registers(address[0],len(address)))

        self.values = UINT16toINT64(self.values, self.big_endian, signed)
        for i in range(0, len(self.values)):
            self.values[i] = round(self.values[i]*MultiplierList[i], roundto)

        self.Result = dict(zip(VarNameList, self.values))
        return self.Result

    #Method to read FLOAT16 variable
    def read_FLOAT16(self, VarNameList, AddressList, MultiplierList, roundto=3, functioncode=3):
        # Arguments:
        # VarNameList       :   list of variable name
        # AddressList       :   list of variable register address in decimal (relative address)
        # MultiplierList    :   list of multiplier
        # roundto           :   number of digits after decimal point
        #                       any positive integer number >> to limit the number of digits after decimal point
        #                       None                        >> to disable
        # functioncode      :   functioncode for modbus reading operation
        #                       3 >> for Holding Register
        #                       4 >> for Input Register
        # Return            :   dictionary of variable name and its value
        
        self.values = []

        if functioncode == 3:
            for address in AddressList:
                self.values.extend(self.dev.read_holding_registers(address[0],len(address)))
        elif functioncode == 4:
            for address in AddressList:
                self.values.extend(self.dev.read_input_registers(address[0],len(address)))

        self.values = UINT16toFLOAT16(self.values)
        
        for i in range(0, len(self.values)):
            self.values[i] = round(self.values[i]*MultiplierList[i], roundto)

        self.Result = dict(zip(VarNameList, self.values))
        return self.Result
    
    #Method to read FLOAT32 variable
    def read_FLOAT32(self, VarNameList, AddressList, MultiplierList, roundto=3, functioncode=3):
        # Arguments:
        # VarNameList       :   list of variable name
        # AddressList       :   list of variable register address in decimal (relative address)
        # MultiplierList    :   list of multiplier
        # roundto           :   number of digits after decimal point
        #                       any positive integer number >> to limit the number of digits after decimal point
        #                       None                        >> to disable
        # functioncode      :   functioncode for modbus reading operation
        #                       3 >> for Holding Register
        #                       4 >> for Input Register
        # Return            :   dictionary of variable name and its value
        
        self.values = []

        if functioncode == 3:
            for address in AddressList:
                self.values.extend(self.dev.read_holding_registers(address[0],len(address)))
        elif functioncode == 4:
            for address in AddressList:
                self.values.extend(self.dev.read_input_registers(address[0],len(address)))

        self.values = UINT16toFLOAT32(self.values, self.big_endian)
        for i in range(0, len(self.values)):
            self.values[i] = round(self.values[i]*MultiplierList[i], roundto)
        
        self.Result = dict(zip(VarNameList, self.values))
        return self.Result
    
    #Method to read FLOAT64 variable
    def read_FLOAT64(self, VarNameList, AddressList, MultiplierList, roundto=3, functioncode=3):
        # Arguments:
        # VarNameList       :   list of variable name
        # AddressList       :   list of variable register address in decimal (relative address)
        # MultiplierList    :   list of multiplier
        # roundto           :   number of digits after decimal point
        #                       any positive integer number >> to limit the number of digits after decimal point
        #                       None                        >> to disable
        # functioncode      :   functioncode for modbus reading operation
        #                       3 >> for Holding Register
        #                       4 >> for Input Register
        # Return            :   dictionary of variable name and its value
        
        self.values = []

        if functioncode == 3:
            for address in AddressList:
                self.values.extend(self.dev.read_holding_registers(address[0],len(address)))
        elif functioncode == 4:
            for address in AddressList:
                self.values.extend(self.dev.read_input_registers(address[0],len(address)))

        self.values = UINT16toFLOAT64(self.values, self.big_endian)
        for i in range(0, len(self.values)):
            self.values[i] = round(self.values[i]*MultiplierList[i], roundto)

        self.Result = dict(zip(VarNameList, self.values))
        return self.Result

    #Method to read STRING variable
    def read_STRING(self, VarNameList, AddressList, functioncode=3):
        # Arguments:
        # VarNameList       :   list of variable name
        # AddressList       :   list of variable register address in decimal (relative address)
        # functioncode      :   functioncode for modbus reading operation
        #                       3 >> for Holding Register
        #                       4 >> for Input Register
        # Return            :   dictionary of variable name and its value
        
        self.values = []
        if functioncode == 3:
            for address in AddressList:
                _uint16Val = self.dev.read_holding_registers(address[0],len(address))
                self.values.append(UINT16toSTRING(_uint16Val, self.big_endian))
        elif functioncode == 4:
            for address in AddressList:
                _uint16Val = self.dev.read_input_registers(address[0],len(address))
                self.values.append(UINT16toSTRING(_uint16Val, self.big_endian))
        
        self.Result = dict(zip(VarNameList, self.values))
        return self.Result

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ WRITE METHODS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    # Method to write binary value on discrete output register (Coil)
    def write_bit(self, registerAddress, value):
        # Arguments:
        # registerAddress   :   register address in decimal (relative address)
        # value             :   0 or 1
        
        self.dev.write_single_coil(registerAddress, value)

    # Method to write numeric value on holding register
    def write_num(self, registerAddress, value, valueType):
        # Arguments:
        # registerAddress   :   register START address in decimal (relative address)
        # value             :   numerical value
        # valueType         :   UINT16, UINT32, UINT64, INT16, INT32, INT64, FLOAT16,
        #                       FLOAT32, FLOAT64, STRING

        startAddress = registerAddress
        val = None
        
        if valueType == UINT16:
            val = [value]
        elif valueType == INT16:
            val = INT16toUINT16([value])
        elif valueType == UINT32:
            val = INT32toUINT16(value, self.big_endian, signed=False)
        elif valueType == INT32:
            val = INT32toUINT16(value, self.big_endian, signed=True)
        elif valueType == UINT64:
            val = INT64toUINT16(value, self.big_endian, signed=False)
        elif valueType == INT64:
            val = INT64toUINT16(value, self.big_endian, signed=True)
        elif valueType == FLOAT16:
            val = FLOAT16toUINT16([value])
        elif valueType == FLOAT32:
            val = FLOAT32toUINT16(value, self.big_endian)
        elif valueType == FLOAT64:
            val = FLOAT64toUINT16(value, self.big_endian)
        elif valueType == STRING:
            val = STRINGtoUINT16(value, self.big_endian)
    
        # write multiple registers
        self.dev.write_multiple_registers(startAddress, val)

    def close(self):
        self.dev.close()
Exemplo n.º 34
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time

# min_read_bit
# minimal code for read 10 bits on IPv4 192.168.0.200 and print result on stdout

from pyModbusTCP.client import ModbusClient
c = ModbusClient(host="192.168.0.200", auto_open=True)

while True:
    # read 10 bits at address 20480
    bits = c.read_coils(20480, 10)
    print("bit ad #0 to 9: "+str(bits) if bits else "read error")
    # sleep 2s
    time.sleep(2)
Exemplo n.º 35
0
    # Taken from https://stackoverflow.com/a/16444786/4504053
    binary_string = bin(struct.unpack('!i', struct.pack('!f', num))[0])
    return [True if x == '1' else False for x in binary_string]


if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)

    SERVER_HOST = '10.72.21.89'
    SERVER_PORT = 5020
    logging.debug('Open connection to {}:{}'.format(SERVER_HOST, SERVER_PORT))
    client = ModbusClient(host=SERVER_HOST, port=SERVER_PORT, auto_open=True)

    logging.debug('Send gyro data')
    # plyer.gyroscope.enable()
    # x, y, z = plyer.gyroscope.orientation
    # plyer.gyroscope.disable()
    x, y, z = 1, 0.1, -0.1
    address_offset = 1
    for data in (x, y, z):
        logging.debug('Sending value: {}'.format(data))
        binary_data = number_to_array_bits(data)
        logging.debug('Data length: {}'.format(len(binary_data)))
        rr = client.write_multiple_registers(address_offset, binary_data)
        address_offset += len(binary_data)

    bits = client.read_coils(1, 32)
    logging.debug('Reading data from slave: {}'.format(bits))

    logging.debug('Script complete.')
Exemplo n.º 36
0
import time

SERVER_HOST = "localhost"
SERVER_PORT = 502

c = ModbusClient()

# uncomment this line to see debug message
#c.debug(True)

# define modbus server host, port
c.host(SERVER_HOST)
c.port(SERVER_PORT)

while True:
    # open or reconnect TCP to server
    if not c.is_open():
        if not c.open():
            print("unable to connect to "+SERVER_HOST+":"+str(SERVER_PORT))

    # if open() is ok, read coils (modbus function 0x01)
    if c.is_open():
        # read 10 bits at address 0, store result in regs list
        bits = c.read_coils(0, 10)
        # if success display registers
        if bits:
            print("bit ad #0 to 9: "+str(bits))

    # sleep 2s before next polling
    time.sleep(2)