class RenkeRsRaN01Jt(SitModbusDevice):

    # CONSTANTS

    DEFAULT_SLAVE_ADDRESS = 1
    DEFAULT_MODBUS_PORT = '/dev/ttyUSB0'
    DEFAULT_TARGET_MODE = SitModbusDevice.TARGET_MODE_RTU
    PARSER_DESCRIPTION = 'Actions with RS-RA-N01-JT from ali irradiance sensor' + SitConstants.DEFAULT_HELP_LICENSE_NOTICE

    # CLASS ATTRIBUTES

    _byte_order = Endian.Big
    _word_order = Endian.Big
    _substract_one_to_register_index = False
    _rtu_baudrate = 4800
    _rtu_parity = 'N'
    _rtu_timeout = 10  #seconds

    # FUNCTIONS DEFINITION
    """
		Initialize
	"""
    def __init__(self,
                 a_slave_address=DEFAULT_SLAVE_ADDRESS,
                 a_port=DEFAULT_MODBUS_PORT,
                 an_ip_address=None):
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)
        try:
            self.init_arg_parse()
            assert self.valid_slave_address(
                a_slave_address
            ), 'a_slave_address parameter invalid:{}'.format(l_slave_address)
            l_slave_address = a_slave_address
            l_usb_port = self.DEFAULT_MODBUS_PORT
            if __name__ == '__main__':
                if (hasattr(self._args, 'slave_address')
                        and self._args.slave_address):
                    l_slave_address = self._args.slave_address
                if (hasattr(self._args, 'usb_port') and self._args.usb_port):
                    l_usb_port = self._args.usb_port
            super().__init__(l_slave_address,
                             self.DEFAULT_TARGET_MODE,
                             a_port=l_usb_port,
                             an_ip_address=self._args.host_ip)
            self._logger = SitLogger().new_logger(self.__class__.__name__,
                                                  self._args.host_mac)
            self._init_sit_modbus_registers(l_slave_address)

            self.invariants()
            #self._logger.debug('init->' + self.out())
        except OSError as l_e:
            self._logger.warning(
                "init-> OSError, probably rollingfileAppender" % (l_e))
            if e.errno != errno.ENOENT:
                raise l_e
        except Exception as l_e:
            print('Error in init: %s' % (l_e))
            raise l_e
            #exit(1)

    def _init_sit_modbus_registers(self, a_slave_address):
        """
			Initializes self._sit_modbus_registers
		"""
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)

        l_reg_list = OrderedDict()

        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt16u(
                'GHI',
                'Total irradiation on the external irradiation sensor/pyranometer (W/m2)',
                0x0,
                a_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'Int16u',
                an_is_metadata=False))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt16u('GHIDev',
                               'Solar radiation deviation (0~1800)',
                               0x52,
                               a_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               'Int16u',
                               an_is_metadata=False))
        #SitUtils.od_extend(l_reg_list, RegisterTypeInt32u('WDigIo', 'Active power setpoint Digital I/O', 31235, l_slave_address, SitModbusRegister.ACCESS_MODE_R, '%', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))

        self.append_modbus_registers(l_reg_list)

        #		self.add_cc_only_sit_modbus_registers(1)
        #		self.add_common_sit_modbus_registers(2)

        self.invariants()

    def _header_rows(self):
        return [['#Mn', 'renke'], ['#Md', 'rs-ra-n01-jt']]

    def sma_fix2(self, a_sit_modbus_register):
        """
		"""
        l_new_val = a_sit_modbus_register.value / 100
        self._logger.debug(
            'sma_fix2->Setting new value-> old:{} new:{}'.format(
                a_sit_modbus_register.value, l_new_val))
        a_sit_modbus_register.value = l_new_val

    def _W_event(self, a_sit_modbus_register):
        """
		Called by modbus_device.call_sit_modbus_registers_events()
		"""
        self._logger.debug('_W_event-> register:{}'.format(
            a_sit_modbus_register.out_short()))
        l_short_desc = 'W'
        l_min_val = self.MIN_W_FOR_RAISE_EVENT_GENERATION
        l_val = a_sit_modbus_register.value
        l_sit_dt = SitDateTime()

        if a_sit_modbus_register.short_description == l_short_desc:
            l_start_time = time(8, 30)
            l_end_time = time(16, 30)
            l_is_day, l_valid_time = l_sit_dt.time_is_between(
                datetime.now().time(), l_start_time, l_end_time)
            #			l_is_between_sunrise_sunset = l_sit_dt.now_is_into_sunrise_sunset_from_conf(self._sit_json_conf)
            #
            #			self._logger.debug('read_sit_modbus_register-> l_is_day:{} l_valid_time:{} l_is_between_sunrise_sunset:{}'.format(l_is_day, l_valid_time, l_is_between_sunrise_sunset))
            l_msg = '_W_event-> register_index:{} value ({}) '.format(
                a_sit_modbus_register.register_index, l_val)
            l_msg += ' between {} and {}'.format(l_start_time, l_end_time)
            self._logger.info(
                '_W_event-> DEVICE IS GENERATING {} kW'.format(l_val))
            if (l_valid_time and l_val <= l_min_val):
                l_msg = '_W_event-> register_index:{} value ({} <= {}), valid_time:{}'.format(
                    a_sit_modbus_register.register_index, l_val, l_min_val,
                    l_valid_time)
                self._logger.warning(l_msg)
                # Create Dir
                l_dir = '/tmp/solarity_events'
                if not os.path.exists(l_dir):
                    os.makedirs(l_dir)
                l_file = self.__class__.__name__ + '_event_{}_register_{}_slave_{}'.format(
                    datetime.now().strftime("%Y%m%d_%H"),
                    a_sit_modbus_register.register_index,
                    a_sit_modbus_register.slave_address)
                l_file_abs_path = l_dir + '/' + l_file
                if not os.path.exists(l_file_abs_path):
                    self._logger.info(
                        '_W_event-> Event not sent, sending email file:{}'.
                        format(l_file_abs_path))
                    # SEND MAIL
                    l_subject = 'event with failure on $(hostname) slave:' + str(
                        a_sit_modbus_register.slave_address
                    ) + ' $(date +%Y%m%d_%H%M%S) W val:(' + str(
                        l_val) + ' <= ' + str(l_min_val) + ')W '
                    l_body = [
                        'event in slave:{} with failure on $(hostname) $(date +%Y%m%d_%H%M%S) review file {}'
                        .format(
                            a_sit_modbus_register.slave_address,
                            self.csv_file_path(
                                a_sit_modbus_register.slave_address))
                    ]
                    l_body.append(' Between {} and {}'.format(
                        l_start_time, l_end_time))
                    l_body.append('Register->out:{}'.format(
                        a_sit_modbus_register.out_human_readable(
                            a_with_description=self._args.long)))
                    l_subject, l_body = self._setted_parts(l_subject, l_body)
                    SitUtils.send_mail(
                        self.events_mail_receivers(), l_subject, l_body, [
                            self.csv_file_path(
                                a_sit_modbus_register.slave_address)
                        ])

                    os.mknod(l_file_abs_path)
                else:
                    self._logger.warning(
                        '_W_event-> Event already sent, not sending email file:{}'
                        .format(l_file_abs_path))

            else:
                l_msg = '_W_event-> Event not raised register_index:{} value ({} > {}), valid_time:{}'.format(
                    a_sit_modbus_register.register_index, l_val, l_min_val,
                    l_valid_time)
                self._logger.debug(l_msg)

# ACCESS

# IMPLEMENTATION

# EXECUTE ARGS

    """
		Parsing arguments and calling corresponding functions
	"""
    def execute_corresponding_args(self):
        try:
            self.connect()
            if self._args.verbose:
                self._logger.setLevel(logging.DEBUG)
            else:
                self._logger.setLevel(logging.INFO)
            if self._args.store_values or self._args.display_all or self._args.test or self._args.raise_event:
                assert self.valid_slave_address(
                    self._slave_address), 'Invalid slave address {}'.format(
                        self._slave_address)
                self.read_all_sit_modbus_registers()
                if self._args.store_values:
                    self.store_values_into_csv(self._sit_modbus_registers,
                                               self._slave_address)
                if self._args.display_all:
                    print(
                        self.out_human_readable(
                            a_with_description=self._args.long))
                if self._args.raise_event:
                    assert len(self._sit_modbus_registers
                               ) > 0, 'modbus_registers_not_empty'
                    self.call_sit_modbus_registers_events()
                if self._args.test:
                    self.test()


