def getStationData(self, jsonData): #daily summary for yesterday try: dailysummary = jsonData["history"]["dailysummary"][0] temperature = self.__toFloat(dailysummary["meantempm"]) mintemp = self.__toFloat(dailysummary["mintempm"]) maxtemp = self.__toFloat(dailysummary["maxtempm"]) rh = self.__toFloat(dailysummary["humidity"]) minrh = self.__toFloat(dailysummary["minhumidity"]) maxrh = self.__toFloat(dailysummary["maxhumidity"]) dewpoint = self.__toFloat(dailysummary["meandewptm"]) wind = self.__toFloat(dailysummary["meanwindspdm"]) if wind is not None: wind = wind / 3.6 # convertred from kmetersph to mps maxpressure = self.__toFloat(dailysummary["maxpressurem"]) minpressure = self.__toFloat(dailysummary["minpressurem"]) pressure = None if maxpressure is not None and minpressure is not None: pressure = (maxpressure / 2 + minpressure / 2) / 10 #converted to from mb to kpa rain = self.__toFloat(dailysummary["precipm"]) #time utc jutc = jsonData["history"]["utcdate"] yyyy = self.__toInt(jutc["year"]) mm = self.__toInt(jutc["mon"]) dd = self.__toInt(jutc["mday"]) hour = self.__toInt(jutc["hour"]) mins = self.__toInt(jutc["min"]) log.debug("Observations for date: %d/%d/%d Temp: %s, Rain: %s" % (yyyy, mm, dd, temperature, rain)) dd = datetime.datetime(yyyy, mm, dd, hour, mins) timestamp = calendar.timegm(dd.timetuple()) timestamp = self.__parseDateTime(timestamp) self.addValue(RMParser.dataType.TEMPERATURE, timestamp, temperature) self.addValue(RMParser.dataType.MINTEMP, timestamp, mintemp) self.addValue(RMParser.dataType.MAXTEMP, timestamp, maxtemp) self.addValue(RMParser.dataType.RH, timestamp, rh) self.addValue(RMParser.dataType.MINRH, timestamp, minrh) self.addValue(RMParser.dataType.MAXRH, timestamp, maxrh) self.addValue(RMParser.dataType.WIND, timestamp, wind) self.addValue(RMParser.dataType.RAIN, timestamp, rain) # self.addValue(RMParser.dataType.QPF, timestamp, rain) # uncomment to report measured rain as previous day QPF self.addValue(RMParser.dataType.DEWPOINT, timestamp, dewpoint) self.addValue(RMParser.dataType.PRESSURE, timestamp, pressure) except: log.warning("Failed to get daily summary") self.lastKnownError = "Warning: Failed to get daily summary" self.__getSimpleForecast()
def __refreshWIFI(self): timestamp = rmCurrentTimestamp() lastWIFICheckTimestamp = globalWIFI.wifiInterface.lastWIFICheckTimestamp oldIP = globalWIFI.wifiInterface.ipAddress if lastWIFICheckTimestamp is None or oldIP is None or ( timestamp - lastWIFICheckTimestamp) >= self.__wifiRefreshTimeout: try: globalWIFI.detect() if oldIP != globalWIFI.wifiInterface.ipAddress: log.info( "Refreshed WIFI Information. (old: %s new ip: %s)" % ( ` oldIP `, ` globalWIFI.wifiInterface.ipAddress `)) if RMOSPlatform().AUTODETECTED == RMOSPlatform.ANDROID: return # Handle None IP if globalWIFI.wifiInterface.ipAddress is None: if self.__lastNoneIpTimestamp is None or ( timestamp - self.__lastNoneIpTimestamp ) < self.__wifiNoneIpTimeout: # First occurrence of None IP OR we can wait some more time. if self.__lastNoneIpTimestamp is None: self.__lastNoneIpTimestamp = timestamp log.debug( "Refreshed WIFI Information - no IP detected. Give it some more time: %d seconds!" % (self.__wifiNoneIpTimeout - (timestamp - self.__lastNoneIpTimestamp), )) return else: globalWIFI.restart() log.warn( "Refreshed WIFI Information - WIFI quick reloaded because no IP detected. New IP is %s" % ` globalWIFI.wifiInterface.ipAddress `) self.__lastNoneIpTimestamp = None # Reset None IP timestamp. # Check if we never connected to this AP, set back AP mode and restart app if globalWIFI.wifiInterface.mode == "managed" and not globalWIFI.hasConnectedOnce( ): if globalWIFI.wifiInterface.hasClientLink: globalWIFI.saveHasConnectedOnce(True) else: log.warning( "WIFI Watcher Client IP (%s) configuration failed, restarting in AP mode." % oldIP) globalWIFI.setDefaultAP() globalWIFI.saveHasConnectedOnce(False) globalWIFI.restart() self.__mainManager.touchWakeMessage() except Exception, e: log.error(e)
def perform(self): timeNow = rmNowDateTime() timeNow = rmNowDateTime().fromordinal(timeNow.toordinal()-1) yyyy = timeNow.year mm = timeNow.month dd = timeNow.day self.params["_nearbyStationsIDList"] = [] self.params["_airportStationsIDList"] = [] apiKey = self.params.get("apiKey", None) if apiKey is None or not apiKey or not isinstance(apiKey, str): log.error("No API Key provided") self.lastKnownError = "Error: No API Key provided" return self.apiURL = "http://api.wunderground.com/api/" + str(apiKey) + "/geolookup/conditions/hourly10day/history_" + str(yyyy) + str(mm).zfill(2) + str(dd).zfill(2) +"/q/" if self.params.get("useCustomStation"): stationName = self.params.get("customStationName") if(stationName is None or not stationName or not isinstance(stationName, str)): log.error("Station ID cannot be empty") self.lastKnownError = "Error: Station ID cannot be empty" return log.debug("getting data from specified station") if len(stationName) > 4: self.apiURL += "pws:" + stationName + ".json" #url for pws else: self.apiURL += stationName + ".json" #url for pws else: s = self.settings llat = s.location.latitude llon = s.location.longitude self.apiURL += str(llat) + "," + str(llon) + ".json" log.debug(self.apiURL) d = self.openURL(self.apiURL) jsonContent = d.read() if jsonContent is None: log.error("Failed to get WUnderground JSON contents") self.lastKnownError = "Error: Bad response" return self.jsonResponse = json.loads(jsonContent) #populate nearby stations self.getNearbyStations(self.jsonResponse) self.getStationData(self.jsonResponse) if self.params.get("useCustomStation") and self.params.get("useSolarRadiation"): self.__getSolarRadiation() elif self.params.get("useSolarRadiation"): log.warning("Unable to get solar radiation. You need to specify a pws.") return
def __checkThreads(self): timestamp = rmCurrentTimestamp() # Work around for a system date change resetWatcher = not self.__lastCheckTimestamp is None and \ abs(timestamp - self.__lastCheckTimestamp) >= self.__systemTimeChangeThreshold everythingOk = True if resetWatcher: fromTime = rmTimestampToDateAsString( self.__lastCheckTimestamp ) if self.__lastCheckTimestamp else None toTime = rmTimestampToDateAsString(timestamp) log.warning( "System time has changed (from %s, to %s)! Resetting thread watcher!" % (fromTime, toTime)) self.__lastWatchdogTimestamp = None for threadId in self.__data: details = self.__getThreadEntry(threadId) details[RMThreadWatcher.LastUpdateKey] = None if self.__mainManager: self.__mainManager.systemDateTimeChanged() else: for threadId in self.__data: details = self.__getThreadEntry(threadId) timeoutHint = details[RMThreadWatcher.TimeoutHintKey] lastUpdate = details[RMThreadWatcher.LastUpdateKey] if timeoutHint is None: log.debug("Thread %d (%s) has no timeout hint!" % (threadId, details[RMThreadWatcher.NameHintKey])) elif lastUpdate is None: log.debug("Thread %d (%s) is not started yet!" % (threadId, details[RMThreadWatcher.NameHintKey])) elif timeoutHint < (timestamp - lastUpdate): everythingOk = False log.debug("Thread %d (%s) didn't responde since [%s] (timeoutHint=%d, timeout=%d)!" % \ (threadId, details[RMThreadWatcher.NameHintKey], rmTimestampToDateAsString(lastUpdate), timeoutHint, (timestamp - lastUpdate))) self.__lastCheckTimestamp = timestamp return everythingOk
def getNearbyStations(self, jsonData): nearbyStations = jsonData["location"][ "nearby_weather_stations"] airportStations = None pwsStations = None try: airportStations = nearbyStations["airport"] except: log.warning("No airport stations found!") self.lastKnownError = "Warning: No airport stations found!" try: pwsStations = nearbyStations["pws"] except: log.warning("No pws stations found!") self.lastKnownError = "Warning: No pws stations found!" if(pwsStations is not None): arrStations = pwsStations["station"] for st in arrStations: self.params["_nearbyStationsIDList"].append(str(st["id"]) + "(" + str(st["distance_km"]) + "km" + "; lat=" + str(round(st["lat"],2)) + ", lon=" + str(round(st["lon"],2)) + ")") if(airportStations is not None): arrStations = airportStations["station"] for st in arrStations: distance = None if not st["icao"]: continue lat = self.__toFloat(st["lat"]) lon = self.__toFloat(st["lon"]) llat = self.settings.location.latitude llon = self.settings.location.longitude if lat is not None and lon is not None: # some airports don't report lat/lon distance = distanceBetweenGeographicCoordinatesAsKm(lat, lon, llat, llon) if distance is not None: distance = self.__toInt(round(distance)) else: distance = -1 self.params["_airportStationsIDList"].append(str(st["icao"]) + "(" + str(distance) + "km" + "; lat=" + str(round(lat,2)) + ", lon=" + str(round(lon,2)) + ")" ) return self.params["_nearbyStationsIDList"]
def __refreshWIFI(self): timestamp = rmCurrentTimestamp() lastWIFICheckTimestamp = globalWIFI.wifiInterface.lastWIFICheckTimestamp oldIP = globalWIFI.wifiInterface.ipAddress if lastWIFICheckTimestamp is None or oldIP is None or (timestamp - lastWIFICheckTimestamp) >= self.__wifiRefreshTimeout: try: globalWIFI.detect() if oldIP != globalWIFI.wifiInterface.ipAddress: log.info("Refreshed WIFI Information. (old: %s new ip: %s)" % (`oldIP`, `globalWIFI.wifiInterface.ipAddress`)) if RMOSPlatform().AUTODETECTED == RMOSPlatform.ANDROID: return # Handle None IP if globalWIFI.wifiInterface.ipAddress is None: if self.__lastNoneIpTimestamp is None or (timestamp - self.__lastNoneIpTimestamp) < self.__wifiNoneIpTimeout: # First occurrence of None IP OR we can wait some more time. if self.__lastNoneIpTimestamp is None: self.__lastNoneIpTimestamp = timestamp log.debug("Refreshed WIFI Information - no IP detected. Give it some more time: %d seconds!" % (self.__wifiNoneIpTimeout - (timestamp - self.__lastNoneIpTimestamp), )) return else: globalWIFI.restart() log.warn("Refreshed WIFI Information - WIFI quick reloaded because no IP detected. New IP is %s" % `globalWIFI.wifiInterface.ipAddress`) self.__lastNoneIpTimestamp = None # Reset None IP timestamp. # Check if we never connected to this AP, set back AP mode and restart app if globalWIFI.wifiInterface.mode == "managed" and not globalWIFI.hasConnectedOnce(): if globalWIFI.wifiInterface.hasClientLink: globalWIFI.saveHasConnectedOnce(True) else: log.warning("WIFI Watcher Client IP (%s) configuration failed, restarting in AP mode." % oldIP) globalWIFI.setDefaultAP() globalWIFI.saveHasConnectedOnce(False) globalWIFI.restart() self.__mainManager.touchWakeMessage() except Exception, e: log.error(e)
def getNearbyStations(self, jsonData): try: nearestStation = jsonData["location"].get("id") except: log.warning("No closest station found!") self.lastKnownError = "Warning: No closest station found!" return closestURL = "https://api.willyweather.com.au/v2/" + self.apiKey + "/search/closest.json" closestURLParams = [("id", nearestStation), ("weatherTypes", "general"), ("units", "distance:km")] try: d = self.openURL(closestURL, closestURLParams) if d is None: return closest = json.loads(d.read()) if self.parserDebug: log.info(closest) for i in closest["general"]: id = i["id"] name = i["name"] region = i["region"] postcode = i["postcode"] distance = i["distance"] infoStr = "Station ID = " + str( id) + " (" + name + ", " + region + ", " + str( postcode) + ", " + str(distance) + " kms away)" self.params["_nearbyStationsIDList"].append(infoStr) if self.parserDebug: log.debug(self.params["_nearbyStationsIDList"]) except Exception, e: log.error("*** Error running WillyWeather parser") log.exception(e)
def __checkThreads(self): timestamp = rmCurrentTimestamp() # Work around for a system date change resetWatcher = not self.__lastCheckTimestamp is None and \ abs(timestamp - self.__lastCheckTimestamp) >= self.__systemTimeChangeThreshold everythingOk = True if resetWatcher: fromTime = rmTimestampToDateAsString(self.__lastCheckTimestamp) if self.__lastCheckTimestamp else None toTime = rmTimestampToDateAsString(timestamp) log.warning("System time has changed (from %s, to %s)! Resetting thread watcher!" % (fromTime, toTime)) self.__lastWatchdogTimestamp = None for threadId in self.__data: details = self.__getThreadEntry(threadId) details[RMThreadWatcher.LastUpdateKey] = None if self.__mainManager: self.__mainManager.systemDateTimeChanged() else: for threadId in self.__data: details = self.__getThreadEntry(threadId) timeoutHint = details[RMThreadWatcher.TimeoutHintKey] lastUpdate = details[RMThreadWatcher.LastUpdateKey] if timeoutHint is None: log.debug("Thread %d (%s) has no timeout hint!" % (threadId, details[RMThreadWatcher.NameHintKey])) elif lastUpdate is None: log.debug("Thread %d (%s) is not started yet!" % (threadId, details[RMThreadWatcher.NameHintKey])) elif timeoutHint < (timestamp - lastUpdate): everythingOk = False log.debug("Thread %d (%s) didn't responde since [%s] (timeoutHint=%d, timeout=%d)!" % \ (threadId, details[RMThreadWatcher.NameHintKey], rmTimestampToDateAsString(lastUpdate), timeoutHint, (timestamp - lastUpdate))) self.__lastCheckTimestamp = timestamp return everythingOk
def setParserParams(self, parserID, params): parserConfig = self.findParserConfig(parserID) if parserConfig is None: return False parser = self.parsers[parserConfig] newParams = copy.deepcopy(parser.params) hasChanges = False try: for key, oldValue in parser.params.iteritems(): newValue = params.get(key, None) if newValue is not None: if oldValue is None or type(oldValue) == type(newValue): newParams[key] = newValue hasChanges = True else: log.warning("Types do not match: oldType=%s, newType=%s" % (type(oldValue), type(newValue))) except Exception, e: log.exception(e) return False
def getNearbyStations(self, jsonData): try: nearbyStations = jsonData["location"]["nearby_weather_stations"] except: log.warning("No nearby stations found!") self.lastKnownError = "Warning: No nearby stations found!" return airportStations = None pwsStations = None try: airportStations = nearbyStations["airport"] except: log.warning("No airport stations found!") self.lastKnownError = "Warning: No airport stations found!" try: pwsStations = nearbyStations["pws"] except: log.warning("No pws stations found!") self.lastKnownError = "Warning: No pws stations found!" if pwsStations is not None: arrStations = pwsStations["station"] for st in arrStations: self.params["_nearbyStationsIDList"].append( str(st["id"]) + "(" + str(st["distance_km"]) + "km" + "; lat=" + str(round(st["lat"], 2)) + ", lon=" + str(round(st["lon"], 2)) + ")") if airportStations is not None: arrStations = airportStations["station"] for st in arrStations: distance = None if not st["icao"]: continue lat = self.__toFloat(st["lat"]) lon = self.__toFloat(st["lon"]) llat = self.settings.location.latitude llon = self.settings.location.longitude if lat is not None and lon is not None: # some airports don't report lat/lon distance = distanceBetweenGeographicCoordinatesAsKm( lat, lon, llat, llon) if distance is not None: distance = self.__toInt(round(distance)) infoStr = "(" + str(distance) + "km" + "; lat=" + str( round(lat, 2)) + ", lon=" + str(round(lon, 2)) + ")" else: distance = -1 infoStr = "(unknown distance)" self.params["_airportStationsIDList"].append( str(st["icao"]) + infoStr)
def setParserParams(self, parserID, params): parserConfig = self.findParserConfig(parserID) if parserConfig is None: return False parser = self.parsers[parserConfig] newParams = copy.deepcopy(parser.params) hasChanges = False try: for key, oldValue in parser.params.iteritems(): newValue = params.get(key, None) if newValue is not None: if oldValue is None or type(oldValue) == type(newValue): newParams[key] = newValue hasChanges = True else: log.warning( "Types do not match: oldType=%s, newType=%s" % (type(oldValue), type(newValue))) except Exception, e: log.exception(e) return False
def getNearbyStations(self, jsonData): airportStations = {} pwsStations = {} llat = self.settings.location.latitude llon = self.settings.location.longitude try: for key in jsonData['response']: if len(key['id']) == 4: airportStations.update({str(key['id']): key['loc']}) log.debug("airportStations: {}".format(airportStations)) except: log.warning("No airport stations found!") self.lastKnownError = "Warning: No airport stations found!" try: for key in jsonData['response']: if ("MID" in key['id']) or ("PWS" in key['id']): pwsStations.update({str(key['id']): key['loc']}) log.debug("pwsStations: {}".format(pwsStations)) except: log.warning("No pws stations found!") self.lastKnownError = "Warning: No pws stations found!" if pwsStations: # arrStations = pwsStations["station"] for key in pwsStations: # print key # print pwsStations.get(key)['lat'] distance = None lat = pwsStations.get(key)['lat'] lon = pwsStations.get(key)['long'] log.debug("lat: {}, lon: {}, llat: {}, llon: {}".format( lat, lon, llat, llon)) if lat is not None and lon is not None: # some airports don't report lat/lon distance = distanceBetweenGeographicCoordinatesAsKm( lat, lon, llat, llon) print(distance) if distance is not None: distance = int(round(distance)) infoStr = "(" + str(distance) + "km" + "; lat=" + str( round(lat, 2)) + ", lon=" + str(round(lon, 2)) + ")" else: distance = -1 infoStr = "(unknown distance)" self.params["_nearbyStationsIDList"].append(key + infoStr) log.debug(self.params["_nearbyStationsIDList"]) if airportStations: for key in airportStations: distance = None lat = airportStations.get(key)['lat'] lon = airportStations.get(key)['long'] log.debug("lat: {}, lon: {}, llat: {}, llon: {}".format( lat, lon, llat, llon)) if lat is not None and lon is not None: # some airports don't report lat/lon distance = distanceBetweenGeographicCoordinatesAsKm( lat, lon, llat, llon) print(distance) if distance is not None: distance = int(round(distance)) infoStr = "(" + str(distance) + "km" + "; lat=" + str( round(lat, 2)) + ", lon=" + str(round(lon, 2)) + ")" else: distance = -1 infoStr = "(unknown distance)" self.params["_airportStationsIDList"].append(key + infoStr) log.debug(self.params["_airportStationsIDList"])
def run(self, parserId = None, forceRunParser = False, forceRunMixer = False): currentTimestamp = rmCurrentTimestamp() forceRunParser = True if not forceRunParser and self.__lastRunningTimestamp is not None and (currentTimestamp - self.__lastRunningTimestamp) < self.__runningInterval: # We want to run the parser only each N minutes. This condition is not met, try later. log.debug("Parser %r not run lastRunning timestamp %s current %s" % (parserId, self.__lastRunningTimestamp, currentTimestamp)) return None, None self.__lastRunningTimestamp = currentTimestamp newValuesAvailable = False newForecast = RMForecastInfo(None, currentTimestamp) log.debug("*** BEGIN Running parsers: %d (%s)" % (newForecast.timestamp, rmTimestampToDateAsString(newForecast.timestamp))) for parserConfig in self.parsers: if parserId is not None and parserId != parserConfig.dbID: continue log.debug(" * Parser: %s -> %s" % (parserConfig, parserConfig.runtimeLastForecastInfo)) if parserConfig.enabled: if parserConfig.failCounter >= self.__maxFails: if forceRunParser or parserConfig.lastFailTimestamp is None or (abs(newForecast.timestamp - parserConfig.lastFailTimestamp) >= self.__delayAfterMaxFails): parserConfig.failCounter = 0 parserConfig.lastFailTimestamp = None else: if parserConfig.failCounter == self.__maxFails: log.warning(" * Parser: %s - ignored because of lack of data (failCounter=%s, lastFail=%s)!" % (parserConfig, `parserConfig.failCounter`, rmTimestampToDateAsString(parserConfig.lastFailTimestamp))) parserConfig.failCounter += 1 # Increment this to get rid of the above message. continue elif parserConfig.failCounter > 0: retryDelay = min(self.__minDelayBetweenFails + (parserConfig.failCounter - 1) * self.__stepDelayBetweenFails, self.__maxDelayBetweenFails) nextRetryTimestamp = parserConfig.lastFailTimestamp + retryDelay if newForecast.timestamp < nextRetryTimestamp: log.debug(" * Ignored because retry delay %d (sec) was not reached" % retryDelay) continue log.debug(" * Parser retry after previous fail") parser = self.parsers[parserConfig] lastUpdate = None if parserConfig.runtimeLastForecastInfo: # Check if parser hasn't run with an invalid future date if parserConfig.runtimeLastForecastInfo.timestamp <= currentTimestamp: lastUpdate = parserConfig.runtimeLastForecastInfo.timestamp # Save the newest parser run if lastUpdate is not None and lastUpdate > self.__lastUpdateTimestamp: self.__lastUpdateTimestamp = lastUpdate if not forceRunParser and not self.forceParsersRun and (lastUpdate != None and (newForecast.timestamp - lastUpdate) < parser.parserInterval): log.debug(" * Ignored because interval %d not expired for timestamp %d lastUpdate: %d" % (parser.parserInterval, newForecast.timestamp, lastUpdate)) continue log.debug(" * Running parser %s with interval %d" % (parser.parserName, parser.parserInterval)) parser.settings = globalSettings.getSettings() parser.runtime[RMParser.RuntimeDayTimestamp] = rmCurrentDayTimestamp() try: parser.lastKnownError = '' parser.isRunning = True parser.perform() parser.isRunning = False except Exception, e: log.error(" * Cannot execute parser %s" % parser.parserName) log.exception(e) parser.isRunning = False if len(parser.lastKnownError) == 0: parser.lastKnownError = 'Error: Failed to run' if not parser.hasValues(): parserConfig.failCounter += 1 parserConfig.lastFailTimestamp = newForecast.timestamp if len(parser.lastKnownError) == 0: parser.lastKnownError = 'Error: parser returned no values' parser.isRunning = False if parserConfig.failCounter == 1: log.warn (" * Parser %s returned no values" % parser.parserName) continue parserConfig.failCounter = 0 parserConfig.lastFailTimestamp = None if newForecast.id == None: self.forecastTable.addRecordEx(newForecast) parserConfig.runtimeLastForecastInfo = newForecast if not globalSettings.vibration: self.parserDataTable.removeEntriesWithParserIdAndTimestamp(parserConfig.dbID, parser.getValues()) self.parserDataTable.addRecords(newForecast.id, parserConfig.dbID, parser.getValues()) parser.clearValues() newValuesAvailable = True
def perform(self): timeNow = rmNowDateTime() timeYesterday = rmNowDateTime().fromordinal(timeNow.toordinal() - 1) yyyyy = timeYesterday.year mmy = timeYesterday.month ddy = timeYesterday.day yyyy = timeNow.year mm = timeNow.month dd = timeNow.day self.params["_nearbyStationsIDList"] = [] self.params["_airportStationsIDList"] = [] self.lastKnownError = "" apiKey = self.params.get("apiKey", None) if apiKey is None or not apiKey or not isinstance(apiKey, str): log.error("No API Key provided") self.lastKnownError = "Error: No API Key provided" return self.apiURL = "http://api.wunderground.com/api/" + str( apiKey) + "/geolookup/conditions/forecast10day/yesterday/q/" success = False if self.params.get("useCustomStation"): stationName = self.params.get("customStationName") if (stationName is None or not stationName or not isinstance(stationName, str)): log.error("Station ID cannot be empty") self.lastKnownError = "Error: Station ID cannot be empty" return log.debug("getting data from specified station") #try to split self.arrStationNames = stationName.split(",") for stationName in self.arrStationNames: if len(stationName) > 4: self.csapiURL = self.apiURL + "pws:" + stationName + ".json" # url for pws else: self.csapiURL = self.apiURL + stationName + ".json" # url for airport stations log.debug(self.apiURL) d = self.openURL(self.csapiURL) jsonContent = d.read() if jsonContent is None: self.lastKnownError = "Error: Bad response" continue self.jsonResponse = json.loads(jsonContent) err = self.jsonResponse.get("response").get("error") if not err: success = True break self.lastKnownError = "Error: Failed to get custom station" log.error(self.lastKnownError) else: s = self.settings llat = s.location.latitude llon = s.location.longitude self.apiURL += str(llat) + "," + str(llon) + ".json" log.debug(self.apiURL) d = self.openURL(self.apiURL) jsonContent = d.read() if jsonContent is None: self.lastKnownError = "Error: Bad response" return self.jsonResponse = json.loads(jsonContent) err = self.jsonResponse.get("response").get("error") if not err: success = True if not success: log.error(self.lastKnownError) return #populate nearby stations self.getNearbyStations(self.jsonResponse) self.getStationData(self.jsonResponse) if self.params.get("useCustomStation") and self.params.get( "useSolarRadiation"): self.__getSolarRadiation() elif self.params.get("useSolarRadiation"): log.warning( "Unable to get solar radiation. You need to specify a pws.") return
def getStationData(self, jsonData): #daily summary try: dailysummary = jsonData["history"]["dailysummary"][0] temperature = self.__toFloat(dailysummary["meantempm"]) mintemp = self.__toFloat(dailysummary["mintempm"]) maxtemp = self.__toFloat(dailysummary["maxtempm"]) rh = self.__toFloat(dailysummary["humidity"]) minrh = self.__toFloat(dailysummary["minhumidity"]) maxrh = self.__toFloat(dailysummary["maxhumidity"]) dewpoint = self.__toFloat(dailysummary["meandewptm"]) wind = self.__toFloat(dailysummary["meanwindspdm"]) / 3.6 # convertred from kmetersph to meterps pressure = self.__toFloat(dailysummary["maxpressurem"])/2 + self.__toFloat(dailysummary["minpressurem"])/2 # to be compared rain = self.__toFloat(dailysummary["precipm"]) solarradiation = self.__toFloat(jsonData["current_observation"]["solarradiation"]) #to be compared condition = self.conditionConvert(jsonData["current_observation"]["weather"]) log.debug("Wunderground parser - got daily data") #time utc jutc = jsonData["history"]["utcdate"] yyyy = self.__toInt(jutc["year"]) mm = self.__toInt(jutc["mon"]) dd = self.__toInt(jutc["mday"]) hour = self.__toInt(jutc["hour"]) mins = self.__toInt(jutc["min"]) log.debug("Wunderground parser - got time") dd = datetime.datetime(yyyy, mm, dd, hour, mins) timestamp = calendar.timegm( dd.timetuple()) timestamp = self.__parseDateTime(timestamp) self.addValue(RMParser.dataType.TEMPERATURE, timestamp, temperature) self.addValue(RMParser.dataType.MINTEMP, timestamp, mintemp) self.addValue(RMParser.dataType.MAXTEMP, timestamp, maxtemp) self.addValue(RMParser.dataType.RH, timestamp, rh) self.addValue(RMParser.dataType.MINRH, timestamp, minrh) self.addValue(RMParser.dataType.MAXRH, timestamp, maxrh) self.addValue(RMParser.dataType.WIND, timestamp, wind) self.addValue(RMParser.dataType.RAIN, timestamp, rain) self.addValue(RMParser.dataType.DEWPOINT, timestamp, dewpoint) self.addValue(RMParser.dataType.PRESSURE, timestamp, pressure) self.addValue(RMParser.dataType.SOLARRADIATION, timestamp, solarradiation) self.addValue(RMParser.dataType.CONDITION, timestamp, condition) except: log.warning("Failed to get daily summary") self.lastKnownError = "Warning: Failed to get daily summary" try: #forecast hourly tuple = datetime.datetime.fromtimestamp(int(time.time())).timetuple() dayTimestamp = int(datetime.datetime(tuple.tm_year, tuple.tm_mon, tuple.tm_mday).strftime("%s")) maxDayTimestamp = dayTimestamp + globalSettings.parserDataSizeInDays * 86400 forecastArrray = jsonData["hourly_forecast"] timestampF = [] temperatureF = [] depointF = [] windF = [] humidityF = [] qpf = [] conditionF = [] log.debug("Wunderground parser - getting forecast") for hourF in forecastArrray: tt = self.__toInt(hourF["FCTTIME"]["epoch"]) if(tt > maxDayTimestamp): break timestampF.append(self.__toInt(tt)) temperatureF.append(self.__toFloat(hourF["temp"]["metric"])) depointF.append(self.__toFloat(hourF["dewpoint"]["metric"])) windF.append(self.__toFloat(hourF["wspd"]["metric"])/ 3.6) # convertred from kmetersph to meterps humidityF.append(self.__toFloat(hourF["humidity"])) qpf.append(self.__toFloat(hourF["qpf"]["metric"])) conditionF.append(self.conditionConvert(hourF["condition"])) temperatureF = zip(timestampF, temperatureF) depointF = zip(timestampF, depointF) windF = zip(timestampF, windF) humidityF = zip(timestampF, humidityF) qpf = zip(timestampF, qpf) conditionF = zip(timestampF, conditionF) self.addValues(RMParser.dataType.RH, humidityF) self.addValues(RMParser.dataType.TEMPERATURE, temperatureF) self.addValues(RMParser.dataType.QPF, qpf) self.addValues(RMParser.dataType.DEWPOINT, depointF) self.addValues(RMParser.dataType.WIND, windF) self.addValues(RMParser.dataType.CONDITION, conditionF) log.debug("Wunderground parser - got forecast") except: log.error("Failed to get forecast!") self.lastKnownError = "Error: Failed to get forecast" return
def perform(self): timeNow = rmNowDateTime() timeYesterday = rmNowDateTime().fromordinal(timeNow.toordinal()-1) yyyyy = timeYesterday.year mmy = timeYesterday.month ddy = timeYesterday.day yyyy = timeNow.year mm = timeNow.month dd = timeNow.day self.params["_nearbyStationsIDList"] = [] self.params["_airportStationsIDList"] = [] apiKey = self.params.get("apiKey", None) if apiKey is None or not apiKey or not isinstance(apiKey, str): log.error("No API Key provided") self.lastKnownError = "Error: No API Key provided" return self.apiURL = "http://api.wunderground.com/api/" + str(apiKey) + "/geolookup/conditions/forecast10day/yesterday/q/" # / history_ # " \ # + str(yyyyy) + str(mmy).zfill(2) + str(ddy).zfill(2)\ # + str(yyyy) + str(mm).zfill(2) + str(dd).zfill(2)+" / q / " if self.params.get("useCustomStation"): stationName = self.params.get("customStationName") if(stationName is None or not stationName or not isinstance(stationName, str)): log.error("Station ID cannot be empty") self.lastKnownError = "Error: Station ID cannot be empty" return log.debug("getting data from specified station") if len(stationName) > 4: self.apiURL += "pws:" + stationName + ".json" #url for pws else: self.apiURL += stationName + ".json" #url for pws else: s = self.settings llat = s.location.latitude llon = s.location.longitude self.apiURL += str(llat) + "," + str(llon) + ".json" log.debug(self.apiURL) d = self.openURL(self.apiURL) jsonContent = d.read() if jsonContent is None: log.error("Failed to get WUnderground JSON contents") self.lastKnownError = "Error: Bad response" return self.jsonResponse = json.loads(jsonContent) #populate nearby stations self.getNearbyStations(self.jsonResponse) self.getStationData(self.jsonResponse) if self.params.get("useCustomStation") and self.params.get("useSolarRadiation"): self.__getSolarRadiation() elif self.params.get("useSolarRadiation"): log.warning("Unable to get solar radiation. You need to specify a pws.") return
def getStationData(self, jsonData): # daily summary for yesterday try: if self.params.get("useCustomStation"): dailysummary = jsonData["response"]["periods"][0]["summary"] else: dailysummary = jsonData["response"][0]["periods"][0]["summary"] log.debug("Daily Summary: {}".format(dailysummary)) temperature = self.__toFloat(dailysummary["temp"]["avgC"]) mintemp = self.__toFloat(dailysummary["temp"]["minC"]) maxtemp = self.__toFloat(dailysummary["temp"]["maxC"]) rh = self.__toFloat(dailysummary["rh"]["avg"]) minrh = self.__toFloat(dailysummary["rh"]["min"]) maxrh = self.__toFloat(dailysummary["rh"]["max"]) dewpoint = self.__toFloat(dailysummary["dewpt"]["avgC"]) wind = self.__toFloat(dailysummary["wind"]["avgKPH"]) if wind is not None: wind = wind / 3.6 # convertred from kmetersph to mps maxpressure = self.__toFloat(dailysummary["pressure"]["maxMB"]) minpressure = self.__toFloat(dailysummary["pressure"]["minMB"]) pressure = None if maxpressure is not None and minpressure is not None: pressure = (maxpressure / 2 + minpressure / 2) / 10 # converted to from mb to kpa rain = self.__toFloat(dailysummary["precip"]["totalMM"]) # time utc timestamp = dailysummary["range"]["maxTimestamp"] print(timestamp) timestampiso = dailysummary["range"]["maxDateTimeISO"] print("Observations for date: %s Temp: %s, Rain: %s" % (timestampiso[0:16].replace("T", " "), temperature, rain)) timestamp = self.__parseDateTime(timestamp) self.addValue(RMParser.dataType.TEMPERATURE, timestamp, temperature) self.addValue(RMParser.dataType.MINTEMP, timestamp, mintemp) self.addValue(RMParser.dataType.MAXTEMP, timestamp, maxtemp) self.addValue(RMParser.dataType.RH, timestamp, rh) self.addValue(RMParser.dataType.MINRH, timestamp, minrh) self.addValue(RMParser.dataType.MAXRH, timestamp, maxrh) self.addValue(RMParser.dataType.WIND, timestamp, wind) self.addValue(RMParser.dataType.RAIN, timestamp, rain) # self.addValue(RMParser.dataType.QPF, timestamp, rain) # uncomment to report measured rain as previous day QPF self.addValue(RMParser.dataType.DEWPOINT, timestamp, dewpoint) self.addValue(RMParser.dataType.PRESSURE, timestamp, pressure) if self.params.get("useSolarRadiation"): solarradiation = self.__toFloat( dailysummary["solrad"]["avgWM2"]) # needs to be converted from watt/sqm*h to Joule/sqm if solarradiation is not None: solarradiation *= 0.0864 self.addValue(RMParser.dataType.SOLARRADIATION, timestamp, solarradiation) log.debug( "temp {}, minT {}, maxT {}, rh {}, minrh {}, maxrh {}, dewpoint {}, wind (MPS) {}, maxpress {}, " "minpress {}, avgpress {}, rain {}, solrad {}".format( temperature, mintemp, maxtemp, rh, minrh, maxrh, dewpoint, wind, maxpressure, minpressure, pressure, rain, solarradiation)) except: log.warning("Failed to get daily summary") self.lastKnownError = "Warning: Failed to get daily summary"
def getStationData(self, jsonData): #daily summary for yesterday try: dailysummary = jsonData["history"]["dailysummary"][0] temperature = self.__toFloat(dailysummary["meantempm"]) mintemp = self.__toFloat(dailysummary["mintempm"]) maxtemp = self.__toFloat(dailysummary["maxtempm"]) rh = self.__toFloat(dailysummary["humidity"]) minrh = self.__toFloat(dailysummary["minhumidity"]) maxrh = self.__toFloat(dailysummary["maxhumidity"]) dewpoint = self.__toFloat(dailysummary["meandewptm"]) wind = self.__toFloat(dailysummary["meanwindspdm"]) if wind is not None: wind = wind / 3.6 # convertred from kmetersph to mps maxpressure = self.__toFloat(dailysummary["maxpressurem"]) minpressure = self.__toFloat(dailysummary["minpressurem"]) pressure = None if maxpressure is not None and minpressure is not None: pressure = (maxpressure/2 + minpressure/2) / 10 #converted to from mb to kpa rain = self.__toFloat(dailysummary["precipm"]) #time utc jutc = jsonData["history"]["utcdate"] yyyy = self.__toInt(jutc["year"]) mm = self.__toInt(jutc["mon"]) dd = self.__toInt(jutc["mday"]) hour = self.__toInt(jutc["hour"]) mins = self.__toInt(jutc["min"]) log.debug("Observations for date: %d/%d/%d Temp: %s, Rain: %s" % (yyyy, mm, dd, temperature, rain)) dd = datetime.datetime(yyyy, mm, dd, hour, mins) timestamp = calendar.timegm( dd.timetuple()) timestamp = self.__parseDateTime(timestamp) self.addValue(RMParser.dataType.TEMPERATURE, timestamp, temperature) self.addValue(RMParser.dataType.MINTEMP, timestamp, mintemp) self.addValue(RMParser.dataType.MAXTEMP, timestamp, maxtemp) self.addValue(RMParser.dataType.RH, timestamp, rh) self.addValue(RMParser.dataType.MINRH, timestamp, minrh) self.addValue(RMParser.dataType.MAXRH, timestamp, maxrh) self.addValue(RMParser.dataType.WIND, timestamp, wind) self.addValue(RMParser.dataType.RAIN, timestamp, rain) self.addValue(RMParser.dataType.DEWPOINT, timestamp, dewpoint) self.addValue(RMParser.dataType.PRESSURE, timestamp, pressure) except: log.warning("Failed to get daily summary") self.lastKnownError = "Warning: Failed to get daily summary" try: #forecast hourly tuple = datetime.datetime.fromtimestamp(int(time.time())).timetuple() dayTimestamp = int(datetime.datetime(tuple.tm_year, tuple.tm_mon, tuple.tm_mday).strftime("%s")) maxDayTimestamp = dayTimestamp + globalSettings.parserDataSizeInDays * 86400 forecastArrray = jsonData["hourly_forecast"] timestampF = [] temperatureF = [] depointF = [] windF = [] humidityF = [] qpf = [] conditionF = [] for hourF in forecastArrray: tt = self.__toInt(hourF["FCTTIME"]["epoch"]) if(tt > maxDayTimestamp): break timestampF.append(self.__toInt(tt)) temperatureF.append(self.__toFloat(hourF["temp"]["metric"])) depointF.append(self.__toFloat(hourF["dewpoint"]["metric"])) wind = self.__toFloat(hourF["wspd"]["metric"]) if wind is not None: windF.append(wind/ 3.6) # convertred from kmetersph to meterps humidityF.append(self.__toFloat(hourF["humidity"])) qpf.append(self.__toFloat(hourF["qpf"]["metric"])) conditionF.append(self.conditionConvert(hourF["condition"])) temperatureF = zip(timestampF, temperatureF) depointF = zip(timestampF, depointF) windF = zip(timestampF, windF) humidityF = zip(timestampF, humidityF) qpf = zip(timestampF, qpf) conditionF = zip(timestampF, conditionF) self.addValues(RMParser.dataType.RH, humidityF) self.addValues(RMParser.dataType.TEMPERATURE, temperatureF) self.addValues(RMParser.dataType.QPF, qpf) self.addValues(RMParser.dataType.DEWPOINT, depointF) self.addValues(RMParser.dataType.WIND, windF) self.addValues(RMParser.dataType.CONDITION, conditionF) except: log.error("Failed to get forecast!") self.lastKnownError = "Error: Failed to get forecast"
def perform(self): timeNow = rmNowDateTime() timeYesterday = rmNowDateTime().fromordinal(timeNow.toordinal() - 1) yyyyy = timeYesterday.year mmy = timeYesterday.month ddy = timeYesterday.day yyyy = timeNow.year mm = timeNow.month dd = timeNow.day limit = 10 self.params["_nearbyStationsIDList"] = [] self.params["_airportStationsIDList"] = [] log.debug("Params: {}".format(self.params)) clientID = self.params.get("clientID", None) if clientID is None or not clientID or not isinstance(clientID, str): log.error("No Client ID provided") self.lastKnownError = "Error: No Client ID provided" return secret = self.params.get("Secret", None) if secret is None or not secret or not isinstance(secret, str): log.error("No Secret provided") self.lastKnownError = "Error: No Secret provided" return if self.params.get("useCustomStation"): stationName = self.params.get("customStationName") if stationName is None or not stationName or not isinstance( stationName, str): stationName = ":auto" log.info( "Station name not valid, using automatic location identifier" ) limit = 10 else: stationName = ":auto" log.info("Station not set, using automatic location identifier") limit = 10 stationName = stationName.replace(" ", "") log.debug("stationName: {}".format(stationName)) apiURL = \ "http://api.aerisapi.com/observations/summary/" + stationName + "?&format=json&radius=75mi&filter=allstations&limit=" + \ str(limit) + "&client_id=" \ + str(clientID) + "&client_secret=" + str(secret) log.debug("apiURL is: {}".format(apiURL)) self.jsonResponse = self.apiCall(apiURL) log.debug(self.jsonResponse) if self.jsonResponse['success']: # populate nearby stations if self.params.get("useCustomStation") and self.params.get( "customStationName"): pass else: log.debug("Getting nearby stations") self.getNearbyStations(self.jsonResponse) return self.getStationData(self.jsonResponse) if self.params.get("useCustomStation") and self.params.get( "useSolarRadiation"): pass elif self.params.get("useSolarRadiation"): log.warning( "Unable to get solar radiation. You need to specify a pws.") log.debug("self.parserForecast={}".format(self.parserForecast)) if self.parserForecast: apiURL = \ "http://api.aerisapi.com/forecasts/" + stationName + "?&format=json&filter=mdnt2mdnt&limit=7" + \ "&client_id=" + str(clientID) + "&client_secret=" + str(secret) log.debug("Getting forecast from {}".format(apiURL)) self.jsonResponse = self.apiCall(apiURL) self.__getSimpleForecast() return