if mod['parity'] == "E":
                            instrument.serial.parity = serial.PARITY_EVEN

                    if mod['parity'] == "N":
                            instrument.serial.parity = serial.PARITY_NONE

                    writestring = ("{},{}").format(d.hour*60*60+d.minute*60+d.second,channel['channel'])
                    try:
                            writestring+= (",{}").format(instrument.read_string(103))
                    except ValueError as e:
                            print(e)
                    for register in mod['registers']:
                            writestring += ","
                            value = -1
                            if register['only'] == "" or register['only'] == channel['type']:
                                    if register['float'] != -1:
                                            try:
                                                    #value = instrument.read_float(register['float'])
                                                    values = instrument.read_registers(register['float'],numberOfRegisters=2)
                                                    registerstring = chr(values[1].to_bytes(2,byteorder='big')[0]) + chr(values[1].to_bytes(2,byteorder='big')[1]) + chr(values[0].to_bytes(2,byteorder='big')[0]) + chr(values[1].to_bytes(2,byteorder='big')[1])
                                                    value = minmod._bytestringToFloat(registerstring)
                                            except ValueError as e:
                                                    print(e)

                            writestring += ("{}").format(value)

                    writestring += "\n"
                    print(writestring)
            time.sleep(5)
Exemple #2
0
                        try:
                                writestring+= (",{}").format(instrument.read_string(103))
                        except ValueError as e:
                                print(e)
                        for register in mod['registers']:
                                headerstring += ("{},").format(register['name'])
                                unitstring += ("{},").format(register['units'])
                                writestring += ","
                                value = "NA"
                                if register['only'] == "" or register['only'] == channel['type']:
                                        if register['float'] != "NA":
                                                try:
                                                        #value = instrument.read_float(register['float'])
                                                        values = instrument.read_registers(register['float'],numberOfRegisters=2)
                                                        registerstring = chr(values[1].to_bytes(2,byteorder='big')[0]) + chr(values[1].to_bytes(2,byteorder='big')[1]) + chr(values[0].to_bytes(2,byteorder='big')[0]) + chr(values[1].to_bytes(2,byteorder='big')[1])
                                                        value = minmod._bytestringToFloat(registerstring)*register['convert']
                                                except ValueError as e:
                                                        print(e)

                                        print("Value: {}".format(value))

                                writestring += ("{}").format(value)

                        headerstring += "\n"
                        unitstring += "\n"
                        writestring += "\n"
                        print(writestring)
                        if d.hour < mod['savetime']:
                                datafilepath = monthpath + ("{}-{}-{}+{}hr.csv").format(d.year,d.month,d.day-1,mod['savetime'])
                        else:
                                datafilepath = monthpath + ("{}-{}-{}+{}hr.csv").format(d.year,d.month,d.day,mod['savetime'])
                instrument.serial.parity = serial.PARITY_NONE

            writestring = ("{},{}").format(d.hour * 60 * 60 + d.minute * 60 + d.second, channel["channel"])
            try:
                writestring += (",{}").format(instrument.read_string(103))
            except ValueError as e:
                print(e)
            for register in mod["registers"]:
                writestring += ","
                value = -1
                if register["only"] == "" or register["only"] == channel["type"]:
                    if register["float"] != -1:
                        try:
                            # value = instrument.read_float(register['float'])
                            values = instrument.read_registers(register["float"], numberOfRegisters=2)
                            registerstring = (
                                chr(values[1].to_bytes(2, byteorder="big")[0])
                                + chr(values[1].to_bytes(2, byteorder="big")[1])
                                + chr(values[0].to_bytes(2, byteorder="big")[0])
                                + chr(values[1].to_bytes(2, byteorder="big")[1])
                            )
                            value = minmod._bytestringToFloat(registerstring)
                        except ValueError as e:
                            print(e)

                writestring += ("{}").format(value)

            writestring += "\n"
            print(writestring)
        time.sleep(5)