#			if self._args.manual_restart:
#				self.manual_restart()
        except Exception as l_e:
            self._logger.exception(
                "execute_corresponding_args-> Exception occured: %s" % (l_e))
            print('Error: %s' % (l_e))
            raise l_e
        finally:
            if self.is_connected():
                self.disconnect()
        self.invariants()

    def add_arg_parse_modbus_device(self):
        super().add_arg_parse()

    def add_arg_parse(self):
        """
		Override method
		"""
        self.add_arg_parse_modbus_device()
        self._parser.add_argument(
            '-e',
            '--raise_event',
            help='Raises the corresponding event if setted',
            action="store_true")
        #self._parser.add_argument('-r', '--manual_restart', help='Sends a manual restart to inverter manager', action="store_true")
        self._parser.add_argument('-c',
                                  '--slave_address',
                                  help='Slave address of modbus device',
                                  nargs='?')
        self._parser.add_argument('-p',
                                  '--usb_port',
                                  help='USB port',
                                  nargs='?')

    def add_required_named(self, a_required_named):
        pass

    def test(self):
        """
			Test function
		"""
        try:
            self._logger.info("################# BEGIN #################")
            #			l_sit_dt = SitDateTime()
            #			l_is_between_sunrise_sunset = l_sit_dt.now_is_into_sunrise_sunset_from_conf(self._sit_json_conf)
            #self.call_sit_modbus_registers_events(l_slave)
            #			self._logger.info("--> ************* device models *************: %s" % (l_d.models))	 #Lists properties to be loaded with l_d.<property>.read() and then access them
            #			self._logger.info("-->inverter ************* l_d.inverter.points *************: %s" % (l_d.inverter.points))	#Gives the inverter available properties
            #			self._logger.info("-->inverter ************* common *************: %s" % (l_d.common))
            #			self._logger.info("-->inverter ************* common Serial Number *************: %s" % (l_d.common.SN))
            self._logger.info("################# END #################")
        except Exception as l_e:
            self._logger.exception("Exception occured: %s" % (l_e))
            print('Error: %s' % (l_e))
            self._logger.error('Error: %s' % (l_e))
            raise l_e

    def events_mail_receivers(self):
        return [
            '*****@*****.**',
            '*****@*****.**'
        ]
        #return ['*****@*****.**']
        #return ['*****@*****.**', '*****@*****.**']

    def invariants_modbus_device(self):
        super().invariants()

    def invariants(self):
        self.invariants_modbus_device()
Beispiel #2
0
class SmartLogger1000a(SitModbusDevice):

    # CONSTANTS

    DEFAULT_SLAVE_ADDRESS = 1
    DEFAULT_MODBUS_PORT = 502
    DEFAULT_TARGET_MODE = SitModbusDevice.TARGET_MODE_TCP
    MIN_W_FOR_RAISE_EVENT_GENERATION = 5000
    PARSER_DESCRIPTION = 'Actions with Huawei smart logger 1000a device. ' + SitConstants.DEFAULT_HELP_LICENSE_NOTICE

    # CLASS ATTRIBUTES

    _byte_order = Endian.Big
    _word_order = Endian.Big
    _substract_one_to_register_index = False

    # FUNCTIONS DEFINITION
    """
		Initialize
	"""
    def __init__(self,
                 a_slave_address=DEFAULT_SLAVE_ADDRESS,
                 a_port=DEFAULT_MODBUS_PORT,
                 an_ip_address=None):
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)
        try:
            self.init_arg_parse()
            assert self.valid_slave_address(
                a_slave_address
            ), 'a_slave_address parameter invalid:{}'.format(l_slave_address)
            l_slave_address = a_slave_address
            if __name__ == '__main__':
                if (hasattr(self._args, 'slave_address')
                        and self._args.slave_address):
                    l_slave_address = self._args.slave_address
            super().__init__(l_slave_address,
                             self.DEFAULT_TARGET_MODE,
                             a_port=self.DEFAULT_MODBUS_PORT,
                             an_ip_address=self._args.host_ip)
            self._logger = SitLogger().new_logger(self.__class__.__name__,
                                                  self._args.host_mac)
            self._init_sit_modbus_registers(l_slave_address)

            self.invariants()
            #self._logger.debug('init->' + self.out())
        except OSError as l_e:
            self._logger.warning(
                "init-> OSError, probably rollingfileAppender" % (l_e))
            if e.errno != errno.ENOENT:
                raise l_e
        except Exception as l_e:
            print('Error in init: %s' % (l_e))
            raise l_e
            #exit(1)

    def _init_sit_modbus_registers(self, a_slave_address):
        """
			Initializes self._sit_modbus_registers
		"""
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)
        self.add_common_sit_modbus_registers(1)

        self.invariants()

    def add_common_sit_modbus_registers(self, a_slave_address):
        """
		Common devices registers
		"""
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)
        assert a_slave_address == 1 or a_slave_address >= 3, 'Dont ask for slave_address 2, the add_cc_only_sit_modbus_registers is done for that! addr:{}'.format(
            a_slave_address)

        l_reg_list = OrderedDict()
        l_slave_address = a_slave_address
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeStringVar(SitConstants.SS_REG_SHORT_ABB_SERIAL_NUMBER,
                                  'ESN',
                                  40713,
                                  10,
                                  l_slave_address,
                                  SitModbusRegister.ACCESS_MODE_R,
                                  'W',
                                  an_is_metadata=True))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(SitConstants.SS_REG_SHORT_ABB_AC_POWER,
                               'Total active output power of all inverters',
                               40525,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               'W',
                               an_is_metadata=False,
                               an_event=SitModbusRegisterEvent(self._W_event)))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(
                SitConstants.SS_REG_SHORT_ABB_AC_S_REACTIVE_POWER,
                'Reactive power',
                40544,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'kVar',
                an_is_metadata=False))

        # Active power control
        #	SitUtils.od_extend(l_reg_list, RegisterTypeInt16u(SitConstants.SS_REG_SHORT_ABB_STATUS_OPERATING_STATE, 'Plant Status 1=Unlimited/2Limited/3Idle/4Fault/5Communication_interrupt', 40543, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'Enum', an_is_metadata=False)) # Not working on tranque sante and maristas santamaria
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt16u('PlantSt2',
                               'Plant Status 2 0=ildle/1=on-grid/...',
                               40566,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               'Enum',
                               an_is_metadata=False))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt16u('ActPwrCtlMode',
                               'Active power control mode 0=no limit/other...',
                               40737,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               'Enum',
                               an_is_metadata=False))
        #Meter
        # UNABLE TO READ IT SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('WMeter', 'Active power of meter', 32278, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'W', an_is_metadata=False))

        #Huawei specials
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(
                SitConstants.SS_REG_SHORT_EXTRA_HUAWEI_ACT_POWER_ADJ,
                'Active Power adjustment',
                40426,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'Int',
                an_is_metadata=False))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt16u(
                SitConstants.SS_REG_SHORT_EXTRA_HUAWEI_ACT_POWER_ADJ_PCT,
                'Active Power adjustment percentage',
                40428,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                '%',
                an_is_metadata=False))

        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u(
                'LifeTimeKWHOut',
                'Equals the total energy yield generatedby all inverters.',
                40560,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'UInt',
                an_is_metadata=False))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u(
                'TodaykWhOutput',
                'Equals daily energy yield generated byall inverters.',
                40562,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'UInt',
                an_is_metadata=False))

        #SitUtils.od_extend(l_reg_list, RegisterTypeStrVar('Mn', 'Model', 30000, 15, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'String15', an_is_metadata=True))

        # CLUSTER AND INVERTERS
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32u('Vr', 'Version number of the SMA Modbus profile', 30001, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'Int32u', an_is_metadata=True))
        #
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32u('ID', 'SUSy ID (of the Cluster Controller)', 30003, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'Int32u', an_is_metadata=True))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32u('SN', 'Serial number (of the Cluster Controller)', 30005, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'Int32u', an_is_metadata=True))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('NewData', 'Modbus data change: meter value is increased by the Cluster Controller if new data is available.', 30007, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'Int32u', an_is_metadata=False))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeSmaCCDeviceClass('DeviceClass', 'Device Class', 30051, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'Enum', an_is_metadata=True))
        #
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('W', 'Current active power on all line conductors (W), accumulated values of the inverters', 30775, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'W', an_is_metadata=False, an_event=SitModbusRegisterEvent(self._W_event)))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt64u('Wh', 'Total energy fed in across all line conductors, in Wh (accumulated values of the inverters) System param', 30513, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'Wh', an_is_metadata=False))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('VAr', 'Reactive power on all line conductors (var), accumulated values of the inverters', 30805, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'VAr', an_is_metadata=False))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt64u('TotWhDay', 'Energy fed in on current day across all line conductors, in Wh (accumulated values of the inverters)', 30517, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'Wh', an_is_metadata=False))
        #
        self.append_modbus_registers(l_reg_list)

    def _W_event(self, a_sit_modbus_register):
        """
		Called by modbus_device.call_sit_modbus_registers_events()
		"""
        self._logger.debug('_W_event-> register:{}'.format(
            a_sit_modbus_register.out_short()))
        l_short_desc = 'W'
        l_min_val = self.MIN_W_FOR_RAISE_EVENT_GENERATION
        l_val = a_sit_modbus_register.value
        l_sit_dt = SitDateTime()

        if a_sit_modbus_register.short_description == l_short_desc:
            l_start_time = time(8, 30)
            l_end_time = time(16, 30)
            l_is_day, l_valid_time = l_sit_dt.time_is_between(
                datetime.now().time(), l_start_time, l_end_time)
            #			l_is_between_sunrise_sunset = l_sit_dt.now_is_into_sunrise_sunset_from_conf(self._sit_json_conf)
            #
            #			self._logger.debug('read_sit_modbus_register-> l_is_day:{} l_valid_time:{} l_is_between_sunrise_sunset:{}'.format(l_is_day, l_valid_time, l_is_between_sunrise_sunset))
            l_msg = '_W_event-> register_index:{} value ({}) '.format(
                a_sit_modbus_register.register_index, l_val)
            l_msg += ' between {} and {}'.format(l_start_time, l_end_time)
            self._logger.info(
                '_W_event-> DEVICE IS GENERATING {} kW'.format(l_val))
            if (l_valid_time and l_val <= l_min_val):
                l_msg = '_W_event-> register_index:{} value ({} <= {}), valid_time:{}'.format(
                    a_sit_modbus_register.register_index, l_val, l_min_val,
                    l_valid_time)
                self._logger.warning(l_msg)
                # Create Dir
                l_dir = '/tmp/solarity_events'
                if not os.path.exists(l_dir):
                    os.makedirs(l_dir)
                l_file = self.__class__.__name__ + '_event_{}_register_{}_slave_{}'.format(
                    datetime.now().strftime("%Y%m%d_%H"),
                    a_sit_modbus_register.register_index,
                    a_sit_modbus_register.slave_address)
                l_file_abs_path = l_dir + '/' + l_file
                if not os.path.exists(l_file_abs_path):
                    self._logger.info(
                        '_W_event-> Event not sent, sending email file:{}'.
                        format(l_file_abs_path))
                    # SEND MAIL
                    l_subject = 'event with failure on $(hostname) slave:' + str(
                        a_sit_modbus_register.slave_address
                    ) + ' $(date +%Y%m%d_%H%M%S) W val:(' + str(
                        l_val) + ' <= ' + str(l_min_val) + ')W '
                    l_body = [
                        'event in slave:{} with failure on $(hostname) $(date +%Y%m%d_%H%M%S) review file {}'
                        .format(
                            a_sit_modbus_register.slave_address,
                            self.csv_file_path(
                                a_sit_modbus_register.slave_address))
                    ]
                    l_body.append(' Between {} and {}'.format(
                        l_start_time, l_end_time))
                    l_body.append('Register->out:{}'.format(
                        a_sit_modbus_register.out_human_readable(
                            a_with_description=self._args.long)))
                    l_subject, l_body = self._setted_parts(l_subject, l_body)
                    SitUtils.send_mail(
                        self.events_mail_receivers(), l_subject, l_body, [
                            self.csv_file_path(
                                a_sit_modbus_register.slave_address)
                        ])

                    os.mknod(l_file_abs_path)
                else:
                    self._logger.warning(
                        '_W_event-> Event already sent, not sending email file:{}'
                        .format(l_file_abs_path))

            else:
                l_msg = '_W_event-> Event not raised register_index:{} value ({} > {}), valid_time:{}'.format(
                    a_sit_modbus_register.register_index, l_val, l_min_val,
                    l_valid_time)
                self._logger.debug(l_msg)

    def _setted_parts(self, a_subject, a_body):
        return a_subject, a_body

    def manual_restart(self):
        """
		Manual restart 
		documented on p.45 of doc
		"""
        l_res = 'test_res'
        self._logger.info('manual_restart-> NOW')
        #a_register_index, a_slave_address, a_value):
        l_res = self.write_register_value(0, 201, 1)
        self._logger.info('manual_restart-> result:{}'.format(l_res))

        return l_res

    def read_all_sit_modbus_registers(self):
        """
		Read inverters data
		"""
        super().read_all_sit_modbus_registers()

