def perform(self):
        url = 'https://api.ambientweather.net/v1/devices/' + str(
            self.params["macAddress"])
        parameterList = [("apiKey", str(self.params["apiKey"])),
                         ("applicationKey",
                          str(self.params["applicationKey"])), ("limit", "1")]

        log.info('Getting data from {0}'.format(str(url)))
        data = self.openURL(url, parameterList)

        if data is None:
            self.lastKnownError = "Error: No data received from server"
            log.error(self.lastKnownError)
            return

        station = json.loads(data.read())
        for entry in station:
            dateutc = entry["dateutc"] / 1000  # from milliseconds

            if 'tempf' in entry:
                temp = convertFahrenheitToCelsius(entry["tempf"])
                self.addValue(RMParser.dataType.TEMPERATURE, dateutc, temp,
                              False)

            if 'humidity' in entry:
                self.addValue(RMParser.dataType.RH, dateutc, entry["humidity"],
                              False)

            if 'windspeedmph' in entry:
                windspeed = entry["windspeedmph"] * 0.44704  # to meters/sec
                self.addValue(RMParser.dataType.WIND, dateutc, windspeed,
                              False)

            if 'solarradiation' in entry:
                solarrad = convertRadiationFromWattsToMegaJoules(
                    entry["solarradiation"])
                self.addValue(RMParser.dataType.SOLARRADIATION, dateutc,
                              solarrad, False)

            if 'dailyrainin' in entry:
                rain = convertInchesToMM(entry["dailyrainin"])
                self.addValue(RMParser.dataType.RAIN, dateutc, rain, False)

            if 'baromrelin' in entry:
                pressure = entry["baromrelin"] * 3.38639  # to kPa
                self.addValue(RMParser.dataType.PRESSURE, dateutc, pressure,
                              False)

            if 'dewPoint' in entry:
                dewpoint = convertFahrenheitToCelsius(entry["dewPoint"])
                self.addValue(RMParser.dataType.DEWPOINT, dateutc, dewpoint,
                              False)
        return True
    def parsePacket(self, raw_data):
        self.lastKnownError = ""
        if raw_data is None or len(raw_data) < 99:
            self.lastKnownError = "Invalid data response"
            return False

        timestamp = rmCurrentTimestamp()
        if self.parserDebug:
            hex_string = binascii.hexlify(raw_data).decode('utf-8')
            log.info("Raw Data LOOP %s" % hex_string)
        try:
            ack = struct.unpack('c', raw_data[0:1])[0]
            L = struct.unpack('c', raw_data[1:2])[0]
            O1 = struct.unpack('c', raw_data[2:3])[0]
            O2 = struct.unpack('c', raw_data[3:4])[0]
            pkt_type = struct.unpack('B', raw_data[5:6])[0]
            next_record = struct.unpack('H', raw_data[6:8])[0]
        except Exception:
            self.lastKnownError = "Invalid data format"
            return False

        if L != 'L' and O1 != 'O' and O2 != 'O':
            self.lastKnownError = "Unknown packet encoding"
            return False

        pressure = struct.unpack('H', raw_data[8:10])[0] / 1000
        pressure *= 3.386  # inHg to kPa
        log.info("Barometer: %s" % pressure)
        self.addValue(RMParser.dataType.PRESSURE, timestamp, pressure)

        outside_temp = struct.unpack('h', raw_data[13:15])[0] / 10
        outside_temp = convertFahrenheitToCelsius(outside_temp)
        log.info("Outside Temp: %s" % outside_temp)
        self.addValue(RMParser.dataType.TEMPERATURE, timestamp, outside_temp)

        #wind_speed = struct.unpack('B', raw_data[15:16])[0]
        #wind_dir = struct.unpack('H', raw_data[17:19])[0]
        ten_min_avg_wind_spd = struct.unpack('B', raw_data[16:17])[0]
        ten_min_avg_wind_spd /= 2.237  # mph to mps
        log.info("Wind Speed (10min avg): %s" % ten_min_avg_wind_spd)

        out_hum = struct.unpack('B', raw_data[34:35])[0]
        log.info("Humidity: %s" % out_hum)
        self.addValue(RMParser.dataType.RH, timestamp, out_hum)

        #rain_rate = struct.unpack('H', raw_data[42:44])[0] * 0.01
        if self.params["useSolarRadiation"]:
            solar_radiation = struct.unpack('H', raw_data[45:47])[0]
            log.info("Solar Radiation: %s" % solar_radiation)
            self.addValue(RMParser.dataType.SOLARRADIATION, timestamp,
                          solar_radiation)

        day_rain = struct.unpack('H', raw_data[51:53])[0] * 0.01
        day_rain = convertInchesToMM(day_rain)
        log.info("Day Rain: %s", day_rain)
        self.addValue(RMParser.dataType.RAIN, timestamp, day_rain)

        if self.params["useStationEvapoTranpiration"]:
            day_et = struct.unpack('H', raw_data[57:59])[0] / 1000
            day_et = convertInchesToMM(day_et)
            log.info("Day EvapoTranspiration: %s" % day_et)

        #xmtr_battery_status = struct.unpack('?', raw_data[87:88])[0]
        #console_battery_volts = ((struct.unpack('h', raw_data[88:90])[0] * 300) / 512) / 100.0

        forecast_icon = struct.unpack('c', raw_data[90:91])[0]
        rainmachine_icon = self.conditionConvert(ord(forecast_icon))
        log.info("Condition: %s -> %s" %
                 (ord(forecast_icon), rainmachine_icon))
        self.addValue(RMParser.dataType.CONDITION, timestamp, rainmachine_icon)
        #crc  = struct.unpack('h', raw_data[98:100])[0]

        return True
    def perform(self):
        s = self.settings
        URL = "http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdXMLclient.php"
        URLDaily = "http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php"
        URLParams = [("lat", s.location.latitude),
                  ("lon", s.location.longitude)] + \
            [
                ("startDate", datetime.date.today().strftime("%Y-%m-%d")),
                #("endDate", (datetime.date.today() + datetime.timedelta(6)).strftime("%Y-%m-%d")),
                ("format", "24 hourly"),
                ("numDays", 6),
                ("Unit", "e")
            ]

        #-----------------------------------------------------------------------------------------------
        #
        # Get hourly data.
        #
        d = self.openURL(URL, URLParams)
        if d is None:
            return

        tree = e.parse(d)

        if tree.getroot().tag == 'error':
            log.error("*** No hourly information found in response!")
            self.lastKnownError = "Error: No hourly information found"
            tree.getroot().clear()
            del tree
            tree = None
        else:
            # We get them in English units need in Metric units
            maxt = self.__parseWeatherTag(tree, 'temperature', 'maximum')
            maxt = convertFahrenheitToCelsius(maxt)

            mint = self.__parseWeatherTag(tree, 'temperature', 'minimum', useStartTimes=False) # for mint we want the end-time to be saved in DB
            mint = convertFahrenheitToCelsius(mint)

            temp = self.__parseWeatherTag(tree, 'temperature', 'hourly')
            temp = convertFahrenheitToCelsius(temp)

            qpf = self.__parseWeatherTag(tree, 'precipitation', 'liquid')
            qpf = convertInchesToMM(qpf)

            dew = self.__parseWeatherTag(tree, 'temperature', 'dew point')
            dew = convertFahrenheitToCelsius(dew)

            wind = self.__parseWeatherTag(tree, 'wind-speed', 'sustained')
            wind = convertKnotsToMS(wind)

            # These are as percentages
            pop = self.__parseWeatherTag(tree, 'probability-of-precipitation', '12 hour')
            humidity = self.__parseWeatherTag(tree, 'humidity', 'relative')
            minHumidity = self.__parseWeatherTag(tree, 'humidity', 'minimum relative')
            maxHumidity = self.__parseWeatherTag(tree, 'humidity', 'maximum relative')

            tree.getroot().clear()
            del tree
            tree = None

            self.addValues(RMParser.dataType.MINTEMP, mint)
            self.addValues(RMParser.dataType.MAXTEMP, maxt)
            self.addValues(RMParser.dataType.TEMPERATURE, temp)
            self.addValues(RMParser.dataType.QPF, qpf)
            self.addValues(RMParser.dataType.DEWPOINT, dew)
            self.addValues(RMParser.dataType.WIND, wind)
            self.addValues(RMParser.dataType.POP, pop)
            self.addValues(RMParser.dataType.RH, humidity)
            self.addValues(RMParser.dataType.MINRH, minHumidity)
            self.addValues(RMParser.dataType.MAXRH, maxHumidity)

        #-----------------------------------------------------------------------------------------------
        #
        # Get daily data.
        #
        d = self.openURL(URLDaily, URLParams)
        tree = e.parse(d)

        if tree.getroot().tag == 'error':
            log.error("*** No daily information found in response!")
            self.lastKnownError = "Error: No daily information found"
            tree.getroot().clear()
            del tree
            tree = None
        else:
            conditions = self.__parseWeatherTag(tree, 'conditions-icon', 'forecast-NWS', 'icon-link')
            parsedConditions = []

            for c in conditions:
                if c and len(c) >= 2:
                    try:
                        cv = self.conditionConvert(c[1].rsplit('.')[-2].rsplit('/')[-1])
                    except:
                        cv = RMWeatherConditions.Unknown

                    parsedConditions.append((c[0], cv))

            tree.getroot().clear()
            del tree
            tree = None

            self.addValues(RMParser.dataType.CONDITION, parsedConditions)

        if self.parserDebug:
            log.debug(self.result)
