Beispiel #1
0
 def __init__(self, params, status, raw_data):
     self.logger = logging.getLogger('pywws.DataLogger')
     self.params = params
     self.status = status
     self.raw_data = raw_data
     # connect to weather station
     ws_type = self.params.get('fixed', 'ws type')
     if ws_type:
         self.params.unset('fixed', 'ws type')
         self.params.set('config', 'ws type', ws_type)
     ws_type = self.params.get('config', 'ws type', 'Unknown')
     avoid = eval(self.params.get('config', 'usb activity margin', '3.0'))
     self.ws = WeatherStation.weather_station(
         ws_type=ws_type, params=self.params, status=self.status,
         avoid=avoid)
     # check for valid weather station type
     fixed_block = self.check_fixed_block()
     if ws_type not in ('1080', '3080'):
         print "Unknown weather station type. Please edit weather.ini"
         print "and set 'ws type' to '1080' or '3080', as appropriate."
         if fixed_block['lux_wm2_coeff'] == 0.0:
             print "Your station is probably a '1080' type."
         else:
             print "Your station is probably a '3080' type."
         sys.exit(1)
     # check computer clock isn't earlier than last stored data
     last_stored = self.raw_data.before(datetime.max)
     if last_stored and datetime.utcnow() < last_stored:
         raise ValueError('Computer time is earlier than last stored data')
Beispiel #2
0
def WeatherStation_init():
    """ create kumunication Object für WeatherStation."""
    try:
        ws = WeatherStation.weather_station()
    except:
        raise NameError("WS conection error")
    return (ws)
Beispiel #3
0
    def run(self, generate_event, send_event, context={}):

        from pywws import WeatherStation
        station = WeatherStation.weather_station()

        for data, last_ptr, logged in station.live_data():
            if not logged:
                try:
                    if data['abs_pressure'] is not None:
                        e = generate_event('press')
                        e.value = (10 * (4.5 + (data['abs_pressure']))) / 10
                        send_event(e)

                    if data['temp_in'] is not None:
                        e = generate_event('temp')
                        e.sensor = 0
                        e.value = data['temp_in']
                        send_event(e)

                    if data['hum_in'] is not None:
                        e = generate_event('hum')
                        e.sensor = 0
                        e.value = data['hum_in']
                        send_event(e)

                    if data['temp_out'] is not None:
                        e = generate_event('temp')
                        e.sensor = 1
                        e.value = data['temp_out']
                        send_event(e)

                    if data['hum_out'] is not None:
                        e = generate_event('hum')
                        e.sensor = 1
                        e.value = data['hum_out']
                        send_event(e)

                    if data['rain'] is not None:
                        e = generate_event('rain')
                        e.total = (136 * (data['rain'])) / 100
                        e.rate = 0
                        send_event(e)

                    if data['wind_ave'] is not None and data['wind_dir'] < 16:
                        e = generate_event('wind')
                        e.create_child('mean')
                        e.mean.speed = data['wind_ave']
                        e.mean.dir = 22.5 * (data['wind_dir'])
                        if data['wind_gust']:
                            e.create_child('gust')
                            e.gust.speed = data['wind_gust']
                            e.gust.dir = 22.5 * (data['wind_dir'])
                        send_event(e)

                except Exception, e:
                    self.logger.error(e)
Beispiel #4
0
    def run(self, generate_event, send_event, context={}):

        from pywws import WeatherStation
        station = WeatherStation.weather_station()

        for data, last_ptr, logged in station.live_data():
            if not logged:
                try:
                    if data['abs_pressure'] is not None:
                        e = generate_event('press')
                        e.value = (10*(4.5+(data['abs_pressure'])))/10
                        send_event(e)

                    if data['temp_in'] is not None:                    
                        e = generate_event('temp')
                        e.sensor = 0
                        e.value = data['temp_in']
                        send_event(e)

                    if data['hum_in'] is not None:
                        e = generate_event('hum')
                        e.sensor = 0
                        e.value = data['hum_in']
                        send_event(e)

                    if data['temp_out'] is not None:
                        e = generate_event('temp')
                        e.sensor = 1
                        e.value = data['temp_out']
                        send_event(e)

                    if data['hum_out'] is not None:
                        e = generate_event('hum')
                        e.sensor = 1
                        e.value = data['hum_out']
                        send_event(e)

                    if data['rain'] is not None:
                        e = generate_event('rain')
                        e.total = (136*(data['rain']))/100 
                        e.rate = 0
                        send_event(e)

                    if data['wind_ave'] is not None and data['wind_dir'] < 16:
                        e = generate_event('wind')
                        e.create_child('mean')
                        e.mean.speed = data['wind_ave']
                        e.mean.dir = 22.5*(data['wind_dir']) 
                        if data['wind_gust']:
                            e.create_child('gust')
                            e.gust.speed = data['wind_gust']
                            e.gust.dir = 22.5*(data['wind_dir'])
                        send_event(e)

                except Exception, e:
                    self.logger.error(e)
Beispiel #5
0
 # check arguments
 if len(args) != 0:
     print >>sys.stderr, 'Error: no arguments allowed\n'
     print >>sys.stderr, __usage__.strip()
     return 2
 # process options
 verbose = 0
 for o, a in opts:
     if o in ('-h', '--help'):
         print __usage__.strip()
         return 0
     elif o in ('-v', '--verbose'):
         verbose += 1
 # do it!
 logger = ApplicationLogger(verbose)
 ws = WeatherStation.weather_station()
 fixed_block = ws.get_fixed_block()
 if not fixed_block:
     print "No valid data block found"
     return 3
 # loop
 ptr = ws.data_start
 total_count = 0
 bad_count = 0
 while True:
     if total_count % 1000 == 0:
         active = ws.current_pos()
     while True:
         ptr += 0x20
         if ptr >= 0x10000:
             ptr = ws.data_start
