コード例 #1
0
 def run(self):
     if plugin_options['use_control']:  # if plugin is enabled
         log.clear(NAME)
         log.info(NAME, _(u'CLI Control is enabled.'))
         try:
             station_on = signal('station_on')
             station_on.connect(on_station_on)
             station_off = signal('station_off')
             station_off.connect(on_station_off)
             station_clear = signal('station_clear')
             station_clear.connect(on_station_clear)
         except Exception:
             log.error(
                 NAME,
                 _(u'CLI Control plug-in') + ':\n' + traceback.format_exc())
             pass
     else:
         log.clear(NAME)
         log.info(NAME, _(u'CLI Control is disabled.'))
コード例 #2
0
def run_command(cmd):
    """run command"""
    if plugin_options['use_control']:
        try:
            proc = subprocess.Popen(
                cmd,
                stderr=subprocess.STDOUT,  # merge stdout and stderr
                stdout=subprocess.PIPE,
                shell=True)
            output = proc.communicate()[0]
            output = output.decode('utf8')  #.strip()
            log.info(NAME, output)
            if plugin_options['use_log']:
                update_log(cmd, output)
        except:
            log.error(
                NAME,
                _(u'CLI Control plug-in') + ':\n' + traceback.format_exc())
            pass
コード例 #3
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
def create_default_graph():
    """Create default graph json file."""

    down = _(u'Downloading')
    up = _(u'Uploading')
    ping = _(u'Ping')

    graph_data = [{
        "station": down,
        "balances": {}
    }, {
        "station": up,
        "balances": {}
    }, {
        "station": ping,
        "balances": {}
    }]
    write_graph_log(graph_data)
    log.info(NAME, _('Deleted all log files OK'))
コード例 #4
0
    def POST(self):
        qdict = web.input(myfile={})
        errorCode = qdict.get('errorCode', 'none')

        #web.debug(qdict['myfile'].filename)    # This is the filename
        #web.debug(qdict['myfile'].value)       # This is the file contents
        #web.debug(qdict['myfile'].file.read()) # Or use a file(-like) object

        try:
            fname = qdict['myfile'].filename
            upload_type = fname[-4:len(fname)]
            types = ['.mp3', '.wav']
            if upload_type not in types:  # check file type is ok
                log.info(
                    NAME,
                    datetime_string() + ': ' +
                    _(u'Error. File must be in mp3 or wav format!'))
                errorCode = qdict.get('errorCode', 'Etype')
                return self.plugin_render.voice_notification_sounds(
                    plugin_options, errorCode)
            else:
                fout = open(os.path.join(plugin_data_dir(), fname),
                            'wb')  # ASCI_convert(fname)
                fout.write(qdict['myfile'].file.read())
                fout.close()
                log.info(
                    NAME,
                    datetime_string() + ': ' +
                    _(u'Uploading file sucesfully.'))
                errorCode = qdict.get('errorCode', 'UplOK')
                read_folder()
                return self.plugin_render.voice_notification_sounds(
                    plugin_options, errorCode)

        except Exception:
            log.error(
                NAME,
                _(u'Voice Station plug-in') + ':\n' + traceback.format_exc())
            errorCode = qdict.get('errorCode', 'Eupl')
            return self.plugin_render.voice_notification_sounds(
                plugin_options, errorCode)

        raise web.seeother(plugin_url(sound_page), True)
コード例 #5
0
    def run(self):
        log.clear(NAME)
        log.info(NAME, 'Test started for ' + str(pulse_options['test_time']) + ' sec.')
        station = stations.get(pulse_options['test_output'])

        for x in range(0, pulse_options['test_time']):
            station.active = True
            time.sleep(0.5)
            station.active = False
            time.sleep(0.5)

            if self._stop_event.is_set():
                break

        log.info(NAME, 'Test stopped.')

        # Activate again if needed:
        if station.remaining_seconds != 0:
            station.active = True
コード例 #6
0
ファイル: __init__.py プロジェクト: lthill/OSPy-plugins
def set_counter(i2cbus):
    try:
        if options['address']:
            pcf_addr = 0x51
        else:
            pcf_addr = 0x50
        i2cbus.write_byte_data(pcf_addr, 0x00,
                               0x20)  # status registr setup to "EVENT COUNTER"
        i2cbus.write_byte_data(pcf_addr, 0x01, 0x00)  # reset LSB
        i2cbus.write_byte_data(pcf_addr, 0x02, 0x00)  # reset midle Byte
        i2cbus.write_byte_data(pcf_addr, 0x03, 0x00)  # reset MSB
        log.info(NAME, _('Setup PCF8583 as event counter is OK'))
        return 1
    except:
        log.error(
            NAME,
            _('Water Meter plug-in') + ':\n' +
            _('Setup PCF8583 as event counter - FAULT'))
        return None
