示例#1
0
def read_rainfall():
    """Read todays rainfall."""
    watcher.feed()
    rain_last_hour_mm, rain_today_mm = (0.0, 0.0)
    File.logger().info('%s - Req to: %s', clock.timestamp(), _RAIN_URL)
    with requests.get(_RAIN_URL) as response:
        File.logger().info('%s - HTTP status: %d', clock.timestamp(),
                           response.status_code)
        if response.status_code == 200:
            first_line = True
            for line in response.iter_lines():
                if first_line:
                    first_line = False
                    continue
                gc.collect()
                text = line.decode('utf-8', 'ignore').strip()
                values = text.split(',')
                if len(values) == 3:
                    day = int(values[1].split('/')[0])
                    if day == clock.day_of_month():
                        mm = float(values[2])
                        rain_today_mm += mm
                        rain_last_hour_mm = mm
        else:
            raise ValueError("HTTP status %d" % response.status_code)

    File.logger().info('%s - Last hour %.1fmm, today %.1fmm',
                       clock.timestamp(), rain_last_hour_mm, rain_today_mm)
    print('Last hour %.1fmm, today %.1fmm' %
          (rain_last_hour_mm, rain_today_mm))
    return round(rain_last_hour_mm), round(rain_today_mm)
示例#2
0
def read_forecast():
    """Read the weather forecast."""
    watcher.feed()

    start_regex = ure.compile(r'timeseries')
    continue_regex = ure.compile(r'\},\{')
    hour_regex = ure.compile(r'next_1_hours')
    precip_regex = ure.compile(r'precipitation_amount\":(\d+\.\d)')
    date_regex = ure.compile(r'time\":\"(\d+-\d+-\d+)T')
    # Large chunk size more performant as less regex's run. Must be less than
    # characters in one timeseries element in the response.
    chunkSize = 1000
    windowSize = chunkSize * 2

    rain_today_mm, rain_tomorrow_mm = (0.0, 0.0)
    window = memoryview(bytearray(windowSize))
    emptyChunk = bytes(chunkSize)
    periodFound, hourFound, precipFound, dateFound = False, False, False, False

    File.logger().info('%s - Req to: %s', clock.timestamp(), _FORECAST_URL)
    with requests.get(_FORECAST_URL, headers=secrets.HEADER) as response:
        File.logger().info('%s - HTTP status: %d', clock.timestamp(),
                           response.status_code)
        if response.status_code == 200 or response.status_code == 203:
            for chunk in response.iter_content(chunkSize):
                # Populate response window
                window[0:chunkSize] = window[chunkSize:windowSize]
                if len(chunk) == chunkSize:
                    window[chunkSize:windowSize] = chunk
                else:
                    # last chunk is short
                    window[chunkSize:windowSize] = emptyChunk
                    window[chunkSize:chunkSize + len(chunk)] = chunk
                # print(window)
                windowBytes = bytes(window)  # regex requires bytes
                # Gather precipitation data
                if continue_regex.search(windowBytes) or\
                   start_regex.search(windowBytes):
                    periodFound = True
                if periodFound and hour_regex.search(windowBytes):
                    hourFound = True
                if periodFound and not dateFound:
                    if (dateGroup := date_regex.search(windowBytes)):
                        dateFound = True
                        date = dateGroup.group(1).decode()
                if hourFound and not precipFound:
                    if (precipGroup := precip_regex.search(windowBytes)):
                        precipFound = True
                        mm = float(precipGroup.group(1))
                if dateFound and precipFound:
                    periodFound, hourFound = False, False
                    dateFound, precipFound = False, False
                    # print(date, mm)
                    if clock.greater_than_tommorow(date):
                        break
                    elif clock.equal_to_today(date):
                        rain_today_mm += mm
                    else:
                        rain_tomorrow_mm += mm
示例#3
0
def send(rain_data, battery_volts):
    """Send weather and system information to Thingspeak."""
    watcher.feed()
    data_tuple = rain_data.get_data()
    url = _URL.format(key=secrets.THINGSPEAK_API_KEY,
                      *data_tuple,
                      volts=battery_volts,
                      status=int(not rain_data.rainfall_occurring()))
    File.logger().info('%s - Req to: %s', clock.timestamp(), url)
    with requests.get(url) as response:
        File.logger().info('%s - HTTP status: %d', clock.timestamp(),
                           response.status_code)
        if response.status_code != 200:
            raise ValueError("HTTP status %d" % response.status_code)
