def perform_update(): global stats try: # ignore local chmod permission command = "git config core.filemode false" # http://superuser.com/questions/204757/git-chmod-problem-checkout-screws-exec-bit subprocess.check_output(command.split()) command = "git reset --hard" subprocess.check_output(command.split()) command = "git pull" output = subprocess.check_output(command.split()).decode('utf8') # Go back to master (refactor is old): if checker is not None: if checker.status['remote_branch'] == 'origin/refactor': command = 'git checkout master' subprocess.check_output(command.split()) log.debug(NAME, _(u'Update result') + ': ' + output) if options.run_logEV: logEV.save_events_log( _(u'System OSPy'), _(u'Updated to version') + ': {}'.format(str(stats['ver_new']))) report_restarted() restart(wait=4) except Exception: log.error(NAME, _(u'System update plug-in') + ':\n' + traceback.format_exc())
def set_counter(i2cbus): try: addr = 0 if wind_options['address']: addr = 0x51 else: addr = 0x50 try_io(lambda: i2cbus.write_byte_data(addr, 0x00, 0x20) ) # status registr setup to "EVENT COUNTER" try_io(lambda: i2cbus.write_byte_data(addr, 0x01, 0x00)) # reset LSB try_io(lambda: i2cbus.write_byte_data(addr, 0x02, 0x00) ) # reset midle Byte try_io(lambda: i2cbus.write_byte_data(addr, 0x03, 0x00)) # reset MSB log.debug( NAME, _(u'Wind speed monitor plug-in') + ': ' + _(u'Setup PCF8583 as event counter - OK')) except: log.error( NAME, _(u'Wind speed monitor plug-in') + ':\n' + _(u'Setup PCF8583 as event counter - FAULT')) log.error( NAME, _(u'Wind speed monitor plug-in') + u'%s' % traceback.format_exc())
def POST(self): x = web.input(myfile={}) #web.debug(x['myfile'].filename) # This is the filename #web.debug(x['myfile'].value) # This is the file contents #web.debug(x['myfile'].file.read()) # Or use a file(-like) object try: name = '' name = x['myfile'].filename if name in ('voice.mp3', 'voice0.mp3', 'voice1.mp3', 'voice2.mp3', 'voice3.mp3', 'voice4.mp3', 'voice5.mp3', 'voice6.mp3', 'voice7.mp3', 'voice8.mp3', 'voice9.mp3', 'voice10.mp3', 'voice11.mp3', 'voice12.mp3', 'voice13.mp3', 'voice14.mp3', 'voice15.mp3', 'voice16.mp3', 'voice17.mp3', 'voice18.mp3', 'voice19.mp3', 'voice20.mp3'): fout = open(os.path.join(MP3_FILE_FOLDER, name), 'w') fout.write(x['myfile'].file.read()) fout.close() log.info(NAME, _('Saving MP3 %s file OK.') % name) else: log.info( NAME, _('Error. MP3 file: %s name is not voice.mp3 or voice0.mp3...voice20.mp3' ) % name) except Exception: log.error( NAME, _('Voice Notification plug-in') + ':\n' + traceback.format_exc()) raise web.seeother(plugin_url(settings_page), True)
def try_mail(text, logtext, attachment=None, subject=None): ### Try send e-mail ### log.clear(NAME) try: email(text, subject, attachment) # send email with attachment from log.info(NAME, _(u'E-mail was sent') + ':\n' + logtext) if not options.run_logEM: log.info(NAME, _(u'E-mail logging is disabled in options...')) else: logEM.save_email_log(subject or email_options['emlsubject'], logtext, _(u'Sent')) except Exception: log.error(NAME, _(u'E-mail was not sent! Connection to Internet not ready.')) logEM.save_email_log(subject or email_options['emlsubject'], logtext, _(u'E-mail was not sent! Connection to Internet not ready.')) if not options.run_logEM: log.info(NAME, _(u'E-mail logging is disabled in options...')) if email_options["emlrepeater"]: # saving e-mails is enabled data = {} data['date'] = str(datetime.now().strftime('%d.%m.%Y')) data['time'] = str(datetime.now().strftime('%H:%M:%S')) data['text'] = u'%s' % text data['logtext'] = u'%s' % logtext data['subject'] = u'%s' % email_options['emlsubject'] data['attachment'] = u'%s' % attachment update_saved_emails(data) # saving e-mail data to file: saved_emails.json
def notify_station_off(name, **kw): if plugin_options['enabled']: current_time = datetime.datetime.now() try: if int(current_time.hour) >= int( plugin_options['start_hour']) and int( current_time.hour) <= int(plugin_options['stop_hour']): st_nr = int(kw[u"txt"]) log.clear(NAME) log.info( NAME, datetime_string() + u': ' + _(u'Stations {} OFF').format(str(st_nr + 1))) data = {} if len(plugin_options['sounds']) > 0: data['song'] = plugin_options['sounds'][int( plugin_options['off'][st_nr])] path = os.path.join(plugin_data_dir(), data['song']) if os.path.isfile(path): update_song_queue(data) # save song name to song queue else: log.info( NAME, datetime_string() + u': ' + _(u'File not exists!')) except Exception: log.error( NAME, _(u'Voice Station plug-in') + ':\n' + traceback.format_exc())
def get_overview(): """Returns the info data as a list of lines.""" result = [] log.clear(NAME) meminfo = helpers.get_meminfo() netdevs = helpers.get_netdevs() result.append('System release: ' + platform.release()) result.append('System name: ' + platform.system()) result.append('Node: ' + platform.node()) result.append('Machine: ' + platform.machine()) result.append('Total memory: ' + meminfo['MemTotal']) result.append('Free memory: ' + meminfo['MemFree']) if netdevs: for dev, info in netdevs.items(): result.append('%-16s %s MiB %s MiB' % (dev + ':', info['rx'], info['tx'])) else: result.append('Network: Unknown') result.append('Uptime: ' + helpers.uptime()) result.append('CPU temp: ' + helpers.get_cpu_temp(options.temp_unit) + ' ' + options.temp_unit) result.append('MAC adress: ' + helpers.get_mac()) try: result.append('I2C HEX Adress:') rev = str(0 if helpers.get_rpi_revision() == 1 else 1) cmd = 'sudo i2cdetect -y ' + rev result.append(process(cmd)) except Exception: log.error(NAME, 'System info plug-in:\n' + traceback.format_exc()) log.info(NAME, result) return result
def try_mail(self, text, attachment=None): log.clear(NAME) try: email(text, attach=attachment) # send email with attachment from log.info(NAME, 'Email was sent:\n' + text) except Exception: log.error(NAME, 'Email was not sent!\n' + traceback.format_exc())
def GET(self): global must_stop qdict = web.input() if checker is not None: stop = helpers.get_input(qdict, 'stop', False, lambda x: True) clear = helpers.get_input(qdict, 'clear', False, lambda x: True) if 'test' in qdict: command = -1 data = {} if 'state' in qdict and int(qdict['state']) == 1: command = plugin_options['on'][int(qdict['test'])] if 'state' in qdict and int(qdict['state']) == 0: command = plugin_options['off'][int(qdict['test'])] if len(plugin_options['sounds']) > 0 and command != -1: data['song'] = plugin_options['sounds'][command] path = os.path.join(plugin_data_dir(), data['song']) if os.path.isfile(path): log.info( NAME, datetime_string() + u': ' + _(u'Button test, song {}.').format(data['song'])) update_song_queue(data) # save song name to song queue else: log.info( NAME, datetime_string() + u': ' + _(u'File not exists!')) else: log.info( NAME, datetime_string() + u': ' + _(u'File not exists!')) if stop: must_stop = True log.info(NAME, datetime_string() + u': ' + _(u'Button Stop.')) if clear: must_stop = True song_queue = read_song_queue() while len(song_queue) > 0: song_queue = read_song_queue() del song_queue[0] write_song_queue(song_queue) log.clear(NAME) log.info( NAME, datetime_string() + u': ' + _(u'Button clear playlist.')) try: return self.plugin_render.voice_station(plugin_options, log.events(NAME)) except Exception: log.error( NAME, _(u'Voice Station plug-in') + ':\n' + traceback.format_exc()) set_to_default() return self.plugin_render.voice_station(plugin_options, log.events(NAME))
def POST(self): qdict = web.input() #print 'qdict: ', qdict try: ### add code to update commands ### if 'use_control' in qdict: if qdict['use_control'] == 'on': plugin_options.__setitem__( 'use_control', True) #__setitem__(self, key, value) else: plugin_options.__setitem__('use_control', False) commands = {u'on': [], u'off': []} for i in range(options.output_count): commands['on'].append(qdict['con' + str(i)]) commands['off'].append(qdict['coff' + str(i)]) #print 'commands: ', commands plugin_options.__setitem__('on', commands['on']) plugin_options.__setitem__('off', commands['off']) #print 'plugin_options:', plugin_options if sender is not None: sender.update() except Exception: log.error( NAME, _('CLI Control plug-in') + ':\n' + traceback.format_exc()) raise web.seeother(plugin_url(settings_page), True)
def GET(self): qdict = web.input() errorCode = qdict.get('errorCode', 'none') if 'delete' in qdict: delete = qdict['delete'] if len(plugin_options['sounds']) > 0: del_file = os.path.join(plugin_data_dir(), plugin_options['sounds'][int(delete)]) if os.path.isfile(del_file): os.remove(del_file) errorCode = qdict.get('errorCode', 'DelOK') read_folder() log.debug( NAME, datetime_string() + ': ' + _(u'Deleting file has sucesfully.')) else: errorCode = qdict.get('errorCode', 'DelNex') log.error( NAME, datetime_string() + ': ' + _(u'File for deleting not found!')) return self.plugin_render.voice_station_sounds(plugin_options, errorCode)
def run(self): report_index = 0 while not self._stop.is_set(): try: if lcd_options['use_lcd']: # if LCD plugin is enabled if lcd_options['debug_line']: log.clear(NAME) line1 = get_report(report_index) line2 = get_report(report_index + 1) if report_index >= 25: report_index = 0 line1 = get_report(report_index) line2 = get_report(report_index + 1) update_lcd(line1, line2) if lcd_options['debug_line'] and line1 is not None: log.info(NAME, line1) if lcd_options['debug_line'] and line2 is not None: log.info(NAME, line2) report_index += 2 self._sleep(2) except Exception: log.error(NAME, _('LCD display plug-in:') + '\n' + traceback.format_exc()) self._sleep(5)
def try_send(self, text): log.clear(NAME) try: send_data(text) # send get data log.info(NAME, _('Remote was sent') + ':\n' + text) except Exception: log.error(NAME, _('Remote was not sent') + '!\n' + traceback.format_exc())
def counter( i2cbus ): # reset PCF8583, measure pulses and return number pulses per second try: pulses = 0 addr = 0 if wind_options['address']: addr = 0x51 else: addr = 0x50 # reset PCF8583 try_io(lambda: i2cbus.write_byte_data(addr, 0x01, 0x00)) # reset LSB try_io(lambda: i2cbus.write_byte_data(addr, 0x02, 0x00) ) # reset midle Byte try_io(lambda: i2cbus.write_byte_data(addr, 0x03, 0x00)) # reset MSB time_.sleep(10) # read number (pulses in counter) and translate to DEC counter = try_io(lambda: i2cbus.read_i2c_block_data(addr, 0x00)) num1 = (counter[1] & 0x0F) # units num10 = (counter[1] & 0xF0) >> 4 # dozens num100 = (counter[2] & 0x0F) # hundred num1000 = (counter[2] & 0xF0) >> 4 # thousand num10000 = (counter[3] & 0x0F) # tens of thousands num100000 = (counter[3] & 0xF0) >> 4 # hundreds of thousands pulses = (num100000 * 100000) + (num10000 * 10000) + ( num1000 * 1000) + (num100 * 100) + (num10 * 10) + num1 return pulses except: log.error( NAME, _(u'Wind speed monitor plug-in') + u'%s' % traceback.format_exc()) time_.sleep(10) return None
def read_buttons(): try: import smbus bus = smbus.SMBus(0 if helpers.get_rpi_revision() == 1 else 1) # Set 8 GPA pins as input pull-UP try_io(lambda: bus.write_byte_data(plugin_options[ 'i2c_addr'], 0x0C, 0xFF)) #bus.write_byte_data(0x27,0x0C,0xFF) # Wait for device time.sleep(0.2) # Read state of GPIOA register MySwitch = try_io( lambda: bus.read_byte_data(plugin_options[ 'i2c_addr'], 0x12)) # MySwitch = bus.read_byte_data(0x27,0x12) inBut = 255 - MySwitch # inversion number for led off if button is not pressed led_outputs(inBut) # switch on actual led if button is pressed button_number = -1 if inBut == 128: button_number = 7 log.debug(NAME, _(u'Switch 8 pressed')) if inBut == 64: button_number = 6 log.debug(NAME, _(u'Switch 7 pressed')) if inBut == 32: button_number = 5 log.debug(NAME, _(u'Switch 6 pressed')) if inBut == 16: button_number = 4 log.debug(NAME, _(u'Switch 5 pressed')) if inBut == 8: button_number = 3 log.debug(NAME, _(u'Switch 4 pressed')) if inBut == 4: button_number = 2 log.debug(NAME, _(u'Switch 3 pressed')) if inBut == 2: button_number = 1 log.debug(NAME, _(u'Switch 2 pressed')) if inBut == 1: button_number = 0 log.debug(NAME, _(u'Switch 1 pressed')) return button_number #if button is not pressed return -1 except Exception: log.clear(NAME) log.error(NAME, datetime_string() + ': ' + _(u'Read button - FAULT')) log.error( NAME, _(u'Is hardware connected? Is bus address corectly setuped?')) #log.error(NAME, '\n' + traceback.format_exc()) pass return -1
def run(self): once_text = True two_text = True while not self._stop.is_set(): try: if sms_options["use_sms"]: # if use_sms is enable (on) if two_text: log.clear(NAME) log.info(NAME, _('SMS Modem plug-in is enabled')) once_text = True two_text = False if not os.path.exists("/usr/bin/gammu"): #http://askubuntu.com/questions/448358/automating-apt-get-install-with-assume-yes #sudo apt-get install -y gammu #sudo apt-get install -y python-gammu log.clear(NAME) log.info(NAME, _('Gammu is not installed.')) log.info(NAME, _('Please wait installing Gammu...')) cmd = "sudo apt-get install -y gammu" proc_install(self, cmd) log.info( NAME, _('Please wait installing Python-Gammu...')) cmd = "sudo apt-get install -y python-gammu" proc_install(self, cmd) log.info(NAME, _('Testing attached GSM ttyUSB...')) cmd = "sudo dmesg | grep tty" proc_install(self, cmd) if not os.path.exists("/root/.gammurc"): log.info( NAME, _('Saving Gammu config to /root/.gammurc...')) f = open("/root/.gammurc", "w") f.write("[gammu]\n") f.write("port = /dev/ttyUSB0\n") f.write("model = \n") f.write("connection = at19200\n") f.write("synchronizetime = yes\n") f.write("logfile =\n") f.close() sms_check(self) # Check SMS command from modem else: if once_text: log.clear(NAME) log.info(NAME, _('SMS Modem plug-in is disabled')) once_text = False two_text = True self._sleep(10) except Exception: log.error( NAME, _('SMS Modem plug-in') + ':\n' + traceback.format_exc()) self._sleep(60)
def update_log(): """Update data in json files.""" global sender ### Data for log ### try: log_data = read_log() except: write_log([]) log_data = read_log() from datetime import datetime data = {'datetime': datetime_string()} data['date'] = str(datetime.now().strftime('%d.%m.%Y')) data['time'] = str(datetime.now().strftime('%H:%M:%S')) data['down'] = str(sender.status['down']) data['up'] = str(sender.status['up']) data['ping'] = str(sender.status['ping']) log_data.insert(0, data) if speed_options['log_records'] > 0: log_data = log_data[:speed_options['log_records']] try: write_log(log_data) except: write_log([]) ### Data for graph log ### try: graph_data = read_graph_log() except: create_default_graph() graph_data = read_graph_log() timestamp = int(time.time()) try: downdata = graph_data[0]['balances'] downval = {'total': sender.status['down']} downdata.update({timestamp: downval}) updata = graph_data[1]['balances'] upval = {'total': sender.status['up']} updata.update({timestamp: upval}) pingdata = graph_data[2]['balances'] pingval = {'total': sender.status['ping']} pingdata.update({timestamp: pingval}) write_graph_log(graph_data) log.info(NAME, _('Saving to log files OK')) except: log.error(NAME, _('Speed Monitor plug-in') + ':\n' + traceback.format_exc()) pass
def send_email(msg, attachments): """Send email""" message = datetime_string() + ': ' + str(msg) try: from plugins.email_notifications import email email(message, attach=attachments) log.info(NAME, _('Email was sent') + ': ' + message) except Exception: log.error(NAME, _('Email was not sent') + '! ' + traceback.format_exc())
def to_decimal(number): try: import decimal return decimal.Decimal(float(number)) except decimal.InvalidOperation: log.clear(NAME) log.error(NAME, _(u'Water Consumption Counter plug-in') + traceback.format_exc()) pass return decimal.Decimal('0.0')
def run(self): try: self.update_statistics() except Exception: self.started.set() log.error( NAME, _(u'Usage statistics plug-in') + ':\n' + traceback.format_exc())
def write_song_queue(json_data): try: _dir = os.path.join(plugin_data_dir(), 'json') if not os.path.exists(_dir): os.makedirs(_dir) with open(os.path.join(plugin_data_dir(), 'json', 'song_queue.json'), 'w') as song_queue: json.dump(json_data, song_queue) except Exception: log.error(NAME, _(u'Voice Station plug-in') + ':\n' + traceback.format_exc())
def run(self): global stats temp_upd = None if plugin_options['use_footer']: temp_upd = showInFooter( ) # instantiate class to enable data in footer temp_upd.button = "system_update/status" # button redirect on footer temp_upd.label = _(u'System Update') # label on footer msg = _(u'Waiting to state') temp_upd.val = msg.encode('utf8').decode('utf8') # value on footer while not self._stop_event.is_set(): try: if plugin_options['use_update']: log.clear(NAME) self._update_rev_data() if self.status['can_update']: msg = _(u'New OSPy version is available!') stats['can_update'] = True report_ospyupdate() else: msg = _(u'Up-to-date') stats['can_update'] = False if self.status['can_update'] and plugin_options[ 'auto_update']: perform_update() self.started.set() else: msg = _(u'Plugin is not enabled') if plugin_options['use_footer']: if temp_upd is not None: temp_upd.val = msg.encode('utf8').decode( 'utf8') # value on footer else: log.error( NAME, _(u'Error: restart this plugin! Show in homepage footer have enabled.' )) self._sleep(3600) except Exception: self.started.set() log.error( NAME, _(u'System update plug-in') + ':\n' + traceback.format_exc()) self._sleep(60)
def led_outputs(led): try: import smbus bus = smbus.SMBus(1 if get_rpi_revision() >= 2 else 0) bus.write_byte_data(0x27,0x01,0x00) bus.write_byte_data(0x27,0x13,led) except Exception: log.error(NAME, _('Button plug-in') + ':' + _('Set LED - FAULT')) log.error(NAME, '\n' + traceback.format_exc()) pass
def run_command(cmd): try: proc = subprocess.Popen( cmd, stderr=subprocess.STDOUT, # merge stdout and stderr stdout=subprocess.PIPE, shell=True) output = proc.communicate()[0].decode('utf-8') log.info(NAME, output) except Exception: log.error(NAME, _('Astral plug-in') + ':\n' + traceback.format_exc())
def run(self): last_rain = False finished_count = len( [run for run in log.finished_runs() if not run['blocked']]) if email_options[ "emlpwron"]: # if eml_power_on send email is enable (on) body = (datetime_string() + ': System was powered on.') if email_options["emllog"]: self.try_mail(body, EVENT_FILE) else: self.try_mail(body) while not self._stop_event.is_set(): try: # Send E-amil if rain is detected if email_options["emlrain"]: if inputs.rain_sensed() and not last_rain: body = (datetime_string() + ': System detected rain.') self.try_mail(body) last_rain = inputs.rain_sensed() # Send E-mail if a new finished run is found if email_options["emlrun"]: finished = [ run for run in log.finished_runs() if not run['blocked'] ] if len(finished) > finished_count: body = datetime_string() + ':\n' for run in finished[finished_count:]: duration = (run['end'] - run['start']).total_seconds() minutes, seconds = divmod(duration, 60) body += "Finished run:\n" body += " Program: %s\n" % run['program_name'] body += " Station: %s\n" % stations.get( run['station']).name body += " Start time: %s \n" % datetime_string( run['start']) body += " Duration: %02d:%02d\n\n" % (minutes, seconds) self.try_mail(body) finished_count = len(finished) self._sleep(5) except Exception: log.error(NAME, 'E-mail plug-in:\n' + traceback.format_exc()) self._sleep(60)
def POST(self): qdict = web.input( skip_stations=[]) # skip_stations [] for multiple select try: if 'enabled' in qdict: if qdict['enabled'] == 'on': plugin_options.__setitem__('enabled', True) else: plugin_options.__setitem__('enabled', False) if 'voice_start_station' in qdict: plugin_options.__setitem__('voice_start_station', qdict['voice_start_station']) if 'pre_time' in qdict: plugin_options.__setitem__('pre_time', qdict['pre_time']) if 'repeating' in qdict: plugin_options.__setitem__('repeating', qdict['repeating']) if 'skip_stations' in qdict: plugin_options.__setitem__('skip_stations', qdict['skip_stations']) if 'volume' in qdict: plugin_options.__setitem__('volume', qdict['volume']) if 'start_hour' in qdict: plugin_options.__setitem__('start_hour', qdict['start_hour']) if 'stop_hour' in qdict: plugin_options.__setitem__('stop_hour', qdict['stop_hour']) commands = {'on': [], 'off': []} for i in range(0, options.output_count): if 'con' + str(i) in qdict: commands['on'].append(int(qdict['con' + str(i)])) else: commands['on'].append(-1) plugin_options.__setitem__('on', commands['on']) if checker is not None: checker.update() except Exception: log.error( NAME, _(u'Voice Notification plug-in') + ':\n' + traceback.format_exc()) raise web.seeother(plugin_url(settings_page), True)
def run(self): global blocker report_index = 0 rebooted = signal('rebooted') rebooted.connect(notify_rebooted) restarted = signal('restarted') restarted.connect(notify_restarted) poweroff = signal('poweroff') poweroff.connect(notify_poweroff) ospyupdate = signal('ospyupdate') ospyupdate.connect(notify_ospyupdate) while not self._stop_event.is_set(): try: if lcd_options[ 'use_lcd'] and not blocker: # if LCD plugin is enabled if lcd_options['debug_line']: log.clear(NAME) line1 = get_report(report_index) line2 = get_report(report_index + 1) if report_index >= 31: report_index = 0 skip_lines = False if line1 is None and line2 is None: skip_lines = True if not skip_lines: update_lcd(line1, line2) if lcd_options['debug_line'] and line1 is not None: L1 = line1.decode('utf8') log.info(NAME, L1) if lcd_options['debug_line'] and line2 is not None: L2 = line2.decode('utf8') log.info(NAME, L2) self._sleep(2) report_index += 2 time.sleep(0.1) except Exception: log.error( NAME, _('LCD display plug-in:') + '\n' + traceback.format_exc()) self._sleep(5)
def run(self): log.clear(NAME) if not self._stop.is_set(): if plugin_options["use_mqtt"]: try: atexit.register(on_restart) publish_status() except Exception: log.error( NAME, _('MQTT plug-in') + ':\n' + traceback.format_exc()) self._sleep(60)
def average_list(lst): ### Average of a list ### try: if is_python2(): return int(sum(lst) / float(len(lst))) else: import statistics return int(statistics.mean(lst)) except: log.error( NAME, _(u'Water Tank Monitor plug-in') + ':\n' + traceback.format_exc()) return -1
def try_mail(self, text, attachment=None, subject=None): log.clear(NAME) try: email(text, attach=attachment) # send email with attachment from log.info(NAME, _('Email was sent') + ':\n' + text) if not options.run_logEM: log.info(NAME, _('Email logging is disabled in options...')) logEM.save_email_log(subject or email_options['emlsubject'], text, _('Sent')) except Exception: log.error(NAME, _('Email was not sent!') + '\n' + traceback.format_exc()) logEM.save_email_log(subject or email_options['emlsubject'], text, _('Unsent')) if not options.run_logEM: log.info(NAME, _('Email logging is disabled in options...'))
def run(self): try: master_one_on = signal('master_one_on') master_one_on.connect(notify_master_one_on) master_one_off = signal('master_one_off') master_one_off.connect(notify_master_one_off) master_two_on = signal('master_two_on') master_two_on.connect(notify_master_two_on) master_two_off = signal('master_two_off') master_two_off.connect(notify_master_two_off) except Exception: log.clear(NAME) log.error(NAME, _(u'Water Consumption Counter plug-in') + traceback.format_exc()) self._sleep(60)