From 687e3c6ca7b2a60426b57550bf1c85f0554b5cd6 Mon Sep 17 00:00:00 2001 From: Samer Albahra Date: Fri, 3 Jul 2015 01:10:59 -0500 Subject: [PATCH] Remove unnecessary IIFE https://stackoverflow.com/questions/21531329/are-node-js-modules-need-to -be-wrapped-inside-the-module-pattern --- routes/weather.js | 688 +++++++++++++++++++++++----------------------- 1 file changed, 343 insertions(+), 345 deletions(-) diff --git a/routes/weather.js b/routes/weather.js index 8d6843c..86f5f73 100644 --- a/routes/weather.js +++ b/routes/weather.js @@ -1,427 +1,425 @@ -( function() { +var http = require( "http" ), +// parseXML = require( "xml2js" ).parseString, + Cache = require( "../models/Cache" ), - var http = require( "http" ), -// parseXML = require( "xml2js" ).parseString, - Cache = require( "../models/Cache" ), + // Define regex filters to match against location + filters = { + gps: /^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/, + pws: /^(?:pws|icao):/, + url: /^https?:\/\/([\w\.-]+)(:\d+)?(\/.*)?$/, + time: /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})([+-])(\d{2})(\d{2})/ + }; - // Define regex filters to match against location - filters = { - gps: /^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/, - pws: /^(?:pws|icao):/, - url: /^https?:\/\/([\w\.-]+)(:\d+)?(\/.*)?$/, - time: /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})([+-])(\d{2})(\d{2})/ - }; +// Takes a PWS or ICAO location and resolves the GPS coordinates +function getPWSCoordinates( location, weatherUndergroundKey, callback ) { + var url = "http://api.wunderground.com/api/" + weatherUndergroundKey + + "/conditions/forecast/q/" + encodeURIComponent( location ) + ".json"; - // Takes a PWS or ICAO location and resolves the GPS coordinates - function getPWSCoordinates( location, weatherUndergroundKey, callback ) { - var url = "http://api.wunderground.com/api/" + weatherUndergroundKey + - "/conditions/forecast/q/" + encodeURIComponent( location ) + ".json"; + httpRequest( url, function( data ) { + data = JSON.parse( data ); - httpRequest( url, function( data ) { - data = JSON.parse( data ); + if ( typeof data === "object" && data.current_observation && data.current_observation.observation_location ) { + callback( [ data.current_observation.observation_location.latitude, + data.current_observation.observation_location.longitude ] ); + } else { + callback( false ); + } + } ); +} - if ( typeof data === "object" && data.current_observation && data.current_observation.observation_location ) { - callback( [ data.current_observation.observation_location.latitude, - data.current_observation.observation_location.longitude ] ); - } else { - callback( false ); - } - } ); - } +// If location does not match GPS or PWS/ICAO, then attempt to resolve +// location using Weather Underground autocomplete API +function resolveCoordinates( location, callback ) { - // If location does not match GPS or PWS/ICAO, then attempt to resolve - // location using Weather Underground autocomplete API - function resolveCoordinates( location, callback ) { + // Generate URL for autocomplete request + var url = "http://autocomplete.wunderground.com/aq?h=0&query=" + + encodeURIComponent( location ); - // Generate URL for autocomplete request - var url = "http://autocomplete.wunderground.com/aq?h=0&query=" + - encodeURIComponent( location ); + httpRequest( url, function( data ) { - httpRequest( url, function( data ) { + // Parse the reply for JSON data + data = JSON.parse( data ); - // Parse the reply for JSON data - data = JSON.parse( data ); + // Check if the data is valid + if ( typeof data.RESULTS === "object" && data.RESULTS.length ) { - // Check if the data is valid - if ( typeof data.RESULTS === "object" && data.RESULTS.length ) { + // If it is, reply with an array containing the GPS coordinates + callback( [ data.RESULTS[0].lat, data.RESULTS[0].lon ] ); + } else { - // If it is, reply with an array containing the GPS coordinates - callback( [ data.RESULTS[0].lat, data.RESULTS[0].lon ] ); - } else { + // Otherwise, indicate no data was found + callback( false ); + } + } ); +} - // Otherwise, indicate no data was found - callback( false ); - } - } ); - } +// Retrieve weather data to complete the weather request +function getWeatherData( location, callback ) { - // Retrieve weather data to complete the weather request - function getWeatherData( location, callback ) { + // Get the API key from the environment variables + var WSI_API_KEY = process.env.WSI_API_KEY, - // Get the API key from the environment variables - var WSI_API_KEY = process.env.WSI_API_KEY, + // Generate URL using The Weather Company API v1 in Imperial units + url = "http://api.weather.com/v1/geocode/" + location[0] + "/" + location[1] + + "/observations/current.json?apiKey=" + WSI_API_KEY + "&language=en-US&units=e"; - // Generate URL using The Weather Company API v1 in Imperial units - url = "http://api.weather.com/v1/geocode/" + location[0] + "/" + location[1] + - "/observations/current.json?apiKey=" + WSI_API_KEY + "&language=en-US&units=e"; + // Perform the HTTP request to retrieve the weather data + httpRequest( url, function( data ) { - // Perform the HTTP request to retrieve the weather data - httpRequest( url, function( data ) { + try { + var weather = JSON.parse( data ); - try { - var weather = JSON.parse( data ); + location = location.join( "," ); - location = location.join( "," ); + Cache.findOne( { location: location }, function( err, record ) { - Cache.findOne( { location: location }, function( err, record ) { + if ( record && record.yesterdayHumidity !== null ) { + weather.yesterdayHumidity = record.yesterdayHumidity; + } - if ( record && record.yesterdayHumidity !== null ) { - weather.yesterdayHumidity = record.yesterdayHumidity; - } + // Return the data to the callback function if successful + callback( weather ); + } ); - // Return the data to the callback function if successful - callback( weather ); - } ); + updateCache( location, weather ); + } catch ( err ) { - updateCache( location, weather ); - } catch (err) { + // Otherwise indicate the request failed + callback( false ); + } - // Otherwise indicate the request failed - callback( false ); - } - - } ); - } + } ); +} /* - // Retrieve the historical weather data for the provided location - function getYesterdayWeatherData( location, callback ) { +// Retrieve the historical weather data for the provided location +function getYesterdayWeatherData( location, callback ) { - // Get the API key from the environment variables - var WSI_HISTORY_KEY = process.env.WSI_HISTORY_KEY, + // Get the API key from the environment variables + var WSI_HISTORY_KEY = process.env.WSI_HISTORY_KEY, - // Generate a Date object for the current time - today = new Date(), + // Generate a Date object for the current time + today = new Date(), - // Generate a Date object for the previous day by subtracting a day (in milliseconds) from today - yesterday = new Date( today.getTime() - 1000 * 60 * 60 * 24 ), + // Generate a Date object for the previous day by subtracting a day (in milliseconds) from today + yesterday = new Date( today.getTime() - 1000 * 60 * 60 * 24 ), - // Generate URL using WSI Cleaned History API in Imperial units showing daily average values - url = "http://cleanedobservations.wsi.com/CleanedObs.svc/GetObs?ID=" + WSI_HISTORY_KEY + - "&Lat=" + location[0] + "&Long=" + location[1] + - "&Req=davg&startdate=" + toUSDate( yesterday ) + "&enddate=" + toUSDate( yesterday ) + "&TS=LST"; + // Generate URL using WSI Cleaned History API in Imperial units showing daily average values + url = "http://cleanedobservations.wsi.com/CleanedObs.svc/GetObs?ID=" + WSI_HISTORY_KEY + + "&Lat=" + location[0] + "&Long=" + location[1] + + "&Req=davg&startdate=" + toUSDate( yesterday ) + "&enddate=" + toUSDate( yesterday ) + "&TS=LST"; - // Perform the HTTP request to retrieve the weather data - httpRequest( url, function( xml ) { - parseXML( xml, function ( err, result ) { - callback( result.WeatherResponse.WeatherRecords[0].WeatherData[0].$ ); - }); - } ); - } + // Perform the HTTP request to retrieve the weather data + httpRequest( url, function( xml ) { + parseXML( xml, function ( err, result ) { + callback( result.WeatherResponse.WeatherRecords[0].WeatherData[0].$ ); + }); + } ); +} */ - // Update weather cache record in the local database - function updateCache( location, weather ) { - // Search for a cache record for the provided location - Cache.findOne( { location: location }, function( err, record ) { +// Update weather cache record in the local database +function updateCache( location, weather ) { - // If a record is found update the data and save it - if ( record ) { + // Search for a cache record for the provided location + Cache.findOne( { location: location }, function( err, record ) { - record.currentHumidityTotal += weather.observation.imperial.rh; - record.currentHumidityCount++; - record.save(); + // If a record is found update the data and save it + if ( record ) { - } else { + record.currentHumidityTotal += weather.observation.imperial.rh; + record.currentHumidityCount++; + record.save(); - // If no cache record is found, generate a new one and save it - new Cache( { - location: location, - currentHumidityTotal: weather.observation.imperial.rh, - currentHumidityCount: 1 - } ).save(); + } else { - } - } ); + // If no cache record is found, generate a new one and save it + new Cache( { + location: location, + currentHumidityTotal: weather.observation.imperial.rh, + currentHumidityCount: 1 + } ).save(); + + } + } ); +} + +// Calculates the resulting water scale using the provided weather data, adjustment method and options +function calculateWeatherScale( adjustmentMethod, adjustmentOptions, weather ) { + + // Calculate the average temperature + var temp = ( weather.observation.imperial.temp_max_24hour + weather.observation.imperial.temp_min_24hour ) / 2, + + // Relative humidity and if unavailable default to 0 + rh = weather.yesterdayHumidity || weather.observation.imperial.rh || 0, + + // The absolute precipitation in the past 48 hours + precip = weather.observation.imperial.precip_2day || weather.observation.imperial.precip_24hour; + + if ( typeof temp !== "number" ) { + + // If the maximum and minimum temperatures are not available then use the current temperature + temp = weather.observation.imperial.temp; } - // Calculates the resulting water scale using the provided weather data, adjustment method and options - function calculateWeatherScale( adjustmentMethod, adjustmentOptions, weather ) { + // Zimmerman method + if ( adjustmentMethod === 1 ) { - // Calculate the average temperature - var temp = ( weather.observation.imperial.temp_max_24hour + weather.observation.imperial.temp_min_24hour ) / 2, + var humidityFactor = ( 30 - rh ), + tempFactor = ( ( temp - 70 ) * 4 ), + precipFactor = ( precip * -2 ); - // Relative humidity and if unavailable default to 0 - rh = weather.yesterdayHumidity || weather.observation.imperial.rh || 0, - - // The absolute precipitation in the past 48 hours - precip = weather.observation.imperial.precip_2day || weather.observation.imperial.precip_24hour; - - if ( typeof temp !== "number" ) { - - // If the maximum and minimum temperatures are not available then use the current temperature - temp = weather.observation.imperial.temp; - } - - // Zimmerman method - if ( adjustmentMethod === 1 ) { - - var humidityFactor = ( 30 - rh ), - tempFactor = ( ( temp - 70 ) * 4 ), - precipFactor = ( precip * -2 ); - - // Apply adjustment options, if provided, by multiplying the percentage against the factor - if ( adjustmentOptions ) { - if ( adjustmentOptions.hasOwnProperty( "h" ) ) { - humidityFactor = humidityFactor * ( adjustmentOptions.h / 100 ); - } - - if ( adjustmentOptions.hasOwnProperty( "t" ) ) { - tempFactor = tempFactor * ( adjustmentOptions.t / 100 ); - } - - if ( adjustmentOptions.hasOwnProperty( "r" ) ) { - precipFactor = precipFactor * ( adjustmentOptions.r / 100 ); - } + // Apply adjustment options, if provided, by multiplying the percentage against the factor + if ( adjustmentOptions ) { + if ( adjustmentOptions.hasOwnProperty( "h" ) ) { + humidityFactor = humidityFactor * ( adjustmentOptions.h / 100 ); } - // Apply all of the weather modifying factors and clamp the result between 0 and 200%. - return parseInt( Math.min( Math.max( 0, 100 + humidityFactor + tempFactor + precipFactor ), 200 ) ); + if ( adjustmentOptions.hasOwnProperty( "t" ) ) { + tempFactor = tempFactor * ( adjustmentOptions.t / 100 ); + } + + if ( adjustmentOptions.hasOwnProperty( "r" ) ) { + precipFactor = precipFactor * ( adjustmentOptions.r / 100 ); + } } - return -1; + // Apply all of the weather modifying factors and clamp the result between 0 and 200%. + return parseInt( Math.min( Math.max( 0, 100 + humidityFactor + tempFactor + precipFactor ), 200 ) ); } - // Checks if the weather data meets any of the restrictions set by OpenSprinkler. - // Restrictions prevent any watering from occurring and are similar to 0% watering level. - // - // All queries will return a restrict flag if the current weather indicates rain. - // - // California watering restriction prevents watering if precipitation over two days is greater - // than 0.01" over the past 48 hours. - function checkWeatherRestriction( adjustmentValue, weather ) { + return -1; +} - // Define all the weather codes that indicate rain - var adverseCodes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]; +// Checks if the weather data meets any of the restrictions set by OpenSprinkler. +// Restrictions prevent any watering from occurring and are similar to 0% watering level. +// +// All queries will return a restrict flag if the current weather indicates rain. +// +// California watering restriction prevents watering if precipitation over two days is greater +// than 0.01" over the past 48 hours. +function checkWeatherRestriction( adjustmentValue, weather ) { - if ( adverseCodes.indexOf( weather.observation.icon_code ) !== -1 ) { + // Define all the weather codes that indicate rain + var adverseCodes = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 ]; - // If the current weather indicates rain, add a restrict flag to the weather script indicating - // the controller should not water. + if ( adverseCodes.indexOf( weather.observation.icon_code ) !== -1 ) { + + // If the current weather indicates rain, add a restrict flag to the weather script indicating + // the controller should not water. + return true; + } + + var californiaRestriction = ( adjustmentValue >> 7 ) & 1; + + if ( californiaRestriction ) { + + // If the California watering restriction is in use then prevent watering + // if more then 0.01" of rain has accumulated in the past 48 hours + if ( weather.observation.imperial.precip_2day > 0.01 || weather.observation.imperial.precip_24hour > 0.01 ) { return true; } - - var californiaRestriction = ( adjustmentValue >> 7 ) & 1; - - if ( californiaRestriction ) { - - // If the California watering restriction is in use then prevent watering - // if more then 0.01" of rain has accumulated in the past 48 hours - if ( weather.observation.imperial.precip_2day > 0.01 || weather.observation.imperial.precip_24hour > 0.01 ) { - return true; - } - } - - return false; } - // API Handler when using the weatherX.py where X represents the - // adjustment method which is encoded to also carry the watering - // restriction and therefore must be decoded - exports.getWeather = function( req, res ) { + return false; +} - // The adjustment method is encoded by the OpenSprinkler firmware and must be - // parsed. This allows the adjustment method and the restriction type to both - // be saved in the same byte. - var adjustmentMethod = req.params[0] & ~( 1 << 7 ), - adjustmentOptions = req.query.wto, - location = req.query.loc, - weatherUndergroundKey = req.query.key, - outputFormat = req.query.format, +// API Handler when using the weatherX.py where X represents the +// adjustment method which is encoded to also carry the watering +// restriction and therefore must be decoded +exports.getWeather = function( req, res ) { + + // The adjustment method is encoded by the OpenSprinkler firmware and must be + // parsed. This allows the adjustment method and the restriction type to both + // be saved in the same byte. + var adjustmentMethod = req.params[0] & ~( 1 << 7 ), + adjustmentOptions = req.query.wto, + location = req.query.loc, + weatherUndergroundKey = req.query.key, + outputFormat = req.query.format, // firmwareVersion = req.query.fwv, - remoteAddress = req.headers[ "x-forwarded-for" ] || req.connection.remoteAddress, + remoteAddress = req.headers[ "x-forwarded-for" ] || req.connection.remoteAddress, - // Function that will accept the weather after it is received from the API - // Data will be processed to retrieve the resulting scale, sunrise/sunset, timezone, - // and also calculate if a restriction is met to prevent watering. - finishRequest = function( weather ) { - if ( !weather || typeof weather.observation !== "object" || typeof weather.observation.imperial !== "object" ) { - res.send( "Error: No weather data found." ); - return; - } - - var data = { - scale: calculateWeatherScale( adjustmentMethod, adjustmentOptions, weather ), - restrict: checkWeatherRestriction( req.params[0], weather ) ? 1 : 0, - tz: getTimezone( weather.observation.obs_time_local ), - sunrise: getSunData( weather )[0], - sunset: getSunData( weather )[1], - eip: ipToInt( remoteAddress ) - }; - - // Return the response to the client in the requested format - if ( outputFormat === "json" ) { - res.json( data ); - } else { - res.send( "&scale=" + data.scale + - "&restrict=" + data.restrict + - "&tz=" + data.tz + - "&sunrise=" + data.sunrise + - "&sunset=" + data.sunset + - "&eip=" + data.eip - ); - } - }; - - // Exit if no location is provided - if ( !location ) { - res.send( "Error: No location provided." ); - return; - } - - // X-Forwarded-For header may contain more than one IP address and therefore - // the string is split against a comma and the first value is selected - remoteAddress = remoteAddress.split(",")[0]; - - // Parse weather adjustment options - try { - - // Reconstruct JSON string from deformed controller output - adjustmentOptions = JSON.parse( "{" + adjustmentOptions + "}" ); - } catch (err) { - - // If the JSON is not valid, do not incorporate weather adjustment options - adjustmentOptions = false; - } - - // Parse location string - if ( filters.gps.test( location ) ) { - - // Handle GPS coordinates by storing each coordinate in an array - location = location.split( "," ); - location = [ parseFloat( location[0] ), parseFloat( location[1] ) ]; - - // Continue with the weather request - getWeatherData( location, finishRequest ); - - } else if ( filters.pws.test( location ) ) { - - // Handle locations using PWS or ICAO (Weather Underground) - if ( !weatherUndergroundKey ) { - - // If no key is provided for Weather Underground then the PWS or ICAO cannot be resolved - res.send( "Error: Weather Underground key required when using PWS or ICAO location." ); + // Function that will accept the weather after it is received from the API + // Data will be processed to retrieve the resulting scale, sunrise/sunset, timezone, + // and also calculate if a restriction is met to prevent watering. + finishRequest = function( weather ) { + if ( !weather || typeof weather.observation !== "object" || typeof weather.observation.imperial !== "object" ) { + res.send( "Error: No weather data found." ); return; } - getPWSCoordinates( location, weatherUndergroundKey, function( result ) { - if ( result === false ) { - res.send( "Error: Unable to resolve location" ); - return; - } + var data = { + scale: calculateWeatherScale( adjustmentMethod, adjustmentOptions, weather ), + restrict: checkWeatherRestriction( req.params[0], weather ) ? 1 : 0, + tz: getTimezone( weather.observation.obs_time_local ), + sunrise: getSunData( weather )[0], + sunset: getSunData( weather )[1], + eip: ipToInt( remoteAddress ) + }; - location = result; - getWeatherData( location, finishRequest ); - } ); - } else { - - // Attempt to resolve provided location to GPS coordinates when it does not match - // a GPS coordinate or Weather Underground location using Weather Underground autocomplete - resolveCoordinates( location, function( result ) { - if ( result === false ) { - res.send( "Error: Unable to resolve location" ); - return; - } - - location = result; - getWeatherData( location, finishRequest ); - } ); - } - }; - - // Generic HTTP request handler that parses the URL and uses the - // native Node.js http module to perform the request - function httpRequest( url, callback ) { - url = url.match( filters.url ); - - var options = { - host: url[1], - port: url[2] || 80, - path: url[3] + // Return the response to the client in the requested format + if ( outputFormat === "json" ) { + res.json( data ); + } else { + res.send( "&scale=" + data.scale + + "&restrict=" + data.restrict + + "&tz=" + data.tz + + "&sunrise=" + data.sunrise + + "&sunset=" + data.sunset + + "&eip=" + data.eip + ); + } }; - http.get( options, function( response ) { - var data = ""; + // Exit if no location is provided + if ( !location ) { + res.send( "Error: No location provided." ); + return; + } - // Reassemble the data as it comes in - response.on( "data", function( chunk ) { - data += chunk; - } ); + // X-Forwarded-For header may contain more than one IP address and therefore + // the string is split against a comma and the first value is selected + remoteAddress = remoteAddress.split( "," )[0]; - // Once the data is completely received, return it to the callback - response.on( "end", function() { - callback( data ); - } ); - } ).on( "error", function() { + // Parse weather adjustment options + try { - // If the HTTP request fails, return false - callback( false ); + // Reconstruct JSON string from deformed controller output + adjustmentOptions = JSON.parse( "{" + adjustmentOptions + "}" ); + } catch ( err ) { + + // If the JSON is not valid, do not incorporate weather adjustment options + adjustmentOptions = false; + } + + // Parse location string + if ( filters.gps.test( location ) ) { + + // Handle GPS coordinates by storing each coordinate in an array + location = location.split( "," ); + location = [ parseFloat( location[0] ), parseFloat( location[1] ) ]; + + // Continue with the weather request + getWeatherData( location, finishRequest ); + + } else if ( filters.pws.test( location ) ) { + + // Handle locations using PWS or ICAO (Weather Underground) + if ( !weatherUndergroundKey ) { + + // If no key is provided for Weather Underground then the PWS or ICAO cannot be resolved + res.send( "Error: Weather Underground key required when using PWS or ICAO location." ); + return; + } + + getPWSCoordinates( location, weatherUndergroundKey, function( result ) { + if ( result === false ) { + res.send( "Error: Unable to resolve location" ); + return; + } + + location = result; + getWeatherData( location, finishRequest ); } ); - } + } else { - // Accepts a time string formatted in ISO-8601 and returns the timezone. - // The timezone output is formatted for OpenSprinkler Unified firmware. - function getTimezone( time ) { + // Attempt to resolve provided location to GPS coordinates when it does not match + // a GPS coordinate or Weather Underground location using Weather Underground autocomplete + resolveCoordinates( location, function( result ) { + if ( result === false ) { + res.send( "Error: Unable to resolve location" ); + return; + } - // Match the provided time string against a regex for parsing - time = time.match( filters.time ); + location = result; + getWeatherData( location, finishRequest ); + } ); + } +}; - var hour = parseInt( time[7] + time[8] ), - minute = parseInt( time[9] ); +// Generic HTTP request handler that parses the URL and uses the +// native Node.js http module to perform the request +function httpRequest( url, callback ) { + url = url.match( filters.url ); - // Convert the timezone into the OpenSprinkler encoded format - minute = ( minute / 15 >> 0 ) / 4; - hour = hour + ( hour >=0 ? minute : -minute ); + var options = { + host: url[1], + port: url[2] || 80, + path: url[3] + }; - return ( ( hour + 12 ) * 4 ) >> 0; - } + http.get( options, function( response ) { + var data = ""; - // Function to return the sunrise and sunset times from the weather reply - function getSunData( weather ) { + // Reassemble the data as it comes in + response.on( "data", function( chunk ) { + data += chunk; + } ); - // Sun times are parsed from string against a regex to identify the timezone - var sunrise = weather.observation.sunrise.match( filters.time ), - sunset = weather.observation.sunset.match( filters.time ); + // Once the data is completely received, return it to the callback + response.on( "end", function() { + callback( data ); + } ); + } ).on( "error", function() { - return [ + // If the HTTP request fails, return false + callback( false ); + } ); +} - // Values are converted to minutes from midnight for the controller - parseInt( sunrise[4] ) * 60 + parseInt( sunrise[5] ), - parseInt( sunset[4] ) * 60 + parseInt( sunset[5] ) - ]; - } +// Accepts a time string formatted in ISO-8601 and returns the timezone. +// The timezone output is formatted for OpenSprinkler Unified firmware. +function getTimezone( time ) { - // Converts IP string to integer - function ipToInt( ip ) { - ip = ip.split( "." ); - return ( ( ( ( ( ( +ip[0] ) * 256 ) + ( +ip[1] ) ) * 256 ) + ( +ip[2] ) ) * 256 ) + ( +ip[3] ); - } + // Match the provided time string against a regex for parsing + time = time.match( filters.time ); + + var hour = parseInt( time[7] + time[8] ), + minute = parseInt( time[9] ); + + // Convert the timezone into the OpenSprinkler encoded format + minute = ( minute / 15 >> 0 ) / 4; + hour = hour + ( hour >= 0 ? minute : -minute ); + + return ( ( hour + 12 ) * 4 ) >> 0; +} + +// Function to return the sunrise and sunset times from the weather reply +function getSunData( weather ) { + + // Sun times are parsed from string against a regex to identify the timezone + var sunrise = weather.observation.sunrise.match( filters.time ), + sunset = weather.observation.sunset.match( filters.time ); + + return [ + + // Values are converted to minutes from midnight for the controller + parseInt( sunrise[4] ) * 60 + parseInt( sunrise[5] ), + parseInt( sunset[4] ) * 60 + parseInt( sunset[5] ) + ]; +} + +// Converts IP string to integer +function ipToInt( ip ) { + ip = ip.split( "." ); + return ( ( ( ( ( ( +ip[0] ) * 256 ) + ( +ip[1] ) ) * 256 ) + ( +ip[2] ) ) * 256 ) + ( +ip[3] ); +} /* - function f2c( temp ) { - return ( temp - 32 ) * 5 / 9; - } +function f2c( temp ) { + return ( temp - 32 ) * 5 / 9; +} - function mm2in( x ) { - return x * 0.03937008; - } +function mm2in( x ) { + return x * 0.03937008; +} - function ft2m( x ) { - return x * 0.3048; - } +function ft2m( x ) { + return x * 0.3048; +} - // Resolves the Month / Day / Year of a Date object - function toUSDate( date ){ - return ( date.getMonth() + 1 ) + "/" + date.getDate() + "/" + date.getFullYear(); - } +// Resolves the Month / Day / Year of a Date object +function toUSDate( date ){ + return ( date.getMonth() + 1 ) + "/" + date.getDate() + "/" + date.getFullYear(); +} */ -} )();