Beispiel #6
0
 # check arguments
 if len(args) != 0:
     print >> sys.stderr, 'Error: no arguments allowed\n'
     print >> sys.stderr, __usage__.strip()
     return 2
 # process options
 verbose = 0
 for o, a in opts:
     if o in ('-h', '--help'):
         print __usage__.strip()
         return 0
     elif o in ('-v', '--verbose'):
         verbose += 1
 # do it!
 logger = ApplicationLogger(verbose)
 ws = WeatherStation.weather_station()
 fixed_block = ws.get_fixed_block()
 if not fixed_block:
     print "No valid data block found"
     return 3
 # loop
 ptr = ws.data_start
 total_count = 0
 bad_count = 0
 while True:
     if total_count % 1000 == 0:
         active = ws.current_pos()
     while True:
         ptr += 0x20
         if ptr >= 0x10000:
             ptr = ws.data_start
Beispiel #7
0
def LogData(params, status, raw_data, sync=None, clear=False):
    logger = logging.getLogger('pywws.LogData')
    # connect to weather station
    ws_type = params.get('fixed', 'ws type')
    if ws_type:
        params.unset('fixed', 'ws type')
        params.set('config', 'ws type', ws_type)
    ws_type = params.get('config', 'ws type', 'Unknown')
    ws = WeatherStation.weather_station(
        ws_type=ws_type, params=params, status=status)
    fixed_block = CheckFixedBlock(ws, params, status, logger)
    if not fixed_block:
        logger.error("Invalid data from weather station")
        return 3
    # check for valid weather station type
    if ws.ws_type not in ('1080', '3080'):
        print "Unknown weather station type. Please edit weather.ini"
        print "and set 'ws type' to '1080' or '3080', as appropriate."
        if fixed_block['lux_wm2_coeff'] == 0.0:
            print "Your station is probably a '1080' type."
        else:
            print "Your station is probably a '3080' type."
        sys.exit(1)
    # get sync config value
    if sync is None:
        if fixed_block['read_period'] <= 5:
            sync = int(params.get('config', 'logdata sync', '1'))
        else:
            sync = int(params.get('config', 'logdata sync', '0'))
    # get address and date-time of last complete logged data
    logger.info('Synchronising to weather station')
    range_hi = datetime.max
    range_lo = datetime.min
    last_delay = ws.get_data(ws.current_pos())['delay']
    if last_delay == 0:
        prev_date = datetime.min
    else:
        prev_date = datetime.utcnow()
    for data, last_ptr, logged in ws.live_data(logged_only=(sync > 1)):
        last_date = data['idx']
        logger.debug('Reading time %s', last_date.strftime('%H:%M:%S'))
        if logged:
            break
        if sync < 2 and ws._station_clock:
            err = last_date - datetime.fromtimestamp(ws._station_clock)
            last_date -= timedelta(
                minutes=data['delay'], seconds=err.seconds % 60)
            logger.debug('log time %s', last_date.strftime('%H:%M:%S'))
            last_ptr = ws.dec_ptr(last_ptr)
            break
        if sync < 1:
            hi = last_date - timedelta(minutes=data['delay'])
            if last_date - prev_date > timedelta(seconds=50):
                lo = hi - timedelta(seconds=60)
            elif data['delay'] == last_delay:
                lo = hi - timedelta(seconds=60)
                hi = hi - timedelta(seconds=48)
            else:
                lo = hi - timedelta(seconds=48)
            last_delay = data['delay']
            prev_date = last_date
            range_hi = min(range_hi, hi)
            range_lo = max(range_lo, lo)
            err = (range_hi - range_lo) / 2
            last_date = range_lo + err
            logger.debug('est log time %s +- %ds (%s..%s)',
                         last_date.strftime('%H:%M:%S'), err.seconds,
                         lo.strftime('%H:%M:%S'), hi.strftime('%H:%M:%S'))
            if err < timedelta(seconds=15):
                last_ptr = ws.dec_ptr(last_ptr)
                break
    # go back through stored data, until we catch up with what we've already got
    logger.info('Fetching data')
    Catchup(ws, logger, raw_data, last_date, last_ptr)
    if clear:
        logger.info('Clearing weather station memory')
        ptr = ws.fixed_format['data_count'][0]
        ws.write_data([(ptr, 1), (ptr+1, 0)])