示例#4
0
    def getHourlyData(self, URL, URLParams, headers):

        d = self.openURL(URL, URLParams, headers=headers)
        if d is None:
            return False
        try:
            tree = e.parse(d)
        except:
            return False

        if tree.getroot().tag == 'error':
            log.error("*** No hourly information found in response!")
            self.lastKnownError = "Retrying hourly data retrieval"
            tree.getroot().clear()
            del tree
            tree = None
            return False

        # Reset lastKnownError from a previous function call
        self.lastKnownError = ""

        # We get them in English units need in Metric units
        maxt = self.__parseWeatherTag(tree, 'temperature', 'maximum')
        maxt = convertFahrenheitToCelsius(maxt)

        mint = self.__parseWeatherTag(tree, 'temperature', 'minimum', useStartTimes=False) # for mint we want the end-time to be saved in DB
        mint = convertFahrenheitToCelsius(mint)

        temp = self.__parseWeatherTag(tree, 'temperature', 'hourly')
        temp = convertFahrenheitToCelsius(temp)

        qpf = self.__parseWeatherTag(tree, 'precipitation', 'liquid')
        qpf = convertInchesToMM(qpf)

        dew = self.__parseWeatherTag(tree, 'temperature', 'dew point')
        dew = convertFahrenheitToCelsius(dew)

        wind = self.__parseWeatherTag(tree, 'wind-speed', 'sustained')
        wind = convertKnotsToMS(wind)

        # These are as percentages
        pop = self.__parseWeatherTag(tree, 'probability-of-precipitation', '12 hour')
        pop = convertToInt(pop)

        humidity = self.__parseWeatherTag(tree, 'humidity', 'relative')
        humidity = convertToFloat(humidity)

        minHumidity = self.__parseWeatherTag(tree, 'humidity', 'minimum relative')
        minHumidity = convertToFloat(minHumidity)

        maxHumidity = self.__parseWeatherTag(tree, 'humidity', 'maximum relative')
        maxHumidity = convertToFloat(maxHumidity)

        tree.getroot().clear()
        del tree
        tree = None

        # Save
        self.addValues(RMParser.dataType.MINTEMP, mint)
        self.addValues(RMParser.dataType.MAXTEMP, maxt)
        self.addValues(RMParser.dataType.TEMPERATURE, temp)
        self.addValues(RMParser.dataType.QPF, qpf)
        self.addValues(RMParser.dataType.DEWPOINT, dew)
        self.addValues(RMParser.dataType.WIND, wind)
        self.addValues(RMParser.dataType.POP, pop)
        self.addValues(RMParser.dataType.RH, humidity)
        self.addValues(RMParser.dataType.MINRH, minHumidity)
        self.addValues(RMParser.dataType.MAXRH, maxHumidity)

        return True