コード例 #7
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
def publish_status(status="UP"):
    global last_status, flag_connected
    client = get_client()
    time.sleep(2)
    if client and plugin_options["use_mqtt"]:  # Publish message
        if status != last_status:
            last_status = status
            log.info(
                NAME,
                datetime_string() + ' ' + _('Subscribing to topic') + ': ' +
                str(plugin_options['publish_up_down']))
            client.subscribe(plugin_options['publish_up_down'])
            if plugin_options["use_mqtt_secondary"]:
                log.info(
                    NAME,
                    datetime_string() + ' ' + _('Subscribing to topic') +
                    ': ' + str(plugin_options['control_topic']))
                client.subscribe(plugin_options['control_topic'])
            client.publish(plugin_options['publish_up_down'], status)
コード例 #8
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
 def _botCmd_subscribe(self, bot, update):
     chats = self._currentChats
     txt=''
     if update.message.chat.id not in list(chats):
         chats.append(update.message.chat.id)
         self._currentChats = chats
         plugin_options['currentChats'] = chats
         txt= _(u'Hi! you are now added to the {} announcement.').format(options.name)
         log.info(NAME, txt)
         if is_python2():
             bot.sendMessage(update.message.chat.id, text=txt.encode('utf-8'))
         else:    
             bot.sendMessage(update.message.chat.id, text=txt)            
     else:
         txt= _(u'Sorry, please enter the correct AccessKey!')
         log.info(NAME, txt)
         if is_python2():
             bot.sendMessage(update.message.chat.id, text=txt.encode('utf-8'))
         else:    
             bot.sendMessage(update.message.chat.id, text=txt) 
コード例 #9
0
def notify_ospyupdate(name, **kw):
    ### OSPy new version availbale ###
    global blocker
    blocker = True
    log.info(NAME, datetime_string() + ': ' + _('System OSPy Has Update'))
    if lcd_options['address'] == 0:
        find_lcd_address()
    if lcd_options['address'] != 0:
        from . import pylcd  # Library for LCD 16x2 PCF8574
        lcd = pylcd.lcd(lcd_options['address'],
                        0 if helpers.get_rpi_revision() == 1 else 1,
                        lcd_options['hw_PCF8574']
                        )  # (address, bus, hw version for expander)
        # DF - alter RPi version test fallback to value that works on BBB
    else:
        lcd = dummy_lcd

    try_io(lambda: lcd.lcd_clear())
    try_io(lambda: lcd.lcd_puts(ASCI_convert(_('System OSPy')), 1))
    try_io(lambda: lcd.lcd_puts(ASCI_convert(_('Has Update')), 2))
コード例 #10
0
def on_zone_change(name, **kw):
    """ Switch relays when core program signals a change in station state."""
    #   command = "wget http://xxx.xxx.xxx.xxx/relay1on"
    log.clear(NAME)
    log.info(NAME, _('Zone change signaled...'))

    for station in stations.get():
        if station.active:
            command = plugin_options['on']
            data = command[station.index]
            if data:
                #print 'data:', data
                run_command(data)
        else:
            command = plugin_options['off']
            data = command[station.index]
            if data:
                #print 'data:', data
                run_command(data)

    return
コード例 #11
0
def update_log(status):
    """Update data in json files."""

    ### 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['state'] = str(status)
      
    log_data.insert(0, data)
    if ups_options['log_records'] > 0:
        log_data = log_data[:ups_options['log_records']]
    write_log(log_data)

    ### Data for graph log ###
    try:
        graph_data = read_graph_log()
    except:
        create_default_graph()
        graph_data = read_graph_log()

    timestamp = int(time.time())

    try:
        state = graph_data[0]['balances']
        stateval = {'total': status}
        state.update({timestamp: stateval})
    
        write_graph_log(graph_data)
        log.info(NAME, _(u'Saving to log  files OK'))        
    except:
        create_default_graph()