Beispiel #8
0
    def process(self, live_data, template_file):
        def jump(idx, count):
            while count > 0:
                new_idx = data_set.after(idx + SECOND)
                if new_idx == None:
                    break
                idx = new_idx
                count -= 1
            while count < 0:
                new_idx = data_set.before(idx)
                if new_idx == None:
                    break
                idx = new_idx
                count += 1
            return idx, count == 0

        params = self.params
        if not live_data:
            idx = self.calib_data.before(datetime.max)
            if not idx:
                self.logger.error("No calib data - run Process.py first")
                return
            live_data = self.calib_data[idx]
        pressure_trend_text = WeatherStation.pressure_trend_text
        wind_dir_text = WeatherStation.get_wind_dir_text()
        dew_point = WeatherStation.dew_point
        wind_chill = WeatherStation.wind_chill
        apparent_temp = WeatherStation.apparent_temp
        rain_hour = self._rain_hour
        rain_day = self._rain_day
        pressure_offset = eval(self.params.get('fixed', 'pressure offset'))
        fixed_block = eval(self.params.get('fixed', 'fixed block'))
        # start off with no time rounding
        round_time = None
        # start off in hourly data mode
        data_set = self.hourly_data
        # start off in utc
        time_zone = utc
        # jump to last item
        idx, valid_data = jump(datetime.max, -1)
        if not valid_data:
            self.logger.error("No summary data - run Process.py first")
            return
        data = data_set[idx]
        # open template file file
        if sys.version_info[0] >= 3:
            tmplt = open(template_file, 'r', encoding=self.encoding)
        else:
            tmplt = open(template_file, 'r')
        # do the text processing
        while True:
            line = tmplt.readline()
            if line == '':
                break
            parts = line.split('#')
            for i in range(len(parts)):
                if i % 2 == 0:
                    # not a processing directive
                    if i == 0 or parts[i] != '\n':
                        yield parts[i]
                    continue
                if parts[i] and parts[i][0] == '!':
                    # comment
                    continue
                command = shlex.split(parts[i])
                if command == []:
                    # empty command == print a single '#'
                    yield '#'
                elif command[0] in data.keys() + ['calc']:
                    # output a value
                    if not valid_data:
                        continue
                    # format is: key fmt_string no_value_string conversion
                    # get value
                    if command[0] == 'calc':
                        x = eval(command[1])
                        del command[1]
                    else:
                        x = data[command[0]]
                    # adjust time
                    if isinstance(x, datetime):
                        if round_time:
                            x += round_time
                        x = x.replace(tzinfo=utc)
                        x = x.astimezone(time_zone)
                    # convert data
                    if x != None and len(command) > 3:
                        x = eval(command[3])
                    # get format
                    fmt = '%s'
                    if len(command) > 1:
                        fmt = command[1]
                    # write output
                    if x == None:
                        if len(command) > 2:
                            yield command[2]
                    elif isinstance(x, datetime):
                        yield x.strftime(fmt)
                    elif not self.use_locale:
                        yield fmt % (x)
                    elif sys.version_info >= (2, 7) or '%%' not in fmt:
                        yield locale.format_string(fmt, x)
                    else:
                        yield locale.format_string(
                            fmt.replace('%%', '##'), x).replace('##', '%')
                elif command[0] == 'monthly':
                    data_set = self.monthly_data
                    idx, valid_data = jump(datetime.max, -1)
                    data = data_set[idx]
                elif command[0] == 'daily':
                    data_set = self.daily_data
                    idx, valid_data = jump(datetime.max, -1)
                    data = data_set[idx]
                elif command[0] == 'hourly':
                    data_set = self.hourly_data
                    idx, valid_data = jump(datetime.max, -1)
                    data = data_set[idx]
                elif command[0] == 'raw':
                    data_set = self.calib_data
                    idx, valid_data = jump(datetime.max, -1)
                    data = data_set[idx]
                elif command[0] == 'live':
                    data_set = self.calib_data
                    idx = datetime.max
                    valid_data = True
                    data = live_data
                elif command[0] == 'timezone':
                    if command[1] == 'utc':
                        time_zone = utc
                    elif command[1] == 'local':
                        time_zone = Local
                    else:
                        self.logger.error("Unknown time zone: %s", command[1])
                        return
                elif command[0] == 'roundtime':
                    if eval(command[1]):
                        round_time = timedelta(seconds=30)
                    else:
                        round_time = None
                elif command[0] == 'jump':
                    prevdata = data
                    idx, valid_data = jump(idx, int(command[1]))
                    data = data_set[idx]
                elif command[0] == 'goto':
                    prevdata = data
                    time_str = command[1]
                    if '%' in time_str:
                        lcl = idx.replace(tzinfo=utc).astimezone(time_zone)
                        time_str = lcl.strftime(time_str)
                    new_idx = DataStore.safestrptime(time_str)
                    new_idx = new_idx.replace(tzinfo=time_zone).astimezone(utc)
                    new_idx = data_set.after(new_idx.replace(tzinfo=None))
                    if new_idx:
                        idx = new_idx
                        data = data_set[idx]
                        valid_data = True
                    else:
                        valid_data = False
                elif command[0] == 'loop':
                    loop_count = int(command[1])
                    loop_start = tmplt.tell()
                elif command[0] == 'endloop':
                    loop_count -= 1
                    if valid_data and loop_count > 0:
                        tmplt.seek(loop_start, 0)
                else:
                    self.logger.error(
                        "Unknown processing directive: #%s#", parts[i])
                    return
        tmplt.close()
        return
Beispiel #9
0
def LiveLog(data_dir):
    logger = logging.getLogger('pywws.LiveLog')
    params = DataStore.params(data_dir)
    status = DataStore.status(data_dir)
    # localise application
    Localisation.SetApplicationLanguage(params)
    # connect to weather station
    ws_type = params.get('fixed', 'ws type')
    if ws_type:
        params.unset('fixed', 'ws type')
        params.set('config', 'ws type', ws_type)
    ws_type = params.get('config', 'ws type', '1080')
    ws = WeatherStation.weather_station(
        ws_type=ws_type, params=params, status=status)
    fixed_block = CheckFixedBlock(ws, params, status, logger)
    if not fixed_block:
        logger.error("Invalid data from weather station")
        return 3
    # open data file stores
    raw_data = DataStore.data_store(data_dir)
    calib_data = DataStore.calib_store(data_dir)
    hourly_data = DataStore.hourly_store(data_dir)
    daily_data = DataStore.daily_store(data_dir)
    monthly_data = DataStore.monthly_store(data_dir)
    # create a RegularTasks object
    tasks = Tasks.RegularTasks(
        params, status, calib_data, hourly_data, daily_data, monthly_data)
    # get time of last logged data
    two_minutes = timedelta(minutes=2)
    last_stored = raw_data.before(datetime.max)
    if last_stored == None:
        last_stored = datetime.min
    if datetime.utcnow() < last_stored:
        raise ValueError('Computer time is earlier than last stored data')
    last_stored += two_minutes
    # get live data
    hour = timedelta(hours=1)
    next_hour = datetime.utcnow().replace(
                                    minute=0, second=0, microsecond=0) + hour
    next_ptr = None
    for data, ptr, logged in ws.live_data(
                                    logged_only=(not tasks.has_live_tasks())):
        now = data['idx']
        if logged:
            if ptr == next_ptr:
                # data is contiguous with last logged value
                raw_data[now] = data
            else:
                # catch up missing data
                Catchup(ws, logger, raw_data, now, ptr)
            next_ptr = ws.inc_ptr(ptr)
            # process new data
            Process.Process(params, status, raw_data, calib_data,
                            hourly_data, daily_data, monthly_data)
            # do tasks
            tasks.do_tasks()
            if now >= next_hour:
                next_hour += hour
                fixed_block = CheckFixedBlock(ws, params, status, logger)
                if not fixed_block:
                    logger.error("Invalid data from weather station")
                    return 3
                # save any unsaved data
                raw_data.flush()
        else:
            tasks.do_live(data)
    return 0
