UNPKG

ayla

Version:

Ayla at your service.

147 lines (114 loc) 5.3 kB
# WEATHER UNDERGROUND API # ----------------------------------------------------------------------------- class Wunderground extends (require "./baseApi.coffee") expresser = require "expresser" database = expresser.database logger = expresser.logger settings = expresser.settings async = require "async" lodash = require "lodash" moment = require "moment" # INIT # ------------------------------------------------------------------------- # Init the Wunderground module. init: => @baseInit() # Start collecting weather data. start: => @getCurrentWeather() @baseStart() # Stop collecting weather data. stop: => @baseStop() # API BASE METHODS # ------------------------------------------------------------------------- # Helper to make requests to Weather Underground for stations defined on the settings. # The callback result will be the average of station data. apiRequest: (path, options, callback) => if not settings.wunderground.api? logger.warn "Wunderground.apiRequest", "Wundeground API settings are not defined. Abort!" return if not callback? and lodash.isFunction options callback = options options = {} # Set tasks and stations arrays. tasks = [] # Set queries based on options (default or stationIds). if options.stationIds? queries = options.stationIds reqUrl = settings.wunderground.api.url + settings.wunderground.api.clientId + "/#{path}/q/pws:" else queries = [settings.wunderground.defaultQuery] reqUrl = settings.wunderground.api.url + settings.wunderground.api.clientId + "/#{path}/q/" # Iterate stations and create a HTTP request for each station. for q in queries do (q) => task = (cb) => @makeRequest reqUrl + "#{q}.json", cb # Add task and debug log. tasks.push task # Run tasks in parallel. async.parallelLimit tasks, settings.general.parallelTasksLimit, (err, results) => if err? @logError "Wunderground.apiRequest", path, err else logger.debug "Wunderground.apiRequest", path, results callback err, results if callback? # Helper to get average data from different stations. getAverageResult: (data, field) => result = {} # Iterate data and get average values. for d in data for prop in settings.wunderground.resultFields try if d[field][prop]? curValue = result[prop] nextValue = d[field][prop].toString() # Parse next value. if nextValue.indexOf("%") >= 0 nextValue = nextValue.replace "%", "" if not isNaN nextValue nextValue = parseFloat nextValue # Set result data. if not curValue? or curValue is "" result[prop] = nextValue else if not isNaN curValue result[prop] = ((curValue + nextValue) / 2).toFixed(2) else if curValue.indexOf(nextValue) < 0 result[prop] += ", " + nextValue catch ex @logError "Wunderground.getAverageResult", ex # Return result. return result # GET WEATHER DATA # ------------------------------------------------------------------------- # Get the current weather conditions. getCurrentWeather: (callback) => logger.debug "Wunderground.getCurrentWeather" @apiRequest "conditions", {stationIds: settings.wunderground.stationIds}, (err, results) => if not err? currentConditions = @getAverageResult results, "current_observation" @setData "current", currentConditions callback err, currentConditions if callback? # Get sunrise and sunset hours and other astronomy details for today. getAstronomy: (callback) => logger.debug "Wunderground.getAstronomy" @apiRequest "astronomy", (err, result) => if not err? astronomy = result[0].moon_phase @setData "astronomy", astronomy callback err, astronomy if callback? # JOBS # ------------------------------------------------------------------------- # Refresh weather data every few minutes. jobGetWeather: => @getCurrentWeather() # Refresh astronomy data once a day. jobGetAstronomy: => @getAstronomy() # Singleton implementation. # ----------------------------------------------------------------------------- Wunderground.getInstance = -> @instance = new Wunderground() if not @instance? return @instance module.exports = exports = Wunderground.getInstance()