#		l_reg_index = 42109
#		l_slave_address = 3
#		self.read_inverter_data(l_slave_address)

    def read_inverter_data(self, a_slave_address):
        """
		Was for test but not working
		"""
        assert False, 'deprecated'
        l_reg = RegisterTypeInt64u(
            'Wh2',
            'Total energy fed in across all line conductors, in Wh (accumulated values of the inverters) System param',
            30513,
            SitModbusRegister.ACCESS_MODE_R,
            'Wh',
            an_is_metadata=False,
            a_slave_address=a_slave_address)
        self.read_inverter_data_register(l_reg, a_slave_address)
        print(l_reg.out_human_readable(a_with_description=True))

#		l_reg = RegisterTypeInt32u('SN', 'Serial Number', a_reg_index + 1, SitModbusRegister.ACCESS_MODE_R, 'Int32u', an_is_metadata=True)
#		self.read_inverter_data_register(l_reg, a_slave_address)
#
#		l_reg = RegisterTypeInt16u('UnitID', 'Unit ID', a_reg_index + 3, SitModbusRegister.ACCESS_MODE_R, 'Int32u', an_is_metadata=True)
#		self.read_inverter_data_register(l_reg, a_slave_address)

    def read_inverter_data_register(self, a_register, a_slave_address):
        """
		Reads given inverter data
		Was for test but not working
		"""
        assert False, 'deprecated'
        try:
            self.read_sit_modbus_register(a_register, a_slave_address)
            if self._args.store_values:
                pass

    #			self.store_values_into_csv([l_reg], l_slave)
            if self._args.display_all:
                print('***************** INVERTER slave:{} ******************'.
                      format(a_slave_address))
                print(
                    a_register.out_human_readable(
                        a_with_description=self._args.long))
        except ModbusException as l_e:
            self._logger.error(
                'read_inverter_data-> error reading register {}'.format(l_e))
        except Exception as l_e:
            raise l_e

# ACCESS

# IMPLEMENTATION

# EXECUTE ARGS
    """
		Parsing arguments and calling corresponding functions
	"""
    def execute_corresponding_args(self):
        try:
            self.connect()
            if self._args.verbose:
                self._logger.setLevel(logging.DEBUG)
            else:
                self._logger.setLevel(logging.INFO)
            if self._args.store_values or self._args.display_all or self._args.test or self._args.raise_event:
                assert self.valid_slave_address(
                    self._slave_address), 'Invalid slave address {}'.format(
                        self._slave_address)
                self.read_all_sit_modbus_registers()
                if self._args.store_values:
                    self.store_values_into_csv(self._sit_modbus_registers,
                                               self._slave_address)
                if self._args.display_all:
                    print(
                        self.out_human_readable(
                            a_with_description=self._args.long))
                if self._args.raise_event:
                    assert len(self._sit_modbus_registers
                               ) > 0, 'modbus_registers_not_empty'
                    self.call_sit_modbus_registers_events()
                if self._args.test:
                    self.test()