def LiveLog(data_dir):
    logger = logging.getLogger('pywws.LiveLog')
    params = DataStore.params(data_dir)
    # localise application
    Localisation.SetApplicationLanguage(params)
    # connect to weather station
    ws_type = params.get('config', 'ws type')
    if ws_type:
        params._config.remove_option('config', 'ws type')
        params.set('fixed', 'ws type', ws_type)
    ws_type = params.get('fixed', 'ws type', '1080')
    ws = WeatherStation.weather_station(ws_type=ws_type)
    fixed_block = CheckFixedBlock(ws, params, logger)
    if not fixed_block:
        logger.error("Invalid data from weather station")
        return 3
    # open data file stores
    raw_data = DataStore.data_store(data_dir)
    calib_data = DataStore.calib_store(data_dir)
    hourly_data = DataStore.hourly_store(data_dir)
    daily_data = DataStore.daily_store(data_dir)
    monthly_data = DataStore.monthly_store(data_dir)
    # create a RegularTasks object
    tasks = Tasks.RegularTasks(
        params, calib_data, hourly_data, daily_data, monthly_data)
    # get time of last logged data
    two_minutes = timedelta(minutes=2)
    last_stored = raw_data.before(datetime.max)
    if last_stored == None:
        last_stored = datetime.min
    if datetime.utcnow() < last_stored:
        raise ValueError('Computer time is earlier than last stored data')
    last_stored += two_minutes
    # get live data
    hour = timedelta(hours=1)
    next_hour = datetime.utcnow().replace(
                                    minute=0, second=0, microsecond=0) + hour
    next_ptr = None
    for data, ptr, logged in ws.live_data(
                                    logged_only=(not tasks.has_live_tasks())):
        now = data['idx']
        if logged:
            if ptr == next_ptr:
                # data is contiguous with last logged value
                raw_data[now] = data
            else:
                # catch up missing data
                Catchup(ws, logger, raw_data, now, ptr)
            next_ptr = ws.inc_ptr(ptr)
            # process new data
            Process.Process(params, raw_data, calib_data,
                            hourly_data, daily_data, monthly_data)
            # do tasks
            tasks.do_tasks()
            if now >= next_hour:
                next_hour += hour
                fixed_block = CheckFixedBlock(ws, params, logger)
                if not fixed_block:
                    logger.error("Invalid data from weather station")
                    return 3
            params.flush()
        else:
            tasks.do_live(data)
    return 0