コード例 #12
0
    def GET(self):
        global sender
        qdict = web.input()
        delete = helpers.get_input(qdict, 'delete', False, lambda x: True)
        show = helpers.get_input(qdict, 'show', False, lambda x: True)
        state = helpers.get_input(qdict, 'state', False, lambda x: True)

        if sender is not None and 'test' in qdict:
            test = qdict['test']
            if state:
                log.clear(NAME)
                log.info(NAME, _(u'Test CMD: {} ON.').format(int(test) + 1))
                command = plugin_options['on']
                data = command[int(test)]
                if data:
                    run_command(data)
            else:
                log.clear(NAME)
                log.info(NAME, _(u'Test CMD: {} OFF.').format(int(test) + 1))
                command = plugin_options['off']
                data = command[int(test)]
                if data:
                    run_command(data)

        if sender is not None and delete:
            write_log([])
            log.info(NAME, _(u'Deleted all log files OK'))
            raise web.seeother(plugin_url(settings_page), True)

        if sender is not None and show:
            raise web.seeother(plugin_url(log_page), True)

        return self.plugin_render.cli_control(plugin_options, log.events(NAME))
コード例 #13
0
    def POST(self):
        plugin_options.web_update(
            web.input(**plugin_options))  #for save multiple select

        if checker is not None:
            checker.update()

        try:
            qdict = web.input()
            read_test = None

            if 'test' in qdict:
                read_test = qdict['test']

            if read_test == 'voice.mp3':  # play voice.mp3 for test
                log.clear(NAME)
                log.info(NAME, _('Testing button %s...') % read_test)
                play_voice(self, "voice.mp3")

            else:  # play voicexx.mp3 for test
                tsound = [
                    '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'
                ]
                if read_test in tsound:
                    log.clear(NAME)
                    log.info(NAME, _('Testing button %s...') % read_test)
                    play_voice(self, "%s" % read_test)  # play for test

        except Exception:
            log.error(
                NAME,
                _('Voice Notification plug-in') + ':\n' +
                traceback.format_exc())

        raise web.seeother(plugin_url(settings_page), True)
コード例 #14
0
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
コード例 #15
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
    def GET(self):
        global water_sender

        qdict = web.input()
        reset = helpers.get_input(qdict, 'reset', False, lambda x: True)

        if water_sender is not None and reset:
            if options['enabled']:
                qdict['enabled'] = u'on' 
            if options['address']:
                qdict['address']  = u'on'
            qdict['sum'] = 0
            qdict['log_date_last_reset'] =  datetime_string()
                
            options.web_update(qdict)    
            log.clear(NAME)
            log.info(NAME, str(options['log_date_last_reset']) + ' ' + _(u'Water summary was reseting...'))
            log.info(NAME, _(u'Please wait for minutes/hours data...'))
            
            raise web.seeother(plugin_url(settings_page), True)

        return self.plugin_render.water_meter(options, log.events(NAME))
コード例 #16
0
    def POST(self):
        global saved_emails
        
        email_options.web_update(web.input())
        qdict = web.input()
        test = get_input(qdict, 'test', False, lambda x: True)
        delete = get_input(qdict, 'del', False, lambda x: True)

        if email_sender is not None:
            email_sender.update()

            if test:
                body = datetime_string() + ': ' + _(u'This is test e-mail from OSPy. You can ignore it.')
                logtext = _(u'This is test e-mail from OSPy. You can ignore it.')
                try_mail(body, logtext)
            
            if delete:
                log.info(NAME, datetime_string() + ': ' + _(u'Email Queue was deleted.'))         
                write_email([])
                saved_emails = 0

        raise web.seeother(plugin_url(settings_page), True)
コード例 #17
0
ファイル: __init__.py プロジェクト: LuSkBk/OSPy-plugins
def update_log(status):
    log_data = read_log()
    data = {'datetime': datetime_string()}
    data['date'] = str(datetime.now().strftime('%d.%m.%Y'))
    data['time'] = str(datetime.now().strftime('%H:%M:%S'))
    data['temp'] = str(status['temp'])
    data['humi'] = str(status['humi'])
    data['outp'] = str(status['outp'])
    if plugin_options['ds_used'] > 0:
        data['ds0'] = str(status['DS0'])
    else:
        data['ds0'] = str('not used')
    if plugin_options['ds_used'] > 1:
        data['ds1'] = str(status['DS1'])
    else:
        data['ds1'] = str('not used')
    if plugin_options['ds_used'] > 2:
        data['ds2'] = str(status['DS2'])
    else:
        data['ds2'] = str('not used')
    if plugin_options['ds_used'] > 3:
        data['ds3'] = str(status['DS3'])
    else:
        data['ds3'] = str('not used')
    if plugin_options['ds_used'] > 4:
        data['ds4'] = str(status['DS4'])
    else:
        data['ds4'] = str('not used')
    if plugin_options['ds_used'] > 5:
        data['ds5'] = str(status['DS5'])
    else:
        data['ds5'] = str('not used')

    log_data.insert(0, data)
    if plugin_options['log_records'] > 0:
        log_data = log_data[:plugin_options['log_records']]
    write_log(log_data)
    log.info(NAME, _('Saving log to file.'))
