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)
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)
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")
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:
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)):
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]))