Beispiel #11
0
    def process(self, live_data, template_file):
        def jump(idx, count):
            while count > 0:
                new_idx = data_set.after(idx + SECOND)
                if new_idx == None:
                    break
                idx = new_idx
                count -= 1
            while count < 0:
                new_idx = data_set.before(idx)
                if new_idx == None:
                    break
                idx = new_idx
                count += 1
            return idx, count == 0

        params = self.params
        if not live_data:
            idx = self.calib_data.before(datetime.max)
            if not idx:
                self.logger.error("No calib data - run Process.py first")
                return
            live_data = self.calib_data[idx]
        pressure_trend_text = WeatherStation.pressure_trend_text
        wind_dir_text = WeatherStation.get_wind_dir_text()
        dew_point = WeatherStation.dew_point
        wind_chill = WeatherStation.wind_chill
        apparent_temp = WeatherStation.apparent_temp
        rain_hour = self._rain_hour
        rain_day = self._rain_day
        pressure_offset = eval(self.params.get('fixed', 'pressure offset'))
        fixed_block = eval(self.params.get('fixed', 'fixed block'))
        # start off with no time rounding
        round_time = None
        # start off in hourly data mode
        data_set = self.hourly_data
        # start off in utc
        time_zone = utc
        # jump to last item
        idx, valid_data = jump(datetime.max, -1)
        if not valid_data:
            self.logger.error("No summary data - run Process.py first")
            return
        data = data_set[idx]
        # open template file file
        if sys.version_info[0] >= 3:
            tmplt = open(template_file, 'r', encoding=self.encoding)
        else:
            tmplt = open(template_file, 'r')
        # do the text processing
        while True:
            line = tmplt.readline()
            if line == '':
                break
            parts = line.split('#')
            for i in range(len(parts)):
                if i % 2 == 0:
                    # not a processing directive
                    if i == 0 or parts[i] != '\n':
                        yield parts[i]
                    continue
                if parts[i] and parts[i][0] == '!':
                    # comment
                    continue
                command = shlex.split(parts[i])
                if command == []:
                    # empty command == print a single '#'
                    yield '#'
                elif command[0] in data.keys() + ['calc']:
                    # output a value
                    if not valid_data:
                        continue
                    # format is: key fmt_string no_value_string conversion
                    # get value
                    if command[0] == 'calc':
                        x = eval(command[1])
                        del command[1]
                    else:
                        x = data[command[0]]
                    # adjust time
                    if isinstance(x, datetime):
                        if round_time:
                            x += round_time
                        x = x.replace(tzinfo=utc)
                        x = x.astimezone(time_zone)
                    # convert data
                    if x != None and len(command) > 3:
                        x = eval(command[3])
                    # get format
                    fmt = '%s'
                    if len(command) > 1:
                        fmt = command[1]
                    # write output
                    if x == None:
                        if len(command) > 2:
                            yield command[2]
                    elif isinstance(x, datetime):
                        yield x.strftime(fmt)
                    elif not self.use_locale:
                        yield fmt % (x)
                    elif sys.version_info >= (2, 7) or '%%' not in fmt:
                        yield locale.format_string(fmt, x)
                    else:
                        yield locale.format_string(fmt.replace('%%', '##'),
                                                   x).replace('##', '%')
                elif command[0] == 'monthly':
                    data_set = self.monthly_data
                    idx, valid_data = jump(datetime.max, -1)
                    data = data_set[idx]
                elif command[0] == 'daily':
                    data_set = self.daily_data
                    idx, valid_data = jump(datetime.max, -1)
                    data = data_set[idx]
                elif command[0] == 'hourly':
                    data_set = self.hourly_data
                    idx, valid_data = jump(datetime.max, -1)
                    data = data_set[idx]
                elif command[0] == 'raw':
                    data_set = self.calib_data
                    idx, valid_data = jump(datetime.max, -1)
                    data = data_set[idx]
                elif command[0] == 'live':
                    data_set = self.calib_data
                    idx = datetime.max
                    valid_data = True
                    data = live_data
                elif command[0] == 'timezone':
                    if command[1] == 'utc':
                        time_zone = utc
                    elif command[1] == 'local':
                        time_zone = Local
                    else:
                        self.logger.error("Unknown time zone: %s", command[1])
                        return
                elif command[0] == 'roundtime':
                    if eval(command[1]):
                        round_time = timedelta(seconds=30)
                    else:
                        round_time = None
                elif command[0] == 'jump':
                    prevdata = data
                    idx, valid_data = jump(idx, int(command[1]))
                    data = data_set[idx]
                elif command[0] == 'goto':
                    prevdata = data
                    time_str = command[1]
                    if '%' in time_str:
                        lcl = idx.replace(tzinfo=utc).astimezone(time_zone)
                        time_str = lcl.strftime(time_str)
                    new_idx = DataStore.safestrptime(time_str)
                    new_idx = new_idx.replace(tzinfo=time_zone).astimezone(utc)
                    new_idx = data_set.after(new_idx.replace(tzinfo=None))
                    if new_idx:
                        idx = new_idx
                        data = data_set[idx]
                        valid_data = True
                    else:
                        valid_data = False
                elif command[0] == 'loop':
                    loop_count = int(command[1])
                    loop_start = tmplt.tell()
                elif command[0] == 'endloop':
                    loop_count -= 1
                    if valid_data and loop_count > 0:
                        tmplt.seek(loop_start, 0)
                else:
                    self.logger.error("Unknown processing directive: #%s#",
                                      parts[i])
                    return
        tmplt.close()
        return
