Exemplo n.º 1
0
    def post(self, uid):
        '''
        POST to control module coil output states
        (Make the blinkey lights go blinkey)
        '''

        # Parse the form data
        parser = reqparse.RequestParser()
        parser.add_argument("type")
        parser.add_argument("output")
        parser.add_argument("state")
        parser.add_argument("ips", action='append')
        args = parser.parse_args()

        outputs = ['all_clear', 'emergency', 'lightning', 'a', 'b', 'c']

        # Iterate over the outputs and send the state for each one
        # True = On, False = Off
        for idx, output in enumerate(outputs):
            if output == args['output']:
                for ip in args['ips']:
                    c = ModbusClient(host=ip,
                                     port=502,
                                     auto_open=True,
                                     timeout=1)
                    coil = idx + 16
                    c.write_single_coil(coil, args['state'])

        return (200)
Exemplo n.º 2
0
def testPCL():
    c = ModbusClient(host=getIpPLC(), port=getPortPLC(), auto_open=True)
    print(c)
    is_ok = c.write_single_coil(0, 1)
    print(is_ok)
    if is_ok:
        return "is ok"
    else:
        return "is not ok"
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.º 4
0
 def modbus_write(self, progress_callback):
     c = ModbusClient(host="localhost", auto_open=False)
     connection_ok = c.open()
     if connection_ok:
         try:
             c.write_single_coil(0, self.coil)
             c.close()
         except:
             print("modbus exception")
             pass
         else:
             print("other")
             pass
         finally:
             #print("passed")
             pass
     else:
         print("could not open")
         pass
    def __init__(self, modbus_address):
        self.areTopicsAlive = {}
        faultTime = rospy.get_time()

        #Initialise communication with ModbusClient
        adam = ModbusClient(host="192.168.1.3",
                            port=502,
                            auto_open=True,
                            auto_close=False)

        rospy.Subscriber("/1/failures", TopicState, self.callback)
        rospy.Subscriber("/2/failures", TopicState, self.callback)

        #While System has not been shutdown
        while not rospy.is_shutdown():
            #If for some reason the watchdogs or subscription fail tell PLCs
            if len(self.areTopicsAlive.keys()) == 0:
                adam.write_single_coil(int(modbus_address), False)
            #If watch dogs are functioning
            else:
                #Check current state of every topic
                for key in self.areTopicsAlive.keys():
                    #If there is a failure in one of the topics
                    if self.areTopicsAlive[key] == 0:
                        #Set pin to LOW
                        adam.write_single_coil(int(modbus_address), False)
                        faultTime = rospy.get_time()
                        rospy.logerr(
                            "System is not working. Topic %s has failed", key)
                #If there has been no fault for 2 secs set pin back to HIGH
                if rospy.get_time() - faultTime >= 2:
                    adam.write_single_coil(int(modbus_address), True)
            sleep(0.2)
Exemplo n.º 6
0
 def state_off(self, name_x):
     SERVER_HOST = name_x
     SERVER_PORT = 502
     c = ModbusClient()
     c.host(SERVER_HOST)
     c.port(SERVER_PORT)
     c.open()
     is_ok = c.write_single_coil(32768, False)
     if is_ok:
         self.first_read_label_text = str('kapali')
         self.image_source = "sf0.png"
     else:
         self.first_read_label_text = str('failed')
Exemplo n.º 7
0
def callback(marker_array, inputs):
    output_address = inputs[0]
    input_address = inputs[1]
    zone_distance = inputs[2]
    grid_x = inputs[3]
    #Create a connection with the ADAM-6052
    adam = ModbusClient(host="192.168.1.3",
                        port=502,
                        auto_open=True,
                        auto_close=False)

    #Calculate distance to nearest object
    distance = 100
    for marker in marker_array.markers:
        xpos = marker.pose.position.x
        xsize = marker.scale.x
        #Set distance if new distance is smaller
        if xpos - float(xsize) / 2 - grid_x < distance:
            distance = xpos - float(xsize) / 2 - grid_x

    a = adam.read_discrete_inputs(int(input_address))
    #If it is a valid read
    if type(a) == type([]):
        #If HIGH
        if a[0] == 1:
            rospy.loginfo("System is in reduced distance mode")
            #If there is an obstruction less than xm detected write pin False
            if distance <= int(zone_distance):
                rospy.logwarn("Obstruction has been detected")
                adam.write_single_coil(int(output_address), False)
            #If there is an no obstruction less than xm detected write pin False
            else:
                rospy.loginfo("No Obsturction has been detected")
                adam.write_single_coil(int(output_address), True)
        #If LOW
        elif a[0] == 0:
            #If there is an obstruction detected write pin False
            if len(marker_array.markers) > 0:
                rospy.logwarn("Obstruction has been detected")
                adam.write_single_coil(int(output_address), False)
            #If there is no obstruction detected write pin True
            else:
                rospy.loginfo("No Obsturction has been detected")
                adam.write_single_coil(int(output_address), True)
    else:
        rospy.logwarn("Connection to adam failed")