#			if self._args.manual_restart:
#				self.manual_restart()
        except Exception as l_e:
            self._logger.exception(
                "execute_corresponding_args-> Exception occured: %s" % (l_e))
            print('Error: %s' % (l_e))
            raise l_e
        finally:
            if self.is_connected():
                self.disconnect()
        self.invariants()

    def add_arg_parse_modbus_device(self):
        super().add_arg_parse()

    def add_arg_parse(self):
        """
		Override method
		"""
        self.add_arg_parse_modbus_device()
        self._parser.add_argument(
            '-e',
            '--raise_event',
            help='Raises the corresponding event if setted',
            action="store_true")
        #self._parser.add_argument('-r', '--manual_restart', help='Sends a manual restart to inverter manager', action="store_true")
        self._parser.add_argument('-c',
                                  '--slave_address',
                                  help='Slave address of modbus device',
                                  nargs='?')

    def add_required_named(self, a_required_named):
        pass

    def test(self):
        """
			Test function
		"""
        try:
            self._logger.info("################# BEGIN #################")
            #			l_sit_dt = SitDateTime()
            #			l_is_between_sunrise_sunset = l_sit_dt.now_is_into_sunrise_sunset_from_conf(self._sit_json_conf)
            #self.call_sit_modbus_registers_events(l_slave)
            #			self._logger.info("--> ************* device models *************: %s" % (l_d.models))	 #Lists properties to be loaded with l_d.<property>.read() and then access them
            #			self._logger.info("-->inverter ************* l_d.inverter.points *************: %s" % (l_d.inverter.points))	#Gives the inverter available properties
            #			self._logger.info("-->inverter ************* common *************: %s" % (l_d.common))
            #			self._logger.info("-->inverter ************* common Serial Number *************: %s" % (l_d.common.SN))
            self._logger.info("################# END #################")
        except Exception as l_e:
            self._logger.exception("Exception occured: %s" % (l_e))
            print('Error: %s' % (l_e))
            self._logger.error('Error: %s' % (l_e))
            raise l_e

    def events_mail_receivers(self):
        return [
            '*****@*****.**',
            '*****@*****.**'
        ]
        #return ['*****@*****.**']
        #return ['*****@*****.**', '*****@*****.**']

    def invariants_modbus_device(self):
        super().invariants()

    def invariants(self):
        self.invariants_modbus_device()
class SunnyTripower60(InverterManager):

    # CONSTANTS

    DEFAULT_SLAVE_ADDRESS = 126
    MIN_KW_FOR_RAISE_EVENT_GENERATION = 5

    # FUNCTIONS DEFINITION
    """
		Initialize
	"""
    def __init__(self, a_slave_address=DEFAULT_SLAVE_ADDRESS):
        assert self.valid_slave_address(
            a_slave_address), 'init invalid slave address'
        try:
            self.init_arg_parse()
            l_slave_address = a_slave_address
            if (hasattr(self._args, 'slave_address')
                    and self._args.slave_address):
                self._slave_addresses_list = SitUtils.args_to_list(
                    self._args.slave_address)
            if self._slave_addresses_list is None:
                self._slave_addresses_list = [a_slave_address]

            assert self.valid_slave_address_list(
                self._slave_addresses_list
            ), 'Given script arguments are not valid, or could not be parsed:{}'.format(
                self._slave_addresses_list)
            assert self.valid_ip(
                self._args.host_ip), 'valid ip address:{}'.format(
                    self._args.host_ip)

            #a_slave_address=DEFAULT_SLAVE_ADDRESS, a_port=DEFAULT_MODBUS_PORT, an_ip_address=None
            super().__init__(l_slave_address,
                             a_port=self.DEFAULT_MODBUS_PORT,
                             an_ip_address=self._args.host_ip)
            self._logger = SitLogger().new_logger(__name__,
                                                  self._args.host_mac)
            #self._logger.debug('init->' + self.out())
        except OSError as l_e:
            self._logger.warning(
                "init-> OSError, probably rollingfileAppender" % (l_e))
            if e.errno != errno.ENOENT:
                raise l_e
        except Exception as l_e:
            print('Error in init: %s' % (l_e))
            raise l_e
            #exit(1)
        self.invariants()

    def _init_sit_modbus_registers(self, a_slave_address):
        """
			Initializes self._sit_modbus_registers
		"""
        assert len(self._sit_modbus_registers) == 0
        l_reg_list = OrderedDict()
        l_slave_address = a_slave_address

        self._add_common_registers(l_reg_list, l_slave_address)

        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt16uScaleFactor('A',
                                          'AC Current sum of all inverters',
                                          40188,
                                          l_slave_address,
                                          SitModbusRegister.ACCESS_MODE_R,
                                          'A',
                                          a_scale_factor=40192))

        self.append_modbus_registers(l_reg_list)

        #error self.add_modbus_register('ID', 'Model ID (ID): 120 = Sunspec nameplate model', 40238, SitModbusRegister.REGISTER_TYPE_INT_16_U, SitModbusRegister.ACCESS_MODE_R, 'uint16')
        #error self.add_modbus_register('VArPct_Mod', 'Mode of the percentile reactive power limitation: 1 = in % of WMax', 40365, SitModbusRegister.REGISTER_TYPE_ENUM_16, SitModbusRegister.ACCESS_MODE_R, 'enum16')
        #self.add_modbus_register('VArPct_Ena', 'Control of the percentile reactive power limitation,(SMA: Qext): 1 = activated', 40365, SitModbusRegister.REGISTER_TYPE_ENUM_16, SitModbusRegister.ACCESS_MODE_RW, 'enum16')
        self.invariants()

    """
		Parsing arguments and calling corresponding functions
	"""

    def execute_corresponding_args(self):
        self.invariants()
        try:
            self.connect()
            if self._args.verbose:
                self._logger.setLevel(logging.DEBUG)
            else:
                self._logger.setLevel(logging.INFO)
            if (self._args.store_values or self._args.display_all
                    or self._args.raise_event or self._args.test):
                assert self.valid_slave_address_list(
                    self._slave_addresses_list
                ), 'Slave addresses list is invalid:{}'.format(
                    self._slave_addresses_list)
                # FOR EACH SLAVE
                for l_slave in self._slave_addresses_list:
                    self._sit_modbus_registers = OrderedDict()
                    try:
                        self._init_sit_modbus_registers(l_slave)
                        assert len(self._sit_modbus_registers
                                   ) > 0, 'modbusregisters empty'
                        self.read_all_sit_modbus_registers()
                        if self._args.store_values:
                            self.store_values_into_csv(
                                self._sit_modbus_registers, l_slave)
                        if self._args.display_all:
                            print(
                                self.out_human_readable(
                                    a_with_description=self._args.long))
                        if self._args.raise_event:
                            self.call_sit_modbus_registers_events()
                        if self._args.test:
                            self.test()
                    except ModbusException as l_e:
                        self._logger.exception(
                            'execute_corresponding_args Exception:{}'.format(
                                l_e), l_e)
                        #pass it because of other slave addresses
                    except Exception as l_e:
                        self._logger.exception(
                            'execute_corresponding_args Exception:{}'.format(
                                l_e), l_e)
                        raise l_e
        except Exception as l_e:
            self._logger.exception(
                "execute_corresponding_args-> Exception occured: %s" % (l_e))
            print('Error: %s' % (l_e))
            raise l_e
        finally:
            if self.is_connected():
                self.disconnect()
        self.invariants()

    def add_arg_parse(self):
        """
		Override method
		"""
        self.add_arg_parse_modbus_device()
        self._parser.add_argument(
            '-e',
            '--raise_event',
            help='Raises the corresponding event if setted',
            action="store_true")
        self._parser.add_argument('-c',
                                  '--slave_address',
                                  help='Slave address of modbus device',
                                  nargs='?',
                                  required=True)

    """
		Test function
	"""

    def test(self):
        self.invariants()
        try:
            print("################# BEGIN #################")
            #			self._logger.info("--> ************* device models *************: %s" % (l_d.models))	 #Lists properties to be loaded with l_d.<property>.read() and then access them
            #			self._logger.info("-->inverter ************* l_d.inverter.points *************: %s" % (l_d.inverter.points))	#Gives the inverter available properties
            #			self._logger.info("-->inverter ************* common *************: %s" % (l_d.common))
            #			self._logger.info("-->inverter ************* common Serial Number *************: %s" % (l_d.common.SN))
            print("################# END #################")
        except Exception as l_e:
            self._logger.exception("Exception occured: %s" % (l_e))
            print('Error: %s' % (l_e))
            self._logger.error('Error: %s' % (l_e))
            raise l_e
        self.invariants()

    def invariants(self):
        self.invariants_modbus_device()