Beispiel #12
0
def main():
    # read wws2mysql.ini config
    config = ConfigParser.ConfigParser()
    config.readfp(open('wws2mysql.ini'))

    # init slogging
    syslog.openlog(ident=config.get('syslog', 'ident'),
                   logoption=syslog.LOG_PID,
                   facility=syslog.LOG_LOCAL7)

    # db connection information
    dbcon = {
        'engine': config.get('mysql_db', 'engine'),
        'user': config.get('mysql_db', 'user'),
        'password': config.get('mysql_db', 'password'),
        'host': config.get('mysql_db', 'host'),
        'database': config.get('mysql_db', 'database'),
        'table': config.get('mysql_db', 'table')
    }

    print(dbcon)

    #tries to reconnection
    i = 6
    conection = True
    #reconnect loop
    while (conection and (i > 0)):
        conection = False
        i -= 1
        # init interface to Wetter station
        print("start wws connection")
        try:
            ws = WeatherStation_init()
        except:
            conection = True
            print("wws connection error")
            continue
        syslog.syslog(syslog.LOG_DEBUG, "connected to weather station")

        # init time synchronization
        print("synchronization of wws timing")
        try:
            last_date = WeatherStation_synctime(ws)
        except:
            conection = True
            print("timing error")
            continue
        syslog.syslog(syslog.LOG_DEBUG, "weather station is synchronized")

        # init database connection
        print("init database")
        try:
            sqldb = db.mysql_interface(dbcon['engine'], dbcon['user'],
                                       dbcon['password'], dbcon['host'],
                                       dbcon['database'])
        except:
            conection = True
            print("db conection error!")
            continue
        syslog.syslog(syslog.LOG_DEBUG, "database connection initialized")
    # if connection field multiple times raise error
    if (conection):
        syslog.syslog(syslog.LOG_ERR,
                      "Connection establishment field multiple times!")
        raise NameError("Waring! connection field multiple times!")

    # read Fixblock
    fixb = WeatherStation_fixed_block(ws)

    # fined ptr position
    max_data = WeatherStation_ptr_pos(fixb)

    # read data from ring buffer
    # currant position in ring buffer
    r_pos_a = r_pos = ws.current_pos()

    # read last db entry
    last_entry = sqldb.read_last_entry(dbcon['table'], last_by='ID')
    # Value 5 in list is the time of the measurement.
    # Value
    delay = 5

    # if db is empty use a dummy entry.
    if (last_entry == None):
        syslog.syslog(syslog.LOG_INFO,
                      "weather station database is probably empty")
        last_entry = [
            0, 1, 2, 3, 4,
            datetime.datetime(1970, 1, 1, 0, 0, 0), 6, 7, 8, 9, 10, 360, 360
        ]

    print(last_entry)

    # all data of ring buffer
    all_data = {}
    max_data = 0

    #debug
    #r_ptss= []

    # if data from wws is newer then in db start synchronization.
    if (verify_wws2db_timing(last_date, last_entry[5], delay - 2)):
        block = ws.get_data(r_pos)
        last_date = last_date - datetime.timedelta(minutes=block['delay'],
                                                   seconds=0)
        last_date.replace(second=0)
        block['idz'] = last_date

        # determinant current end of ring buffer
        if (ws.get_data(ws.inc_ptr(r_pos), unbuffered=False)['delay'] is None):
            ptr_stop = 256
        else:
            ptr_stop = ws.inc_ptr(r_pos)

        # read ring buffer
        while (r_pos_a != ptr_stop) and (last_date > last_entry[5]):
            #while (r_pos_a != ptr_stop) and (verify_wws2db_timing( last_date, last_entry[5], delay-2)):
            r_pos_a = ws.dec_ptr(r_pos_a)

            # debug
            #r_ptss.append(r_pos_a)

            #tray to reconnect
            i = 4
            while (i > 0):
                try:
                    block = ws.get_data(r_pos_a, unbuffered=False)
                except:
                    i -= 1
                    print("\n USB Timed out!\n")
                    # reconnect to wws
                    del ws
                    try:
                        ws = WeatherStation.weather_station()
                    except:
                        print("wws connection error")
                        syslog.syslog(
                            syslog.LOG_ERR,
                            "Connection field multiple times well synchronizing!"
                        )
                        raise NameError(
                            "Waring!Connection field multiple times well synchronizing!"
                        )
                    print("\n reconnected!\n\n")
                    continue
                break

            # add timestamps
            # ATTENTION!! Time allwaise in utc time
            # http://de.wikipedia.org/wiki/Koordinierte_Weltzeit
            last_date = last_date - datetime.timedelta(minutes=block['delay'],
                                                       seconds=0)
            last_date.replace(second=0)
            block['idz'] = last_date
            # add pointer to list
            block['ptr'] = r_pos_a

            print block
            all_data[max_data] = block
            max_data += 1

        # write data to db
        print("writing to DB")
        # daten in umgekerter reienfolge in db schreiben.  damit sie cronologisch richtig sind mit der id.
        i = len(all_data) - 2  # maximale anzahl zu syncronisirenden daten
        # -1 wegen 0 zehlbeginn; -1 wegen bereitz in db vorhandenen datensatz
        while (i >= 0):
            print(i)
            # round long floats
            for k in all_data[i]:
                if (isinstance(all_data[i][k], float)):
                    all_data[i][k] = round(all_data[i][k], 2)
            # insert in db
            print(all_data[i])
            sqldb.insert_in_db(dbcon['table'], all_data[i])
            # commuting cycle. every 10 entry auto commit.
            if (i % 10 == 0):
                sqldb.commit()
            i -= 1
        # final commit for uncommitted enters
        sqldb.commit()

        syslog.syslog(syslog.LOG_INFO,
                      "weather station synchronization was successful")
    else:
        print("db already actual.")
        syslog.syslog(syslog.LOG_INFO, "weather station db was already actual")

    # test output to file
    if (config.getboolean('file_output', 'output')):
        print "writing to file"
        write_to_file('out.txt', fixb, all_data)

    print "all complete"
    del ws
    del sqldb

    return 0
Beispiel #13
0
    def run(self, generate_event, send_event, context={}):
        from pywws import WeatherStation

        # cyclic try connecting to weather station (when USB is disconnected)
        while True:
            try:
                station = WeatherStation.weather_station()

                for data, last_ptr, logged in station.live_data():

                    if not logged:
                        try:
                            if data['abs_pressure'] is not None:
                                e = generate_event('press')
                                e.value = data['abs_pressure']
                                send_event(e)

                            if data['temp_in'] is not None:
                                e = generate_event('temp')
                                e.sensor = 0
                                e.value = data['temp_in']
                                send_event(e)

                            if data['hum_in'] is not None:
                                e = generate_event('hum')
                                e.sensor = 0
                                e.value = data['hum_in']
                                send_event(e)

                            if data['temp_out'] is not None:
                                e = generate_event('temp')
                                e.sensor = 1
                                e.value = data['temp_out']
                                send_event(e)

                            if data['hum_out'] is not None:
                                e = generate_event('hum')
                                e.sensor = 1
                                e.value = data['hum_out']
                                send_event(e)

                            if data['rain'] is not None:
                                e = generate_event('rain')
                                e.total = data['rain']
                                e.rate = 0
                                send_event(e)

                            if data['wind_ave'] is not None and 0 <= data[
                                    'wind_dir'] < 16:
                                dir_degrees = data[
                                    'wind_dir'] * 22.5  # 360 / 16 = 22.5
                                e = generate_event('wind')
                                e.create_child('mean')
                                e.mean.speed = data['wind_ave']
                                e.mean.dir = dir_degrees
                                e.create_child('gust')
                                if data['wind_gust'] is not None:
                                    e.gust.speed = data['wind_gust']
                                    e.gust.dir = dir_degrees
                                else:
                                    e.gust.speed = None
                                    e.gust.dir = None
                                send_event(e)

                        except Exception, e:
                            self.logger.error(e)
            except IOError, e:
                self.logger.error('Exception IOError: ' + str(e))
            finally:
Beispiel #14
0
    def run(self, generate_event, send_event, context={}):

        from pywws import WeatherStation

	# pywws manages a wh1080 by default. Therefore '3080' shall be passed.
        station = WeatherStation.weather_station('3080')

        for data, last_ptr, logged in station.live_data():
            if not logged:
                try:
                    if data['abs_pressure'] is not None:
                        e = generate_event('press')
                        e.value = (10*(4.5+230+(data['abs_pressure'])))/10
                        #e.value = (10*(data['abs_pressure']))/10
                        send_event(e)

                    if data['temp_in'] is not None:                    
                        e = generate_event('temp')
                        e.sensor = 0
                        e.value = data['temp_in']
                        send_event(e)

                    if data['hum_in'] is not None:
                        e = generate_event('hum')
                        e.sensor = 0
                        e.value = data['hum_in']
                        send_event(e)

                    if data['temp_out'] is not None:
                        e = generate_event('temp')
                        e.sensor = 1
                        e.value = data['temp_out']
                        send_event(e)

                    if data['hum_out'] is not None:
                        e = generate_event('hum')
                        e.sensor = 1
                        e.value = data['hum_out']
                        send_event(e)

                    if data['rain'] is not None:
                        e = generate_event('rain')
                        e.total = (136*(data['rain']))/100 
                        e.rate = 0
                        send_event(e)

                    if data['wind_ave'] is not None and data['wind_dir'] < 16:
                        e = generate_event('wind')
                        e.create_child('mean')
                        e.mean.speed = data['wind_ave']
                        e.mean.dir = 22.5*(data['wind_dir']) 

                        e.create_child('gust')
                        e.gust.speed = 0.0;
                        e.gust.dir = 0.0;
                        if data['wind_gust']:
                            #e.create_child('gust')
                            e.gust.speed = data['wind_gust']
                            e.gust.dir = 22.5*(data['wind_dir'])
                        send_event(e)

                    # pywws manages "uv" in the case of 3080 stations 
                    if data['uv'] is not None:
                        e = generate_event('uv')
                        e.sensor = 1
                        e.value = data['uv']
                        send_event(e)

                    # pywws manages the "illuminance" in the case of 3080 stations 
                    if data['illuminance'] is not None:
                        e = generate_event('rad')
                        e.sensor = 1
                        e.value = (meteo.convert_illuminance_wm2(data['illuminance']))
                        send_event(e)

                except Exception, e:
                    self.logger.error(e)


                except Exception, e:
                    self.logger.error(e)