Exemple #4
0
    def _genericCommand(self, functioncode, registeraddress, value=None, \
            numberOfDecimals=0, numberOfRegisters=1, signed=False, payloadformat=None):
        """Generic command for reading and writing registers and bits.
        Args:
            * functioncode (int): Modbus function code.
            * registeraddress (int): The register address  (use decimal numbers, not hex).
            * value (numerical or string or None or list of int): The value to store in the register. Depends on payloadformat.
            * numberOfDecimals (int): The number of decimals for content conversion. Only for a single register.
            * numberOfRegisters (int): The number of registers to read/write. Only certain values allowed, depends on payloadformat.
            * signed (bool): Whether the data should be interpreted as unsigned or signed. Only for a single register or for payloadformat='long'.
            * payloadformat (None or string): None, 'long', 'float', 'string', 'register', 'registers'. Not necessary for single registers or bits.
        If a value of 77.0 is stored internally in the slave register as 770,
        then use ``numberOfDecimals=1`` which will divide the received data from the slave by 10
        before returning the value. Similarly ``numberOfDecimals=2`` will divide
        the received data by 100 before returning the value. Same functionality is also used
        when writing data to the slave.
        Returns:
            The register data in numerical value (int or float), or the bit value 0 or 1 (int), or ``None``.
        Raises:
            ValueError, TypeError, IOError
        """
        NUMBER_OF_BITS = 1
        NUMBER_OF_BYTES_FOR_ONE_BIT = 1
        NUMBER_OF_BYTES_BEFORE_REGISTERDATA = 1
        ALL_ALLOWED_FUNCTIONCODES = list(range(
            1, 7)) + [15, 16] + [22]  # To comply with both Python2 and Python3
        MAX_NUMBER_OF_REGISTERS = 255

        # Payload format constants, so datatypes can be told apart.
        # Note that bit datatype not is included, because it uses other functioncodes.
        PAYLOADFORMAT_LONG = 'long'
        PAYLOADFORMAT_FLOAT = 'float'
        PAYLOADFORMAT_STRING = 'string'
        PAYLOADFORMAT_REGISTER = 'register'
        PAYLOADFORMAT_REGISTERS = 'registers'

        ALL_PAYLOADFORMATS = [PAYLOADFORMAT_LONG, PAYLOADFORMAT_FLOAT, \
            PAYLOADFORMAT_STRING, PAYLOADFORMAT_REGISTER, PAYLOADFORMAT_REGISTERS]

        ## Check input values ##
        minimalmodbus._checkFunctioncode(
            functioncode, ALL_ALLOWED_FUNCTIONCODES
        )  # Note: The calling facade functions should validate this
        minimalmodbus._checkRegisteraddress(registeraddress)
        minimalmodbus._checkInt(numberOfDecimals,
                                minvalue=0,
                                description='number of decimals')
        minimalmodbus._checkInt(numberOfRegisters,
                                minvalue=1,
                                maxvalue=MAX_NUMBER_OF_REGISTERS,
                                description='number of registers')
        minimalmodbus._checkBool(signed, description='signed')

        if payloadformat is not None:
            if payloadformat not in ALL_PAYLOADFORMATS:
                raise ValueError(
                    'Wrong payload format variable. Given: {0!r}'.format(
                        payloadformat))

        ## Check combinations of input parameters ##
        numberOfRegisterBytes = numberOfRegisters * _NUMBER_OF_BYTES_PER_REGISTER

        # Payload format
        if functioncode in [3, 4, 6, 16] and payloadformat is None:
            payloadformat = PAYLOADFORMAT_REGISTER

        if functioncode in [3, 4, 6, 16]:
            if payloadformat not in ALL_PAYLOADFORMATS:
                raise ValueError('The payload format is unknown. Given format: {0!r}, functioncode: {1!r}.'.\
                    format(payloadformat, functioncode))
        else:
            if payloadformat is not None:
                raise ValueError('The payload format given is not allowed for this function code. ' + \
                    'Given format: {0!r}, functioncode: {1!r}.'.format(payloadformat, functioncode))

                # Signed and numberOfDecimals
        if signed:
            if payloadformat not in [
                    PAYLOADFORMAT_REGISTER, PAYLOADFORMAT_LONG
            ]:
                raise ValueError('The "signed" parameter can not be used for this data format. ' + \
                    'Given format: {0!r}.'.format(payloadformat))

        if numberOfDecimals > 0 and payloadformat != PAYLOADFORMAT_REGISTER:
            raise ValueError('The "numberOfDecimals" parameter can not be used for this data format. ' + \
                'Given format: {0!r}.'.format(payloadformat))

            # Number of registers
        if functioncode not in [3, 4, 16] and numberOfRegisters != 1:
            raise ValueError('The numberOfRegisters is not valid for this function code. ' + \
                'NumberOfRegisters: {0!r}, functioncode {1}.'.format(numberOfRegisters, functioncode))

        if functioncode == 16 and payloadformat == PAYLOADFORMAT_REGISTER and numberOfRegisters != 1:
            raise ValueError('Wrong numberOfRegisters when writing to a ' + \
                'single register. Given {0!r}.'.format(numberOfRegisters))
            # Note: For function code 16 there is checking also in the content conversion functions.

            # Value
        if functioncode in [5, 6, 15, 16, 22] and value is None:
            raise ValueError('The input value is not valid for this function code. ' + \
                'Given {0!r} and {1}.'.format(value, functioncode))

        if functioncode == 16 and payloadformat in [
                PAYLOADFORMAT_REGISTER, PAYLOADFORMAT_FLOAT, PAYLOADFORMAT_LONG
        ]:
            minimalmodbus._checkNumerical(value, description='input value')

        if functioncode == 6 and payloadformat == PAYLOADFORMAT_REGISTER:
            minimalmodbus._checkNumerical(value, description='input value')

            # Value for string
        if functioncode == 16 and payloadformat == PAYLOADFORMAT_STRING:
            minimalmodbus._checkString(value,
                                       'input string',
                                       minlength=1,
                                       maxlength=numberOfRegisterBytes)
            # Note: The string might be padded later, so the length might be shorter than numberOfRegisterBytes.

            # Value for registers
        if functioncode == 16 and payloadformat == PAYLOADFORMAT_REGISTERS:
            if not isinstance(value, list):
                raise TypeError(
                    'The value parameter must be a list. Given {0!r}.'.format(
                        value))

            if len(value) != numberOfRegisters:
                raise ValueError('The list length does not match number of registers. ' + \
                    'List: {0!r},  Number of registers: {1!r}.'.format(value, numberOfRegisters))

        ## Build payload to slave ##
        if functioncode in [1, 2]:
            payloadToSlave = minimalmodbus._numToTwoByteString(registeraddress) + \
                            minimalmodbus._numToTwoByteString(NUMBER_OF_BITS)

        elif functioncode in [3, 4]:
            payloadToSlave = minimalmodbus._numToTwoByteString(registeraddress) + \
                            minimalmodbus._numToTwoByteString(numberOfRegisters)

        elif functioncode == 5:
            payloadToSlave = minimalmodbus._numToTwoByteString(registeraddress) + \
                            minimalmodbus._createBitpattern(functioncode, value)

        elif functioncode == 6:
            payloadToSlave = minimalmodbus._numToTwoByteString(registeraddress) + \
                            minimalmodbus._numToTwoByteString(value, numberOfDecimals, signed=signed)

        elif functioncode == 15:
            payloadToSlave = minimalmodbus._numToTwoByteString(registeraddress) + \
                            minimalmodbus._numToTwoByteString(NUMBER_OF_BITS) + \
                            minimalmodbus._numToOneByteString(NUMBER_OF_BYTES_FOR_ONE_BIT) + \
                            minimalmodbus._createBitpattern(functioncode, value)

        elif functioncode == 16:
            if payloadformat == PAYLOADFORMAT_REGISTER:
                registerdata = minimalmodbus._numToTwoByteString(
                    value, numberOfDecimals, signed=signed)

            elif payloadformat == PAYLOADFORMAT_STRING:
                registerdata = minimalmodbus._textstringToBytestring(
                    value, numberOfRegisters)

            elif payloadformat == PAYLOADFORMAT_LONG:
                registerdata = minimalmodbus._longToBytestring(
                    value, signed, numberOfRegisters)

            elif payloadformat == PAYLOADFORMAT_FLOAT:
                registerdata = minimalmodbus._floatToBytestring(
                    value, numberOfRegisters)

            elif payloadformat == PAYLOADFORMAT_REGISTERS:
                registerdata = minimalmodbus._valuelistToBytestring(
                    value, numberOfRegisters)

            assert len(registerdata) == numberOfRegisterBytes
            payloadToSlave = minimalmodbus._numToTwoByteString(registeraddress) + \
                            minimalmodbus._numToTwoByteString(numberOfRegisters) + \
                            minimalmodbus._numToOneByteString(numberOfRegisterBytes) + \
                            registerdata
        elif functioncode == 22:
            registerdata = minimalmodbus._valuelistToBytestring(value, 2)
            payloadToSlave = minimalmodbus._numToTwoByteString(registeraddress) + \
                            registerdata
        ## Communicate ##
        payloadFromSlave = self._performCommand(functioncode, payloadToSlave)

        ## Check the contents in the response payload ##
        if functioncode in [1, 2, 3, 4]:
            minimalmodbus._checkResponseByteCount(
                payloadFromSlave)  # response byte count

        if functioncode in [5, 6, 15, 16]:
            minimalmodbus._checkResponseRegisterAddress(
                payloadFromSlave, registeraddress)  # response register address

        if functioncode == 5:
            minimalmodbus._checkResponseWriteData(
                payloadFromSlave,
                minimalmodbus._createBitpattern(functioncode,
                                                value))  # response write data

        if functioncode == 6:
            minimalmodbus._checkResponseWriteData(payloadFromSlave, \
                minimalmodbus._numToTwoByteString(value, numberOfDecimals, signed=signed))  # response write data

        if functioncode == 15:
            minimalmodbus._checkResponseNumberOfRegisters(
                payloadFromSlave, NUMBER_OF_BITS)  # response number of bits

        if functioncode == 16:
            minimalmodbus._checkResponseNumberOfRegisters(
                payloadFromSlave,
                numberOfRegisters)  # response number of registers

        ## Calculate return value ##
        if functioncode in [1, 2]:
            registerdata = payloadFromSlave[
                NUMBER_OF_BYTES_BEFORE_REGISTERDATA:]
            if len(registerdata) != NUMBER_OF_BYTES_FOR_ONE_BIT:
                raise ValueError('The registerdata length does not match NUMBER_OF_BYTES_FOR_ONE_BIT. ' + \
                    'Given {0}.'.format(len(registerdata)))

            return minimalmodbus._bitResponseToValue(registerdata)

        if functioncode in [3, 4]:
            registerdata = payloadFromSlave[
                NUMBER_OF_BYTES_BEFORE_REGISTERDATA:]
            if len(registerdata) != numberOfRegisterBytes:
                raise ValueError('The registerdata length does not match number of register bytes. ' + \
                    'Given {0!r} and {1!r}.'.format(len(registerdata), numberOfRegisterBytes))

            if payloadformat == PAYLOADFORMAT_STRING:
                return minimalmodbus._bytestringToTextstring(
                    registerdata, numberOfRegisters)

            elif payloadformat == PAYLOADFORMAT_LONG:
                return minimalmodbus._bytestringToLong(registerdata, signed,
                                                       numberOfRegisters)

            elif payloadformat == PAYLOADFORMAT_FLOAT:
                return minimalmodbus._bytestringToFloat(
                    registerdata, numberOfRegisters)

            elif payloadformat == PAYLOADFORMAT_REGISTERS:
                return minimalmodbus._bytestringToValuelist(
                    registerdata, numberOfRegisters)

            elif payloadformat == PAYLOADFORMAT_REGISTER:
                return minimalmodbus._twoByteStringToNum(registerdata,
                                                         numberOfDecimals,
                                                         signed=signed)

            raise ValueError('Wrong payloadformat for return value generation. ' + \
                'Given {0}'.format(payloadformat))

        if functioncode == 22:
            registerdata = payloadFromSlave[
                NUMBER_OF_BYTES_BEFORE_REGISTERDATA:]
            return ("OK")