class DataManager(SitModbusDevice):

    # CONSTANTS

    DEFAULT_SLAVE_ADDRESS = 1
    DEFAULT_MODBUS_PORT = 502
    DEFAULT_TARGET_MODE = SitModbusDevice.TARGET_MODE_TCP
    MIN_W_FOR_RAISE_EVENT_GENERATION = 2000
    PARSER_DESCRIPTION = 'Actions with sma data manager device. ' + SitConstants.DEFAULT_HELP_LICENSE_NOTICE

    # CLASS ATTRIBUTES

    _byte_order = Endian.Big
    _word_order = Endian.Big
    _substract_one_to_register_index = False

    # FUNCTIONS DEFINITION
    """
		Initialize
	"""
    def __init__(self,
                 a_slave_address=DEFAULT_SLAVE_ADDRESS,
                 a_port=DEFAULT_MODBUS_PORT,
                 an_ip_address=None):
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)
        try:
            self.init_arg_parse()
            assert self.valid_slave_address(
                a_slave_address
            ), 'a_slave_address parameter invalid:{}'.format(l_slave_address)
            l_slave_address = a_slave_address
            if __name__ == '__main__':
                if (hasattr(self._args, 'slave_address')
                        and self._args.slave_address):
                    l_slave_address = self._args.slave_address
            super().__init__(l_slave_address,
                             self.DEFAULT_TARGET_MODE,
                             a_port=self.DEFAULT_MODBUS_PORT,
                             an_ip_address=self._args.host_ip)
            self._logger = SitLogger().new_logger(self.__class__.__name__,
                                                  self._args.host_mac)
            self._init_sit_modbus_registers(l_slave_address)

            self.invariants()
            #self._logger.debug('init->' + self.out())
        except OSError as l_e:
            self._logger.warning(
                "init-> OSError, probably rollingfileAppender" % (l_e))
            if e.errno != errno.ENOENT:
                raise l_e
        except Exception as l_e:
            print('Error in init: %s' % (l_e))
            raise l_e
            #exit(1)

    def _init_sit_modbus_registers(self, a_slave_address):
        """
			Initializes self._sit_modbus_registers
		"""
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)
        self.add_common_sit_modbus_registers(1)
        self.add_dm_only_sit_modbus_registers(2)

        self.invariants()

    def add_common_sit_modbus_registers(self, a_slave_address):
        """
		Common devices registers
		"""
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)
        assert a_slave_address == 1 or a_slave_address >= 3, 'Dont ask for slave_address 2, the add_cc_only_sit_modbus_registers is done for that! addr:{}'.format(
            a_slave_address)

        l_reg_list = OrderedDict()
        l_slave_address = a_slave_address

        # CLUSTER AND INVERTERS
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u('Vr',
                               'Version number of the SMA Modbus profile',
                               30001,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               'Int32u',
                               an_is_metadata=True))

        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u('ID',
                               'SUSy ID (of the Data manager)',
                               30003,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               'Int32u',
                               an_is_metadata=True))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u('SN',
                               'Serial number (of the Cluster Controller)',
                               30005,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               'Int32u',
                               an_is_metadata=True))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(
                'NewData',
                'Modbus data change: meter value is increased by the Cluster Controller if new data is available.',
                30007,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'Int32u',
                an_is_metadata=False))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeSmaCCDeviceClass('DeviceClass',
                                         'Device Class',
                                         30051,
                                         l_slave_address,
                                         SitModbusRegister.ACCESS_MODE_R,
                                         'Enum',
                                         an_is_metadata=True))

        # Doc tells unitID=2?? p.16
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(
                'W',
                'Current active power on all line conductors (W), accumulated values of the inverters',
                30775,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'W',
                an_is_metadata=False,
                an_event=SitModbusRegisterEvent(self._W_event)))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt64u(
                'Wh',
                'Total energy fed in across all line conductors, in Wh (accumulated values of the inverters) System param',
                30513,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'Wh',
                an_is_metadata=False))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(
                'VAr',
                'Reactive power on all line conductors (var), accumulated values of the inverters',
                30805,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'VAr',
                an_is_metadata=False))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt64u(
                'TotWhDay',
                'Energy fed in on current day across all line conductors, in Wh (accumulated values of the inverters)',
                30517,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'Wh',
                an_is_metadata=False))

        self.append_modbus_registers(l_reg_list)

    def add_dm_only_sit_modbus_registers(self, a_slave_address):
        """
		Registers particular to cluster controller
		"""
        assert self.valid_slave_address(
            a_slave_address), 'invalid a_slave_address:{}'.format(
                a_slave_address)
        assert a_slave_address == 2, 'add_cc_only_sit_modbus_registers->for this part slave_address should be =2 and is:{}'.format(
            a_slave_address)

        l_reg_list = OrderedDict()
        l_slave_address = a_slave_address
        #
        #PARAMETERS UNIT_ID = 2 (p.26 of doc)
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u('WDigIo',
                               'Active power setpoint Digital I/O',
                               31235,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               '%',
                               an_is_metadata=False,
                               a_post_set_value_call=self.sma_fix2))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u('WAnalog',
                               'Active power setpoint Analog',
                               31237,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               '%',
                               an_is_metadata=False,
                               a_post_set_value_call=self.sma_fix2))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u('WSetPoint',
                               'Active power setpoint in %s',
                               31239,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               '%',
                               an_is_metadata=False,
                               a_post_set_value_call=self.sma_fix2))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(
                'WSetPointDirMar',
                'Active power setpoint in %s Specification Modbus Direct marketing',
                31241,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                '%',
                an_is_metadata=False,
                a_post_set_value_call=self.sma_fix2))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u(
                'ResSetPoint',
                'Resulting setpoint (minimum value definition of all specifications)',
                31243,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                '%',
                an_is_metadata=False,
                a_post_set_value_call=self.sma_fix2))
        #Strange
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(
                'WExport',
                'Current utility grid export active power P in W (actual value of the active power fed in at the grid-connection point; measured with an external measuring device).',
                31249,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                '%',
                an_is_metadata=False))

        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32s(
                'VArExport',
                'Current utility grid export reactive power Q in VAr (actual value of the reactive power fed in at the grid- connection point; measured with an external measuring device).',
                31251,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                '%',
                an_is_metadata=False))

        #SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('AC_1', 'Analog current input 1 (mA)', 34637, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'mA', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('AC_2', 'Analog current input 2 (mA)', 34639, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'mA', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('AC_3', 'Analog current input 3 (mA)', 34641, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'mA', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('AC_4', 'Analog current input 4 (mA)', 34643, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'mA', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))
        #
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('InDCV_1', 'Analog voltage input 1 (V)', 34645, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'V', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('InDCV_2', 'Analog voltage input 2 (V)', 34647, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'V', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('InDCV_3', 'Analog voltage input 3 (V)', 34649, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'V', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))
        #		SitUtils.od_extend(l_reg_list, RegisterTypeInt32s('InDCV_4', 'Analog voltage input 4 (V)', 34651, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'V', an_is_metadata=False, a_post_set_value_call=self.sma_fix2))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt16s(
                'WSetPointDirTotal',
                'Direct marketer: Active power setpoint P, in % of the maximum active power (PMAX) of the PV plant. -100-0=Load|0=No active power|0-100 generator',
                40493,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                '%',
                an_is_metadata=False,
                a_post_set_value_call=self.sma_fix2))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u('WSetPointMan',
                               'Active power setpoint (manual specification)',
                               41167,
                               l_slave_address,
                               SitModbusRegister.ACCESS_MODE_R,
                               '%',
                               an_is_metadata=False,
                               a_post_set_value_call=self.sma_fix2))
        # IRRADIATIONS
        # not working on sanbe, getting max_int, SitUtils.od_extend(l_reg_list, RegisterTypeInt32u('IrradiationSurfaceTot', 'Total irradiation on the sensor surface (W/m2)', 34613, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'W/m2', an_is_metadata=False))
        SitUtils.od_extend(
            l_reg_list,
            RegisterTypeInt32u(
                'GHI',
                'Total irradiation on the external irradiation sensor/pyranometer (W/m2)',
                34623,
                l_slave_address,
                SitModbusRegister.ACCESS_MODE_R,
                'W/m2',
                an_is_metadata=False))

        self.append_modbus_registers(l_reg_list)

    def sma_fix2(self, a_sit_modbus_register):
        """
		"""
        l_new_val = a_sit_modbus_register.value / 100
        self._logger.debug(
            'sma_fix2->Setting new value-> old:{} new:{}'.format(
                a_sit_modbus_register.value, l_new_val))
        a_sit_modbus_register.value = l_new_val

    def _W_event(self, a_sit_modbus_register):
        """
		Called by modbus_device.call_sit_modbus_registers_events()
		"""
        self._logger.debug('_W_event-> register:{}'.format(
            a_sit_modbus_register.out_short()))
        l_short_desc = 'W'
        l_min_val = self.MIN_W_FOR_RAISE_EVENT_GENERATION
        l_val = a_sit_modbus_register.value
        l_sit_dt = SitDateTime()

        if a_sit_modbus_register.short_description == l_short_desc:
            l_start_time = time(8, 30)
            l_end_time = time(16, 30)
            l_is_day, l_valid_time = l_sit_dt.time_is_between(
                datetime.now().time(), l_start_time, l_end_time)
            #			l_is_between_sunrise_sunset = l_sit_dt.now_is_into_sunrise_sunset_from_conf(self._sit_json_conf)
            #
            #			self._logger.debug('read_sit_modbus_register-> l_is_day:{} l_valid_time:{} l_is_between_sunrise_sunset:{}'.format(l_is_day, l_valid_time, l_is_between_sunrise_sunset))
            l_msg = '_W_event-> register_index:{} value ({}) '.format(
                a_sit_modbus_register.register_index, l_val)
            l_msg += ' between {} and {}'.format(l_start_time, l_end_time)
            self._logger.info(
                '_W_event-> DEVICE IS GENERATING {} kW'.format(l_val))
            if (l_valid_time and l_val <= l_min_val):
                l_msg = '_W_event-> register_index:{} value ({} <= {}), valid_time:{}'.format(
                    a_sit_modbus_register.register_index, l_val, l_min_val,
                    l_valid_time)
                self._logger.warning(l_msg)
                # Create Dir
                l_dir = '/tmp/solarity_events'
                if not os.path.exists(l_dir):
                    os.makedirs(l_dir)
                l_file = self.__class__.__name__ + '_event_{}_register_{}_slave_{}'.format(
                    datetime.now().strftime("%Y%m%d_%H"),
                    a_sit_modbus_register.register_index,
                    a_sit_modbus_register.slave_address)
                l_file_abs_path = l_dir + '/' + l_file
                if not os.path.exists(l_file_abs_path):
                    self._logger.info(
                        '_W_event-> Event not sent, sending email file:{}'.
                        format(l_file_abs_path))
                    # SEND MAIL
                    l_subject = 'event with failure on $(hostname) slave:' + str(
                        a_sit_modbus_register.slave_address
                    ) + ' $(date +%Y%m%d_%H%M%S) W val:(' + str(
                        l_val) + ' <= ' + str(l_min_val) + ')W '
                    l_body = [
                        'event in slave:{} with failure on $(hostname) $(date +%Y%m%d_%H%M%S) review file {}'
                        .format(
                            a_sit_modbus_register.slave_address,
                            self.csv_file_path(
                                a_sit_modbus_register.slave_address))
                    ]
                    l_body.append(' Between {} and {}'.format(
                        l_start_time, l_end_time))
                    l_body.append('Register->out:{}'.format(
                        a_sit_modbus_register.out_human_readable(
                            a_with_description=self._args.long)))
                    l_subject, l_body = self._setted_parts(l_subject, l_body)
                    SitUtils.send_mail(
                        self.events_mail_receivers(), l_subject, l_body, [
                            self.csv_file_path(
                                a_sit_modbus_register.slave_address)
                        ])

                    os.mknod(l_file_abs_path)
                else:
                    self._logger.warning(
                        '_W_event-> Event already sent, not sending email file:{}'
                        .format(l_file_abs_path))

            else:
                l_msg = '_W_event-> Event not raised register_index:{} value ({} > {}), valid_time:{}'.format(
                    a_sit_modbus_register.register_index, l_val, l_min_val,
                    l_valid_time)
                self._logger.debug(l_msg)

    def _setted_parts(self, a_subject, a_body):
        return a_subject, a_body

    def manual_restart(self):
        """
		Manual restart 
		documented on p.45 of doc
		"""
        l_res = 'test_res'
        self._logger.info('manual_restart-> NOW')
        #a_register_index, a_slave_address, a_value):
        l_res = self.write_register_value(0, 201, 1)
        self._logger.info('manual_restart-> result:{}'.format(l_res))

        return l_res

    def read_all_sit_modbus_registers(self):
        """
		Read inverters data
		"""
        super().read_all_sit_modbus_registers()