示例#5
0
    def getHourlyData(self, URL, URLParams, headers):

        d = self.openURL(URL, URLParams, headers=headers)
        if d is None:
            return False
        try:
            tree = e.parse(d)
        except:
            return False

        #tree = e.parse("/tmp/noaa-fl-2019-06-04-1.xml")

        if tree.getroot().tag == 'error':
            log.error("*** No hourly information found in response!")
            self.lastKnownError = "Retrying hourly data retrieval"
            tree.getroot().clear()
            del tree
            tree = None
            return False

        # Reset lastKnownError from a previous function call
        self.lastKnownError = ""

        # We get them in English units need in Metric units

        # 2019-06-01: If we send that weather properties we want (qpf=qpf&mint=mint) in request URL NOAA response forgets
        # past hours in current day resulting in a forecast requested at the end of the day
        # having null/0 qpf forgetting the older values which could had more qpf so we need to process QPF first and
        # determine which entries don't have full days with qpf reported (especially current day) then completely skip
        # this day for the rest of the weather properties so we don't have a forecast entry with null/0 qpf

        # Algorithm allows multiple partial days to be skipped because incomplete but we currently only skip today

        # QPF needs to be the first tag parsed to build the skippedDays structure
        qpf = self.__parseWeatherTag(tree,
                                     'precipitation',
                                     'liquid',
                                     skippedDays=self.skippedDays,
                                     addToSkippedDays=True)
        qpf = convertInchesToMM(qpf)

        maxt = self.__parseWeatherTag(tree,
                                      'temperature',
                                      'maximum',
                                      skippedDays=self.skippedDays)
        maxt = convertFahrenheitToCelsius(maxt)

        mint = self.__parseWeatherTag(
            tree,
            'temperature',
            'minimum',
            useStartTimes=False,
            skippedDays=self.skippedDays
        )  # for mint we want the end-time to be saved in DB
        mint = convertFahrenheitToCelsius(mint)

        temp = self.__parseWeatherTag(tree,
                                      'temperature',
                                      'hourly',
                                      skippedDays=self.skippedDays)
        temp = convertFahrenheitToCelsius(temp)

        dew = self.__parseWeatherTag(tree,
                                     'temperature',
                                     'dew point',
                                     skippedDays=self.skippedDays)
        dew = convertFahrenheitToCelsius(dew)

        wind = self.__parseWeatherTag(tree,
                                      'wind-speed',
                                      'sustained',
                                      skippedDays=self.skippedDays)
        wind = convertKnotsToMS(wind)

        # These are as percentages
        pop = self.__parseWeatherTag(tree,
                                     'probability-of-precipitation',
                                     '12 hour',
                                     skippedDays=self.skippedDays)
        pop = convertToInt(pop)

        humidity = self.__parseWeatherTag(tree,
                                          'humidity',
                                          'relative',
                                          skippedDays=self.skippedDays)
        humidity = convertToFloat(humidity)

        minHumidity = self.__parseWeatherTag(tree,
                                             'humidity',
                                             'minimum relative',
                                             skippedDays=self.skippedDays)
        minHumidity = convertToFloat(minHumidity)

        maxHumidity = self.__parseWeatherTag(tree,
                                             'humidity',
                                             'maximum relative',
                                             skippedDays=self.skippedDays)
        maxHumidity = convertToFloat(maxHumidity)

        if self.parserDebug:
            tree.write('noaa-' +
                       str(rmTimestampToDateAsString(rmCurrentTimestamp())) +
                       ".xml")

        tree.getroot().clear()
        del tree
        tree = None

        # Save
        self.addValues(RMParser.dataType.MINTEMP, mint)
        self.addValues(RMParser.dataType.MAXTEMP, maxt)
        self.addValues(RMParser.dataType.TEMPERATURE, temp)
        self.addValues(RMParser.dataType.QPF, qpf)
        self.addValues(RMParser.dataType.DEWPOINT, dew)
        self.addValues(RMParser.dataType.WIND, wind)
        self.addValues(RMParser.dataType.POP, pop)
        self.addValues(RMParser.dataType.RH, humidity)
        self.addValues(RMParser.dataType.MINRH, minHumidity)
        self.addValues(RMParser.dataType.MAXRH, maxHumidity)

        return True
