#!/usr/bin/env python # ---------------------------------------------------------------------------# # import the various server implementations # ---------------------------------------------------------------------------# from pymodbus.client.sync import ModbusTcpClient as ModbusClient # ---------------------------------------------------------------------------# # import python packages # ---------------------------------------------------------------------------# from pymongo import MongoClient import pytest import struct # ---------------------------------------------------------------------------# # configure the client logging # ---------------------------------------------------------------------------# import logging logging.basicConfig() log = logging.getLogger() log.setLevel(logging.INFO) # ---------------------------------------------------------------------------# # Modbus Client Setup # ---------------------------------------------------------------------------# modbus_client = ModbusClient('localhost', port=502) # ---------------------------------------------------------------------------# # Mongo DB Setup # ---------------------------------------------------------------------------# mongo_client = MongoClient() mongo_db = mongo_client.tag_data mongo_tags = mongo_db.tag_vals def close_enough(a, b): return abs(a - b) < 0.001 def float_to_bytes(float_val): ''' Converts a float to little-endian bytes ''' packed_string = struct.pack('f', float_val) unpacked_list = list(struct.unpack('HH', packed_string)) return unpacked_list def integer_to_byte(integer_val): ''' Converts an integer to its byte ''' packed_string = struct.pack('h', integer_val) unpacked = list(struct.unpack('H', packed_string)) return unpacked def lebyte_to_float(word_list): ''' Converts list of little-endian bytes to float ''' packed_string = struct.pack("HH", *word_list) unpacked_float = struct.unpack("f", packed_string)[0] return unpacked_float def lebyte_to_integer(word_list): ''' Converts list(size = 1) of little-endian bytes to Integer ''' try: packed_string = struct.pack("H", *word_list) unpacked_int = struct.unpack("h", packed_string)[0] except Exception as e: print("Unable to convert {} to integer".format(word_list)) return False return unpacked_int def read_holding_registers(num_registers): with open('holding_registers.csv', 'wb') as csvfile: modbus_client.connect() for i in range(0, num_registers - 1): reg = modbus_client.read_holding_registers(i, 1).registers csvfile.write("{},{}\n".format(i + 1, reg[0])) print("{},{}".format(i + 1, reg[0])) def read_input_registers(num_registers): with open('input_registers.csv', 'wb') as csvfile: modbus_client.connect() for i in range(0, num_registers - 1): reg = modbus_client.read_input_registers(i, 1).registers csvfile.write("{},{}\n".format(i + 1, reg[0])) print("{},{}".format(i + 1, reg[0])) def read_coils(num_registers): with open('coils.csv', 'wb') as csvfile: modbus_client.connect() for i in range(0, num_registers - 1): reg = modbus_client.read_coils(i, 1).bits csvfile.write("{},{}\n".format(i + 1, reg[0])) print("{},{}".format(i + 1, reg[0])) def read_discrete_inputs(num_registers): with open('discrete_inputs.csv', 'wb') as csvfile: modbus_client.connect() for i in range(0, num_registers - 1): reg = modbus_client.read_discrete_inputs(i, 1).bits csvfile.write("{},{}\n".format(i + 1, reg[0])) print("{},{}".format(i + 1, reg[0])) def db_read_holding_registers(): tag_in_db = mongo_tags.find({"register_type": 'hr'}) with open('db_holding_registers.csv', 'wb') as csvfile: for db_tag in tag_in_db: try: database_value = db_tag['val'] except KeyError: print("No value in DB for {}".format(db_tag['tag_name'])) reg = [] reg_string = "" try: if db_tag['tag_type'][-3:] == 'INT': reg = modbus_client.read_holding_registers(db_tag['register_number'] - 1, 1).registers elif db_tag['tag_type'] == 'REAL': reg = modbus_client.read_holding_registers(db_tag['register_number'] - 1, 2).registers # print(reg) except AttributeError: print("Could not get register {} for {}".format(db_tag['register_number'], db_tag['tag_name'])) continue if reg: if len(reg) == 2: # r = reg.reverse() modbus_value = lebyte_to_float(reg) reg_string = "{},{}".format(reg[0], reg[1]) else: modbus_value = lebyte_to_integer(reg) reg_string = "{}".format(reg[0]) print("{},{},{},{},{}".format(db_tag['register_number'], db_tag['tag_name'], database_value, modbus_value, reg_string)) csvfile.write("{},{},{},{},{}\n".format(db_tag['register_number'], db_tag['tag_name'], database_value, modbus_value, reg_string)) modbus_client.close() def db_read_input_registers(): tag_in_db = mongo_tags.find({"register_type": 'ir'}) with open('db_input_registers.csv', 'wb') as csvfile: for db_tag in tag_in_db: try: database_value = db_tag['val'] except KeyError: print("No value in DB for {}".format(db_tag['tag_name'])) continue reg = [] try: if db_tag['tag_type'][-3:] == 'INT': reg = modbus_client.read_input_registers(db_tag['register_number'] - 1, 1).registers elif db_tag['tag_type'] == 'REAL': reg = modbus_client.read_input_registers(db_tag['register_number'] - 1, 2).registers # print(reg) except AttributeError: print("Could not get register {} for {}".format(db_tag['register_number'], db_tag['tag_name'])) continue if reg: if len(reg) == 2: # r = reg.reverse() modbus_value = lebyte_to_float(reg) reg_string = "{},{}".format(reg[0], reg[1]) else: modbus_value = lebyte_to_integer(reg) reg_string = "{}".format(reg[0]) print("{},{},{},{},{}".format(db_tag['register_number'], db_tag['tag_name'], database_value, modbus_value, reg_string)) csvfile.write("{},{},{},{},{}\n".format(db_tag['register_number'], db_tag['tag_name'], database_value, modbus_value, reg_string)) modbus_client.close() def db_read_coils(): modbus_client.connect() tag_in_db = mongo_tags.find({"register_type": 'co'}) with open('db_coils.csv', 'wb') as csvfile: for db_tag in tag_in_db: try: database_value = db_tag['val'] except KeyError: print("No value in DB for {}".format(db_tag['tag_name'])) continue try: reg = modbus_client.read_coils(db_tag['register_number'] - 1, 1).bits print("{},{},{},{}".format(db_tag['register_number'], db_tag['tag_name'], database_value, reg[0])) csvfile.write("{},{},{},{}\n".format(db_tag['register_number'], db_tag['tag_name'], database_value, reg[0])) except AttributeError: print("Could not get register {} for {}".format(db_tag['register_number'], db_tag['tag_name'])) continue def db_read_discrete_inputs(): modbus_client.connect() tag_in_db = mongo_tags.find({"register_type": 'di'}) with open('db_discrete_inputs.csv', 'wb') as csvfile: for db_tag in tag_in_db: try: database_value = db_tag['val'] except KeyError: print("No value in DB for {}".format(db_tag['tag_name'])) continue try: reg = modbus_client.read_discrete_inputs(db_tag['register_number'] - 1, 1).bits print("{},{},{},{}".format(db_tag['register_number'], db_tag['tag_name'], database_value, reg[0])) csvfile.write("{},{},{},{}\n".format(db_tag['register_number'], db_tag['tag_name'], database_value, reg[0])) except AttributeError: print("Could not get register {} for {}".format(db_tag['register_number'], db_tag['tag_name'])) continue if __name__ == '__main__': print("Holding Registers") # read_holding_registers(158) db_read_holding_registers() print("Input Registers") # read_input_registers(22753) db_read_input_registers() print("Coils") # read_coils(19) db_read_coils() print("Discrete Inputs") # read_discrete_inputs(2) db_read_discrete_inputs()