#		l_reg_index = 42109
#		l_slave_address = 3
#		self.read_inverter_data(l_slave_address)

    def read_inverter_data(self, a_slave_address):
        """
		Was for test but not working
		"""
        assert False, 'deprecated'
        l_reg = RegisterTypeInt64u(
            'Wh2',
            'Total energy fed in across all line conductors, in Wh (accumulated values of the inverters) System param',
            30513,
            SitModbusRegister.ACCESS_MODE_R,
            'Wh',
            an_is_metadata=False,
            a_slave_address=a_slave_address)
        self.read_inverter_data_register(l_reg, a_slave_address)
        print(l_reg.out_human_readable(a_with_description=True))

#		l_reg = RegisterTypeInt32u('SN', 'Serial Number', a_reg_index + 1, SitModbusRegister.ACCESS_MODE_R, 'Int32u', an_is_metadata=True)
#		self.read_inverter_data_register(l_reg, a_slave_address)
#
#		l_reg = RegisterTypeInt16u('UnitID', 'Unit ID', a_reg_index + 3, SitModbusRegister.ACCESS_MODE_R, 'Int32u', an_is_metadata=True)
#		self.read_inverter_data_register(l_reg, a_slave_address)

    def read_inverter_data_register(self, a_register, a_slave_address):
        """
		Reads given inverter data
		Was for test but not working
		"""
        assert False, 'deprecated'
        try:
            self.read_sit_modbus_register(a_register, a_slave_address)
            if self._args.store_values:
                pass

    #			self.store_values_into_csv([l_reg], l_slave)
            if self._args.display_all:
                print('***************** INVERTER slave:{} ******************'.
                      format(a_slave_address))
                print(
                    a_register.out_human_readable(
                        a_with_description=self._args.long))
        except ModbusException as l_e:
            self._logger.error(
                'read_inverter_data-> error reading register {}'.format(l_e))
        except Exception as l_e:
            raise l_e

# ACCESS

# IMPLEMENTATION

# EXECUTE ARGS
    """
		Parsing arguments and calling corresponding functions
	"""
    def execute_corresponding_args(self):
        try:
            self.connect()
            if self._args.verbose:
                self._logger.setLevel(logging.DEBUG)
            else:
                self._logger.setLevel(logging.INFO)
            if self._args.store_values or self._args.display_all or self._args.test or self._args.raise_event:
                assert self.valid_slave_address(
                    self._slave_address), 'Invalid slave address {}'.format(
                        self._slave_address)
                self.read_all_sit_modbus_registers()
                if self._args.store_values:
                    self.store_values_into_csv(self._sit_modbus_registers,
                                               self._slave_address)
                if self._args.display_all:
                    print(
                        self.out_human_readable(
                            a_with_description=self._args.long))
                if self._args.raise_event:
                    assert len(self._sit_modbus_registers
                               ) > 0, 'modbus_registers_not_empty'
                    self.call_sit_modbus_registers_events()
                if self._args.test:
                    self.test()


#			if self._args.manual_restart:
#				self.manual_restart()
        except Exception as l_e:
            self._logger.exception(
                "execute_corresponding_args-> Exception occured: %s" % (l_e))
            print('Error: %s' % (l_e))
            raise l_e
        finally:
            if self.is_connected():
                self.disconnect()
        self.invariants()

    def add_arg_parse_modbus_device(self):
        super().add_arg_parse()

    def add_arg_parse(self):
        """
		Override method
		"""
        self.add_arg_parse_modbus_device()
        self._parser.add_argument(
            '-e',
            '--raise_event',
            help='Raises the corresponding event if setted',
            action="store_true")
        #self._parser.add_argument('-r', '--manual_restart', help='Sends a manual restart to inverter manager', action="store_true")
        self._parser.add_argument('-c',
                                  '--slave_address',
                                  help='Slave address of modbus device',
                                  nargs='?')

    def add_required_named(self, a_required_named):
        pass

    def test(self):
        """
			Test function
		"""
        try:
            self._logger.info("################# BEGIN #################")
            #			l_sit_dt = SitDateTime()
            #			l_is_between_sunrise_sunset = l_sit_dt.now_is_into_sunrise_sunset_from_conf(self._sit_json_conf)
            #self.call_sit_modbus_registers_events(l_slave)
            #			self._logger.info("--> ************* device models *************: %s" % (l_d.models))	 #Lists properties to be loaded with l_d.<property>.read() and then access them
            #			self._logger.info("-->inverter ************* l_d.inverter.points *************: %s" % (l_d.inverter.points))	#Gives the inverter available properties
            #			self._logger.info("-->inverter ************* common *************: %s" % (l_d.common))
            #			self._logger.info("-->inverter ************* common Serial Number *************: %s" % (l_d.common.SN))
            self._logger.info("################# END #################")
        except Exception as l_e:
            self._logger.exception("Exception occured: %s" % (l_e))
            print('Error: %s' % (l_e))
            self._logger.error('Error: %s' % (l_e))
            raise l_e

    def events_mail_receivers(self):
        return [
            '*****@*****.**',
            '*****@*****.**'
        ]
        #return ['*****@*****.**']
        #return ['*****@*****.**', '*****@*****.**']

    def invariants_modbus_device(self):
        super().invariants()

    def invariants(self):
        self.invariants_modbus_device()