示例#4
0
def connect():
    """Connect to WiFi."""
    secs = WIFI_DELAY
    start = ticks_ms()

    sta_if = network.WLAN(network.STA_IF)
    sta_if.active(True)
    sta_if.connect(secrets.WIFI_SSID, secrets.WIFI_PASSPHRASE)

    while secs >= 0 and not sta_if.isconnected():
        sleep(CHECK_INTERVAL)
        secs -= CHECK_INTERVAL

    if sta_if.isconnected():
        File.logger().info('%s - Connected, address: %s in %d ms',
                           clock.timestamp(),
                           sta_if.ifconfig()[0], ticks_diff(ticks_ms(), start))
        return True
    else:
        sta_if.active(False)
        File.logger().error('%s - WiFi did not connect' % clock.timestamp())
        return False
示例#5
0
def run():
    """Main entry point to execute this program."""
    sleep_enabled = _sleep_enabled()
    try:
        File.logger().info('%s - Awake: %s', clock.timestamp(),
                           machine.wake_reason())
        rainfall = False
        next_wake = config.RTC_ALARM
        battery_volts = _battery_voltage()

        if not sleep_enabled:
            watcher.disable()

        if wifi.connect():
            _resetConnectCount()
            rain_data = weather.get_rain_data()
            rainfall = rain_data.rainfall_occurring()
            thingspeak.send(rain_data, battery_volts)

            if rainfall:
                File.logger().info('%s - System OFF', clock.timestamp())
                _system_off()
            else:
                File.logger().info('%s - System ON', clock.timestamp())
                _system_on()
        else:
            if _incrementConnectCount() > 5:
                # Give up trying to connect to WiFi
                _resetConnectCount()
            else:
                File.logger().info('%s - Set one minute sleep, attempts %d',
                                   clock.timestamp(), _getConnectCount())
                next_wake = config.SLEEP_ONE_MINUTE

    except Exception as ex:
        # Catch exceptions so that device goes back to sleep HTTP calls
        # fail with exceptions.
        File.logger().exc(ex, '%s - Error', clock.timestamp())
    finally:
        try:
            wifi.disconnect()
        except Exception as ex:
            File.logger().exc(ex, '%s - WIFI disconnect error',
                              clock.timestamp())

        if sleep_enabled:
            File.logger().info('%s - Sleeping...', clock.timestamp())
            File.close_log()
            _sleep_until(next_wake)
        else:
            File.close_log()
示例#6
0
 def headers(self, url, params=None, method=urlfetch.GET, other_headers = None):
     oauth_headers = {'oauth_nonce': nonce(),
                      'oauth_callback': self.callback_url,
                      'oauth_signature_method': "HMAC-SHA1",
                      'oauth_timestamp': str(clock.timestamp(clock.now())), 
                      'oauth_consumer_key': self.consumer_key,
                      'oauth_version': '1.0'}
     if other_headers:
         oauth_headers.update(other_headers)
     if self.access_token:
         oauth_headers['oauth_token'] = self.access_token
     oauth_headers['oauth_signature'] = self.sign(url, method, params, oauth_headers)
     oauth_headers['realm'] = ''
     
     return {'Authorization':
             'OAuth ' + ', '.join('%s="%s"' % (key, _encode(value))
                                  for key, value in oauth_headers.items())}
示例#7
0
                if continue_regex.search(windowBytes) or\
                   start_regex.search(windowBytes):
                    periodFound = True
                if periodFound and hour_regex.search(windowBytes):
                    hourFound = True
                if periodFound and not dateFound:
                    if (dateGroup := date_regex.search(windowBytes)):
                        dateFound = True
                        date = dateGroup.group(1).decode()
                if hourFound and not precipFound:
                    if (precipGroup := precip_regex.search(windowBytes)):
                        precipFound = True
                        mm = float(precipGroup.group(1))
                if dateFound and precipFound:
                    periodFound, hourFound = False, False
                    dateFound, precipFound = False, False
                    # print(date, mm)
                    if clock.greater_than_tommorow(date):
                        break
                    elif clock.equal_to_today(date):
                        rain_today_mm += mm
                    else:
                        rain_tomorrow_mm += mm
        else:
            raise ValueError('HTTP status %d' % response.status_code)

    File.logger().info('%s - Today %.1fmm, tomorrow %.1fmm', clock.timestamp(),
                       rain_today_mm, rain_tomorrow_mm)
    print('Today %.1fmm, tomorrow %.1fmm' % (rain_today_mm, rain_tomorrow_mm))
    return round(rain_today_mm), round(rain_tomorrow_mm)