Exemplo n.º 8
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.º 9
0
    def state_on(self, name_x):
        SERVER_HOST = name_x
        SERVER_PORT = 502
        c = ModbusClient()
        c.host(SERVER_HOST)
        c.port(SERVER_PORT)
        c.open()

        is_ok = c.write_single_coil(32768, True)
        bits = c.read_holding_registers(32768)

        if bits:
            self.first_read_label_text = str('Acik')
            self.image_source = "sf_yesil.png"
        else:
            self.first_read_label_text = str('cannotread')
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
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, 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))
Exemplo n.º 12
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)))
c2.host("192.168.1.30")
c2.port(502)
c2.unit_id(1)
c2.open()
c2.close()

cmds = ["config switch physical-port", "edit port4", "set status down", "end"]
exec_ssh_cmds(cmds)

# 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 c.is_open():
    while True:
        # Turn pump on
        c.write_single_coil(1, True)
        # Set pump to 100%
        c.write_single_register(3, 0x64)
        val = c.read_coils(5)[0]
        print(val)

        c2.write_single_coil(1, True)

        if val:
            c.write_single_coil(1, False)

        time.sleep(0.2)
Exemplo n.º 14
0
client = ModbusClient("192.168.68.113", 502)
print("open:", client.open())
while True:
    action = input("action: ")
    client.open()
    try:
        adr = int(input("adress: "))
        if action == "rr":
            print(f"value at {adr}: {client.read_holding_registers(adr)}")
        if action == "rc":
            print(f"value at {adr}: {client.read_coils(adr)}")
        if action == "wr":
            val = int(input("value: "))
            print(f"old value at {adr}: {client.read_holding_registers(adr)}")
            client.write_single_register(adr, val)
            time.sleep(0.1)
            print(f"new value at {adr}: {client.read_holding_registers(adr)}")
        if action == "wc":
            val = input("value: ")
            print(f"old value at {adr}: {client.read_coils(adr)}")
            if val == "t":
                client.write_single_coil(adr, True)
                time.sleep(0.1)
                print(f"new value at {adr}: {client.read_coils(adr)}")
            else:
                client.write_single_coil(adr, False)
                time.sleep(0.1)
                print(f"new value at {adr}: {client.read_coils(adr)}")
    except:
        print("Try again")
Exemplo n.º 15
0
SERVER_U_ID = 1

c = ModbusClient()

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

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

speed = 0.1

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, write coils
    if c.is_open():
        is_ok = c.write_single_coil(1, True)  # Solenoid on
        c.write_single_register(3, 0x64)
        # time.sleep(speed)
        # is_ok = c.write_single_coil(1, False)  # Solenoid off
        #c.write_single_register(3, 0x0)

        time.sleep(speed)