Beispiel #5
0
class ClusterControllerInverter(ClusterController):

# CONSTANTS

	DEFAULT_SLAVE_ADDRESS = 3
	MIN_W_FOR_RAISE_EVENT_GENERATION = 50
	PARSER_DESCRIPTION = 'Actions with sma cluster controller inverter.  ' + SitConstants.DEFAULT_HELP_LICENSE_NOTICE

# CLASS ATTRIBUTES

	_byte_order = Endian.Big
	_word_order = Endian.Big
	_substract_one_to_register_index = False

	_slave_addresses_list = None
	_current_read_device_class = None
	_last_read_slave_address = None
	_last_read_serial_number = None

# INITIALIZE

	"""
		Initialize
	"""
	def __init__(self, a_slave_address=DEFAULT_SLAVE_ADDRESS, a_port=ClusterController.DEFAULT_MODBUS_PORT, an_ip_address=None):
		"""
		slave_address priority to commandline arguments
		"""
		assert self.valid_slave_address(a_slave_address), 'init invalid slave address'
		try:
			self.init_arg_parse()
			l_slave_address = a_slave_address
			if (hasattr(self._args, 'slave_address') and self._args.slave_address):
				self._slave_addresses_list = SitUtils.args_to_list(self._args.slave_address)

			assert self.valid_slave_address_list(self._slave_addresses_list), 'Given script arguments are not valid, or could not be parsed'
			assert self.valid_ip(self._args.host_ip), 'valid ip address:{}'.format(self._args.host_ip)

			super().__init__(l_slave_address, a_port=a_port, an_ip_address=self._args.host_ip) 
			self._logger = SitLogger().new_logger(self.__class__.__name__, self._args.host_mac)

			self.invariants()
			#self._logger.debug('init->' + self.out())
		except OSError as l_e:
			self._logger.warning("init-> OSError, probably rollingfileAppender" % (l_e))
			if e.errno != errno.ENOENT:
				raise l_e
		except Exception as l_e:
			print('Error in init: %s' % (l_e))
			raise l_e
			#exit(1)

	def _init_sit_modbus_registers(self, a_slave_address):
		"""
			Initializes self._sit_modbus_registers
		"""
		self.add_common_sit_modbus_registers(a_slave_address)
		#self.add_cc_only_sit_modbus_registers(a_slave_address)

		self.invariants()


	def add_common_sit_modbus_registers(self, a_slave_address):
		"""
		COMMON REGISTERS to ClusterController and Inverters
		"""
		super().add_common_sit_modbus_registers(a_slave_address)
		l_reg_list = OrderedDict()
		l_slave_address = a_slave_address

		#PARAMETERS UNIT_ID = 2 (p.26 of doc)
		SitUtils.od_extend(l_reg_list, RegisterTypeInt32u('EvtNr', '30213: For error description refere to SMA register address 30247; 30247: Description of the event message, see the documentation of the product', 30247, l_slave_address, SitModbusRegister.ACCESS_MODE_R, 'enum', an_is_metadata=False))


		#SitUtils.od_extend(l_reg_list, RegisterTypeInt32u('EvtNr', '30213: For error description refere to SMA register address 30247; 30247: Description of the event message, see the documentation of the product', 30247, SitModbusRegister.ACCESS_MODE_R, 'enum', an_is_metadata=False, a_slave_address=a_slave_address))

		self.append_modbus_registers(l_reg_list)


# MODBUS READING

	def read_all_sit_modbus_registers(self):
		"""
			Reads all registers and print result as debug
		"""
		self._logger.debug('read_all_sit_modbus_registers-> registers to read count({}) start --------------------------------------------------'.format(len(self._sit_modbus_registers)))

		for l_short_desc, l_sit_reg in self._sit_modbus_registers.items():
			self.read_sit_modbus_register(l_sit_reg)
			# Setting slave address if changed
			if self._last_read_slave_address != l_sit_reg.slave_address:
				self._current_read_device_class = None
				self._last_read_serial_number = None
				self._last_read_slave_address = l_sit_reg.slave_address
			#Setting device class
			if l_sit_reg.short_description == 'DeviceClass':
				self._current_read_device_class = l_sit_reg.value
			elif l_sit_reg.short_description == 'SN':
				self._last_read_serial_number = l_sit_reg.value
			if l_sit_reg.has_post_set_value_call():
				l_sit_reg.call_post_set_value()
			#self._logger.debug('read_all_registers-> sit_register.out():%s' % (l_sit_reg.out()))
			self._logger.debug('read_all_registers-> sit_register.out_short():%s' % (l_sit_reg.out_short()))


# EVENTS


	def _W_event(self, a_sit_modbus_register):
		"""
		REDEFINE

		Called by modbus_device.call_sit_modbus_registers_events()
		"""

		if 'PV inverter' in self._current_read_device_class:
			super()._W_event(a_sit_modbus_register)

	def _setted_parts(self, a_subject, a_body):
		"""
		return subject and body
		"""
		l_sub = a_subject + ' SN:{}'.format(self._last_read_serial_number)
		l_body = a_body
		return l_sub, l_body

# IMPLEMENTATION


# EXECUTE ARGS

	"""
		Parsing arguments and calling corresponding functions
	"""
	def execute_corresponding_args(self):
		try:
			self.connect()
			if self._args.verbose:
				self._logger.setLevel(logging.DEBUG)
			else:
				self._logger.setLevel(logging.INFO)
			if self._args.store_values or self._args.display_all or self._args.test or self._args.raise_event:
				assert self.valid_slave_address_list(self._slave_addresses_list), 'Slave addresses list is invalid:{}'.format(self._slave_addresses_list)
				self._logger.debug('execute_corresponding_args-> _slave_addresses_list:{}'.format(self._slave_addresses_list))
				# FOR EACH SLAVE
				for l_slave in self._slave_addresses_list: 
					self._sit_modbus_registers = OrderedDict()
					try:
						self._init_sit_modbus_registers(l_slave)
						self.read_all_sit_modbus_registers()
						if self._args.store_values:
							self.store_values_into_csv(self._sit_modbus_registers, l_slave)
						if self._args.display_all:
							print(self.out_human_readable(a_with_description=self._args.long))
						if self._args.raise_event:
							assert len(self._sit_modbus_registers) > 0, 'modbus_registers_not_empty'
							self.call_sit_modbus_registers_events()
						if self._args.test:
							self.test()
					except ModbusException as l_e:
						self._logger.error('Modbus error on slave {}, msg:{}'.format(l_slave, l_e))
					except Exception as l_e:
						self._logger.error('Exception on slave {}, msg:{}'.format(l_slave, l_e))
						raise l_e

		except Exception as l_e:
			self._logger.exception("execute_corresponding_args-> Exception occured: %s" % (l_e))
			print('Error: %s' % (l_e))
			raise l_e
		finally:
			if self.is_connected():
				self.disconnect()
		self.invariants()


	def add_arg_parse(self):
		"""
		Override method
		"""
		self.add_arg_parse_modbus_device()
		self._parser.add_argument('-e', '--raise_event', help='Raises the corresponding event if setted', action="store_true")
		self._parser.add_argument('-c', '--slave_address', help='Slave address of modbus device', nargs='?', required=True)

	def add_required_named(self, a_required_named):
		pass

	def test(self):
		"""
			Test function
		"""
		try:
			self._logger.info ("################# BEGIN #################")
#			l_sit_dt = SitDateTime()
#			l_is_between_sunrise_sunset = l_sit_dt.now_is_into_sunrise_sunset_from_conf(self._sit_json_conf)
			#self.call_sit_modbus_registers_events(l_slave)