Exemple #5
0
                if register['only'] == "" or register['only'] == channel[
                        'type']:
                    if register['float'] != "NA":
                        try:
                            #value = instrument.read_float(register['float'])
                            values = instrument.read_registers(
                                register['float'], numberOfRegisters=2)
                            registerstring = chr(values[1].to_bytes(
                                2, byteorder='big')[0]) + chr(
                                    values[1].to_bytes(
                                        2, byteorder='big')[1]) + chr(
                                            values[0].to_bytes(
                                                2, byteorder='big')[0]) + chr(
                                                    values[1].to_bytes(
                                                        2, byteorder='big')[1])
                            value = minmod._bytestringToFloat(
                                registerstring) * register['convert']
                        except ValueError as e:
                            print(e)

                    print("Value: {}".format(value))

                writestring += ("{}").format(value)

            headerstring += "\n"
            unitstring += "\n"
            writestring += "\n"
            print(writestring)
            if d.hour < mod['savetime']:
                datafilepath = monthpath + ("{}-{}-{}+{}hr.csv").format(
                    d.year, d.month, d.day - 1, mod['savetime'])
            else:
Exemple #6
0
 filename = '/home/pi/energy' + str(time.strftime('%m-%d-%Y')) + '.csv'
 f = open(filename, 'a')
 for x in range(len(addrname)):
     f.write(str(addrname[x]))
     f.write(',')
 f.write('\n')
 f.close()
 next_rec_time = round(time.time() + delay)
 try:
     for x in range(len(addr)):
         temp = instrument.read_registers(addr[x], numberOfRegisters=2)
         #print temp
         regStr = chr(temp[1] >> 8) + chr(temp[1] & 0x00FF) + chr(
             temp[0] >> 8) + chr(temp[0] & 0x00FF)
         #print regStr
         flt = minimalmodbus._bytestringToFloat(regStr)
         res[x] = flt
     f = open(filename, 'a')
     f.write(str(time.strftime('%m-%d-%Y %H:%M:%S')) + ',')
     for x in range(len(addr)):
         f.write(str(res[x]))
         f.write(',')
     f.write('\n')
     f.close()
     i = i + 1
     print(i)
 except:
     res = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
     f = open(filename, 'a')
     f.write(str(time.strftime('%m-%d-%Y %H:%M:%S')) + ',')
     for x in range(len(addr)):
Exemple #7
0
 def convert_MODbus_to_standard_float(self, a):
     if len(a) != 2:
         raise Exception('INVALID input')
     b = [a[1], a[0]]
     return minimalmodbus._bytestringToFloat("".join(
         [minimalmodbus._numToTwoByteString(i) for i in b]))