コード例 #18
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
    def GET(self):
        global sender
        qdict = web.input()
        delete = helpers.get_input(qdict, 'delete', False, lambda x: True)
        show = helpers.get_input(qdict, 'show', False, lambda x: True)

        if sender is not None and delete:
            write_log([])
            create_default_graph()
            log.info(NAME, _(u'Deleted all log files OK'))

            raise web.seeother(plugin_url(settings_page), True)

        if sender is not None and 'history' in qdict:
            history = qdict['history']
            plugin_options.__setitem__(
                'history', int(history))  #__setitem__(self, key, value)

        if sender is not None and show:
            raise web.seeother(plugin_url(log_page), True)

        return self.plugin_render.air_temp_humi(plugin_options,
                                                log.events(NAME))
コード例 #19
0
def create_default_graph():
    """Create default graph json file."""

    minimum = _(u'Minimum')
    maximum = _(u'Maximum')
    actual = _(u'Actual')
    volume = _(u'Volume')

    graph_data = [{
        "station": minimum,
        "balances": {}
    }, {
        "station": maximum,
        "balances": {}
    }, {
        "station": actual,
        "balances": {}
    }, {
        "station": volume,
        "balances": {}
    }]
    write_graph_log(graph_data)
    log.info(NAME, _(u'Deleted all log files OK'))
コード例 #20
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
    def run(self):
        log.clear(NAME)
        self._sleep(2)
        if not self._stop_event.is_set():
            if plugin_options["use_mqtt"]:
                try:
                    atexit.register(on_restart)
                    publish_status()
                    self._sleep(1)

                except Exception:
                    log.error(
                        NAME,
                        _('MQTT plug-in') + ':\n' + traceback.format_exc())
                    self._sleep(60)
            else:
                # text on the web if plugin is disabled
                log.clear(NAME)
                log.info(NAME, _('MQTT plug-in is disabled.'))
                on_stop()
                self._sleep(1)
        else:
            self._sleep(2)
コード例 #21
0
    def GET(self):
        global sender
        qdict = web.input()
        position = None
        button = helpers.get_input(qdict, 'btn', False, lambda x: True)
        if sender is not None and button:
            if 'pos' in qdict:
                position = int(qdict['pos'])
                button = int(qdict['btn'])
                if position is not None and position == -1:
                    pos_msg = _('close')
                elif position is not None and position == 0:
                    pos_msg = _('stop')
                elif position is not None and position == 1:
                    pos_msg = _('open')
                else:
                    pos_msg = _('unkown state')
                log.info(
                    NAME,
                    _('Button for blind {}, position {}.').format(
                        button + 1, pos_msg))
                send_cmd_to_blind(button, position)

        return self.plugin_render.venetian_blind(plugin_options)
コード例 #22
0
def find_lcd_address():
    search_range = {addr: 'PCF8574' for addr in range(32, 40)}
    search_range.update({addr: 'PCF8574A' for addr in range(56, 63)})

    try:
        import smbus

        bus = smbus.SMBus(0 if helpers.get_rpi_revision() == 1 else 1)
        # DF - alter RPi version test fallback to value that works on BBB
    except ImportError:
        log.warning(NAME, _('Could not import smbus.'))
    else:

        for addr, pcf_type in search_range.iteritems():
            try:
                # bus.write_quick(addr)
                bus.read_byte(addr) # DF - write_quick doesn't work on BBB
                log.info(NAME, 'Found %s on address 0x%02x' % (pcf_type, addr))
                lcd_options['address'] = addr
                break
            except Exception:
                pass
        else:
            log.warning(NAME, _('Could not find any PCF8574 controller.'))
コード例 #23
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
    def run(self):
        log.clear(NAME)
        log.info(NAME, datetime_string() + ' ' + _(u'Started for {} seconds.').format(plugin_options['open_time']))

        start = datetime.datetime.now()
        sid = int(plugin_options['open_output'])
        end = datetime.datetime.now() + datetime.timedelta(seconds=plugin_options['open_time'])
        new_schedule = {
            'active': True,
            'program': -1,
            'station': sid,
            'program_name': _(u'Door Opening'),
            'fixed': True,
            'cut_off': 0,
            'manual': True,
            'blocked': False,
            'start': start,
            'original_start': start,
            'end': end,
            'uid': '%s-%s-%d' % (str(start), "Manual", sid),
            'usage': stations.get(sid).usage
        }
        log.start_run(new_schedule)
        stations.activate(new_schedule['station'])