#			self._logger.info("--> ************* device models *************: %s" % (l_d.models))	 #Lists properties to be loaded with l_d.<property>.read() and then access them
#			self._logger.info("-->inverter ************* l_d.inverter.points *************: %s" % (l_d.inverter.points))	#Gives the inverter available properties
#			self._logger.info("-->inverter ************* common *************: %s" % (l_d.common))	
#			self._logger.info("-->inverter ************* common Serial Number *************: %s" % (l_d.common.SN))	
			self._logger.info ("################# END #################")
		except Exception as l_e:
			self._logger.exception("Exception occured: %s" % (l_e))
			print('Error: %s' % (l_e))
			self._logger.error('Error: %s' % (l_e))
			raise l_e

	def invariants(self):
		self.invariants_modbus_device()
		assert isinstance(self._slave_addresses_list, list) or self._slave_addresses_list is None, 'self._slave_address is list or None {}'.format(self._slave_addresses_list)
		for l_slave in self._slave_addresses_list:
			assert l_slave >=3, 'l_slave >=3 not the case:{}'.format(l_slave)
class DirectMarketerInterface(InverterManager):

# CONSTANTS

	DEFAULT_SLAVE_ADDRESS = 200

# CLASS ATTRIBUTES

# FUNCTIONS DEFINITION 

	"""
		Initialize
	"""
	def __init__(self, a_slave_address=DEFAULT_SLAVE_ADDRESS):
		try:
			self.init_arg_parse()
			l_slave_address = self.DEFAULT_SLAVE_ADDRESS
			if self._args.slave_address:
				if self.valid_slave_address(self._args.slave_address):
					self._slave_address = int(self._args.slave_address)
			#self, a_slave_address=DEFAULT_SLAVE_ADDRESS, a_port=DEFAULT_MODBUS_PORT, an_ip_address=None
			super().__init__(l_slave_address, a_port=self.DEFAULT_MODBUS_PORT, an_ip_address=self._args.host_ip) 
			self._logger = SitLogger().new_logger(__name__, self._args.host_mac)
			self._init_sit_modbus_registers()
			#self._logger.debug('init->' + self.out())
		except OSError as l_e:
			self._logger.warning("init-> OSError, probably rollingfileAppender" % (l_e))
			if e.errno != errno.ENOENT:
				raise l_e
		except Exception as l_e:
			print('Error in init: %s' % (l_e))
			raise l_e
			#exit(1)

	def _init_sit_modbus_registers(self):
		"""
			Initializes self._sit_modbus_registers
		"""
		#	P.44 of doc
		self.add_modbus_register('OutLimitPerc', 'Specified output limitation through direct marketer n% (0-10000)', 1, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_RW, 'uint16')
		self.add_modbus_register('OutLimitPercMan', 'Manual output limitation that has been set via Sunspec Modbus', 2, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_R, 'uint16')
		self.add_modbus_register('OutLimitPercIoBox', 'Output limitation through the electric utility company that has been set via the IO box.', 3, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_R, 'uint16')
		self.add_modbus_register('OutLimitMin', 'Minimum of all output limitations. The nominal PV system power is derated to this value.', 4, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_R, 'uint16')
#		self.add_modbus_register('Md', 'Model (Md): SMA Inverter Manager', 40021, SitModbusRegister.REGISTER_TYPE_STRING_16, SitModbusRegister.ACCESS_MODE_R, 'String16')
#		self.add_modbus_register('Opt', 'Options (Opt): Inverter Manager name', 40037, SitModbusRegister.REGISTER_TYPE_STRING_8, SitModbusRegister.ACCESS_MODE_R, 'String8')
#		self.add_modbus_register('Vr', 'Version (Vr): Version number of the installed firmware', 40045, SitModbusRegister.REGISTER_TYPE_STRING_8, SitModbusRegister.ACCESS_MODE_R, 'String8')
#		self.add_modbus_register('SN', 'Serial number (SN) of the device that uses the Modbus unit ID', 40053, SitModbusRegister.REGISTER_TYPE_STRING_16, SitModbusRegister.ACCESS_MODE_R, 'String16')
#		self.add_modbus_register('PPVphA', 'Voltage, line conductor L1 to N (PPVphA), in V-V_SF (40199): average value of all inverters', 40196, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_R, 'V', 40199)
#		self.add_modbus_register('AC_A', 'AC Current sum of all inverters', 40188, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_R, 'A', 40192)
#		self.add_modbus_register('W', 'Active power (W), in W-W_SF (40201): sum of all inverters', 40200, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_R, 'W', 40192)
#		self.add_modbus_register('WH', 'Total yield (WH), in Wh WH_SF (40212): sum of all inverters', 40210, SitModbusRegister.REGISTER_TYPE_INT_32, SitModbusRegister.ACCESS_MODE_R, 'WH', 40212)
#		self.add_modbus_register('TmpCab', 'Internal temperature, in °C Tmp_SF (40223): average value of all inverters', 40219, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_R, '°C', 40223)
#		self.add_modbus_register('ID', 'Model ID (ID): 120 = Sunspec nameplate model', 40238, SitModbusRegister.REGISTER_TYPE_INT_16, SitModbusRegister.ACCESS_MODE_R, 'uint16')
#		self.add_modbus_register('VArPct_Mod', 'Mode of the percentile reactive power limitation: 1 = in % of WMax', 40365, SitModbusRegister.REGISTER_TYPE_ENUM_16, SitModbusRegister.ACCESS_MODE_R, 'enum16')
#		self.add_modbus_register('VArPct_Ena', 'Control of the percentile reactive power limitation,(SMA: Qext): 1 = activated', 40365, SitModbusRegister.REGISTER_TYPE_ENUM_16, SitModbusRegister.ACCESS_MODE_RW, 'enum16')

	def init_arg_parse(self):
		"""
			Parsing arguments
		"""
		self._parser = argparse.ArgumentParser(description='Actions with Inverter Manager through TCP')
		self._parser.add_argument('-v', '--verbose', help='increase output verbosity', action="store_true")
		self._parser.add_argument('-t', '--test', help='Runs test method', action="store_true")
		self._parser.add_argument('-u', '--slave_address', help='Slave address of modbus device', nargs='?')

		#self._parser.add_argument('-u', '--base_url', help='NOT_IMPLEMENTED:Gives the base URL for requests actions', nargs='?', default=self.DEFAULT_BASE_URL)
		l_required_named = self._parser.add_argument_group('required named arguments')
		l_required_named.add_argument('-i', '--host_ip', help='Host IP', nargs='?', required=True)
		l_required_named.add_argument('-m', '--host_mac', help='Host MAC', nargs='?', required=True)
#		l_required_named.add_argument('-l', '--longitude', help='Longitude coordinate (beware timezone is set to Chile)', nargs='?', required=True)
#		l_required_named.add_argument('-a', '--lattitude', help='Lattitude coordinate (beware timezone is set to Chile)', nargs='?', required=True)
#		l_required_named.add_argument('-d', '--device_type', help='Device Type:' + ('|'.join(str(l) for l in self.DEVICE_TYPES_ARRAY)), nargs='?', required=True)
		l_args = self._parser.parse_args()
		self._args = l_args

# ACCESS


# IMPLEMENTATION


# EXECUTE ARGS

	"""
		Parsing arguments and calling corresponding functions
	"""
	def execute_corresponding_args(self):
		if self._args.verbose:
			self._logger.setLevel(logging.DEBUG)
		else:
			self._logger.setLevel(logging.DEBUG)
		if self._args.test:
			self.test()

		#if self._args.store_values:

	"""
		Test function
	"""
	def test(self):
		try:
			self.connect()
			self.read_all_sit_modbus_registers()
			print ("################# BEGIN #################")
#			self._logger.info("--> ************* device models *************: %s" % (l_d.models))	 #Lists properties to be loaded with l_d.<property>.read() and then access them
#			self._logger.info("-->inverter ************* l_d.inverter.points *************: %s" % (l_d.inverter.points))	#Gives the inverter available properties
#			self._logger.info("-->inverter ************* common *************: %s" % (l_d.common))	
#			self._logger.info("-->inverter ************* common Serial Number *************: %s" % (l_d.common.SN))	
			print ("################# END #################")
		except Exception as l_e:
			self._logger.exception("Exception occured: %s" % (l_e))
			print('Error: %s' % (l_e))
			self._logger.error('Error: %s' % (l_e))
			raise l_e
		finally:
			self.disconnect()