Beispiel #15
0
def main():
  ws = WeatherStation.weather_station()
  #print ws.get_fixed_block()

  #Make sure you have trailing /
  ROOTDIR='/pub/vault/weather/'
  RAINDATA='RAINDATA.pickle'
  pressure_offset=.48
  # Grab raw current output

  #We should see 'success' in this file if everything uploads to wunderground ok.
  STATUSFILE=ROOTDIR +'wgetfile.log'

  # Necessary Variables
  #============================================================
  # Need to parse this data and create variables for uploading to wunderground
  ID='MyStationID'
  PASSWORD='******'

  THEEPOCHTIME=str(int(round(time.time(), 0)))
  CURRENTTIME=time.strftime("%Y-%m-%d+%T", time.gmtime())
  WEBTIME=urllib.pathname2url(CURRENTTIME)

  #print ws.get_data(ws.current_pos(), unbuffered=False)

  #Create blank dictionary and then copy this from current buffer from WeatherStation.
  currentdata={}
  currentdata = ws.get_data(ws.current_pos(), unbuffered=False) 

  #get_data gives us a dictionary back. Here are the keys to work with
  #'hum_out': 97, 'wind_gust': 0, 'wind_ave': 0, 'rain': 167.7, 'temp_in': 28.900000000000002, 'delay': 0, 'abs_pressure': 1008.8000000000001, 'hum_in': 37, 'temp_out': 12.200000000000001, 'wind_dir': 14

  #=======================================================
  # UNIT CONVERSION 
  #======================================================
  #Now lets convert some of these key/value pairs to a unit that Wunderground uses.
  #Convert Windgust from m/s to MPH
  currentdata['wind_gust']=round(float(currentdata['wind_gust']) * 2.237,1)

  #Convert Wind Speed from m/s to MPH
  currentdata['wind_ave']=round(float(currentdata['wind_ave']) * 2.237, 1)

  #Convert from C to fahrenheit 
  currentdata['temp_in']=round(float(currentdata['temp_in']) * 1.8 + 32, 1)
  currentdata['temp_out']=round(float(currentdata['temp_out']) * 1.8 + 32, 1)

  #Convert RAINTOTAL from mm to inches
  currentdata['rain']=int(currentdata['rain']) * 0.039370

  #Convert barometer from hPa to inches
  currentdata['abs_pressure']=(float(currentdata['abs_pressure']) * 0.0295) + pressure_offset

  # Calculate dewpoint
  # Td = T - ((100 - RH)/5.)   Td is dewpoint, T in celsius 

  DEWPOINT=float(currentdata['temp_out']) - 9/25 * (100 - int(currentdata['hum_out']))
  #TD: =243.04*(LN(RH/100)+((17.625*T)/(243.04+T)))/(17.625-LN(RH/100)-((17.625*T)/(243.04+T))) 

  #Convert wind_dir integer which is 0-16 by 22.5 to give degrees.
  currentdata['wind_dir']=float(currentdata['wind_dir']) * 22.5

  #=====================================================
  # Rain Calculations
  #====================================================
  #RAIN LOGIC. Wunderground wants hourly rainfall, not total which is provided from the weather station.
  # We need to save the total at an hourly period, save epoch time (in seconds) and then we add up the delta for the hourly rollup.
  #Then at the next hour or (3600 seconds), we zero out the hourly and take another total rainfall snapshot.


  if os.path.exists(ROOTDIR + RAINDATA) == True:
       #Create dictionarys to store previous stats and unpack these via pickle file
       raindata={}
       with open(ROOTDIR+RAINDATA, "rb") as dictionaryfh:
         try:
           raindata = pickle.load(dictionaryfh)
         except:
           print "Pickle load had an exception. Going to have to go with current stats as starting point."
           #If the pickle file is bad, then we'll start over like the file doesn't exist 
           raindata['HOURLYSNAPSHOT']= THEEPOCHTIME
           raindata['RAINHOURLY']=currentdata['rain']
           raindata['MIDNIGHTSNAPSHOT']=currentdata['rain']
           RAINDELTA=0
           DAILYRAINTOTAL=0
       dictionaryfh.close()

       #add rain logic here
       #here we'll set RAINDELTA and DAILYTOTAL values
       if int(THEEPOCHTIME) - int(raindata['HOURLYSNAPSHOT']) >= 3600:
        #We need to redo snapshot for our hourly
        raindata['HOURLYSNAPSHOT']= THEEPOCHTIME
        raindata['RAINHOURLY']=currentdata['rain']
        RAINDELTA=0
       else:
         RAINDELTA=float(currentdata['rain']) - float(raindata['RAINHOURLY'])
     
       #Check for midnight
       # Lets also run through a test to see if we need to update the 'dailyrain' value.
       # This we need to take a snapshot at midnight of total rainfall. Then we will do a delta throughout the day based on the snapshot.
       # The idea is, if we're running this script every minute, then we'll land at midnight (since we're not grep'ing on seconds) at least once.
       # If we change the script execution time, then this isn't going to work correctly. If its set under 60 seconds, then we'll just reset a few times
       # which should not be a BIG issue. The likely hood of the rain numbers incrementing much in a few seconds at midnight is very unlikely and
       # I don't think we're going for that kind of accuracy.
      
       #grab time. Then strip out the seconds. Since we're just checking to see if we're at midnight 
       checktime=time.strftime("%T", time.localtime()).split(':')
       timenoseconds=checktime[0] + ':' + checktime[1] 
       if timenoseconds == '00:00':
         print "Its midnight"
         #Starting over since its midnight
         raindata['MIDNIGHTSNAPSHOT'] = float(currentdata['rain'])
         DAILYRAINTOTAL=0

       else:
         print "its NOT midnight" 
         DAILYRAINTOTAL=float(currentdata['rain']) - float(raindata['MIDNIGHTSNAPSHOT']) 


  else:
      print "No pickle file found. Initial run assumed."
      raindata={}
      raindata['HOURLYSNAPSHOT']= THEEPOCHTIME
      raindata['RAINHOURLY']=currentdata['rain']
      raindata['MIDNIGHTSNAPSHOT']=currentdata['rain']
      RAINDELTA=0
      DAILYRAINTOTAL=0 
    

  #Lets dump our dictionary for next run
  with open (ROOTDIR+RAINDATA, 'wb') as dictionaryfh:
    pickle.dump((raindata), dictionaryfh)
  dictionaryfh.close()




  #We need to replicate this:
  #Maybe pycurl or urllib?
  #wget -O$STATUSFILE "http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?ID=$ID&PASSWORD=$PASSWORD&dateutc=$THETIME&winddir=$WINDDIR&windspeedmph=$WINDSPEEDM&windgustmph=$WINDGUSTM&tempf=$TEMPF&rainin=$RAINDELTA&dailyrainin=$DAILYTOTAL&baromin=$BAROINCHES&dewptf=$DEWPOINTF&humidity=$OUTHUMIDITY&weather=&clouds=&softwaretype=vws%20versionxx&action=updateraw"

  buf = cStringIO.StringIO()
  #Set various variables for URL to make it a little more manageable as a string
  WURL='http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?' 
  AUTH='ID=' + ID + '&' + 'PASSWORD='******'&'
  THETIME='dateutc=' + WEBTIME + '&'
  WINDIR='winddir=' + str(currentdata['wind_dir']) + '&'
  WINDSPEED='windspeedmph=' + str(currentdata['wind_ave']) + '&'
  WINDGUST='windgustmph=' + str(currentdata['wind_gust']) + '&'
  TEMP='tempf=' + str(currentdata['temp_out']) + '&'
  RAININ='rainin=' + str(RAINDELTA) + '&' #add variable here
  DAILYRAIN='dailyrainin=' + str(DAILYRAINTOTAL) + '&' 

  BARO='baromin=' + str(currentdata['abs_pressure']) + '&'
  DEW='dewptf=' + str(DEWPOINT) + '&'
  HUM='humidity=' + str(currentdata['hum_out']) + '&' 
  TRAILER="weather=&clouds=&softwaretype=vws%20versionxx&action=updateraw"

  c = pycurl.Curl()
  c.setopt(c.URL, WURL + AUTH + THETIME + WINDIR + WINDSPEED + WINDGUST + TEMP + RAININ + DAILYRAIN + BARO + DEW + HUM + TRAILER)
  c.setopt(c.WRITEFUNCTION, buf.write)
  c.perform()

  #Print output from wunderground 
  print "Sending the following URL: "
  print WURL + AUTH + THETIME + WINDIR + WINDSPEED + WINDGUST + TEMP + RAININ + DAILYRAIN + BARO + DEW + HUM + TRAILER
  print "Returned value: ", buf.getvalue()


  #Print to log file
  with open(ROOTDIR + 'weather.log','w') as rawfile:
     print >> rawfile, "Sending the following URL: ", WURL + AUTH + THETIME + WINDIR + WINDSPEED + WINDGUST + TEMP + RAININ + DAILYRAIN + BARO + DEW + HUM + TRAILER, "   Returned value: ", buf.getvalue() 
  rawfile.close()
  buf.close()