コード例 #24
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
    def run(self):
        try:
            import smbus  # for PCF 8591

            self.adc = smbus.SMBus(1 if get_rpi_revision() >= 2 else 0)
        except ImportError:
            log.warning(NAME, _(u'Could not import smbus.'))

        while not self._stop_event.is_set():
            log.clear(NAME)
            try:
                if self.adc is not None and pcf_options['enabled']:  # if pcf plugin is enabled
                    for i in range(4):
                        val = read_AD(self.adc, i + 1)
                        self.status['ad%d_raw' % i] = val
                        self.status['ad%d' % i] = get_temp(val) if pcf_options['ad%d_temp' % i] else get_volt(val)

                    log.info(NAME, datetime_string())
                    for i in range(4):
                        log.info(NAME, pcf_options['ad%d_label' % i] + ': ' + format(self.status['ad%d' % i],
                                                                                     pcf_options['ad%d_temp' % i]))

                    if pcf_options['enable_log']:
                        update_log(self.status)

                try:
                    write_DA(self.adc, pcf_options['da_value'])
                except Exception:
                    self.adc = None
                    
                self._sleep(max(60, pcf_options['log_interval'] * 60))

            except Exception:
                self.adc = None
                log.error(NAME, _(u'Voltage and Temperature Monitor plug-in') + ':\n' + traceback.format_exc())
                self._sleep(60)
コード例 #25
0
ファイル: __init__.py プロジェクト: lthill/OSPy-plugins
    def POST(self):
        options.__setitem__('sum', 0)
        log.clear(NAME)
        log.info(NAME, _('Water summary was reseting...'))
        log.info(NAME, _('Water in liters'))
        log.info(NAME, _('Water summary') + ': ' + str(options['sum']))

        if water_sender is not None:
            water_sender.update()

        raise web.seeother(plugin_url(settings_page), True)
コード例 #26
0
def on_station_off(name, **kw):
    """ Send CMD to OFF when core program signals in station state."""
    index = int(kw[u"txt"])
    log.clear(NAME)
    log.info(NAME, _(u'Station {} change to OFF').format(index + 1))
    command = plugin_options['off']
    data = command[index]
    if data:
        log.info(NAME,
                 _(u'Im trying to send an OFF command: {}').format(index + 1))
        run_command(data)
    else:
        log.info(NAME, _(u'No command is set for OFF: {}').format(index + 1))
    return
コード例 #27
0
ファイル: __init__.py プロジェクト: LuSkBk/OSPy-plugins
    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...'))
コード例 #28
0
ファイル: __init__.py プロジェクト: martinpihrt/OSPy-plugins
    def POST(self):
        plugin_options.web_update(web.input())

        if checker is not None:
            checker.update()

        if plugin_options['enabled']:
            log.clear(NAME)
            log.info(NAME, _('Pressurizer is enabled.'))
        else:
            log.clear(NAME)
            log.info(NAME, _('Pressurizer is disabled.'))

        log.info(NAME, _('Options has updated.'))
        raise web.seeother(plugin_url(settings_page), True)
コード例 #29
0
def send_email(msg):
    """Send email"""
    message = datetime_string() + ': ' + msg
    try:
        from plugins.email_notifications import email

        Subject = plugin_options['eml_subject']

        email(message, subject=Subject) # send email

        if not options.run_logEM:
           log.info(NAME, _('Email logging is disabled in options...'))
        else:        
           logEM.save_email_log(Subject, message, _('Sent'))

        log.info(NAME, _('Email was sent') + ': ' + message)

    except Exception:
        if not options.run_logEM:
           log.info(NAME, _('Email logging is disabled in options...'))
        else:
           logEM.save_email_log(Subject, message, _('Sent'))

        log.info(NAME, _('Email was not sent') + '! ' + traceback.format_exc())
コード例 #30
0
    def POST(self):
        wind_options.web_update(
            web.input(used_stations=[]))  #for save multiple select

        if wind_sender is not None:
            wind_sender.update()

        if wind_options['use_wind_monitor']:
            log.clear(NAME)
            log.info(NAME, _(u'Wind monitor is enabled.'))
        else:
            log.clear(NAME)
            log.info(NAME, _(u'Wind monitor is disabled.'))

        log.info(NAME, datetime_string() + ' ' + _(u'Options has updated.'))

        raise web.seeother(plugin_url(settings_page), True)