class AmbientWeatherParser(RMParser):
    parserName = "Ambient Weather Network Parser"
    parserDescription = "Live personal weather station data from www.ambientweather.net"
    parserForecast = False
    parserHistorical = True
    parserEnabled = False
    parserDebug = False
    parserInterval = 60 * 60  # hourly
    paserHasData = False

    params = {"apiKey": None, "applicationKey": None, "macAddress": None}

    req_headers = {
        "User-Agent":
        "ambientweather-parser/1.0 (https://github.com/WillCodeForCats/rainmachine-amweather)"
    }

    def perform(self):

        url = 'http://api.ambientweather.net/v1/devices/' + str(
            self.params["macAddress"])
        parameterList = [("apiKey", str(self.params["apiKey"])),
                         ("applicationKey",
                          str(self.params["applicationKey"])), ("limit", "1")]

        log.info('Getting data from {0}'.format(str(url)))

        query_string = urllib.urlencode(parameterList)
        url_query = "?".join([url, query_string])

        try:
            req = urllib2.Request(url=url_query, headers=self.req_headers)
            data = urllib2.urlopen(url=req, timeout=60)
            log.debug("Connected to %s" % (url_query))
        except Exception, e:
            self.lastKnownError = "Connection Error"
            log.error("Error while connecting to %s, error: %s" %
                      (url, e.reason))
            return

        http_status = data.getcode()
        log.debug("http_status = %s" % (http_status))
        if http_status != 200:
            self.lastKnownError = "HTTP Error " + http_status
            log.error("URL %s failed with code %s" % (url, http_status))
            return

        station = json.loads(data.read())
        for entry in station:
            dateutc = entry["dateutc"] / 1000  # from milliseconds

            if 'tempf' in entry:
                temp = convertFahrenheitToCelsius(entry["tempf"])
                self.addValue(RMParser.dataType.TEMPERATURE, dateutc, temp,
                              False)
                log.debug("TEMPERATURE = %s" % (temp))
                self.paserHasData = True

            if 'humidity' in entry:
                self.addValue(RMParser.dataType.RH, dateutc, entry["humidity"],
                              False)
                log.debug("RH = %s" % (entry["humidity"]))
                self.paserHasData = True

            if 'windspeedmph' in entry:
                windspeed = entry["windspeedmph"] * 0.44704  # to meters/sec
                self.addValue(RMParser.dataType.WIND, dateutc, windspeed,
                              False)
                log.debug("WIND = %s" % (windspeed))
                self.paserHasData = True

            if 'solarradiation' in entry:
                solarrad = self.convertRadiationFromWattsToMegaJoules(
                    entry["solarradiation"])
                self.addValue(RMParser.dataType.SOLARRADIATION, dateutc,
                              solarrad, False)
                log.debug("SOLARRADIATION = %s" % (solarrad))
                self.paserHasData = True

            if 'dailyrainin' in entry:
                rain = convertInchesToMM(entry["dailyrainin"])
                self.addValue(RMParser.dataType.RAIN, dateutc, rain, False)
                log.debug("RAIN = %s" % (rain))
                self.paserHasData = True

            if 'baromrelin' in entry:
                pressure = entry["baromrelin"] * 3.38639  # to kPa
                self.addValue(RMParser.dataType.PRESSURE, dateutc, pressure,
                              False)
                log.debug("PRESSURE = %s" % (pressure))
                self.paserHasData = True

            if 'dewPoint' in entry:
                dewpoint = convertFahrenheitToCelsius(entry["dewPoint"])
                self.addValue(RMParser.dataType.DEWPOINT, dateutc, dewpoint,
                              False)
                log.debug("DEWPOINT = %s" % (dewpoint))
                self.paserHasData = True

        if self.paserHasData:
            log.info("Successful update from station %s" %
                     (str(self.params["macAddress"])))
            return True
        else:
            self.lastKnownError = "No Data From Station"
            log.error("Connected, but no data returned from station %s" %
                      (str(self.params["macAddress"])))
            return