Exemplo n.º 16
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.º 17
0
    def onCommand(self, u, Command, Level, Hue):
        Domoticz.Debug(
            str(Devices[u].DeviceID) + ": onCommand called: Parameter '" +
            str(Command) + "', Level: " + str(Level))

        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:
            # == ControlMode  : man = 1, auto = 0, docasny = 2 |  "|Manuál|Automat|Dočasný"
            if (u == self.uControlMode):
                #if Level == 10: atreaControlMode = 1
                if Level == 20: atreaControlMode = 0
                elif Level == 30: atreaControlMode = 2
                client.write_single_register(1015, atreaControlMode)
                client.write_single_register(1016, atreaControlMode)

            # == HeatingSeason  : 0 = non-heating, 1 = heating
            elif (u == self.uHeatingSeason):
                client.write_single_coil(1200, int(Command == "On"))

            # == NightlyCooling  : 0 = recuperation, 1 = cooling
            elif (u == self.uNightlyCooling):
                client.write_single_coil(902, int(Command == "On"))

            # == uPowerCur
            # == uPowerReq
            elif (u == self.uPowerCur):
                atreaPower = int(self._powerDomoticzValueToPercent(Level))
                Domoticz.Debug(
                    str(Devices[u].DeviceID) + ": COMMAND: Level=" +
                    str(Level) + ", atreaPower='" + str(atreaPower) + "'")
                client.write_single_register(1009, atreaPower)
                client.write_single_register(1013, atreaPower)
                client.write_single_register(1015, 2)
                client.write_single_register(1016, 2)

            # == ModeCur                                                        "Vypnuto |    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"
            # == 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í
            elif (u == self.uModeCur):
                if Level == 0:
                    atreaMode = 1
                    self.onCommand(self.uPowerCur, Command, 0, Hue)
                elif Level == 10:
                    atreaMode = 0
                elif Level == 20:
                    atreaMode = 1
                Domoticz.Debug(
                    str(Devices[u].DeviceID) + ": COMMAND: Level=" +
                    str(Level) + ", atreaMode='" + str(atreaMode) + "'")
                client.write_single_register(1008, atreaMode)
                client.write_single_register(1012, atreaMode)
                client.write_single_register(1015, 2)
                client.write_single_register(1016, 2)

        except:
            Domoticz.Error(
                str(Devices[u].DeviceID) +
                ": Modbus update error. Check it out!")

        # Update values now!
        self.onHeartbeat()
        return
Exemplo n.º 18
0
SERVER_PORT = 502
SERVER_U_ID = 1

c = ModbusClient()

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

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

# 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, write coils
if c.is_open():
    for addr in [0, 1, 2, 3]:
        if args.on:
            is_ok = c.write_single_coil(addr, True)  # Solenoid on
        elif args.off:
            is_ok = c.write_single_coil(addr, False)  # Solenoid on
        else:
            print("No command given")
            break
        # time.sleep(1)
        # is_ok = c.write_single_coil(addr, False)  # Solenoid off
Exemplo n.º 19
0
                pass
            elif (keyboard.is_pressed('p')):
                aux = vOut + 10
                vOut = 100 if (aux > 90) else aux
                pass

            #System
            canoIn = True if (vIn > 0) else False
            canoOut = True if (vOut > 0) else False

            aux = nivel + vIn / 10 - vOut / 10
            nivel = 100 if (aux > 99) else (0 if (aux < 1) else aux)

            ledAlarm = True if (nivel >= 75) else False
            vIn = 0 if (nivel == 100) else vIn

            # Sending Data to ScadaBr
            c.write_single_register(0, vIn)
            c.write_single_register(1, vOut)
            c.write_single_register(2, nivel)
            c.write_single_coil(3, canoIn)
            c.write_single_coil(4, canoOut)
            c.write_single_coil(5, ledAlarm)

            # Terminal Data Printing
            print("vIn: %d" % vIn)
            print("vOut: %d" % vOut)
            print("Nivel: %d" % nivel)

            # Waiting Time
            time.sleep(0.2)
Exemplo n.º 20
0
    "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-ygdjt%40schneider-project.iam.gserviceaccount.com"
})
# Initialize the app with a service account, granting admin privileges
firebase_admin.initialize_app(
    cred, {'databaseURL': 'https://schneider-project.firebaseio.com/'})

c = ModbusClient()
c.host("192.168.0.112")
c.port(502)
c.open()
ref = db.reference('connect_plc')
value = ref.get()
app1 = value["appliance1"]
app2 = value["appliance2"]
app3 = value["appliance3"]
c.write_single_coil(0, app1)
c.write_single_coil(1, app2)
c.write_single_coil(2, app3)
status_connect = 0
time_disconnect = ""
time_reconnect = ""
time_delay = 0