示例#7
0
    def perform(self):
        s = self.settings
        URL = "http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdXMLclient.php"
        URLDaily = "http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php"
        URLParams = [("lat", s.location.latitude),
                  ("lon", s.location.longitude)] + \
            [
                ("startDate", datetime.date.today().strftime("%Y-%m-%d")),
                #("endDate", (datetime.date.today() + datetime.timedelta(6)).strftime("%Y-%m-%d")),
                ("format", "24 hourly"),
                ("numDays", 6),
                ("Unit", "e")
            ]

        #-----------------------------------------------------------------------------------------------
        #
        # Get hourly data.
        #
        d = self.openURL(URL, URLParams)
        if d is None:
            return

        tree = e.parse(d)

        if tree.getroot().tag == 'error':
            log.error("*** No hourly information found in response!")
            self.lastKnownError = "Error: No hourly information found"
            tree.getroot().clear()
            del tree
            tree = None
        else:
            # We get them in English units need in Metric units
            maxt = self.__parseWeatherTag(tree, 'temperature', 'maximum')
            maxt = convertFahrenheitToCelsius(maxt)

            mint = self.__parseWeatherTag(tree, 'temperature', 'minimum', useStartTimes=False) # for mint we want the end-time to be saved in DB
            mint = convertFahrenheitToCelsius(mint)

            temp = self.__parseWeatherTag(tree, 'temperature', 'hourly')
            temp = convertFahrenheitToCelsius(temp)

            qpf = self.__parseWeatherTag(tree, 'precipitation', 'liquid')
            qpf = convertInchesToMM(qpf)

            dew = self.__parseWeatherTag(tree, 'temperature', 'dew point')
            dew = convertFahrenheitToCelsius(dew)

            wind = self.__parseWeatherTag(tree, 'wind-speed', 'sustained')
            wind = convertKnotsToMS(wind)

            # These are as percentages
            pop = self.__parseWeatherTag(tree, 'probability-of-precipitation', '12 hour')
            humidity = self.__parseWeatherTag(tree, 'humidity', 'relative')
            minHumidity = self.__parseWeatherTag(tree, 'humidity', 'minimum relative')
            maxHumidity = self.__parseWeatherTag(tree, 'humidity', 'maximum relative')

            tree.getroot().clear()
            del tree
            tree = None

            self.addValues(RMParser.dataType.MINTEMP, mint)
            self.addValues(RMParser.dataType.MAXTEMP, maxt)
            self.addValues(RMParser.dataType.TEMPERATURE, temp)
            self.addValues(RMParser.dataType.QPF, qpf)
            self.addValues(RMParser.dataType.DEWPOINT, dew)
            self.addValues(RMParser.dataType.WIND, wind)
            self.addValues(RMParser.dataType.POP, pop)
            self.addValues(RMParser.dataType.RH, humidity)
            self.addValues(RMParser.dataType.MINRH, minHumidity)
            self.addValues(RMParser.dataType.MAXRH, maxHumidity)

        #-----------------------------------------------------------------------------------------------
        #
        # Get daily data.
        #
        d = self.openURL(URLDaily, URLParams)
        tree = e.parse(d)

        if tree.getroot().tag == 'error':
            log.error("*** No daily information found in response!")
            self.lastKnownError = "Error: No daily information found"
            tree.getroot().clear()
            del tree
            tree = None
        else:
            conditions = self.__parseWeatherTag(tree, 'conditions-icon', 'forecast-NWS', 'icon-link')
            parsedConditions = []

            for c in conditions:
                if c and len(c) >= 2:
                    try:
                        cv = self.conditionConvert(c[1].rsplit('.')[-2].rsplit('/')[-1])
                    except:
                        cv = RMWeatherConditions.Unknown

                    parsedConditions.append((c[0], cv))

            tree.getroot().clear()
            del tree
            tree = None

            self.addValues(RMParser.dataType.CONDITION, parsedConditions)

        if self.parserDebug:
            log.debug(self.result)