#Callbacks
def on_connect(client, userdata, flags, rc):
    print("Connected with Code :" + str(rc))
    # Subscribe Topic
    client.subscribe("esp8266")

    主站写一个 coil,从站读取该值,并将该值赋值给 discrete_input,然后主站再读取该值
    主站写一个 holding_reg,从站读取该值,并赋值给 input_reg,然后主站再读取该值
    """

    coil_value = False
    holding_reg_value = 1
    range_value = 100

    while True:
        if not c.is_open():
            logger.error("not open")
            time.sleep(2)
            continue

        # 写 coils
        c.write_single_coil(1, coil_value)
        logger.debug(f"写 coil,值为 {coil_value}")
        coil_value = not coil_value

        time.sleep(1)

        # 读 discrete_inputs
        inputs = c.read_discrete_inputs(1)
        if inputs is None:
            logger.error("读 discrete_inputs 失败")
            time.sleep(2)
            continue
        logger.debug(f"读 discrete_input,值为 {inputs[0]}")

        # 写 holding_registers
        c.write_single_register(1, holding_reg_value)
Exemplo n.º 22
0
class blower():
    #_____________________________________________________________________________
    def __init__(self, machine, name):
        builder.SetDeviceName(name)
        self.com = ModbusClient(host=machine, port=4000, auto_open=True)  #4000
        self.com.mode(constants.MODBUS_RTU)
        stat = self.com.open()
        self.pv_stat = builder.aIn("stat")
        self.pv_stat.PREC = 1
        self.pv_stat.LOPR = 0
        self.pv_stat.HOPR = 100
        self.pv_temp = builder.aIn("temp")
        self.pv_temp.PREC = 1
        self.pv_temp.LOPR = 0
        self.pv_temp.HOPR = 100
        self.pv_humi = builder.aIn("humidity")
        self.pv_humi.PREC = 1
        self.pv_humi.LOPR = 0
        self.pv_humi.HOPR = 100
        self.pv_humi.HSV = "MINOR"
        self.pv_humi.HHSV = "MAJOR"
        self.pv_humi.HIGH = 45
        self.pv_humi.HIHI = 50
        self.pv_flow = builder.aIn("flow")
        self.pv_flow.PREC = 0
        self.pv_flow.LOPR = 0
        self.pv_flow.HOPR = 600
        self.pv_flow.LOLO = 250
        self.pv_flow.LOW = 300
        self.pv_flow.HIGH = 480
        self.pv_flow.HIHI = 520
        self.pv_flow.LSV = "MINOR"
        self.pv_flow.LLSV = "MAJOR"
        self.pv_flow.HSV = "MINOR"
        self.pv_flow.HHSV = "MAJOR"
        self.stat_pv = builder.boolIn("status",
                                      ZNAM="off",
                                      ONAM="on",
                                      DESC=name)
        self.stat_pv.ZSV = "MAJOR"
        self.pv_on = builder.boolOut("on",
                                     ZNAM="0",
                                     ONAM="1",
                                     HIGH=0.1,
                                     on_update=self.turnOn)
        self.pv_off = builder.boolOut("off",
                                      ZNAM="0",
                                      ONAM="1",
                                      HIGH=0.1,
                                      on_update=self.turnOff)
        self.busy = False
        self.pv_act = builder.boolOut("activity", ZNAM="0", ONAM="1", HIGH=1)
        self.pv_was_on = builder.boolOut("was_on",
                                         ZNAM="0",
                                         ONAM="1",
                                         HIGH=1.5)
        self.pv_was_off = builder.boolOut("was_off",
                                          ZNAM="0",
                                          ONAM="1",
                                          HIGH=1.5)
        self.id_temp = 0
        self.id_stat = 1

    #_____________________________________________________________________________
    def start_monit_loop(self):
        t = threading.Thread(target=self.monitor_loop)
        t.daemon = True
        t.start()

    #_____________________________________________________________________________
    def monitor_loop(self):
        while True:
            time.sleep(2)
            try:
                if self.busy == False: self.read_YOGOGAWA()
            except TypeError:
                print "monitor_loop: reading skipped due to external write, busy:", self.busy
                self.busy = False

    #_____________________________________________________________________________
    def get_1dig(self, i):
        #print i
        return float(i) * 0.1

    #_____________________________________________________________________________
    def read_YOGOGAWA(self):

        self.busy = True

        self.com.unit_id(1)
        resp = self.com.read_holding_registers(1, 2)
        self.pv_stat.set(self.get_1dig(resp[self.id_stat]))
        self.pv_temp.set(self.get_1dig(resp[self.id_temp]))
        #self.pv_stat.set(resp[0])
        #self.pv_temp.set(resp[1])
        #self.get_1dig(resp[0])
        #self.get_1dig(resp[1])

        self.com.unit_id(2)
        resp = self.com.read_holding_registers(1, 1)[0]
        self.pv_humi.set(self.get_1dig(resp))

        self.com.unit_id(3)
        self.pv_flow.set(get_2comp(self.com.read_holding_registers(1, 1)[0]))

        self.busy = False

        self.pv_act.set(1)

    #_____________________________________________________________________________
    def turnOn(self, val):
        if val == 0: return
        while self.busy == True:
            print "turnOn: waiting for busy to clear"
            time.sleep(0.2)
        self.busy = True
        self.com.unit_id(5)
        self.com.write_single_coil(0, True)
        self.busy = False
        #print("funtion turnOn done")
        self.pv_was_on.set(1)

    #_____________________________________________________________________________
    def turnOff(self, val):
        if val == 0: return
        while self.busy == True:
            print "turnOff: waiting for busy to clear"
            time.sleep(0.2)
        self.busy = True
        self.com.unit_id(5)
        self.com.write_single_coil(1, True)
        self.busy = False
        #print("function turnOff done")
        self.pv_was_off.set(1)
Exemplo n.º 23
0
def write(ip, output, state):
    # Initialize modbus
    c = ModbusClient(host=ip, port=502, auto_open=True, timeout=1)
    coil = output+16
    c.write_single_coil(coil, state)
Exemplo n.º 24
0
def set_start_mode_ramp(ModbusClient):
	# Sets the start mode to ramp
	# c is ModbusClient
	wr = ModbusClient.write_single_coil(2,2)
	print('set_start_mode_ramp:' + str(int(wr)))
	return wr
Exemplo n.º 25
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.º 26
0
# 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():
        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(
Exemplo n.º 27
0
class ThermiaGenesis:  # pylint:disable=too-many-instance-attributes
    """Main class to perform modbus requests to heat pump."""

    def __init__(self, host, port=502, kind='inverter', delay=0.1, max_registers=16):
        """Initialize."""

        self.data = {}
        self._client = ModbusClient(host, port=port, unit_id=1, auto_open=True)
        self.firmware = None
        if(kind == MODEL_MEGA): self.model = "Mega"
        else: self.model = "Diplomat Inverter"
        self._host = host
        self._port = port
        self._kind = kind
        self._delay = delay
        self.MAX_REGISTERS = max_registers

        _LOGGER.debug("Using host: %s:%d", host, port)

    async def async_set(self, register, value):  # pylint:disable=too-many-branches
        """Write data to heat pump."""
        ret_value = await self._set_data(register, value)
        self._client.close()

    async def async_update(self, register_types=REG_TYPES, only_registers = None):  # pylint:disable=too-many-branches
        """Update data from heat pump."""
        use_registers = []
        if(only_registers != None):
            #Make sure to sort registers by type and address
            use_registers = sorted(only_registers, key=(lambda x: f"{REGISTERS[x][KEY_REG_TYPE]}-{REGISTERS[x][KEY_ADDRESS]:03}"))
        else:
            use_registers = dict(filter(lambda x: x[1][self._kind], REGISTERS.items())).keys()

        raw_data = await self._get_data(use_registers)
        self._client.close()

        if not raw_data:
            self.data = {}
            return {}

        #_LOGGER.debug("RAW data: %s", raw_data)
        data = {}
        try:
            for i, (name, val) in enumerate(raw_data.items()):
                data[name] = val

            self.firmware = f"{self.data[ATTR_INPUT_SOFTWARE_VERSION_MAJOR]}.{self.data[ATTR_INPUT_SOFTWARE_VERSION_MINOR]}.{self.data[ATTR_INPUT_SOFTWARE_VERSION_MICRO]}"

            _LOGGER.debug("------------- REGISTERS ----------------------")
            for i, (name, val) in enumerate(self.data.items()):
                _LOGGER.debug(f"{REGISTERS[name][KEY_ADDRESS]}\t{val}\t{name}")


        except AttributeError as err:
            _LOGGER.debug("Incomplete data from modbus.")
            _LOGGER.debug(err)
        except KeyError as err: 
            _LOGGER.debug("Incomplete data from modbus.")
            _LOGGER.debug(err)
        except TypeError as err:
            _LOGGER.debug("Incomplete data from modbus.")
            _LOGGER.debug(err)
        self.data = data
        return data

    @property
    def available(self):
        """Return True is data is available."""
        return bool(self.data)


    async def _set_data(self, register, value):
        meta = REGISTERS[register]
        regtype = meta[KEY_REG_TYPE]
        address = meta[KEY_ADDRESS]
        scale = meta[KEY_SCALE]
        await asyncio.sleep(self._delay)
        try:
            if(regtype == REG_COIL):
                _LOGGER.debug(f"Set {regtype} register at {address} value {value} ({value})")
                self._client.write_single_coil(address, value)
            elif(regtype == REG_HOLDING):
                converted_value = int(value * scale)
                if(meta[KEY_DATATYPE] == TYPE_INT):
                    converted_value = num_to_bin(converted_value)
                _LOGGER.debug(f"Set {regtype} register at {address} value {converted_value} ({value}) {scale}")
                self._client.write_single_register(address, converted_value)
            else: 
                raise "This register can not be changed"
        except Exception as e:
            _LOGGER.error(f'exception: {e}')
            print(traceback.format_exc())
        return value


    async def _get_data(self, registers):
        """Retreive data from heat pump."""
        raw_data = {}
        #Split into requests that reads up to self.MAX_REGISTERS within REGISTER_RANGES (register blocks) for the requested registers
        first_chunk_address = 0
        current_type = None
        chunks = []
        chunk = None
        for name in registers:
            meta = REGISTERS[name]

            if(name == ATTR_HOLDING_FIXED_SYSTEM_SUPPLY_SET_POINT):
                #This will give an errror unless coil 42 is True, so skip if we don't know this or if it's false
                enableAttr = ATTR_COIL_ENABLE_FIXED_SYSTEM_SUPPLY_SET_POINT
                if(enableAttr not in raw_data and enableAttr not in self.data): 
                    _LOGGER.debug(f"Will not read {name} since we don't know if {ATTR_COIL_ENABLE_FIXED_SYSTEM_SUPPLY_SET_POINT} is set, include this register in the request to read this")
                    continue
                if(not raw_data[ATTR_COIL_ENABLE_FIXED_SYSTEM_SUPPLY_SET_POINT] and not self.data[ATTR_COIL_ENABLE_FIXED_SYSTEM_SUPPLY_SET_POINT]):
                    _LOGGER.debug(f"Will not read {name} since {ATTR_COIL_ENABLE_FIXED_SYSTEM_SUPPLY_SET_POINT} is False which disables this register")
                    continue

            reg_address = meta[KEY_ADDRESS]
            if(chunk == None #First iteration
                    or chunk[KEY_REG_TYPE] != meta[KEY_REG_TYPE] #New register type
                    or (reg_address - chunk['start']) >= self.MAX_REGISTERS #Exceeds max number of registers per request
                    or reg_address > chunk['range_end']): #Address belongs to another register block
                if(chunk != None):
                    chunks.append(chunk)
                start = meta[KEY_ADDRESS]
                chunk = { KEY_REG_TYPE: meta[KEY_REG_TYPE], 'start': start, 'slots': { name: 0 } }

                if(meta[KEY_DATATYPE] == TYPE_LONG): 
                    chunk['end'] = start + 1
                else: 
                    chunk['end'] = start

                in_range = list(filter(lambda x: x[0] <= start and x[1] >= start, REGISTER_RANGES[self._kind][meta[KEY_REG_TYPE]]))
                chunk['range_end'] = in_range[0][1]

            else:
                chunk['slots'][name] = reg_address - start
                if(meta[KEY_DATATYPE] == TYPE_LONG):
                    chunk['end'] = reg_address + 1
                else:
                    chunk['end'] = reg_address
        if(chunk != None): chunks.append(chunk)
        _LOGGER.info(f"Will make {len(chunks)} requests to read {len(registers)} registers")
        #print(f"Will make {len(chunks)} requests to read {len(registers)} registers")

        try:
            for chunk in chunks:
                await asyncio.sleep(self._delay)
                start_address = chunk['start']
                length = chunk['end'] - chunk['start'] + 1
                regtype = chunk[KEY_REG_TYPE]
                _LOGGER.debug(f"Reading {regtype} {start_address} length {length}")
                read_data = None
                if(regtype == REG_COIL):
                    read_data = self._client.read_coils(start_address, length)
                elif(regtype == REG_DISCRETE_INPUT):
                    read_data = self._client.read_discrete_inputs(start_address, length)
                elif(regtype == REG_INPUT):
                    read_data = self._client.read_input_registers(start_address, length)
                elif(regtype == REG_HOLDING):
                    read_data = self._client.read_holding_registers(start_address, length)
                if read_data:
                    for i, (name, address) in enumerate(chunk['slots'].items()):
                        info = REGISTERS[name]
                        datatype = info[KEY_DATATYPE]
                        scale = info[KEY_SCALE]
                        val = read_data[address]
                        if(datatype == TYPE_LONG):
                            regs = read_data[address:(address+2)]
                            val = word_list_to_long(regs)[0]
                        elif(datatype == TYPE_INT):
                            if(val == 32767): val = 0
                            if(val > 32767): val = val - 65536
                        elif(datatype == TYPE_STATUS):
                            status_str = "OFF"
                            if val == 1:
                                status_str = "Manual Operation"
                            elif val == 2:
                                status_str = "Defrost"
                            elif val == 3:
                                status_str = "Hot water"
                            elif val == 4:
                                status_str = "Heat"
                            elif val == 5:
                                status_str = "Cool"
                            elif val == 6:
                                status_str = "Pool"
                            elif val == 7:
                                status_str = "Anti legionella"
                            elif val == 98:
                                status_str = "Standby"
                            elif val == 99:
                                status_str = "No demand"
                            val = status_str

                        if(scale != 1): val = val / scale
                        raw_data[name] = val
                else:
                    if self._client.last_error() > 0:
                        _LOGGER.error(f'error {self._client.last_error()}')
                    raise Exception(f"Failed to read {regtype} {start_address} length {length}", self._client.last_error())
            #for regtype in register_types:
            #    last_chunk_address = 0
            #    values = []
            #    for chunk in REGISTER_RANGES[self._kind][regtype]:
            #        await asyncio.sleep(self._delay)
            #        start_address = chunk[0]
            #        length = chunk[1] - start_address
            #        #Insert 0 if there is a gap
            #        values.extend([0] * (start_address - last_chunk_address))
            #        _LOGGER.debug(f"Reading {regtype} {start_address} length {length}")
            #        read_data = None
            #        if(regtype == REG_COIL):
            #            read_data = self._client.read_coils(start_address, length)
            #        elif(regtype == REG_DISCRETE_INPUT):
            #            read_data = self._client.read_discrete_inputs(start_address, length)
            #        elif(regtype == REG_INPUT):
            #            read_data = self._client.read_input_registers(start_address, length)
            #        elif(regtype == REG_HOLDING):
            #            read_data = self._client.read_holding_registers(start_address, length)
            #        if read_data:
            #            values.extend(read_data)
            #        else:
            #            if self._client.last_error() > 0:
            #                print(f'error {self._client.last_error()}')
            #                _LOGGER.error(f'error {self._client.last_error()}')
            #            raise Exception(f"Failed to read {regtype} {start_address} length {length}", self._client.last_error())
            #        last_chunk_address = chunk[1]
            #    raw_data[regtype] = values
        except Exception as e:
            _LOGGER.error(f'exception: {e}')
            print(traceback.format_exc())

        return raw_data
import time
from pyModbusTCP.client import ModbusClient

# Equipamentos no chão de fábrica
valvula1 = False
valvula2 = False
nivelTanque1 = 0.0
bracoRobotico = 0

# auto_open=True, auto_close=True
c = ModbusClient()

c.host("172.17.115.225")
c.port(502)

while True:
    if not c.is_open():
        if not c.open():
            print("conexão falhou")

    # on = c.read_coils(4)

    if c.is_open():
        c.write_single_coil(0, valvula1)
Exemplo n.º 29
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.º 30
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.º 31
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.º 32
0
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, 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))
Exemplo n.º 33
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