CumulusMX_vremenska-postaja/webfiles/lib/steelseries/scripts/gauges.js

4391 lines
204 KiB
JavaScript
Raw Normal View History

2023-08-14 01:21:46 +02:00
/*!
* THIS VERSION CUSTOMISED FROM CUMULUS MX DEFAULT WEB SITE
* Last Modified: 2021/08/02 15:42:36
*
* A starter gauges page for Cumulus and Weather Display, based
* on the JavaScript SteelSeries gauges by Gerrit Grunwald.
*
* Created by Mark Crossley, July 2011
* see scriptVer below for latest release
*
* Released under GNU GENERAL PUBLIC LICENSE, Version 2, June 1991
* See the enclosed License file
*
* File encoding = UTF-8
*
*
*/
/* exported gauges */
/*!
* Tiny Pub/Sub - v0.7.0 - 2013-01-29
* https://github.com/cowboy/jquery-tiny-pubsub
* Copyright (c) 2013 "Cowboy" Ben Alman; Licensed MIT
*/
(function ($) {
'use strict';
var o = $({});
$.subscribe = function () {o.on.apply(o, arguments);};
$.unsubscribe = function () {o.off.apply(o, arguments);};
$.publish = function () {o.trigger.apply(o, arguments);};
}(jQuery));
var gauges;
gauges = (function () {
'use strict';
var strings = LANG.EN, // Set to your default language. Store all the strings in one object
config = {
// Script configuration parameters you may want to 'tweak'
scriptVer : '2.7.6',
weatherProgram : 0, // Set 0=Cumulus, 1=Weather Display, 2=VWS, 3=WeatherCat, 4=Meteobridge, 5=WView, 6=WeeWX, 7=WLCOM
imgPathURL : './images/', // *** Change this to the relative path for your 'Trend' graph images
oldGauges : 'gauges.htm', // *** Change this to the relative path for your 'old' gauges page.
realtimeInterval : 15, // *** Download data interval, set to your realtime data update interval in seconds
longPoll : false, // if enabled, use long polling and PHP generated data !!only enable if you understand how this is implemented!!
gaugeMobileScaling : 0.85, // scaling factor to apply when displaying the gauges mobile devices, set to 1 to disable (default 0.85)
graphUpdateTime : 15, // period of pop-up data graph refresh, in minutes (default 15)
stationTimeout : 3, // period of no data change before we declare the station off-line, in minutes (default 3)
pageUpdateLimit : 20, // period after which the page stops automatically updating, in minutes (default 20),
// - set to 0 (zero) to disable this feature
pageUpdatePswd : 'its-me', // password to over ride the page updates time-out, do not set to blank even if you do not use a password - http://<URL>&pageUpdate=its-me
digitalFont : false, // Font control for the gauges & timer
digitalForecast : false, // Font control for the status display, set this to false for languages that use accented characters in the forecasts
showPopupData : true, // Pop-up data displayed
showPopupGraphs : false, // If pop-up data is displayed, show the graphs?
mobileShowGraphs : false, // If false, on a mobile/narrow display, always disable the graphs
showWindVariation : true, // Show variation in wind direction over the last 10 minutes on the direction gauge
showWindMetar : false, // Show the METAR substring for wind speed/direction over the last 10 minutes on the direction gauge popup
showIndoorTempHum : true, // Show the indoor temperature/humidity options
showCloudGauge : true, // Display the Cloud Base gauge
showUvGauge : true, // Display the UV Index gauge
showSolarGauge : true, // Display the Solar gauge
showSunshineLed : true, // Show 'sun shining now' LED on solar gauge
showRoseGauge : true, // Show the optional Wind Rose gauge
showRoseGaugeOdo : true, // Show the optional Wind Rose gauge wind run Odometer
showRoseOnDirGauge : true, // Show the rose data as sectors on the direction gauge
showGaugeShadow : true, // Show a drop shadow outside the gauges
roundCloudbaseVal : true, // Round the value shown on the cloud base gauge to make it easier to read
// The realtime files should be absolute paths, "/xxx.txt" refers to the public root of your web server
realTimeUrlLongPoll: 'realtimegauges-longpoll.php', // *** ALL Users: If using long polling, change to your location of the PHP long poll realtime file ***
// *** the supplied file is for Cumulus only
realTimeUrlCumulus : 'realtimegauges.txt', // *** Cumulus Users: Change to your location of the realtime file ***
realTimeUrlWD : 'customclientraw.txt', // *** WD Users: Change to your location of the ccr file ***
realTimeUrlVWS : 'steelseriesVWSjson.php', // *** VWS Users: Change to your location of the JSON script generator ***
realTimeUrlWC : 'realtimegaugesWC.txt', // *** WeatherCat Users: Change to your location of the JSON script generator ***
realTimeUrlMB : 'MBrealtimegauges.txt', // *** Meteobridge Users: Change to the location of the JSON file
realTimeUrlWView : 'customclientraw.txt', // *** WView Users: Change to your location of the customclientraw.txt file ***
realTimeUrlWeewx : 'gauge-data.txt', // *** WeeWX Users: Change to your location of the gauge data file ***
realTimeUrlWLCOM : 'WLrealtimegauges.php', // *** WLCOM Users: change to location of WLCOMtags.php file ***
useCookies : true, // Persistently store user preferences in a cookie?
tipImages : [],
dashboardMode : false, // Used by Cumulus MX dashboard - SET TO FALSE OTHERWISE
dewDisplayType : 'dew' // Initial 'scale' to display on the 'dew point' gauge.
// 'dew' - Dewpoint
// 'app' - Apparent temperature
// 'wnd' - Wind Chill
// 'feel' - Feels Like
// 'hea' - Heat Index
// 'hum' - Humidex
},
// Gauge global look'n'feel settings
gaugeGlobals = {
minMaxArea : 'rgba(212,132,134,0.3)', // area sector for today's max/min. (red, green, blue, transparency)
windAvgArea : 'rgba(132,212,134,0.3)',
windVariationSector : 'rgba(120,200,120,0.7)', // only used when rose data is shown on direction gauge
frameDesign : steelseries.FrameDesign.TILTED_GRAY,
background : steelseries.BackgroundColor.BEIGE,
foreground : steelseries.ForegroundType.TYPE1,
pointer : steelseries.PointerType.TYPE8,
pointerColour : steelseries.ColorDef.RED,
dirAvgPointer : steelseries.PointerType.TYPE8,
dirAvgPointerColour : steelseries.ColorDef.BLUE,
gaugeType : steelseries.GaugeType.TYPE4,
lcdColour : steelseries.LcdColor.STANDARD,
knob : steelseries.KnobType.STANDARD_KNOB,
knobStyle : steelseries.KnobStyle.SILVER,
labelFormat : steelseries.LabelNumberFormat.STANDARD,
tickLabelOrientation : steelseries.TickLabelOrientation.HORIZONTAL, // was .NORMAL up to v1.6.4
rainUseSectionColours : false, // Only one of these colour options should be true
rainUseGradientColours: false, // Set both to false to use the pointer colour
tempTrendVisible : true,
pressureTrendVisible : true,
uvLcdDecimals : 1,
// sunshine threshold values
sunshineThreshold : 50, // the value in W/m² above which we can consider the Sun to be shining, *if* the current value exceeds...
sunshineThresholdPct : 75, // the percentage of theoretical solar irradiance above which we consider the Sun to be shining
// default gauge ranges - before auto-scaling/ranging
tempScaleDefMinC : -20,
tempScaleDefMaxC : 40,
tempScaleDefMinF : 0,
tempScaleDefMaxF : 100,
baroScaleDefMinhPa : 990,
baroScaleDefMaxhPa : 1030,
baroScaleDefMinkPa : 99,
baroScaleDefMaxkPa : 103,
baroScaleDefMininHg : 29.2,
baroScaleDefMaxinHg : 30.4,
windScaleDefMaxMph : 20,
windScaleDefMaxKts : 20,
windScaleDefMaxMs : 10,
windScaleDefMaxKmh : 30,
rainScaleDefMaxmm : 10,
rainScaleDefMaxIn : 0.5,
rainRateScaleDefMaxmm : 10,
rainRateScaleDefMaxIn : 0.5,
uvScaleDefMax : 10, // Northern Europe may be lower - max. value recorded in the UK is 8, so use a scale of 10 for UK
solarGaugeScaleMax : 1000, // Max value to be shown on the solar gauge - theoretical max without atmosphere ~ 1374 W/m²
// - but Davis stations can read up to 1800, use 1000 for Northern Europe?
cloudScaleDefMaxft : 3000,
cloudScaleDefMaxm : 1000,
shadowColour : 'rgba(0,0,0,0.3)' // Colour to use for gauge shadows - default 30% transparent black
},
commonParams = {
// Common parameters for all the SteelSeries gauges
fullScaleDeflectionTime: 4, // Bigger numbers (seconds) slow the gauge pointer movements more
gaugeType : gaugeGlobals.gaugeType,
minValue : 0,
niceScale : true,
ledVisible : false,
frameDesign : gaugeGlobals.frameDesign,
backgroundColor : gaugeGlobals.background,
foregroundType : gaugeGlobals.foreground,
pointerType : gaugeGlobals.pointer,
pointerColor : gaugeGlobals.pointerColour,
knobType : gaugeGlobals.knob,
knobStyle : gaugeGlobals.knobStyle,
lcdColor : gaugeGlobals.lcdColour,
lcdDecimals : 1,
digitalFont : config.digitalFont,
tickLabelOrientation : gaugeGlobals.tickLabelOrientation,
labelNumberFormat : gaugeGlobals.labelFormat
},
firstRun = true, // Used to set-up units & scales etc
userUnitsSet = false, // Tracks if the display units have been set by a user preference
data = {}, // Stores all the values from realtime.txt
tickTockInterval, // The 1s clock interval timer
// ajaxDelay, used by long polling, the delay between getting a response and queueing the next request, as the default PHP
// script runtime timout is 30 seconds, we do not want the PHP task to run for more than 20 seconds. So queue the next
// request half of the realtime interval, or 20 seconds before it is due, which ever is the larger.
ajaxDelay = config.longPoll ? Math.max(config.realtimeInterval - 20, 0) : config.realtimeInterval,
downloadTimer, // Stores a reference to the ajax download setTimout() timer
timestamp = 0, // the timestamp of last data update on the server.
jqXHR = null, // handle to the jQuery web request
displayUnits = null, // Stores the display units cookie settings
sampleDate,
realtimeVer, // minimum version of the realtime JSON file required
programLink = [
'<a href="https://cumuluswiki.wxforum.net/a/Software" target="_blank" rel="noopener">Cumulus</a>',
'<a href="//www.weather-display.com/" target="_blank" rel="noopener">Weather Display</a>',
'<a href="//www.ambientweather.com/virtualstation.html" target="_blank" rel="noopener">Virtual Weather Station</a>',
'<a href="//trixology.com/weathercat/" target="_blank" rel="noopener">WeatherCat</a>',
'<a href="//www.meteobridge.com/" target="_blank rel="noopener"">Meteobridge</a>',
'<a href="//www.wviewweather.com/" target="_blank" rel="noopener">Wview</a>',
'<a href="//www.weewx.com/" target="_blank" rel="noopener">weewx</a>',
'<a href="//weatherlink.com/" target="_blank" rel="noopener">Weatherlink.com</a>'
],
ledIndicator, statusScroller, statusTimer,
gaugeTemp, gaugeDew, gaugeRain, gaugeRRate,
gaugeHum, gaugeBaro, gaugeWind, gaugeDir,
gaugeUV, gaugeSolar, gaugeCloud, gaugeRose,
/* _imgBackground, // Uncomment if using a background image on the gauges */
// ==================================================================================================================
// Nothing below this line needs to be modified for the gauges as supplied
// - unless you really know what you are doing
// - but remember, if you break it, it's up to you to fix it ;-)
// ==================================================================================================================
//
// init() Called when the document is ready, pre-draws the Status Display then calls
// the first Ajax fetch of realtimegauges.txt. First draw of the gauges now deferred until
// the Ajax data is available as a 'speed up'.
//
init = function (dashboard) {
// Cumulus, Weather Display, VWS, WeatherCat?
switch (config.weatherProgram) {
case 0:
// Cumulus
realtimeVer = 12; // minimum version of the realtime JSON file required
config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlCumulus;
// the trend images to be used for the pop-up data, used in conjunction with config.imgPathURL
// by default this is configured for the Cumulus 'standard' web site
// ** If you specify one image in a sub-array, then you MUST provide images for all the other sub-elements
config.tipImgs = [ // config.tipImgs for Cumulus users using the 'default' weather site
['temp.png', 'intemp.png'], // Temperature: outdoor, indoor
// Temperature: dewpoint, apparent, windChill, heatIndex, humidex
['temp.png', 'temp.png', 'temp.png', 'temp.png', 'temp.png'],
'raint.png', // Rainfall
'rain.png', // Rainfall rate
['hum.png', 'hum.png'], // Humidity: outdoor, indoor
'press.png', // Pressure
'wind.png', // Wind speed
'windd.png', // Wind direction
(config.showUvGauge ? 'uv.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
(config.showSolarGauge ? 'solar.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
(config.showRoseGauge ? 'windd.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
(config.showCloudGauge ? 'press.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
];
break;
case 1:
// Weather Display
realtimeVer = 14; // minimum version of the realtime JSON file required
config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWD;
config.tipImgs = [ // config.tipImgs for Weather Display users with wxgraph
['temp+hum_24hr.php', 'indoor_temp_24hr.php'], // Temperature: outdoor, indoor
// Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
['temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php'],
'rain_24hr.php', // Rainfall
'rain_1hr.php', // Rainfall rate
['humidity_1hr.php', 'humidity_7days.php'], // Humidity: outdoor, indoor
'baro_24hr.php', // Pressure
'windgust_1hr.php', // Wind speed
'winddir_24hr.php', // Wind direction
(config.showUvGauge ? 'uv_24hr.php' : null), // UV graph if UV sensor is present | =null if no UV sensor
(config.showSolarGauge ? 'solar_24hr.php' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
(config.showRoseGauge ? 'winddir_24hr.php' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
(config.showCloudGauge ? 'baro_24hr.php' : null) // Pressure for cloud height | =null if Cloud Height is disabled
];
// WD useer generally use wxgraphs - tweak the CSS to accomadate the different aspect ratio
$('.tipimg').css({
width : '360px',
height: '260px'});
break;
case 2:
// WVS
realtimeVer = 11; // minimum version of the realtime JSON file required
config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlVWS;
config.showRoseGauge = false; // no wind rose data from VWS
config.showCloudGauge = false;
config.tipImgs = [ // config.tipImgs for VWS users
['vws742.jpg', 'vws741.jpg'], // Temperature: outdoor, indoor
// Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
['vws757.jpg', 'vws762.jpg', 'vws754.jpg', 'vws756.jpg', null],
'vws744.jpg', // Rainfall
'vws859.jpg', // Rainfall rate
['vws740.jpg', 'vws739.jpg'], // Humidity: outdoor, indoor
'vws758.jpg', // Pressure
'vws737.jpg', // Wind speed
'vws736.jpg', // Wind direction
(config.showUvGauge ? 'vws752.jpg' : null), // UV graph if UV sensor is present | =null if no UV sensor
(config.showSolarGauge ? 'vws753.jpg' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
(config.showRoseGauge ? 'vws736.jpg' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
(config.showCloudGauge ? 'vws758.jpg' : null) // Pressure for cloud height | =null if Cloud Height is disabled
];
break;
case 3:
// WeatherCat
realtimeVer = 14; // minimum version of the realtime JSON file required
config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWC;
config.tipImgs = [ // config.tipImgs - WeatherCat users using the 'default' weather site
['temperature1.jpg', 'tempin1.jpg'], // Temperature: outdoor, indoor
// Temperature: dewpoint, apparent, windChill, heatIndex, humidex
['dewpoint1.jpg', 'temperature1.jpg', 'windchill1.jpg', 'heatindex1.jpg', 'temperature1.jpg'],
'precipitationc1.jpg', // Rainfall
'precipitation1.jpg', // Rainfall rate
['rh1.jpg', 'rhin1.jpg'], // Humidity: outdoor, indoor
'pressure1.jpg', // Pressure
'windspeed1.jpg', // Wind speed
'winddirection1.jpg', // Wind direction
(config.showUvGauge ? 'uv1.jpg' : null), // UV graph if UV sensor is present | =null if no UV sensor
(config.showSolarGauge ? 'solarrad1.jpg' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
(config.showRoseGauge ? 'winddirection1.jpg' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
(config.showCloudGauge ? 'cloudbase1.jpg' : null) // Pressure for cloud height | =null if Cloud Height is disabled
];
break;
case 4:
// Meteobridge
realtimeVer = 10; // minimum version of the realtime JSON file required
config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlMB;
config.showPopupGraphs = false; // config.tipImgs - no Meteobridge images available
config.showRoseGauge = false; // no windrose data from MB
config.showCloudGauge = false;
config.tipImgs = null; // config.tipImgs - no Meteobridge images available
config.showWindVariation = false; // no wind variation data from MB
break;
case 5:
// WView
realtimeVer = 11; // minimum version of the realtime JSON file required
config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWView;
config.showSunshineLed = false; // WView does not provide the current theoretical solar max required to determine sunshine
config.showWindVariation = false; // no wind variation from WView
config.showRoseGauge = false; // No wind rose array from WView by default - there is a user supplied modification to enable it though.
config.showCloudGauge = false;
config.tipImgs = [ // config.tipImgs for WView users
['tempdaycomp.png', 'indoor_temp.png'], // Temperature: outdoor, indoor
// Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
['tempdaycomp.png', 'tempdaycomp.png', 'heatchillcomp.png', 'heatchillcomp.png', 'tempdaycomp.png'],
'rainday.png', // Rainfall
'rainrate.png', // Rainfall rate
['humidday.png', 'humidday.png'], // Humidity: outdoor, indoor
'baromday.png', // Pressure
'wspeeddaycomp.png', // Wind speed
'wdirday.png', // Wind direction
(config.showUvGauge ? 'uvday.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
(config.showSolarGauge ? 'solarday.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
(config.showRoseGauge ? 'windroseday.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
(config.showCloudGauge ? 'baromday.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
];
break;
case 6:
// weewx
realtimeVer = 14; // minimum version of the realtime JSON file required
config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWeewx;
config.showSunshineLed = true;
config.showWindVariation = true;
config.tipImgs = [ // config.tipImgs for weewx
['dayinouttemp.png', 'dayinouttemp.png'], // Temperature: outdoor, indoor
// Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
['dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png'],
'dayrain.png', // Rainfall
'dayrainrate.png', // Rainfall rate
['dayinouthum.png', 'dayinouthum.png'], // Humidity: outdoor, indoor
'daybarometer.png', // Pressure
'daywind.png', // Wind speed
'daywinddir.png', // Wind direction
(config.showUvGauge ? 'dayuv.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
(config.showSolarGauge ? 'dayradiation.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
(config.showRoseGauge ? 'daywindvec.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
(config.showCloudGauge ? 'daybarometer.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
];
break;
case 7:
// WLCOM
realtimeVer = 10; // minimum version of the realtime JSON file required
config.realTimeURL = config.realTimeUrlWLCOM;
config.showPopupGraphs = false; // config.tipImgs - no WL images available
config.showRoseGauge = false; // no windrose data from WL
config.showCloudGauge = false;
config.tipImgs = null; // config.tipImgs - no WL images available
config.showWindVariation = false; // no wind variation data from WL
break;
default:
// Who knows!
realtimeVer = 0; // minimum version of the realtime JSON file required
config.realtimeURL = null;
config.showPopupGraphs = false;
config.tipImgs = null; // config.tipImgs - unknown
}
// Are we running on a phone device (or really low res screen)?
if ($(window).width() < 480) {
// Change the gauge scaling
config.gaugeScaling = config.gaugeMobileScaling;
// Switch off graphs?
config.showPopupGraphs = config.mobileShowGraphs;
} else {
config.gaugeScaling = 1;
}
// Logo images are used to 'personalise' the gauge backgrounds
// To add a logo to a gauge, add the parameter:
// params.customLayer = _imgBackground;
// to the corresponding drawXxxx() function below.
//
// These are for demo only, to add them remove the comments around the following lines, and
// the _imgBackground definition line above...
/*
_imgBackground = document.createElement('img'); // small logo
$(_imgBackground).attr('src', config.imgPathURL + 'logoSmall.png');
*/
// End of logo images
// Get the display units the user last used when they visited before - if present
displayUnits = getCookie('units');
// Set 'units' radio buttons to match preferred units
if (displayUnits !== null) {
// User wants specific units
userUnitsSet = true;
// temperature
setRadioCheck('rad_unitsTemp', displayUnits.temp);
data.tempunit = '°' + displayUnits.temp;
// rain
setRadioCheck('rad_unitsRain', displayUnits.rain);
data.rainunit = displayUnits.rain;
// pressure
setRadioCheck('rad_unitsPress', displayUnits.press);
data.pressunit = displayUnits.press;
// wind
setRadioCheck('rad_unitsWind', displayUnits.wind);
data.windunit = displayUnits.wind;
displayUnits.windrun = getWindrunUnits(data.windunit);
// cloud base
setRadioCheck('rad_unitsCloud', displayUnits.cloud);
data.cloudunit = displayUnits.cloud;
} else {
// Set the defaults to metric )
// DO NOT CHANGE THESE - THE SCRIPT DEPENDS ON THESE DEFAULTS
// The units actually displayed will be read from the realtime.txt file, or from the users last visit cookie
displayUnits = {
temp : 'C',
rain : 'mm',
press : 'hPa',
wind : 'km/h',
windrun: 'km',
cloud : 'm'
};
data.tempunit = '°C';
data.rainunit = 'mm';
data.pressunit = 'hPa';
data.windunit = 'km/h';
data.cloudunit = 'm';
}
// enable popup data
if (config.showPopupData) {
ddimgtooltip.showTips = config.showPopupData;
}
if (config.showPopupGraphs) {
// Note the number of array elements must match 'i' in ddimgtooltip.tiparray()
ddimgtooltip.tiparray[0][0] = (config.tipImgs[0][0] === null ? null : '');
ddimgtooltip.tiparray[1][0] = (config.tipImgs[1][0] === null ? null : '');
ddimgtooltip.tiparray[2][0] = (config.tipImgs[2] === null ? null : '');
ddimgtooltip.tiparray[3][0] = (config.tipImgs[3] === null ? null : '');
ddimgtooltip.tiparray[4][0] = (config.tipImgs[4][0] === null ? null : '');
ddimgtooltip.tiparray[5][0] = (config.tipImgs[5] === null ? null : '');
ddimgtooltip.tiparray[6][0] = (config.tipImgs[6] === null ? null : '');
ddimgtooltip.tiparray[7][0] = (config.tipImgs[7] === null ? null : '');
ddimgtooltip.tiparray[8][0] = (config.tipImgs[8] === null ? null : '');
ddimgtooltip.tiparray[9][0] = (config.tipImgs[9] === null ? null : '');
ddimgtooltip.tiparray[10][0] = (config.tipImgs[10] === null ? null : '');
ddimgtooltip.tiparray[11][0] = (config.tipImgs[11] === null ? null : '');
}
// draw the status gadgets first, they will display any errors in the initial set-up
ledIndicator = singleLed.getInstance();
statusScroller = singleStatus.getInstance();
statusTimer = singleTimer.getInstance();
gaugeTemp = singleTemp.getInstance();
// Export gaugeTemp.update() so it can be called from the HTML code
if (gaugeTemp) {gauges.doTemp = gaugeTemp.update;}
gaugeDew = singleDew.getInstance();
// Export gaugeDew.update() so it can be called from the HTML code
if (gaugeDew) {gauges.doDew = gaugeDew.update;}
gaugeHum = singleHum.getInstance();
// Export gaugeHum.update() so it can be called from the HTML code
if (gaugeHum) {gauges.doHum = gaugeHum.update;}
gaugeBaro = singleBaro.getInstance();
gaugeWind = singleWind.getInstance();
gaugeDir = singleDir.getInstance();
gaugeRain = singleRain.getInstance();
gaugeRRate = singleRRate.getInstance();
// remove the UV gauge?
if (!config.showUvGauge) {
$('#canvas_uv').parent().remove();
} else {
gaugeUV = singleUV.getInstance();
}
// remove the Solar gauge?
if (!config.showSolarGauge) {
$('#canvas_solar').parent().remove();
} else {
gaugeSolar = singleSolar.getInstance();
}
// remove the Wind Rose?
if (!config.showRoseGauge) {
$('#canvas_rose').parent().remove();
} else {
gaugeRose = singleRose.getInstance();
}
// remove the cloud base gauge?
if (!config.showCloudGauge) {
$('#canvas_cloud').parent().remove();
// and remove cloudbase unit selection options
$('#cloud').parent().remove();
} else {
gaugeCloud = singleCloudBase.getInstance();
}
// Set the language
changeLang(strings, false);
if (!dashboard) {
// Go do get the data!
getRealtime();
// start a timer to update the status time
tickTockInterval = setInterval(
function () {
$.publish('gauges.clockTick', null);
},
1000);
// start a timer to stop the page updates after the timeout period
if (config.pageUpdateLimit > 0 && getUrlParam('pageUpdate') !== config.pageUpdatePswd) {
setTimeout(pageTimeout, config.pageUpdateLimit * 60 * 1000);
}
}
},
//
// singleXXXX functions define a singleton for each of the gauges
//
//
// Singleton for the LED Indicator
//
singleLed = (function () {
var instance; // Stores a reference to the Singleton
var led; // Stores a reference to the SS LED
function init() {
// create led indicator
if ($('#canvas_led').length) {
led = new steelseries.Led(
'canvas_led', {
ledColor: steelseries.LedColor.GREEN_LED,
size : $('#canvas_led').width()
});
setTitle(strings.led_title);
}
function setTitle(newTitle) {
$('#canvas_led').attr('title', newTitle);
}
function setLedColor(newColour) {
if (led) {
led.setLedColor(newColour);
}
}
function setLedOnOff(onState) {
if (led) {
led.setLedOnOff(onState);
}
}
function blink(blinkState) {
if (led) {
led.blink(blinkState);
}
}
return {
setTitle : setTitle,
setLedColor: setLedColor,
setLedOnOff: setLedOnOff,
blink : blink
};
}
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Status Scroller
//
singleStatus = (function () {
var instance; // Stores a reference to the Singleton
var scroller; // Stores a reference to the SS scrolling display
function init() {
// create forecast display
if ($('#canvas_status').length) {
scroller = new steelseries.DisplaySingle(
'canvas_status', {
width : $('#canvas_status').width(),
height : $('#canvas_status').height(),
lcdColor : gaugeGlobals.lcdColour,
unitStringVisible: false,
value : strings.statusStr,
digitalFont : config.digitalForecast,
valuesNumeric : false,
autoScroll : true,
alwaysScroll : false
});
}
function setValue(newTxt) {
if (scroller) {
scroller.setValue(newTxt);
}
}
return {setText: setValue};
}
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Status Timer
//
singleTimer = (function () {
var instance, // Stores a reference to the Singleton
lcd, // Stores a reference to the SS LED
count = 1;
function init() {
function tick() {
if (lcd) {
lcd.setValue(count);
count += config.longPoll ? 1 : -1;
}
}
function reset(val) {
count = val;
}
function setValue(newVal) {
if (lcd) {
lcd.setValue(newVal);
}
}
// create timer display
if ($('#canvas_timer').length) {
lcd = new steelseries.DisplaySingle(
'canvas_timer', {
width : $('#canvas_timer').width(),
height : $('#canvas_timer').height(),
lcdColor : gaugeGlobals.lcdColour,
lcdDecimals : 0,
unitString : strings.timer,
unitStringVisible: true,
digitalFont : config.digitalFont,
value : count
});
// subscribe to data updates
$.subscribe('gauges.clockTick', tick);
}
return {
reset : reset,
setValue: setValue
};
}
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Temperature Gauge
//
singleTemp = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define temperature gauge start values
cache.sections = createTempSections(true);
cache.areas = [];
cache.minValue = gaugeGlobals.tempScaleDefMinC;
cache.maxValue = gaugeGlobals.tempScaleDefMaxC;
cache.title = strings.temp_title_out;
cache.value = gaugeGlobals.tempScaleDefMinC + 0.0001;
cache.maxMinVisible = false;
cache.selected = 'out';
// create temperature radial gauge
if ($('#canvas_temp').length) {
params.size = Math.ceil($('#canvas_temp').width() * config.gaugeScaling);
params.section = cache.sections;
params.area = cache.areas;
params.minValue = cache.minValue;
params.maxValue = cache.maxValue;
params.thresholdVisible = false;
params.minMeasuredValueVisible = cache.maxMinVisible;
params.maxMeasuredValueVisible = cache.maxMinVisible;
params.titleString = cache.title;
params.unitString = data.tempunit;
params.trendVisible = gaugeGlobals.tempTrendVisible;
// params.customLayer = _imgBackground; // uncomment to add a background image - See Logo Images above
ssGauge = new steelseries.Radial('canvas_temp', params);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_temp').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_temp').css(gaugeShadow(params.size));
}
// remove indoor temperature/humidity options?
if (!config.showIndoorTempHum) {
$('#rad_temp1').remove();
$('#lab_temp1').remove();
$('#rad_temp2').remove();
$('#lab_temp2').remove();
$('#rad_hum1').remove();
$('#lab_hum1').remove();
$('#rad_hum2').remove();
$('#lab_hum2').remove();
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
var sel = cache.selected;
// Argument length === 1 when called from radio input
// Argument length === 2 when called from event handler
if (arguments.length === 1) {
sel = arguments[0].value;
}
// if rad isn't specified, just use existing value
var t1, scaleStep, tip;
cache.minValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMinC : gaugeGlobals.tempScaleDefMinF;
cache.maxValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMaxC : gaugeGlobals.tempScaleDefMaxF;
if (sel === 'out') {
cache.low = extractDecimal(data.tempTL);
cache.high = extractDecimal(data.tempTH);
cache.lowScale = getMinTemp(cache.minValue);
cache.highScale = getMaxTemp(cache.maxValue);
cache.value = extractDecimal(data.temp);
cache.title = strings.temp_title_out;
cache.loc = strings.temp_out_info;
cache.trendVal = extractDecimal(data.temptrend);
cache.popupImg = 0;
if (gaugeGlobals.tempTrendVisible) {
t1 = tempTrend(+cache.trendVal, data.tempunit, false);
if (t1 === -9999) {
// trend value isn't currently available
cache.trend = steelseries.TrendState.OFF;
} else if (t1 > 0) {
cache.trend = steelseries.TrendState.UP;
} else if (t1 < 0) {
cache.trend = steelseries.TrendState.DOWN;
} else {
cache.trend = steelseries.TrendState.STEADY;
}
}
} else {
// Indoor
cache.title = strings.temp_title_in;
cache.loc = strings.temp_in_info;
cache.value = extractDecimal(data.intemp);
cache.popupImg = 1;
if (data.intempTL && data.intempTH) {
// Indoor - and Max/Min values supplied
cache.low = extractDecimal(data.intempTL);
cache.high = extractDecimal(data.intempTH);
cache.lowScale = getMinTemp(cache.minValue);
cache.highScale = getMaxTemp(cache.maxValue);
} else {
// Indoor - no Max/Min values supplied
cache.low = cache.value;
cache.lowScale = cache.value;
cache.high = cache.value;
cache.highScale = cache.value;
}
if (gaugeGlobals.tempTrendVisible) {
cache.trend = steelseries.TrendState.OFF;
}
}
// has the gauge type changed?
if (cache.selected !== sel) {
cache.selected = sel;
// Change gauge title
ssGauge.setTitleString(cache.title);
ssGauge.setMaxMeasuredValueVisible(cache.maxMinVisible);
ssGauge.setMinMeasuredValueVisible(cache.maxMinVisible);
if (config.showPopupGraphs && config.tipImgs[0][cache.popupImg] !== null) {
var cacheDefeat = '?' + $('#imgtip0_img').attr('src').split('?')[1];
$('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][cache.popupImg] + cacheDefeat);
}
}
// auto scale the ranges
scaleStep = data.tempunit[1] === 'C' ? 10 : 20;
while (cache.lowScale < cache.minValue) {
cache.minValue -= scaleStep;
if (cache.highScale <= cache.maxValue - scaleStep) {
cache.maxValue -= scaleStep;
}
}
while (cache.highScale > cache.maxValue) {
cache.maxValue += scaleStep;
if (cache.minValue >= cache.minValue + scaleStep) {
cache.minValue += scaleStep;
}
}
if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
ssGauge.setMinValue(cache.minValue);
ssGauge.setMaxValue(cache.maxValue);
ssGauge.setValue(cache.minValue);
}
if (cache.selected === 'out') {
cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
} else if (data.intempTL && data.intempTH) {
// Indoor and min/max avaiable
cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
} else {
// Indoor no min/max avaiable
cache.areas = [];
}
if (gaugeGlobals.tempTrendVisible) {
ssGauge.setTrend(cache.trend);
}
ssGauge.setArea(cache.areas);
ssGauge.setValueAnimated(+cache.value);
if (ddimgtooltip.showTips) {
// update tooltip
if (cache.selected === 'out') {
tip = cache.loc + ' - ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TtempTL +
' | ' +
strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TtempTH;
if (cache.trendVal !== -9999) {
tip += '<br>' +
strings.temp_trend_info + ': ' + tempTrend(cache.trendVal, data.tempunit, true) +
' ' + cache.trendVal + data.tempunit + '/h';
}
} else if (data.TintempTL && data.TintempTH) {
// Indoor and min/max available
tip = cache.loc + ' - ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TintempTL +
' | ' +
strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TintempTH;
} else {
// Indoor no min/max
tip = cache.loc + ': ' + data.intemp + data.tempunit;
}
$('#imgtip0_txt').html(tip);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[0][cache.popupImg] !== null) {
$('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][cache.popupImg] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(), // End singleTemp()
//
// Singleton for the Dewpoint Gauge
//
singleDew = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
var tmp;
// define dew point gauge start values
cache.sections = createTempSections(true);
cache.areas = [];
cache.minValue = gaugeGlobals.tempScaleDefMinC;
cache.maxValue = gaugeGlobals.tempScaleDefMaxC;
cache.value = gaugeGlobals.tempScaleDefMinC + 0.0001;
// Has the end user selected a preferred 'scale' before
tmp = getCookie('dewGauge');
cache.selected = tmp !== null ? tmp : config.dewDisplayType;
setRadioCheck('rad_dew', cache.selected);
switch (cache.selected) {
case 'dew':
cache.title = strings.dew_title;
cache.popupImg = 0;
break;
case 'app':
cache.title = strings.apptemp_title;
cache.popupImg = 1;
break;
case 'feel':
cache.title = strings.feel_title;
cache.popupImg = 1;
break;
case 'wnd':
cache.title = strings.chill_title;
cache.popupImg = 2;
break;
case 'hea':
cache.title = strings.heat_title;
cache.popupImg = 3;
break;
case 'hum':
cache.title = strings.humdx_title;
cache.popupImg = 4;
// no default
}
cache.minMeasuredVisible = false;
cache.maxMeasuredVisible = false;
// create dew point radial gauge
if ($('#canvas_dew').length) {
params.size = Math.ceil($('#canvas_dew').width() * config.gaugeScaling);
params.section = cache.sections;
params.area = cache.areas;
params.minValue = cache.minValue;
params.maxValue = cache.maxValue;
params.thresholdVisible = false;
params.titleString = cache.title;
params.unitString = data.tempunit;
ssGauge = new steelseries.Radial('canvas_dew', params);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_dew').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_dew').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
// if rad isn't specified, just use existing value
var sel = cache.selected;
// Argument length === 2 when called from event handler
if (arguments.length === 1) {
sel = arguments[0].value;
// save the choice in a cookie
setCookie('dewGauge', sel);
}
var tip, scaleStep;
cache.minValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMinC : gaugeGlobals.tempScaleDefMinF;
cache.maxValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMaxC : gaugeGlobals.tempScaleDefMaxF;
cache.lowScale = getMinTemp(cache.minValue);
cache.highScale = getMaxTemp(cache.maxValue);
switch (sel) {
case 'dew': // dew point
cache.low = extractDecimal(data.dewpointTL);
cache.high = extractDecimal(data.dewpointTH);
cache.value = extractDecimal(data.dew);
cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
cache.title = strings.dew_title;
cache.minMeasuredVisible = false;
cache.maxMeasuredVisible = false;
cache.popupImg = 0;
tip = strings.dew_info + ':' +
'<br>' +
'- ' + strings.lowest_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TdewpointTL +
' | ' + strings.highest_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TdewpointTH;
break;
case 'app': // apparent temperature
cache.low = extractDecimal(data.apptempTL);
cache.high = extractDecimal(data.apptempTH);
cache.value = extractDecimal(data.apptemp);
cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
cache.title = strings.apptemp_title;
cache.minMeasuredVisible = false;
cache.maxMeasuredVisible = false;
cache.popupImg = 1;
tip = tip = strings.apptemp_info + ':' +
'<br>' +
'- ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TapptempTL +
' | ' + strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TapptempTH;
break;
case 'feel': // feels like
cache.low = extractDecimal(data.feelslikeTL);
cache.high = extractDecimal(data.feelslikeTH);
cache.value = extractDecimal(data.feelslike);
cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
cache.title = strings.feel_title;
cache.minMeasuredVisible = false;
cache.maxMeasuredVisible = false;
cache.popupImg = 1;
tip = tip = strings.feel_info + ':' +
'<br>' +
'- ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TfeelslikeTL +
' | ' + strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TfeelslikeTH;
break;
case 'wnd': // wind chill
cache.low = extractDecimal(data.wchillTL);
cache.high = extractDecimal(data.wchill);
cache.value = extractDecimal(data.wchill);
cache.areas = [];
cache.title = strings.chill_title;
cache.minMeasuredVisible = true;
cache.maxMeasuredVisible = false;
cache.popupImg = 2;
tip = strings.chill_info + ':' +
'<br>' +
'- ' + strings.lowest_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TwchillTL;
break;
case 'hea': // heat index
cache.low = extractDecimal(data.heatindex);
cache.high = extractDecimal(data.heatindexTH);
cache.value = extractDecimal(data.heatindex);
cache.areas = [];
cache.title = strings.heat_title;
cache.minMeasuredVisible = false;
cache.maxMeasuredVisible = true;
cache.popupImg = 3;
tip = strings.heat_info + ':' +
'<br>' +
'- ' + strings.highest_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TheatindexTH;
break;
case 'hum': // humidex
cache.low = extractDecimal(data.humidex);
cache.high = extractDecimal(data.humidex);
cache.value = extractDecimal(data.humidex);
cache.areas = [];
cache.title = strings.humdx_title;
cache.minMeasuredVisible = false;
cache.maxMeasuredVisible = false;
cache.popupImg = 4;
tip = strings.humdx_info + ': ' + cache.value + data.tempunit;
break;
// no default
}
if (cache.selected !== sel) {
cache.selected = sel;
// change gauge title
ssGauge.setTitleString(cache.title);
// and graph image
if (config.showPopupGraphs && config.tipImgs[1][cache.popupImg] !== null) {
var cacheDefeat = '?' + $('#imgtip1_img').attr('src').split('?')[1];
$('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][cache.popupImg] + cacheDefeat);
}
}
// auto scale the ranges
scaleStep = data.tempunit[1] === 'C' ? 10 : 20;
while (cache.lowScale < cache.minValue) {
cache.minValue -= scaleStep;
if (cache.highScale <= cache.maxValue - scaleStep) {
cache.maxValue -= scaleStep;
}
}
while (cache.highScale > cache.maxValue) {
cache.maxValue += scaleStep;
if (cache.minValue >= cache.minValue + scaleStep) {
cache.minValue += scaleStep;
}
}
if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
ssGauge.setMinValue(cache.minValue);
ssGauge.setMaxValue(cache.maxValue);
ssGauge.setValue(cache.minValue);
}
ssGauge.setMinMeasuredValueVisible(cache.minMeasuredVisible);
ssGauge.setMaxMeasuredValueVisible(cache.maxMeasuredVisible);
ssGauge.setMinMeasuredValue(+cache.low);
ssGauge.setMaxMeasuredValue(+cache.high);
ssGauge.setArea(cache.areas);
ssGauge.setValueAnimated(+cache.value);
if (ddimgtooltip.showTips) {
// update tooltip
$('#imgtip1_txt').html(tip);
}
}
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[1][cache.popupImg] !== null) {
$('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][cache.popupImg] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(), // End of singleDew()
//
// Singleton for the Rainfall Gauge
//
singleRain = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define rain gauge start values
cache.maxValue = gaugeGlobals.rainScaleDefMaxmm;
cache.value = 0.0001;
cache.title = strings.rain_title;
cache.lcdDecimals = 1;
cache.scaleDecimals = 1;
cache.labelNumberFormat = gaugeGlobals.labelFormat;
cache.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(true) : []);
cache.valGrad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(true) : null);
// create rain radial bargraph gauge
if ($('#canvas_rain').length) {
params.size = Math.ceil($('#canvas_rain').width() * config.gaugeScaling);
params.maxValue = cache.maxValue;
params.thresholdVisible = false;
params.titleString = cache.title;
params.unitString = data.rainunit;
params.valueColor = steelseries.ColorDef.BLUE;
params.valueGradient = cache.valGrad;
params.useValueGradient = gaugeGlobals.rainUseGradientColours;
params.useSectionColors = gaugeGlobals.rainUseSectionColour;
params.useSectionColors = gaugeGlobals.rainUseSectionColours;
params.labelNumberFormat = cache.labelNumberFormat;
params.fractionalScaleDecimals = cache.scaleDecimals;
params.niceScale = false;
ssGauge = new steelseries.RadialBargraph('canvas_rain', params);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_rain').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_rain').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
cache.value = extractDecimal(data.rfall);
if (data.rainunit === 'mm') { // 10, 20, 30...
cache.maxValue = Math.max(nextHighest(cache.value, 10), gaugeGlobals.rainScaleDefMaxmm);
} else {
// inches 0.5, 1.0, 2.0, 3.0 ... 10.0, 12.0, 14.0
if (cache.value <= 1) {
cache.maxValue = Math.max(nextHighest(cache.value, 0.5), gaugeGlobals.rainScaleDefMaxIn);
} else if (cache.value <= 6) {
cache.maxValue = Math.max(nextHighest(cache.value, 1), gaugeGlobals.rainScaleDefMaxIn);
} else {
cache.maxValue = Math.max(nextHighest(cache.value, 2), gaugeGlobals.rainScaleDefMaxIn);
}
cache.scaleDecimals = cache.maxValue < 1 ? 2 : 1;
}
if (cache.maxValue !== ssGauge.getMaxValue()) {
// Gauge scale is too low, increase it.
// First set the pointer back to zero so we get a nice animation
ssGauge.setValue(0);
// and redraw the gauge with the new scale
ssGauge.setFractionalScaleDecimals(cache.scaleDecimals);
ssGauge.setMaxValue(cache.maxValue);
}
ssGauge.setValueAnimated(cache.value);
if (ddimgtooltip.showTips) {
// update tooltip
$('#imgtip2_txt').html(strings.LastRain_info + ': ' + data.LastRained);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[2] !== null) {
$('#imgtip2_img').attr('src', config.imgPathURL + config.tipImgs[2] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Rainfall Rate Gauge
//
singleRRate = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define rain rate gauge start values
cache.maxMeasured = 0;
cache.maxValue = gaugeGlobals.rainRateScaleDefMaxmm;
cache.value = 0.0001;
cache.title = strings.rrate_title;
cache.lcdDecimals = 1;
cache.scaleDecimals = 0;
cache.labelNumberFormat = gaugeGlobals.labelFormat;
cache.sections = createRainRateSections(true);
// create rain rate radial gauge
if ($('#canvas_rrate').length) {
params.size = Math.ceil($('#canvas_rrate').width() * config.gaugeScaling);
params.section = cache.sections;
params.maxValue = cache.maxValue;
params.thresholdVisible = false;
params.maxMeasuredValueVisible = true;
params.titleString = cache.title;
params.unitString = data.rainunit + '/h';
params.lcdDecimals = cache.lcdDecimals;
params.labelNumberFormat = cache.labelNumberFormat;
params.fractionalScaleDecimals = cache.scaleDecimals;
params.niceScale = false;
ssGauge = new steelseries.Radial('canvas_rrate', params);
ssGauge.setMaxMeasuredValue(cache.maxMeasured);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_rrate').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_rrate').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
var tip;
cache.value = extractDecimal(data.rrate);
cache.maxMeasured = extractDecimal(data.rrateTM);
cache.overallMax = Math.max(cache.maxMeasured, cache.value); // workaround for VWS bug, not supplying correct max value today
if (data.rainunit === 'mm') { // 10, 20, 30...
cache.maxValue = nextHighest(cache.overallMax, 10);
} else {
// inches 0.5, 1.0, 2.0, 3.0 ... 10, 20, 30...
if (cache.overallMax <= 0.5) {
cache.maxValue = 0.5;
} else if (cache.overallMax <= 10) {
cache.maxValue = nextHighest(cache.overallMax, 1);
} else {
cache.maxValue = nextHighest(cache.overallMax, 10);
}
cache.scaleDecimals = cache.maxValue < 1 ? 2 : (cache.maxValue < 7 ? 1 : 0);
}
if (cache.maxValue !== ssGauge.getMaxValue()) {
ssGauge.setValue(0);
ssGauge.setFractionalScaleDecimals(cache.scaleDecimals);
ssGauge.setMaxValue(cache.maxValue);
}
ssGauge.setValueAnimated(cache.value);
ssGauge.setMaxMeasuredValue(cache.maxMeasured);
if (ddimgtooltip.showTips) {
// update tooltip
tip = strings.rrate_info + ':<br>' +
'- ' + strings.maximum_info + ': ' + data.rrateTM + ' ' + data.rainunit + '/h ' + strings.at + ' ' + data.TrrateTM +
' | ' + strings.max_hour_info + ': ' + extractDecimal(data.hourlyrainTH) + ' ' + data.rainunit + ' ' +
strings.at + ' ' + data.ThourlyrainTH;
$('#imgtip3_txt').html(tip);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[3] !== null) {
$('#imgtip3_img').attr('src', config.imgPathURL + config.tipImgs[3] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Humidity Gauge
//
singleHum = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define humidity gauge start values
cache.areas = [];
cache.value = 0.0001;
cache.title = strings.hum_title_out;
cache.selected = 'out';
// create humidity radial gauge
if ($('#canvas_hum').length) {
params.size = Math.ceil($('#canvas_hum').width() * config.gaugeScaling);
params.section = [
steelseries.Section(0, 20, 'rgba(255,255,0,0.3)'),
steelseries.Section(20, 80, 'rgba(0,255,0,0.3)'),
steelseries.Section(80, 100, 'rgba(255,0,0,0.3)')
];
params.area = cache.areas;
params.maxValue = 100;
params.thresholdVisible = false;
params.titleString = cache.title;
params.unitString = 'RH%';
ssGauge = new steelseries.Radial('canvas_hum', params);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_hum').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_hum').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
var radio;
// Argument length === 2 when called from event handler
if (arguments.length === 1) {
radio = arguments[0];
}
// if rad isn't specified, just use existing value
var sel = (typeof radio === 'undefined' ? cache.selected : radio.value),
tip;
if (sel === 'out') {
cache.value = extractDecimal(data.hum);
cache.areas = [steelseries.Section(+extractDecimal(data.humTL), +extractDecimal(data.humTH), gaugeGlobals.minMaxArea)];
cache.title = strings.hum_title_out;
cache.popupImg = 0;
} else {
cache.value = extractDecimal(data.inhum);
if (data.inhumTL && data.inhumTH) {
cache.areas = [steelseries.Section(+extractDecimal(data.inhumTL), +extractDecimal(data.inhumTH), gaugeGlobals.minMaxArea)];
} else {
cache.areas = [];
}
cache.title = strings.hum_title_in;
cache.popupImg = 1;
}
if (cache.selected !== sel) {
cache.selected = sel;
// Change gauge title
ssGauge.setTitleString(cache.title);
if (config.showPopupGraphs && config.tipImgs[4][cache.popupImg] !== null) {
var cacheDefeat = '?' + $('#imgtip4_img').attr('src').split('?')[1];
$('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][cache.popupImg] + cacheDefeat);
}
}
ssGauge.setArea(cache.areas);
ssGauge.setValueAnimated(cache.value);
if (ddimgtooltip.showTips) {
// update tooltip
if (cache.selected === 'out') {
tip = strings.hum_out_info + ':' +
'<br>' +
'- ' + strings.minimum_info + ': ' + extractDecimal(data.humTL) + '% ' + strings.at + ' ' + data.ThumTL +
' | ' + strings.maximum_info + ': ' + extractDecimal(data.humTH) + '% ' + strings.at + ' ' + data.ThumTH;
} else if (data.inhumTL && data.inhumTH) {
// we have indoor high/low data
tip = strings.hum_in_info + ':' +
'<br>' +
'- ' + strings.minimum_info + ': ' + extractDecimal(data.inhumTL) + '% ' + strings.at + ' ' + data.TinhumTL +
' | ' + strings.maximum_info + ': ' + extractDecimal(data.inhumTH) + '% ' + strings.at + ' ' + data.TinhumTH;
} else {
// no indoor high/low data
tip = strings.hum_in_info + ': ' + extractDecimal(data.inhum) + '%';
}
$('#imgtip4_txt').html(tip);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[4][cache.popupImg] !== null) {
$('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][cache.popupImg] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Barometer Gauge
//
singleBaro = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define pressure/barometer gauge start values
cache.sections = [];
cache.areas = [];
cache.minValue = gaugeGlobals.baroScaleDefMinhPa;
cache.maxValue = gaugeGlobals.baroScaleDefMaxhPa;
cache.value = cache.minValue + 0.0001;
cache.title = strings.baro_title;
cache.lcdDecimals = 1;
cache.scaleDecimals = 0;
cache.labelNumberFormat = gaugeGlobals.labelFormat;
// create pressure/barometric radial gauge
if ($('#canvas_baro').length) {
params.size = Math.ceil($('#canvas_baro').width() * config.gaugeScaling);
params.section = cache.sections;
params.area = cache.areas;
params.minValue = cache.minValue;
params.maxValue = cache.maxValue;
params.niceScale = false;
params.thresholdVisible = false;
params.titleString = cache.title;
params.unitString = data.pressunit;
params.lcdDecimals = cache.lcdDecimals;
params.trendVisible = gaugeGlobals.pressureTrendVisible;
params.labelNumberFormat = cache.labelNumberFormat;
params.fractionalScaleDecimals = cache.scaleDecimals;
ssGauge = new steelseries.Radial('canvas_baro', params);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_baro').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_baro').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
var tip, t1, dps;
cache.recLow = +extractDecimal(data.pressL);
cache.recHigh = +extractDecimal(data.pressH);
cache.todayLow = +extractDecimal(data.pressTL);
cache.todayHigh = +extractDecimal(data.pressTH);
cache.value = +extractDecimal(data.press);
// Convert the WD change over 3 hours to an hourly rate
cache.trendVal = +extractDecimal(data.presstrendval) / (config.weatherProgram === 2 ? 3 : 1);
if (data.pressunit === 'hPa' || data.pressunit === 'mb') {
// default min range 990-1030 - steps of 10 hPa
cache.minValue = Math.min(nextLowest(cache.recLow - 2, 10), gaugeGlobals.baroScaleDefMinhPa);
cache.maxValue = Math.max(nextHighest(cache.recHigh + 2, 10), gaugeGlobals.baroScaleDefMaxhPa);
dps = 1; // 1 decimal place
} else if (data.pressunit === 'kPa') {
// default min range 99-105 - steps of 1 kPa
cache.minValue = Math.min(nextLowest(cache.recLow - 0.2, 1), gaugeGlobals.baroScaleDefMinkPa);
cache.maxValue = Math.max(nextHighest(cache.recHigh + 0.2, 1), gaugeGlobals.baroScaleDefMaxkPa);
dps = 2;
} else {
// inHg: default min range 29.5-30.5 - steps of 0.5 inHg
cache.minValue = Math.min(nextLowest(cache.recLow - 0.1, 0.5), gaugeGlobals.baroScaleDefMininHg);
cache.maxValue = Math.max(nextHighest(cache.recHigh + 0.1, 0.5), gaugeGlobals.baroScaleDefMaxinHg);
dps = 3;
}
cache.trendValRnd = cache.trendVal.toFixed(dps);
cache.todayLowRnd = cache.todayLow.toFixed(dps);
cache.todayHighRnd = cache.todayHigh.toFixed(dps);
if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
ssGauge.setMinValue(cache.minValue);
ssGauge.setMaxValue(cache.maxValue);
ssGauge.setValue(cache.minValue);
}
if (cache.recHigh === cache.todayHigh && cache.recLow === cache.todayLow) {
// VWS does not provide record hi/lo values
cache.sections = [];
cache.areas = [steelseries.Section(cache.todayLow, cache.todayHigh, gaugeGlobals.minMaxArea)];
} else {
cache.sections = [
steelseries.Section(cache.minValue, cache.recLow, 'rgba(255,0,0,0.5)'),
steelseries.Section(cache.recHigh, cache.maxValue, 'rgba(255,0,0,0.5)')
];
cache.areas = [
steelseries.Section(cache.minValue, cache.recLow, 'rgba(255,0,0,0.5)'),
steelseries.Section(cache.recHigh, cache.maxValue, 'rgba(255,0,0,0.5)'),
steelseries.Section(cache.todayLow, cache.todayHigh, gaugeGlobals.minMaxArea)
];
}
if (gaugeGlobals.pressureTrendVisible) {
// Use the baroTrend rather than simple arithmetic test - steady is more/less than zero!
t1 = baroTrend(cache.trendVal, data.pressunit, false);
if (t1 === -9999) {
// trend value isn't currently available
cache.trend = steelseries.TrendState.OFF;
} else if (t1 > 0) {
cache.trend = steelseries.TrendState.UP;
} else if (t1 < 0) {
cache.trend = steelseries.TrendState.DOWN;
} else {
cache.trend = steelseries.TrendState.STEADY;
}
ssGauge.setTrend(cache.trend);
}
ssGauge.setArea(cache.areas);
ssGauge.setSection(cache.sections);
ssGauge.setValueAnimated(cache.value);
if (ddimgtooltip.showTips) {
// update tooltip
tip = strings.baro_info + ':' +
'<br>' +
'- ' + strings.minimum_info + ': ' + cache.todayLowRnd + ' ' + data.pressunit + ' ' + strings.at + ' ' + data.TpressTL +
' | ' + strings.maximum_info + ': ' + cache.todayHighRnd + ' ' + data.pressunit + ' ' + strings.at + ' ' + data.TpressTH;
if (cache.trendVal !== -9999) {
tip += '<br>' +
'- ' + strings.baro_trend_info + ': ' + baroTrend(cache.trendVal, data.pressunit, true) + ' ' +
(cache.trendValRnd > 0 ? '+' : '') + cache.trendValRnd + ' ' + data.pressunit + '/h';
}
$('#imgtip5_txt').html(tip);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[5] !== null) {
$('#imgtip5_img').attr('src', config.imgPathURL + config.tipImgs[5] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Wind Speed Gauge
//
singleWind = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define wind gauge start values
cache.maxValue = gaugeGlobals.windScaleDefMaxKph;
cache.areas = [];
cache.maxMeasured = 0;
cache.value = 0.0001;
cache.title = strings.wind_title;
// create wind speed radial gauge
if ($('#canvas_wind').length) {
params.size = Math.ceil($('#canvas_wind').width() * config.gaugeScaling);
params.area = cache.areas;
params.maxValue = cache.maxValue;
params.niceScale = false;
params.thresholdVisible = false;
params.maxMeasuredValueVisible = true;
params.titleString = cache.title;
params.unitString = data.windunit;
ssGauge = new steelseries.Radial('canvas_wind', params);
ssGauge.setMaxMeasuredValue(cache.maxMeasured);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_wind').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_wind').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
var tip;
cache.value = extractDecimal(data.wlatest);
cache.average = extractDecimal(data.wspeed);
cache.gust = extractDecimal(data.wgust);
cache.maxGustToday = extractDecimal(data.wgustTM);
cache.maxAvgToday = extractDecimal(data.windTM);
switch (data.windunit) {
case 'mph':
case 'kts':
cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 10), gaugeGlobals.windScaleDefMaxMph);
break;
case 'm/s':
cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 5), gaugeGlobals.windScaleDefMaxMs);
break;
default:
cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 20), gaugeGlobals.windScaleDefMaxKmh);
}
cache.areas = [
steelseries.Section(0, +cache.average, gaugeGlobals.windAvgArea),
steelseries.Section(+cache.average, +cache.gust, gaugeGlobals.minMaxArea)
];
if (cache.maxValue !== ssGauge.getMaxValue()) {
ssGauge.setValue(0);
ssGauge.setMaxValue(cache.maxValue);
}
ssGauge.setArea(cache.areas);
ssGauge.setMaxMeasuredValue(cache.maxGustToday);
ssGauge.setValueAnimated(cache.value);
if (ddimgtooltip.showTips) {
// update tooltip
tip = strings.tenminavgwind_info + ': ' + cache.average + ' ' + data.windunit + ' | ' +
strings.maxavgwind_info + ': ' + cache.maxAvgToday + ' ' + data.windunit + '<br>' +
strings.tenmingust_info + ': ' + cache.gust + ' ' + data.windunit + ' | ' +
strings.maxgust_info + ': ' + cache.maxGustToday + ' ' + data.windunit + ' ' +
strings.at + ' ' + data.TwgustTM + ' ' + strings.bearing_info + ': ' + data.bearingTM +
(isNaN(parseFloat(data.bearingTM)) ? '' : '° (' + getord(+data.bearingTM) + ')');
$('#imgtip6_txt').html(tip);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[6] !== null) {
$('#imgtip6_img').attr('src', config.imgPathURL + config.tipImgs[6] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(), // End of singleWind()
//
// Singleton for the Wind Direction Gauge
//
singleDir = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define wind direction gauge start values
cache.valueLatest = 0;
cache.valueAverage = 0;
cache.titles = [strings.latest_web, strings.tenminavg_web];
// create wind direction/compass radial gauge
if ($('#canvas_dir').length) {
params.size = Math.ceil($('#canvas_dir').width() * config.gaugeScaling);
params.pointerTypeLatest = gaugeGlobals.pointer; // default TYPE8,
params.pointerTypeAverage = gaugeGlobals.dirAvgPointer; // default TYPE8
params.pointerColorAverage = gaugeGlobals.dirAvgPointerColour;
params.degreeScale = true; // Show degree scale rather than ordinal directions
params.pointSymbols = strings.compass;
params.roseVisible = false;
params.lcdTitleStrings = cache.titles;
params.useColorLabels = false;
ssGauge = new steelseries.WindDirection('canvas_dir', params);
ssGauge.setValueAverage(+cache.valueAverage);
ssGauge.setValueLatest(+cache.valueLatest);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_dir').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_dir').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
var windSpd, windGst, range, tip, i,
rosePoints = 0,
roseMax = 0,
roseSectionAngle = 0,
roseAreas = [];
cache.valueLatest = extractInteger(data.bearing);
cache.valueAverage = extractInteger(data.avgbearing);
cache.bearingFrom = extractInteger(data.BearingRangeFrom10);
cache.bearingTo = extractInteger(data.BearingRangeTo10);
ssGauge.setValueAnimatedAverage(+cache.valueAverage);
if (cache.valueAverage === 0) {
cache.valueLatest = 0;
}
ssGauge.setValueAnimatedLatest(+cache.valueLatest);
if (config.showWindVariation) {
windSpd = +extractDecimal(data.wspeed);
windGst = +extractDecimal(data.wgust);
switch (data.windunit.toLowerCase()) {
case 'mph':
cache.avgKnots = 0.868976242 * windSpd;
cache.gstKnots = 0.868976242 * windGst;
break;
case 'kts':
cache.avgKnots = windSpd;
cache.gstKnots = windGst;
break;
case 'm/s':
cache.avgKnots = 1.94384449 * windSpd;
cache.gstKnots = 1.94384449 * windGst;
break;
case 'km/h':
cache.avgKnots = 0.539956803 * windSpd;
cache.gstKnots = 0.539956803 * windGst;
break;
// no default
}
cache.avgKnots = Math.round(cache.avgKnots);
cache.gstKnots = Math.round(cache.gstKnots);
if (config.showWindMetar) {
ssGauge.VRB = ' - METAR: ' + ('0' + data.avgbearing).slice(-3) + ('0' + cache.avgKnots).slice(-2) +
'G' + ('0' + cache.gstKnots).slice(-2) + 'KT ';
} else {
ssGauge.VRB = '';
}
if (windSpd > 0) {
// If variation less than 60 degrees, then METAR = Steady
// Unless range = 0 and from/to direction = avg + 180
range = (+cache.bearingTo < +cache.bearingFrom ? 360 + (+cache.bearingTo) : +cache.bearingTo) - (+cache.bearingFrom);
if (cache.avgKnots < 3) { // Europe uses 3kts, USA 6kts as the threshold
if (config.showRoseOnDirGauge) {
ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.windVariationSector)]);
ssGauge.setSection([]);
} else {
ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.minMaxArea)]);
ssGauge.setArea([]);
}
} else if (config.showRoseOnDirGauge) {
ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.windVariationSector)]);
} else {
ssGauge.setSection([]);
ssGauge.setArea([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.minMaxArea)]);
}
if (config.showWindMetar) {
if ((range < 60 && range > 0) || range === 0 && cache.bearingFrom === cache.valueAverage) {
ssGauge.VRB += ' STDY';
} else if (cache.avgKnots < 3) { // Europe uses 3kts, USA 6kts as the threshold
ssGauge.VRB += ' VRB';
} else {
ssGauge.VRB += ' ' + cache.bearingFrom + 'V' + cache.bearingTo;
}
}
} else {
// Zero wind speed, calm
if (config.showWindMetar) {
ssGauge.VRB = ' - METAR: 00000KT';
}
ssGauge.setSection([]);
if (!config.showRoseOnDirGauge) {
ssGauge.setArea([]);
}
}
} else {
ssGauge.VRB = '';
}
// optional rose data on direction gauge
if (config.showRoseOnDirGauge && data.WindRoseData) {
// Process rose data
rosePoints = data.WindRoseData.length;
roseSectionAngle = 360 / rosePoints;
// Find total for all directions
for (i = 0; i < rosePoints; i++) {
roseMax = Math.max(roseMax, data.WindRoseData[i]);
}
// Check we actually have some data, bad things happen if roseMax=0!
if (roseMax > 0) {
// Find relative value for each point, and create a gauge area for it
for (i = 0; i < rosePoints; i++) {
roseAreas[i] = steelseries.Section(
i * roseSectionAngle - roseSectionAngle / 2,
(i + 1) * roseSectionAngle - roseSectionAngle / 2,
'rgba(' + gradient('2020D0', 'D04040', data.WindRoseData[i] / roseMax) + ',' +
(data.WindRoseData[i] / roseMax).toFixed(2) + ')'
);
}
}
ssGauge.setArea(roseAreas);
}
if (ddimgtooltip.showTips) {
// update tooltip
tip = strings.latest_title + ' ' + strings.bearing_info + ': ' + cache.valueLatest + '° (' + getord(+cache.valueLatest) + ')' +
ssGauge.VRB + '<br>' + strings.tenminavg_web + ' ' + strings.bearing_info + ': ' + cache.valueAverage + '° (' +
getord(+cache.valueAverage) + '), ' + strings.dominant_bearing + ': ' + data.domwinddir;
if (!config.showRoseGauge) {
// Wind run is shown on the wind rose if it is available
tip += '<br>' + strings.windruntoday + ': ' + data.windrun + ' ' + displayUnits.windrun;
}
$('#imgtip7_txt').html(tip);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[7] !== null) {
$('#imgtip7_img').attr('src', config.imgPathURL + config.tipImgs[7] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Wind Rose Gauge
//
singleRose = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var buffers = {}; // Stores references to the various canvas buffers
var cache = {}; // various parameters to store for the life time of gauge
var ctxRoseCanvas; // 2D context for the plotted gauge
cache.firstRun = true;
cache.odoDigits = 5; // Total number of odometer digits including the decimal
function init() {
var div, roseCanvas;
// Get the context of the gauge canvas on the HTML page
if ($('#canvas_rose').length) {
cache.gaugeSize = Math.ceil($('#canvas_rose').width() * config.gaugeScaling);
cache.gaugeSize2 = cache.gaugeSize / 2;
cache.showOdo = config.showRoseGaugeOdo || false;
cache.compassStrings = strings.compass;
cache.titleString = strings.windrose;
cache.gaugeOdoTitle = strings.km;
// Create a hidden div to host the Rose plot
div = document.createElement('div');
div.style.display = 'none';
document.body.appendChild(div);
// Calcuate the size of the gauge background and so the size of rose plot required
cache.plotSize = Math.floor(cache.gaugeSize * 0.68);
cache.plotSize2 = cache.plotSize / 2;
// rose plot canvas buffer
buffers.plot = document.createElement('canvas');
buffers.plot.width = cache.plotSize;
buffers.plot.height = cache.plotSize;
buffers.plot.id = 'rosePlot';
buffers.ctxPlot = buffers.plot.getContext('2d');
div.appendChild(buffers.plot);
// Create a steelseries gauge frame
buffers.frame = document.createElement('canvas');
buffers.frame.width = cache.gaugeSize;
buffers.frame.height = cache.gaugeSize;
buffers.ctxFrame = buffers.frame.getContext('2d');
steelseries.drawFrame(
buffers.ctxFrame,
gaugeGlobals.frameDesign,
cache.gaugeSize2,
cache.gaugeSize2,
cache.gaugeSize,
cache.gaugeSize
);
// Create a steelseries gauge background
buffers.background = document.createElement('canvas');
buffers.background.width = cache.gaugeSize;
buffers.background.height = cache.gaugeSize;
buffers.ctxBackground = buffers.background.getContext('2d');
steelseries.drawBackground(
buffers.ctxBackground,
gaugeGlobals.background,
cache.gaugeSize2,
cache.gaugeSize2,
cache.gaugeSize,
cache.gaugeSize
);
// Optional - add a background image
/*
if (g_imgSmall !== null) {
var drawSize = g_size * 0.831775;
var x = (g_size - drawSize) / 2;
buffers.ctxBackground.drawImage(g_imgSmall, x, x, cache.gaugeSize, cache.gaugeSize);
}
*/
// Add the compass points
drawCompassPoints(buffers.ctxBackground, cache.gaugeSize);
// Create a steelseries gauge foreground
buffers.foreground = document.createElement('canvas');
buffers.foreground.width = cache.gaugeSize;
buffers.foreground.height = cache.gaugeSize;
buffers.ctxForeground = buffers.foreground.getContext('2d');
steelseries.drawForeground(
buffers.ctxForeground,
gaugeGlobals.foreground,
cache.gaugeSize,
cache.gaugeSize,
false
);
roseCanvas = document.getElementById('canvas_rose');
ctxRoseCanvas = roseCanvas.getContext('2d');
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_rose').css({width: cache.gaugeSize + 'px', height: cache.gaugeSize + 'px'});
}
// resize canvas on main page
roseCanvas.width = cache.gaugeSize;
roseCanvas.height = cache.gaugeSize;
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_rose').css(gaugeShadow(cache.gaugeSize));
}
// Render an empty gauge, looks better than just the shadow background and odometer ;)
// Paint the gauge frame
ctxRoseCanvas.drawImage(buffers.frame, 0, 0);
// Paint the gauge background
ctxRoseCanvas.drawImage(buffers.background, 0, 0);
// Paint the gauge foreground
ctxRoseCanvas.drawImage(buffers.foreground, 0, 0);
// Create an odometer
if (cache.showOdo) {
cache.odoHeight = Math.ceil(cache.gaugeSize * 0.08); // Sets the size of the odometer
cache.odoWidth = Math.ceil(Math.floor(cache.odoHeight * 0.68) * cache.odoDigits); // 'Magic' number, do not alter
// Create a new canvas for the oodometer
buffers.Odo = document.createElement('canvas');
$(buffers.Odo).attr({
id : 'canvas_odo',
width : cache.odoWidth,
height: cache.odoHeight
});
// Position it
$(buffers.Odo).attr('class', 'odo');
// Insert it into the DOM before the Rose gauge
$(buffers.Odo).insertBefore('#canvas_rose');
// Create the odometer
ssGauge = new steelseries.Odometer('canvas_odo', {
height : cache.odoHeight,
digits : cache.odoDigits - 1,
decimals: 1
});
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
cache.firstRun = false;
function update() {
var rose, offset;
if (ctxRoseCanvas && !cache.firstRun) {
// Clear the gauge
ctxRoseCanvas.clearRect(0, 0, cache.gaugeSize, cache.gaugeSize);
// Clear the existing rose plot
buffers.ctxPlot.clearRect(0, 0, cache.plotSize, cache.plotSize);
// Create a new rose plot
rose = new RGraph.Rose('rosePlot', data.WindRoseData);
rose.Set('chart.strokestyle', 'black');
rose.Set('chart.background.axes.color', 'gray');
rose.Set('chart.colors.alpha', 0.5);
rose.Set('chart.colors', ['Gradient(#408040:red:#7070A0)']);
rose.Set('chart.margin', Math.ceil(40 / data.WindRoseData.length));
rose.Set('chart.title', cache.titleString);
rose.Set('chart.title.size', Math.ceil(0.05 * cache.plotSize));
rose.Set('chart.title.bold', false);
rose.Set('chart.title.color', gaugeGlobals.background.labelColor.getRgbColor());
rose.Set('chart.gutter.top', 0.2 * cache.plotSize);
rose.Set('chart.gutter.bottom', 0.2 * cache.plotSize);
rose.Set('chart.tooltips.effect', 'snap');
rose.Set('chart.labels.axes', '');
rose.Set('chart.background.circles', true);
rose.Set('chart.background.grid.spokes', 16);
rose.Set('chart.radius', cache.plotSize2);
rose.Draw();
// Add title to windrun odometer to the plot
if (cache.showOdo) {
drawOdoTitle(buffers.ctxPlot);
}
// Paint the gauge frame
ctxRoseCanvas.drawImage(buffers.frame, 0, 0);
// Paint the gauge background
ctxRoseCanvas.drawImage(buffers.background, 0, 0);
// Paint the rose plot
offset = Math.floor(cache.gaugeSize2 - cache.plotSize2);
ctxRoseCanvas.drawImage(buffers.plot, offset, offset);
// Paint the gauge foreground
ctxRoseCanvas.drawImage(buffers.foreground, 0, 0);
// update the odometer
if (cache.showOdo) {
ssGauge.setValueAnimated(extractDecimal(data.windrun));
}
// update tooltip
if (ddimgtooltip.showTips) {
$('#imgtip10_txt').html(
strings.dominant_bearing + ': ' + data.domwinddir + '<br>' +
strings.windruntoday + ': ' + data.windrun + ' ' + displayUnits.windrun
);
}
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[10] !== null) {
$('#imgtip10_img').attr('src', config.imgPathURL + config.tipImgs[10] + cacheDefeat);
}
}
// Helper function to put the compass points on the background
function drawCompassPoints(ctx, size) {
ctx.save();
// set the font
ctx.font = 0.08 * size + 'px serif';
ctx.strokeStyle = gaugeGlobals.background.labelColor.getRgbaColor();
ctx.fillStyle = gaugeGlobals.background.labelColor.getRgbColor();
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// Draw the compass points
for (var i = 0; i < 4; i++) {
ctx.translate(size / 2, size * 0.125);
ctx.fillText(cache.compassStrings[i * 2], 0, 0, size);
ctx.translate(-size / 2, -size * 0.125);
// Move to center
ctx.translate(size / 2, size / 2);
ctx.rotate(Math.PI / 2);
ctx.translate(-size / 2, -size / 2);
}
ctx.restore();
}
function drawOdoTitle(ctx) {
ctx.save();
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = 0.05 * cache.gaugeSize + 'px Arial,Verdana,sans-serif';
ctx.strokeStyle = gaugeGlobals.background.labelColor.getRgbaColor();
ctx.fillStyle = gaugeGlobals.background.labelColor.getRgbaColor();
ctx.fillText(cache.gaugeOdoTitle, cache.plotSize2, cache.plotSize * 0.75, cache.plotSize * 0.5);
ctx.restore();
}
function setTitle(newTitle) {
cache.titleString = newTitle;
}
function setOdoTitle(newTitle) {
cache.gaugeOdoTitle = newTitle;
}
function setCompassStrings(newArray) {
cache.compassStrings = newArray;
if (!cache.firstRun) {
// Redraw the background
steelseries.drawBackground(
buffers.ctxBackground,
gaugeGlobals.background,
cache.gaugeSize2,
cache.gaugeSize2,
cache.gaugeSize,
cache.gaugeSize
);
// Add the compass points
drawCompassPoints(buffers.ctxBackground, cache.gaugeSize);
}
}
return {
update : update,
gauge : ssGauge,
drawCompassPoints: drawCompassPoints,
setTitle : setTitle,
setCompassStrings: setCompassStrings,
setOdoTitle : setOdoTitle
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the UV-Index Gauge
//
singleUV = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define UV start values
cache.value = 0.0001;
cache.sections = [
steelseries.Section(0, 2.9, '#289500'),
steelseries.Section(2.9, 5.8, '#f7e400'),
steelseries.Section(5.8, 7.8, '#f85900'),
steelseries.Section(7.8, 10.9, '#d8001d'),
steelseries.Section(10.9, 20, '#6b49c8')
];
// Define value gradient for UV
cache.gradient = new steelseries.gradientWrapper(0, 16,
[0, 0.1, 0.19, 0.31, 0.45, 0.625, 1],
[
new steelseries.rgbaColor(0, 200, 0, 1),
new steelseries.rgbaColor(0, 200, 0, 1),
new steelseries.rgbaColor(255, 255, 0, 1),
new steelseries.rgbaColor(248, 89, 0, 1),
new steelseries.rgbaColor(255, 0, 0, 1),
new steelseries.rgbaColor(255, 0, 144, 1),
new steelseries.rgbaColor(153, 140, 255, 1)
]
);
cache.useSections = false;
cache.useValueGradient = true;
// create UV bargraph gauge
if ($('#canvas_uv').length) {
params.size = Math.ceil($('#canvas_uv').width() * config.gaugeScaling);
params.gaugeType = steelseries.GaugeType.TYPE3;
params.maxValue = gaugeGlobals.uvScaleDefMax;
params.titleString = strings.uv_title;
params.niceScale = false;
params.section = cache.sections;
params.useSectionColors = cache.useSections;
params.valueGradient = cache.gradient;
params.useValueGradient = cache.useValueGradient;
params.lcdDecimals = gaugeGlobals.uvLcdDecimals;
ssGauge = new steelseries.RadialBargraph('canvas_uv', params);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_uv').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_uv').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
var tip, indx;
cache.value = extractDecimal(data.UV);
if (+cache.value === 0) {
indx = 0;
} else if (cache.value < 2.5) {
indx = 1;
} else if (cache.value < 5.5) {
indx = 2;
} else if (cache.value < 7.5) {
indx = 3;
} else if (cache.value < 10.5) {
indx = 4;
} else {
indx = 5;
}
cache.maxValue = Math.max(nextHighest(cache.value, 2), gaugeGlobals.uvScaleDefMax);
if (cache.maxValue !== ssGauge.getMaxValue()) {
ssGauge.setValue(0);
ssGauge.setMaxValue(cache.maxValue);
}
cache.risk = strings.uv_levels[indx];
cache.headLine = strings.uv_headlines[indx];
cache.detail = strings.uv_details[indx];
ssGauge.setUnitString(cache.risk);
ssGauge.setValueAnimated(cache.value);
if (ddimgtooltip.showTips) {
// update tooltip
tip = '<b>' + strings.uv_title + ': ' + cache.value + '</b> - <i>' + strings.solar_maxToday + ': ' + data.UVTH + '</i><br>';
tip += '<i>' + cache.headLine + '</i><br>';
tip += cache.detail;
$('#imgtip8_txt').html(tip);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[8] !== null) {
$('#imgtip8_img').attr('src', config.imgPathURL + config.tipImgs[8] + cacheDefeat);
}
}
return {
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Solar Irradiation Gauge
//
singleSolar = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
// define Solar start values
cache.value = 0.0001;
cache.sections = [
steelseries.Section(0, 600, 'rgba(40,149,0,0.3)'),
steelseries.Section(600, 800, 'rgba(248,89,0,0.3)'),
steelseries.Section(800, 1000, 'rgba(216,0,29,0.3)'),
steelseries.Section(1000, 1800, 'rgba(107,73,200,0.3)')
];
// create Solar gauge
if ($('#canvas_solar').length) {
params.size = Math.ceil($('#canvas_solar').width() * config.gaugeScaling);
params.section = cache.sections;
params.maxValue = gaugeGlobals.solarGaugeScaleMax;
params.titleString = strings.solar_title;
params.unitString = 'W/m\u00B2';
params.niceScale = false;
params.thresholdVisible = false;
params.lcdDecimals = 0;
if (config.showSunshineLed) {
params.userLedVisible = true;
params.userLedColor = steelseries.LedColor.YELLOW_LED;
}
ssGauge = new steelseries.Radial('canvas_solar', params);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_solar').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_solar').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
var tip, percent;
cache.value = +extractInteger(data.SolarRad);
cache.maxToday = extractInteger(data.SolarTM);
cache.currMaxValue = +extractInteger(data.CurrentSolarMax);
percent = (+cache.currMaxValue === 0 ? '--' : Math.round(+cache.value / +cache.currMaxValue * 100));
// Need to rescale the gauge?
cache.maxValue = Math.max(cache.value, cache.currMaxValue, cache.maxToday, gaugeGlobals.solarGaugeScaleMax);
cache.maxValue = nextHighest(cache.maxValue, 100);
if (cache.maxValue !== ssGauge.getMaxValue()) {
ssGauge.setValue(0);
ssGauge.setMaxValue(cache.maxValue);
}
// Set a section (15% of maxScale wide) to show current theoretical max value
if (data.CurrentSolarMax !== 'N/A') {
ssGauge.setArea([
// Sunshine threshold
steelseries.Section(
Math.max(cache.currMaxValue * gaugeGlobals.sunshineThresholdPct / 100, gaugeGlobals.sunshineThreshold),
cache.currMaxValue,
'rgba(255,255,50,0.4)'
),
// Over max threshold
steelseries.Section(
cache.currMaxValue,
Math.min(cache.currMaxValue + cache.maxValue * 0.15, cache.maxValue),
'rgba(220,0,0,0.5)'
)
]);
}
// Set the values
ssGauge.setMaxMeasuredValue(cache.maxToday);
ssGauge.setValueAnimated(cache.value);
if (config.showSunshineLed) {
ssGauge.setUserLedOnOff(
percent !== '--' &&
percent >= gaugeGlobals.sunshineThresholdPct &&
+cache.value >= gaugeGlobals.sunshineThreshold
);
}
if (ddimgtooltip.showTips) {
// update tooltip
tip = '<b>' + strings.solar_title + ': ' + cache.value + ' W/m²</b> - ' +
'<i>' + percent + '% ' + strings.solar_ofMax + '</i><br>' +
strings.solar_currentMax + ': ' + cache.currMaxValue + ' W/m²';
if (typeof data.SolarTM !== 'undefined') {
tip += '<br>' + strings.solar_maxToday + ': ' + cache.maxToday + ' W/m²';
}
$('#imgtip9_txt').html(tip);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[9] !== null) {
$('#imgtip9_img').attr('src', config.imgPathURL + config.tipImgs[9] + cacheDefeat);
}
}
return {
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// Singleton for the Cloudbase Gauge
//
singleCloudBase = (function () {
var instance; // Stores a reference to the Singleton
var ssGauge; // Stores a reference to the SS Gauge
var cache = {}; // Stores various config values and parameters
function init() {
var params = $.extend(true, {}, commonParams);
cache.sections = createCloudBaseSections(true);
cache.value = 0.0001;
cache.maxValue = gaugeGlobals.cloudScaleDefMaxm;
// create Cloud base radial gauge
if ($('#canvas_cloud').length) {
params.size = Math.ceil($('#canvas_cloud').width() * config.gaugeScaling);
params.section = cache.sections;
params.maxValue = cache.maxValue;
params.titleString = strings.cloudbase_title;
params.unitString = strings.metres;
params.thresholdVisible = false;
params.lcdDecimals = 0;
ssGauge = new steelseries.Radial('canvas_cloud', params);
ssGauge.setValue(cache.value);
// over-ride CSS applied size?
if (config.gaugeScaling !== 1) {
$('#canvas_cloud').css({width: params.size + 'px', height: params.size + 'px'});
}
// add a shadow to the gauge
if (config.showGaugeShadow) {
$('#canvas_cloud').css(gaugeShadow(params.size));
}
// subscribe to data updates
$.subscribe('gauges.dataUpdated', update);
$.subscribe('gauges.graphUpdate', updateGraph);
} else {
// cannot draw gauge, return null
return null;
}
function update() {
cache.value = extractInteger(data.cloudbasevalue);
if (data.cloudbaseunit === 'm') {
// adjust metre gauge in jumps of 1000 metres, don't downscale during the session
cache.maxValue = Math.max(nextHighest(cache.value, 1000), gaugeGlobals.cloudScaleDefMaxm, cache.maxValue);
if (cache.value <= 1000 && config.roundCloudbaseVal) {
// and round the value to the nearest 10 m
cache.value = Math.round(cache.value / 10) * 10;
} else if (config.roundCloudbaseVal) {
// and round the value to the nearest 50 m
cache.value = Math.round(cache.value / 50) * 50;
}
} else {
// adjust feet gauge in jumps of 2000 ft, don't downscale during the session
cache.maxValue = Math.max(nextHighest(cache.value, 2000), gaugeGlobals.cloudScaleDefMaxft, cache.maxValue);
if (cache.value <= 2000 && config.roundCloudbaseVal) {
// and round the value to the nearest 50 ft
cache.value = Math.round(cache.value / 50) * 50;
} else if (config.roundCloudbaseVal) {
// and round the value to the nearest 100 ft
cache.value = Math.round(cache.value / 100) * 100;
}
}
if (cache.maxValue !== ssGauge.getMaxValue()) {
if (ssGauge.getMaxValue() > cache.maxValue) {
// Gauge currently showing more than our max (nice scale effct),
// so reset our max to match
cache.maxValue = ssGauge.getMaxValue();
} else {
// Gauge scale is too low, increase it.
// First set the pointer back to zero so we get a nice animation
ssGauge.setValue(0);
// and redraw the gauge with teh new scale
ssGauge.setMaxValue(cache.maxValue);
}
}
ssGauge.setValueAnimated(cache.value);
if (config.showPopupData) {
// static tooltip on cloud gauge
$('#imgtip11_txt').html('<strong>' + strings.cloudbase_popup_title + '</strong><br>' + strings.cloudbase_popup_text);
}
} // End of update()
function updateGraph(evnt, cacheDefeat) {
if (config.tipImgs[11] !== null) {
$('#imgtip11_img').attr('src', config.imgPathURL + config.tipImgs[11] + cacheDefeat);
}
}
return {
data : cache,
update: update,
gauge : ssGauge
};
} // End of init()
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
};
})(),
//
// getRealtime() fetches the realtimegauges JSON data from the server
//
getRealtime = function () {
var url = config.realTimeURL;
if ($.active > 0 && undefined != jqXHR) {
// kill any outstanding requests
jqXHR.abort();
}
if (config.longPoll) {
url += '?timestamp=' + timestamp;
}
jqXHR = $.ajax({
url : url,
cache : (config.longPoll),
dataType: 'json',
timeout : config.longPoll ? (Math.min(config.realtimeInterval, 20) + 21) * 1000 : 21000 // 21 second time-out by default
}).done(function (data) {
checkRtResp(data);
}).fail(function (xhr, status, err) {
checkRtError(xhr, status, err);
});
},
//
// checkRtResp() called by the Ajax fetch once data has been downloaded
//
checkRtResp = function (response) {
var delay;
statusTimer.reset(config.longPoll ? 1 : config.realtimeInterval);
if (config.longPoll && response.status !== 'OK') {
checkRtError(null, 'PHP Error', response.status);
} else {
if (processData(response)) {
delay = ajaxDelay;
} else {
delay = 5;
}
if (delay > 0) {
downloadTimer = setTimeout(getRealtime, delay * 1000);
} else {
getRealtime();
}
}
},
//
// checkRtError() called by the Ajax fetch if an error occurs during the fetching realtimegauges.txt
//
checkRtError = function (xhr, status, error) {
if (xhr == null || xhr.statusText !== 'abort') {
// Clear any existing download timer
clearTimeout(downloadTimer);
// Set the status LED to off
ledIndicator.setLedOnOff(false);
ledIndicator.setTitle(strings.led_title_unknown);
statusScroller.setText(status + ': ' + error);
// wait 5 seconds, then try again...
downloadTimer = setTimeout(getRealtime, 5000);
}
},
//
// processData() massages the data returned in realtimegauges.txt, and posts a gauges.dataUpdated event to update the page
//
processData = function (dataObj) {
var str, dt, tm, today, now, then, tmp, elapsedMins, retVal;
// copy the realtime fields into the global 'data' object
if (config.longPoll) {
timestamp = dataObj.timestamp;
data = dataObj.data;
} else {
// normal polling
data = dataObj;
}
// and check we have the expected version number
if (typeof data.ver !== 'undefined' && data.ver >= realtimeVer) {
// manpulate the last rain time into something more friendly
try {
str = data.LastRainTipISO.split(' ');
dt = str[0].replace(/\//g, '-').split('-'); // WD uses dd/mm/yyyy, we use a '-'
tm = str[1].split(':');
today = new Date();
today.setHours(0, 0, 0, 0);
if (typeof data.dateFormat === 'undefined') {
data.dateFormat = 'y/m/d';
} else {
// frig for WD bug which leaves a trailing % character from the tag
data.dateFormat = data.dateFormat.replace('%', '');
}
if (data.dateFormat === 'y/m/d') {
// ISO/Cumulus format
then = new Date(dt[0], dt[1] - 1, dt[2], tm[0], tm[1], 0, 0);
} else if (data.dateFormat === 'd/m/y') {
then = new Date(dt[2], dt[1] - 1, dt[0], tm[0], tm[1], 0, 0);
} else { // m/d/y
then = new Date(dt[2], dt[0] - 1, dt[1], tm[0], tm[1], 0, 0);
}
if (then.getTime() >= today.getTime()) {
data.LastRained = strings.LastRainedT_info + ' ' + str[1];
} else if (then.getTime() + 86400000 >= today.getTime()) {
data.LastRained = strings.LastRainedY_info + ' ' + str[1];
} else {
data.LastRained = then.getDate().toString() + ' ' + strings.months[then.getMonth()] + ' ' + strings.at + ' ' + str[1];
}
} catch (e) {
data.LastRained = data.LastRainTipISO;
}
if (data.tempunit.length > 1) {
// clean up temperature units - remove html encoded degree symbols
data.tempunit = data.tempunit.replace(/&\S*;/, '°'); // old Cumulus versions uses &deg;, WeatherCat uses &#176;
} else {
// using new realtimegaugesT.txt with Cumulus > 1.9.2
data.tempunit = '°' + data.tempunit;
}
// Check for station off-line
now = Date.now();
tmp = data.timeUTC.split(',');
sampleDate = Date.UTC(tmp[0], tmp[1] - 1, tmp[2], tmp[3], tmp[4], tmp[5]);
if (now - sampleDate > config.stationTimeout * 60 * 1000) {
elapsedMins = Math.floor((now - sampleDate) / (1000 * 60));
// the realtimegauges.txt file isn't being updated
ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
ledIndicator.setTitle(strings.led_title_offline);
ledIndicator.blink(true);
if (elapsedMins < 120) {
// up to 2 hours ago
tm = elapsedMins.toString() + ' ' + strings.StatusMinsAgo;
} else if (elapsedMins < 2 * 24 * 60) {
// up to 48 hours ago
tm = Math.floor(elapsedMins / 60).toString() + ' ' + strings.StatusHoursAgo;
} else {
// days ago!
tm = Math.floor(elapsedMins / (60 * 24)).toString() + ' ' + strings.StatusDaysAgo;
}
data.forecast = strings.led_title_offline + ' ' + strings.StatusLastUpdate + ' ' + tm;
} else if (+data.SensorContactLost === 1) {
// Fine Offset sensor status
ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
ledIndicator.setTitle(strings.led_title_lost);
ledIndicator.blink(true);
data.forecast = strings.led_title_lost;
} else {
ledIndicator.setLedColor(steelseries.LedColor.GREEN_LED);
ledIndicator.setTitle(strings.led_title_ok + '. ' + strings.StatusLastUpdate + ': ' + data.date);
ledIndicator.blink(false);
ledIndicator.setLedOnOff(true);
}
// de-encode the forecast string if required (Cumulus support for extended characters)
data.forecast = $('<div/>').html(data.forecast).text();
data.forecast = data.forecast.trim();
data.pressunit = data.pressunit.trim(); // WView sends ' in', ' mb', or ' hPa'
if (data.pressunit === 'in') { // Cumulus and WView send 'in'
data.pressunit = 'inHg';
}
data.windunit = data.windunit.trim(); // WView sends ' kmh' etc
data.windunit = data.windunit.toLowerCase(); // WeatherCat sends "MPH"
if (data.windunit === 'knots') { // WeatherCat/weewx send "Knots", we use "kts"
data.windunit = 'kts';
}
if (data.windunit === 'kmh' || data.windunit === 'kph') { // WD wind unit omits '/', weewx sends 'kph'
data.windunit = 'km/h';
}
data.rainunit = data.rainunit.trim(); // WView sends ' mm' etc
// take a look at the cloud base data...
// change WeatherCat units from Metres/Feet to m/ft
try {
if (data.cloudbaseunit.toLowerCase() === 'metres') {
data.cloudbaseunit = 'm';
} else if (data.cloudbaseunit.toLowerCase() === 'feet') {
data.cloudbaseunit = 'ft';
}
} catch (e) {
data.cloudbaseunit = '';
}
if (config.showCloudGauge && (
(config.weatherProgram === 4 || config.weatherProgram === 5) ||
data.cloudbasevalue === '')) {
// WeatherCat and VWS (and WView?) do not provide a cloud base value, so we have to calculate it...
// assume if the station uses an imperial wind speed they want cloud base in feet, otherwise metres
data.cloudbaseunit = (data.windunit === 'mph' || data.windunit === 'kts') ? 'ft' : 'm';
data.cloudbasevalue = calcCloudbase(data.temp, data.tempunit, data.dew, data.cloudbaseunit);
}
// Temperature data conversion for display required?
if (data.tempunit[1] !== displayUnits.temp && userUnitsSet) {
// temp needs converting
if (data.tempunit[1] === 'C') {
convTempData(c2f);
} else {
convTempData(f2c);
}
} else if (firstRun) {
displayUnits.temp = data.tempunit[1];
setRadioCheck('rad_unitsTemp', displayUnits.temp);
}
// Rain data conversion for display required?
if (data.rainunit !== displayUnits.rain && userUnitsSet) {
// rain needs converting
convRainData(displayUnits.rain === 'mm' ? in2mm : mm2in);
} else if (firstRun) {
displayUnits.rain = data.rainunit;
setRadioCheck('rad_unitsRain', displayUnits.rain);
}
// Wind data conversion for display required?
if (data.windunit !== displayUnits.wind && userUnitsSet) {
// wind needs converting
convWindData(data.windunit, displayUnits.wind);
} else if (firstRun) {
displayUnits.wind = data.windunit;
displayUnits.windrun = getWindrunUnits(data.windunit);
setRadioCheck('rad_unitsWind', displayUnits.wind);
}
// Pressure data conversion for display required?
if (data.pressunit !== displayUnits.press && userUnitsSet) {
convBaroData(data.pressunit, displayUnits.press);
} else if (firstRun) {
displayUnits.press = data.pressunit;
setRadioCheck('rad_unitsPress', displayUnits.press);
}
// Cloud height data conversion for display required?
if (data.cloudbaseunit !== displayUnits.cloud && userUnitsSet) {
// Cloud height needs converting
convCloudBaseData(displayUnits.cloud === 'm' ? ft2m : m2ft);
} else if (firstRun) {
displayUnits.cloud = data.cloudbaseunit;
setRadioCheck('rad_unitsCloud', displayUnits.cloud);
}
statusScroller.setText(data.forecast);
// first time only, setup units etc
if (firstRun) {
doFirst();
}
// publish the update, use the shared data object rather than transferring it
$.publish('gauges.dataUpdated', {});
retVal = true;
} else {
// set an error message
if (data.ver < realtimeVer) {
statusTimer.setValue(0);
statusScroller.setText('Your ' + config.realTimeURL.substr(config.realTimeURL.lastIndexOf('/') + 1) + ' file template needs updating!');
return false;
} else {
// oh-oh! The number of data fields isn't what we expected
statusScroller.setText(strings.realtimeCorrupt);
}
ledIndicator.setLedOnOff(false);
ledIndicator.setTitle(strings.led_title_unknown);
retVal = false;
}
return retVal;
},
//
// pagetimeout() called once every config.pageUpdateLimit minutes to stop updates and prevent page 'sitters'
//
pageTimeout = function () {
statusScroller.setText(strings.StatusPageLimit);
ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
ledIndicator.setTitle(strings.StatusPageLimit);
ledIndicator.blink(true);
ledIndicator.setTitle(strings.StatusTimeout);
// stop any pending download
clearTimeout(downloadTimer);
// stop any long polling in progress
if ($.active > 0) {
jqXHR.abort();
}
// stop the clock
clearInterval(tickTockInterval);
// clear the timer display
statusTimer.setValue(0);
// set an onclick event on the LED to restart everything
$('#canvas_led').click(
function click() {
// disable the onClick event again
$('#canvas_led').unbind('click');
// reset the timer count to 1
statusTimer.reset(1);
// restart the timer to update the status time
tickTockInterval = setInterval(
function tick() {
$.publish('gauges.clockTick', null);
},
1000
);
// restart the page timeout timer, so we hit this code again
setTimeout(pageTimeout, config.pageUpdateLimit * 60 * 1000);
// refresh the page data
getRealtime();
}
);
},
//
// doFirst() called by doUpdate() the first time the page is updated to set-up various things that are
// only known when the realtimegauges.txt data is available
//
doFirst = function () {
var cacheDefeat = '?' + (new Date()).getTime().toString();
if (data.tempunit[1] === 'F') {
displayUnits.temp = 'F';
setRadioCheck('rad_unitsTemp', 'F');
setTempUnits(false);
}
if (data.pressunit !== 'hPa') {
displayUnits.press = data.pressunit;
setRadioCheck('rad_unitsPress', data.pressunit);
setBaroUnits(data.pressunit);
}
if (data.windunit !== 'km/h') {
displayUnits.wind = data.windunit;
setRadioCheck('rad_unitsWind', data.windunit);
setWindUnits(data.windunit);
}
if (data.rainunit !== 'mm') {
displayUnits.rain = data.rainunit;
setRadioCheck('rad_unitsRain', data.rainunit);
setRainUnits(false);
}
if (config.showSolarGauge && typeof data.SolarTM !== 'undefined' && gaugeSolar) {
gaugeSolar.gauge.setMaxMeasuredValueVisible(true);
}
if (config.showCloudGauge && data.cloudbaseunit !== 'm') {
displayUnits.cloud = data.cloudbaseunit;
setRadioCheck('rad_unitsCloud', data.cloudbaseunit);
setCloudBaseUnits(false);
}
// set the script version on the page
$('#scriptVer').html(config.scriptVer);
// set the version information from the station
$('#programVersion').html(data.version);
$('#programBuild').html(data.build);
$('#programName').html(programLink[config.weatherProgram]);
if (config.showPopupData) {
// now initialise the pop-up script and download the trend images
// - has to be done here as doFirst may remove elements from the page
// - and we delay the download of the images speeding up page display
ddimgtooltip.init('[id^="tip_"]');
// Are we running on a phone device (or really low res screen)?
if ($(window).width() < 480) {
$('.ddimgtooltip').filter(':hidden').width('200px');
}
}
if (config.showPopupData && config.showPopupGraphs) {
// now download the trend images
// - has to be done here as doFirst may remove elements from the page
// - and we delay the download of the images speeding up page display
//
$('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][0] + cacheDefeat);
if (gaugeDew) {
$('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][gaugeDew.data.popupImg] + cacheDefeat);
}
$('#imgtip2_img').attr('src', config.imgPathURL + config.tipImgs[2] + cacheDefeat);
$('#imgtip3_img').attr('src', config.imgPathURL + config.tipImgs[3] + cacheDefeat);
$('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][0] + cacheDefeat);
$('#imgtip5_img').attr('src', config.imgPathURL + config.tipImgs[5] + cacheDefeat);
$('#imgtip6_img').attr('src', config.imgPathURL + config.tipImgs[6] + cacheDefeat);
$('#imgtip7_img').attr('src', config.imgPathURL + config.tipImgs[7] + cacheDefeat);
$('#imgtip8_img').attr('src', config.imgPathURL + config.tipImgs[8] + cacheDefeat);
$('#imgtip9_img').attr('src', config.imgPathURL + config.tipImgs[9] + cacheDefeat);
$('#imgtip10_img').attr('src', config.imgPathURL + config.tipImgs[10] + cacheDefeat);
$('#imgtip11_img').attr('src', config.imgPathURL + config.tipImgs[11] + cacheDefeat);
// start a timer for popup graphic updates
setInterval(
function timeout() {
$.publish('gauges.graphUpdate', '?' + (new Date()).getTime().toString());
},
config.graphUpdateTime * 60 * 1000
);
}
firstRun = false;
},
//
// createTempSections() creates an array of gauge sections appropriate for Celsius or Fahrenheit scales
//
createTempSections = function (celsius) {
var section;
if (celsius) {
section = [
steelseries.Section(-100, -35, 'rgba(195, 92, 211, 0.4)'),
steelseries.Section(-35, -30, 'rgba(139, 74, 197, 0.4)'),
steelseries.Section(-30, -25, 'rgba(98, 65, 188, 0.4)'),
steelseries.Section(-25, -20, 'rgba(62, 66, 185, 0.4)'),
steelseries.Section(-20, -15, 'rgba(42, 84, 194, 0.4)'),
steelseries.Section(-15, -10, 'rgba(25, 112, 210, 0.4)'),
steelseries.Section(-10, -5, 'rgba(9, 150, 224, 0.4)'),
steelseries.Section(-5, 0, 'rgba(2, 170, 209, 0.4)'),
steelseries.Section(0, 5, 'rgba(0, 162, 145, 0.4)'),
steelseries.Section(5, 10, 'rgba(0, 158, 122, 0.4)'),
steelseries.Section(10, 15, 'rgba(54, 177, 56, 0.4)'),
steelseries.Section(15, 20, 'rgba(111, 202, 56, 0.4)'),
steelseries.Section(20, 25, 'rgba(248, 233, 45, 0.4)'),
steelseries.Section(25, 30, 'rgba(253, 142, 42, 0.4)'),
steelseries.Section(30, 40, 'rgba(236, 45, 45, 0.4)'),
steelseries.Section(40, 100, 'rgba(245, 109, 205, 0.4)')
];
} else {
section = [
steelseries.Section(-200, -30, 'rgba(195, 92, 211, 0.4)'),
steelseries.Section(-30, -25, 'rgba(139, 74, 197, 0.4)'),
steelseries.Section(-25, -15, 'rgba(98, 65, 188, 0.4)'),
steelseries.Section(-15, -5, 'rgba(62, 66, 185, 0.4)'),
steelseries.Section(-5, 5, 'rgba(42, 84, 194, 0.4)'),
steelseries.Section(5, 15, 'rgba(25, 112, 210, 0.4)'),
steelseries.Section(15, 25, 'rgba(9, 150, 224, 0.4)'),
steelseries.Section(25, 32, 'rgba(2, 170, 209, 0.4)'),
steelseries.Section(32, 40, 'rgba(0, 162, 145, 0.4)'),
steelseries.Section(40, 50, 'rgba(0, 158, 122, 0.4)'),
steelseries.Section(50, 60, 'rgba(54, 177, 56, 0.4)'),
steelseries.Section(60, 70, 'rgba(111, 202, 56, 0.4)'),
steelseries.Section(70, 80, 'rgba(248, 233, 45, 0.4)'),
steelseries.Section(80, 90, 'rgba(253, 142, 42, 0.4)'),
steelseries.Section(90, 110, 'rgba(236, 45, 45, 0.4)'),
steelseries.Section(110, 200, 'rgba(245, 109, 205, 0.4)')
];
}
return section;
},
//
// createRainSections() returns an array of section highlights for the Rain Rate gauge
//
/*
Assumes 'standard' descriptive limits from UK met office:
< 0.25 mm/hr - Very light rain
0.25mm/hr to 1.0mm/hr - Light rain
1.0 mm/hr to 4.0 mm/hr - Moderate rain
4.0 mm/hr to 16.0 mm/hr - Heavy rain
16.0 mm/hr to 50 mm/hr - Very heavy rain
> 50.0 mm/hour - Extreme rain
Roughly translated to the corresponding Inch rates
< 0.001
0.001 to 0.05
0.05 to 0.20
0.20 to 0.60
0.60 to 2.0
> 2.0
*/
createRainRateSections = function (metric) {
var factor = metric ? 1 : 1 / 25;
return [
steelseries.Section(0, 0.25 * factor, 'rgba(0, 140, 0, 0.5)'),
steelseries.Section(0.25 * factor, 1 * factor, 'rgba(80, 192, 80, 0.5)'),
steelseries.Section(1 * factor, 4 * factor, 'rgba(150, 203, 150, 0.5)'),
steelseries.Section(4 * factor, 16 * factor, 'rgba(212, 203, 109, 0.5)'),
steelseries.Section(16 * factor, 50 * factor, 'rgba(225, 155, 105, 0.5)'),
steelseries.Section(50 * factor, 1000 * factor, 'rgba(245, 86, 59, 0.5)')
];
},
//
// createRainFallSections()returns an array of section highlights for total rainfall in mm or inches
//
createRainfallSections = function (metric) {
var factor = metric ? 1 : 1 / 25;
return [
steelseries.Section(0, 5 * factor, 'rgba(0, 250, 0, 1)'),
steelseries.Section(5 * factor, 10 * factor, 'rgba(0, 250, 117, 1)'),
steelseries.Section(10 * factor, 25 * factor, 'rgba(218, 246, 0, 1)'),
steelseries.Section(25 * factor, 40 * factor, 'rgba(250, 186, 0, 1)'),
steelseries.Section(40 * factor, 50 * factor, 'rgba(250, 95, 0, 1)'),
steelseries.Section(50 * factor, 65 * factor, 'rgba(250, 0, 0, 1)'),
steelseries.Section(65 * factor, 75 * factor, 'rgba(250, 6, 80, 1)'),
steelseries.Section(75 * factor, 100 * factor, 'rgba(205, 18, 158, 1)'),
steelseries.Section(100 * factor, 125 * factor, 'rgba(0, 0, 250, 1)'),
steelseries.Section(125 * factor, 500 * factor, 'rgba(0, 219, 212, 1)')
];
},
//
// createRainfallGradient() returns an array of SS colours for continuous gradient colouring of the total rainfall LED gauge
//
createRainfallGradient = function (metric) {
var grad = new steelseries.gradientWrapper(
0,
(metric ? 100 : 4),
[0, 0.1, 0.62, 1],
[
new steelseries.rgbaColor(15, 148, 0, 1),
new steelseries.rgbaColor(213, 213, 0, 1),
new steelseries.rgbaColor(213, 0, 25, 1),
new steelseries.rgbaColor(250, 0, 0, 1)
]
);
return grad;
},
//
// createClousBaseSections() returns an array of section highlights for the Cloud Base gauge
//
createCloudBaseSections = function (metric) {
var section;
if (metric) {
section = [
steelseries.Section(0, 150, 'rgba(245, 86, 59, 0.5)'),
steelseries.Section(150, 300, 'rgba(225, 155, 105, 0.5)'),
steelseries.Section(300, 750, 'rgba(212, 203, 109, 0.5)'),
steelseries.Section(750, 1000, 'rgba(150, 203, 150, 0.5)'),
steelseries.Section(1000, 1500, 'rgba(80, 192, 80, 0.5)'),
steelseries.Section(1500, 2500, 'rgba(0, 140, 0, 0.5)'),
steelseries.Section(2500, 5500, 'rgba(19, 103, 186, 0.5)')
];
} else {
section = [
steelseries.Section(0, 500, 'rgba(245, 86, 59, 0.5)'),
steelseries.Section(500, 1000, 'rgba(225, 155, 105, 0.5)'),
steelseries.Section(1000, 2500, 'rgba(212, 203, 109, 0.5)'),
steelseries.Section(2500, 3500, 'rgba(150, 203, 150, 0.5)'),
steelseries.Section(3500, 5500, 'rgba(80, 192, 80, 0.5)'),
steelseries.Section(5500, 8500, 'rgba(0, 140, 0, 0.5)'),
steelseries.Section(8500, 18000, 'rgba(19, 103, 186, 0.5)')
];
}
return section;
},
//
// --------------- Helper functions ------------------
//
//
// getord() converts a value in degrees (0-360) into a localised compass point (N, ENE, NE, etc)
//
getord = function (deg) {
if (deg === 0) {
// Special case, 0=No wind, 360=North
return strings.calm;
} else {
return (strings.coords[Math.floor((deg + 11.25) / 22.5) % 16]);
}
},
//
// getUrlParam() extracts the named parameter from the current page URL
//
getUrlParam = function (paramName) {
var name, regexS, regex, results;
name = paramName.replace(/(\[|\])/g, '\\$1');
regexS = '[\\?&]' + name + '=([^&#]*)';
regex = new RegExp(regexS);
results = regex.exec(window.location.href);
if (results === null) {
return '';
} else {
return results[1];
}
},
//
// extractDecimal() returns a decimal number from a string, the decimal point can be either a dot or a comma
// it ignores any text such as pre/appended units
//
extractDecimal = function (str, errVal) {
try {
return (/[-+]?[0-9]+\.?[0-9]*/).exec(str.replace(',', '.'))[0];
} catch (e) {
// error condition
return errVal || -9999;
}
},
//
// extractInteger() returns an integer from a string
// it ignores any text such as pre/appended units
//
extractInteger = function (str, errVal) {
try {
return (/[-+]?[0-9]+/).exec(str)[0];
} catch (e) {
// error condition
return errVal || -9999;
}
},
//
// tempTrend() converts a temperature trend value into a localised string, or +1, 0, -1 depending on the value of bTxt
//
tempTrend = function (trend, units, bTxt) {
// Scale is over 3 hours, in Celsius
var val = trend * 3 * (units[1] === 'C' ? 1 : (5 / 9)),
ret;
if (trend === -9999) {
ret = (bTxt ? '--' : trend);
} else if (val > 5) {
ret = (bTxt ? strings.RisingVeryRapidly : 1);
} else if (val > 3) {
ret = (bTxt ? strings.RisingQuickly : 1);
} else if (val > 1) {
ret = (bTxt ? strings.Rising : 1);
} else if (val > 0.5) {
ret = (bTxt ? strings.RisingSlowly : 1);
} else if (val >= -0.5) {
ret = (bTxt ? strings.Steady : 0);
} else if (val >= -1) {
ret = (bTxt ? strings.FallingSlowly : -1);
} else if (val >= -3) {
ret = (bTxt ? strings.Falling : -1);
} else if (val >= -5) {
ret = (bTxt ? strings.FallingQuickly : -1);
} else {
ret = (bTxt ? strings.FallingVeryRapidly : -1);
}
return ret;
},
//
// baroTrend() converts a pressure trend value into a localised string, or +1, 0, -1 depending on the value of bTxt
//
baroTrend = function (trend, units, bTxt) {
var val = trend * 3,
ret;
// The terms below are the UK Met Office terms for a 3 hour change in hPa
// trend is supplied as an hourly change, so multiply by 3
if (units === 'inHg') {
val *= 33.8639;
} else if (units === 'kPa') {
val *= 10;
// assume everything else is hPa or mb, could be dangerous!
}
if (trend === -9999) {
ret = (bTxt ? '--' : trend);
} else if (val > 6.0) {
ret = (bTxt ? strings.RisingVeryRapidly : 1);
} else if (val > 3.5) {
ret = (bTxt ? strings.RisingQuickly : 1);
} else if (val > 1.5) {
ret = (bTxt ? strings.Rising : 1);
} else if (val > 0.1) {
ret = (bTxt ? strings.RisingSlowly : 1);
} else if (val >= -0.1) {
ret = (bTxt ? strings.Steady : 0);
} else if (val >= -1.5) {
ret = (bTxt ? strings.FallingSlowly : -1);
} else if (val >= -3.5) {
ret = (bTxt ? strings.Falling : -1);
} else if (val >= -6.0) {
ret = (bTxt ? strings.FallingQuickly : -1);
} else {
ret = (bTxt ? strings.FallingVeryRapidly : -1);
}
return ret;
},
//
// getMinTemp() returns the lowest temperature today for gauge scaling
//
getMinTemp = function (deflt) {
return Math.min(
extractDecimal(data.tempTL, deflt),
extractDecimal(data.dewpointTL, deflt),
extractDecimal(data.apptempTL, deflt),
extractDecimal(data.feelslikeTL, deflt),
extractDecimal(data.wchillTL, deflt));
},
//
// getMaxTemp() returns the highest temperature today for gauge scaling
//
getMaxTemp = function (deflt) {
return Math.max(
extractDecimal(data.tempTH, deflt),
extractDecimal(data.apptempTH, deflt),
extractDecimal(data.feelslikeTH, deflt),
extractDecimal(data.heatindexTH, deflt),
extractDecimal(data.humidex, deflt));
},
// Celsius to Fahrenheit
c2f = function c2f(val) {
return (extractDecimal(val) * 9 / 5 + 32).toFixed(1);
},
// Fahrenheit to Celsius
f2c = function f2c(val) {
return ((extractDecimal(val) - 32) * 5 / 9).toFixed(1);
},
// mph to ms
mph2ms = function mph2ms(val) {
return (extractDecimal(val) * 0.447).toFixed(1);
},
// knots to ms
kts2ms = function kts2ms(val) {
return (extractDecimal(val) * 0.515).toFixed(1);
},
// kph to ms
kmh2ms = function kmh2ms(val) {
return (extractDecimal(val) * 0.2778).toFixed(1);
},
// ms to kts
ms2kts = function ms2kts(val) {
return (extractDecimal(val) * 1.9426).toFixed(1);
},
// ms to mph
ms2mph = function ms2mph(val) {
return (extractDecimal(val) * 2.237).toFixed(1);
},
// ms to kph
ms2kmh = function ms2kmh(val) {
return (extractDecimal(val) * 3.6).toFixed(1);
},
// mm to inches
mm2in = function mm2in(val) {
return (extractDecimal(val) / 25.4).toFixed(2);
},
// inches to mm
in2mm = function in2mm(val) {
return (extractDecimal(val) * 25.4).toFixed(1);
},
// miles to km
miles2km = function miles2km(val) {
return (extractDecimal(val) * 1.609344).toFixed(1);
},
// nautical miles to km
nmiles2km = function nmiles2km(val) {
return (extractDecimal(val) * 1.85200).toFixed(1);
},
// km to miles
km2miles = function km2miles(val) {
return (extractDecimal(val) / 1.609344).toFixed(1);
},
// km to nautical miles
km2nmiles = function km2nmiles(val) {
return (extractDecimal(val) / 1.85200).toFixed(1);
},
// hPa to inHg (@0°C)
hpa2inhg = function hpa2inhg(val, decimals) {
return (extractDecimal(val) * 0.029528744).toFixed(decimals || 3);
},
// inHg to hPa (@0°C)
inhg2hpa = function inhg2hpa(val) {
return (extractDecimal(val) / 0.029528744).toFixed(1);
},
// kPa to hPa
kpa2hpa = function kpa2hpa(val) {
return (extractDecimal(val) * 10).toFixed(1);
},
// hPa to kPa
hpa2kpa = function hpa2kpa(val, decimals) {
return (extractDecimal(val) / 10).toFixed(decimals || 2);
},
// m to ft
m2ft = function m2ft(val) {
return (val * 3.2808399).toFixed(0);
},
// ft to m
ft2m = function ft2m(val) {
return (val / 3.2808399).toFixed(0);
},
//
// setCookie() writes the 'obj' in cookie 'name' for persistent storage
//
setCookie = function (name, obj) {
var date = new Date(),
expires;
// cookies valid for 1 year
date.setYear(date.getFullYear() + 1);
expires = '; expires=' + date.toGMTString();
document.cookie = name + '=' + encodeURIComponent(JSON.stringify(obj)) + expires;
},
//
// getCookie() reads the value of cookie 'name' from persistent storage
//
getCookie = function (name) {
var i, x, y,
ret = null,
arrCookies = document.cookie.split(';');
for (i = arrCookies.length; i--;) {
x = arrCookies[i].split('=');
if (x[0].trim() === name) {
try {
y = decodeURIComponent(x[1]);
} catch (e) {
y = x[1];
}
ret = JSON.parse(unescape(y));
break;
}
}
return ret;
},
//
// setRadioCheck() sets the desired value of the HTML radio buttons to be selected
//
setRadioCheck = function (obj, val) {
$('input:radio[name="' + obj + '"]').filter('[value="' + val + '"]').prop('checked', true);
},
//
// convTempData() converts all the temperature values using the supplied conversion function
//
convTempData = function (convFunc) {
data.apptemp = convFunc(data.apptemp);
data.apptempTH = convFunc(data.apptempTH);
data.apptempTL = convFunc(data.apptempTL);
data.feelslike = convFunc(data.feelslike);
data.feelslikeTH = convFunc(data.feelslikeTH);
data.feelslikeTL = convFunc(data.feelslikeTL);
data.dew = convFunc(data.dew);
data.dewpointTH = convFunc(data.dewpointTH);
data.dewpointTL = convFunc(data.dewpointTL);
data.heatindex = convFunc(data.heatindex);
data.heatindexTH = convFunc(data.heatindexTH);
data.humidex = convFunc(data.humidex);
data.intemp = convFunc(data.intemp);
if (data.intempTL && data.intempTH) {
data.intempTL = convFunc(data.intempTL);
data.intempTH = convFunc(data.intempTH);
}
data.temp = convFunc(data.temp);
data.tempTH = convFunc(data.tempTH);
data.tempTL = convFunc(data.tempTL);
data.wchill = convFunc(data.wchill);
data.wchillTL = convFunc(data.wchillTL);
if (convFunc === c2f) {
data.temptrend = (+extractDecimal(data.temptrend) * 9 / 5).toFixed(1);
data.tempunit = '°F';
} else {
data.temptrend = (+extractDecimal(data.temptrend) * 5 / 9).toFixed(1);
data.tempunit = '°C';
}
},
//
// convRainData() converts all the rain data units using the supplied conversion function
//
convRainData = function (convFunc) {
data.rfall = convFunc(data.rfall);
data.rrate = convFunc(data.rrate);
data.rrateTM = convFunc(data.rrateTM);
data.hourlyrainTH = convFunc(data.hourlyrainTH);
data.rainunit = convFunc === mm2in ? 'in' : 'mm';
},
//
// convWindData() converts all the wind values using the supplied conversion function
//
convWindData = function (from, to) {
var fromFunc1, toFunc1,
fromFunc2, toFunc2,
dummy = function (val) {
return val;
};
// convert to m/s & km
switch (from) {
case 'mph':
fromFunc1 = mph2ms;
fromFunc2 = miles2km;
break;
case 'kts':
fromFunc1 = kts2ms;
fromFunc2 = nmiles2km;
break;
case 'km/h':
fromFunc1 = kmh2ms;
fromFunc2 = dummy;
break;
case 'm/s':
// falls through
default:
fromFunc1 = dummy;
fromFunc2 = dummy;
}
// conversion function from km to required units
switch (to) {
case 'mph':
toFunc1 = ms2mph;
toFunc2 = km2miles;
displayUnits.windrun = 'miles';
break;
case 'kts':
toFunc1 = ms2kts;
toFunc2 = km2nmiles;
displayUnits.windrun = 'n.miles';
break;
case 'km/h':
toFunc1 = ms2kmh;
toFunc2 = dummy;
displayUnits.windrun = 'km';
break;
case 'm/s':
// falls through
default:
toFunc1 = dummy;
toFunc2 = dummy;
displayUnits.windrun = 'km';
}
// do the conversions
data.wgust = toFunc1(fromFunc1(data.wgust));
data.wgustTM = toFunc1(fromFunc1(data.wgustTM));
data.windTM = toFunc1(fromFunc1(data.windTM));
data.windrun = toFunc2(fromFunc2(data.windrun));
data.wlatest = toFunc1(fromFunc1(data.wlatest));
data.wspeed = toFunc1(fromFunc1(data.wspeed));
data.windunit = to;
},
//
// convBaroData() converts all the pressure values using the supplied conversion function
//
convBaroData = function (from, to) {
var fromFunc, toFunc,
dummy = function (val) {
return val;
};
// convert to hPa
switch (from) {
case 'hPa':
// falls through
case 'mb':
fromFunc = dummy;
break;
case 'inHg':
fromFunc = inhg2hpa;
break;
case 'kPa':
fromFunc = kpa2hpa;
break;
// no default
}
// convert to required units
switch (to) {
case 'hPa':
// falls through
case 'mb':
toFunc = dummy;
break;
case 'inHg':
toFunc = hpa2inhg;
break;
case 'kPa':
toFunc = hpa2kpa;
break;
// no default
}
data.press = toFunc(fromFunc(data.press));
data.pressH = toFunc(fromFunc(data.pressH));
data.pressL = toFunc(fromFunc(data.pressL));
data.pressTH = toFunc(fromFunc(data.pressTH));
data.pressTL = toFunc(fromFunc(data.pressTL));
data.presstrendval = toFunc(fromFunc(data.presstrendval), 3);
data.pressunit = to;
},
//
// convCloudBaseData() converts all the cloud base data units using the supplied conversion function
//
convCloudBaseData = function (convFunc) {
data.cloudbasevalue = convFunc(data.cloudbasevalue);
data.cloudbaseunit = convFunc === m2ft ? 'ft' : 'm';
},
//
// setUnits() Main data conversion routine, calls all the setXXXX() sub-routines
//
setUnits = function (radio) {
var sel = radio.value;
userUnitsSet = true;
switch (sel) {
// == Temperature ==
case 'C':
displayUnits.temp = sel;
if (data.tempunit[1] !== sel) {
setTempUnits(true);
convTempData(f2c);
if (gaugeTemp) {gaugeTemp.update();}
if (gaugeDew) {gaugeDew.update();}
}
break;
case 'F':
displayUnits.temp = sel;
if (data.tempunit[1] !== sel) {
setTempUnits(false);
convTempData(c2f);
if (gaugeTemp) {gaugeTemp.update();}
if (gaugeDew) {gaugeDew.update();}
}
break;
// == Rainfall ==
case 'mm':
displayUnits.rain = sel;
if (data.rainunit !== sel) {
setRainUnits(true);
convRainData(in2mm);
if (gaugeRain) {gaugeRain.update();}
if (gaugeRRate) {gaugeRRate.update();}
}
break;
case 'in':
displayUnits.rain = sel;
if (data.rainunit !== sel) {
setRainUnits(false);
convRainData(mm2in);
if (gaugeRain) {gaugeRain.update();}
if (gaugeRRate) {gaugeRRate.update();}
}
break;
// == Pressure ==
case 'hPa':
// falls through
case 'inHg':
// falls through
case 'mb':
// falls through
case 'kPa':
displayUnits.press = sel;
if (data.pressunit !== sel) {
convBaroData(data.pressunit, sel);
setBaroUnits(sel);
if (gaugeBaro) {gaugeBaro.update();}
}
break;
// == Wind speed ==
case 'mph':
// falls through
case 'kts':
// falls through
case 'm/s':
// falls through
case 'km/h':
displayUnits.wind = sel;
if (data.windunit !== sel) {
convWindData(data.windunit, sel);
setWindUnits(sel);
if (gaugeWind) {gaugeWind.update();}
if (gaugeDir) {gaugeDir.update();}
if (gaugeRose) {gaugeRose.update();}
}
break;
// == CloudBase ==
case 'm':
displayUnits.cloud = sel;
if (data.cloudbaseunit !== sel) {
setCloudBaseUnits(true);
convCloudBaseData(ft2m);
if (gaugeCloud) {gaugeCloud.update();}
}
break;
case 'ft':
displayUnits.cloud = sel;
if (data.cloudbaseunit !== sel) {
setCloudBaseUnits(false);
convCloudBaseData(m2ft);
if (gaugeCloud) {gaugeCloud.update();}
}
break;
// no default
}
if (config.useCookies) {
setCookie('units', displayUnits);
}
},
setTempUnits = function (celsius) {
if (celsius) {
data.tempunit = '°C';
if (gaugeTemp) {
gaugeTemp.data.sections = createTempSections(true);
gaugeTemp.data.minValue = gaugeGlobals.tempScaleDefMinC;
gaugeTemp.data.maxValue = gaugeGlobals.tempScaleDefMaxC;
}
if (gaugeDew) {
gaugeDew.data.sections = createTempSections(true);
gaugeDew.data.minValue = gaugeGlobals.tempScaleDefMinC;
gaugeDew.data.maxValue = gaugeGlobals.tempScaleDefMaxC;
}
} else {
data.tempunit = '°F';
if (gaugeTemp) {
gaugeTemp.data.sections = createTempSections(false);
gaugeTemp.data.minValue = gaugeGlobals.tempScaleDefMinF;
gaugeTemp.data.maxValue = gaugeGlobals.tempScaleDefMaxF;
}
if (gaugeDew) {
gaugeDew.data.sections = createTempSections(false);
gaugeDew.data.minValue = gaugeGlobals.tempScaleDefMinF;
gaugeDew.data.maxValue = gaugeGlobals.tempScaleDefMaxF;
}
}
if (gaugeTemp) {
gaugeTemp.gauge.setUnitString(data.tempunit);
gaugeTemp.gauge.setSection(gaugeTemp.data.sections);
}
if (gaugeDew) {
gaugeDew.gauge.setUnitString(data.tempunit);
gaugeDew.gauge.setSection(gaugeTemp.data.sections);
}
},
setRainUnits = function (mm) {
if (mm) {
data.rainunit = 'mm';
if (gaugeRain) {
gaugeRain.data.lcdDecimals = 1;
gaugeRain.data.scaleDecimals = 1;
gaugeRain.data.labelNumberFormat = gaugeGlobals.labelFormat;
gaugeRain.data.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(true) : []);
gaugeRain.data.maxValue = gaugeGlobals.rainScaleDefMaxmm;
gaugeRain.data.grad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(true) : null);
}
if (gaugeRRate) {
gaugeRRate.data.lcdDecimals = 1;
gaugeRRate.data.scaleDecimals = 0;
gaugeRRate.data.labelNumberFormat = gaugeGlobals.labelFormat;
gaugeRRate.data.sections = createRainRateSections(true);
gaugeRRate.data.maxValue = gaugeGlobals.rainRateScaleDefMaxmm;
}
} else {
data.rainunit = 'in';
if (gaugeRain) {
gaugeRain.data.lcdDecimals = 2;
gaugeRain.data.scaleDecimals = gaugeGlobals.rainScaleDefMaxIn < 1 ? 2 : 1;
gaugeRain.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
gaugeRain.data.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(false) : []);
gaugeRain.data.maxValue = gaugeGlobals.rainScaleDefMaxIn;
gaugeRain.data.grad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(false) : null);
}
if (gaugeRRate) {
gaugeRRate.data.lcdDecimals = 2;
gaugeRRate.data.scaleDecimals = gaugeGlobals.rainRateScaleDefMaxIn < 1 ? 2 : 1;
gaugeRRate.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
gaugeRRate.data.sections = createRainRateSections(false);
gaugeRRate.data.maxValue = gaugeGlobals.rainRateScaleDefMaxIn;
}
}
if (gaugeRain) {
gaugeRain.data.value = 0;
gaugeRain.gauge.setUnitString(data.rainunit);
gaugeRain.gauge.setSection(gaugeRain.data.sections);
gaugeRain.gauge.setGradient(gaugeRain.data.grad);
gaugeRain.gauge.setFractionalScaleDecimals(gaugeRain.data.scaleDecimals);
gaugeRain.gauge.setLabelNumberFormat(gaugeRain.data.labelNumberFormat);
gaugeRain.gauge.setLcdDecimals(gaugeRain.data.lcdDecimals);
gaugeRain.gauge.setValue(0);
gaugeRain.gauge.setMaxValue(gaugeRain.data.maxValue);
}
if (gaugeRRate) {
gaugeRRate.data.value = 0;
gaugeRRate.gauge.setUnitString(data.rainunit + '/h');
gaugeRRate.gauge.setSection(gaugeRRate.data.sections);
gaugeRRate.gauge.setFractionalScaleDecimals(gaugeRRate.data.scaleDecimals);
gaugeRRate.gauge.setLabelNumberFormat(gaugeRRate.data.labelNumberFormat);
gaugeRRate.gauge.setLcdDecimals(gaugeRRate.data.lcdDecimals);
gaugeRRate.gauge.setValue(0);
gaugeRRate.gauge.setMaxValue(gaugeRRate.data.maxValue);
}
},
setWindUnits = function (to) {
var maxVal;
data.windunit = to;
if (gaugeWind) {
// conversion function to required units
switch (to) {
case 'mph':
maxVal = gaugeGlobals.windScaleDefMaxMph;
break;
case 'kts':
maxVal = gaugeGlobals.windScaleDefMaxKts;
break;
case 'km/h':
maxVal = gaugeGlobals.windScaleDefMaxKmh;
break;
case 'm/s':
maxVal = gaugeGlobals.windScaleDefMaxMs;
break;
// no default
}
// set the gauges
gaugeWind.data.maxValue = maxVal;
gaugeWind.gauge.setUnitString(data.windunit);
gaugeWind.gauge.setValue(0);
}
if (gaugeRose) {
gaugeRose.setOdoTitle(strings[getWindrunUnits(data.windunit)]);
}
},
setBaroUnits = function (to) {
var minVal, maxVal;
if (!gaugeBaro) {return;}
// set to the required units
switch (to) {
case 'hPa':
// falls through
case 'mb':
minVal = gaugeGlobals.baroScaleDefMinhPa;
maxVal = gaugeGlobals.baroScaleDefMaxhPa;
gaugeBaro.data.lcdDecimals = 1;
gaugeBaro.data.scaleDecimals = 0;
gaugeBaro.data.labelNumberFormat = gaugeGlobals.labelFormat;
break;
case 'inHg':
minVal = gaugeGlobals.baroScaleDefMininHg;
maxVal = gaugeGlobals.baroScaleDefMaxinHg;
gaugeBaro.data.lcdDecimals = 2;
gaugeBaro.data.scaleDecimals = 1;
gaugeBaro.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
break;
case 'kPa':
minVal = gaugeGlobals.baroScaleDefMinkPa;
maxVal = gaugeGlobals.baroScaleDefMaxkPa;
gaugeBaro.data.lcdDecimals = 2;
gaugeBaro.data.scaleDecimals = 1;
gaugeBaro.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
break;
// no default
}
data.pressunit = to;
gaugeBaro.gauge.setUnitString(to);
gaugeBaro.gauge.setLcdDecimals(gaugeBaro.data.lcdDecimals);
gaugeBaro.gauge.setFractionalScaleDecimals(gaugeBaro.data.scaleDecimals);
gaugeBaro.gauge.setLabelNumberFormat(gaugeBaro.data.labelNumberFormat);
gaugeBaro.data.minValue = minVal;
gaugeBaro.data.maxValue = maxVal;
gaugeBaro.data.value = gaugeBaro.data.minValue;
},
setCloudBaseUnits = function (m) {
if (!gaugeCloud) {return;}
if (m) {
gaugeCloud.data.sections = createCloudBaseSections(true);
gaugeCloud.data.maxValue = gaugeGlobals.cloudScaleDefMaxm;
} else {
gaugeCloud.data.sections = createCloudBaseSections(false);
gaugeCloud.data.maxValue = gaugeGlobals.cloudScaleDefMaxft;
}
gaugeCloud.data.value = 0;
gaugeCloud.gauge.setUnitString(m ? strings.metres : strings.feet);
gaugeCloud.gauge.setSection(gaugeCloud.data.sections);
},
//
// setLang() switches the HTML page language set, called by changeLang() in language.js
//
setLang = function (newLang) {
// reset to the new language
strings = newLang;
// temperature
if (gaugeTemp) {
if (config.showIndoorTempHum) {
if ($('#rad_temp1').is(':checked')) {
gaugeTemp.data.title = strings.temp_title_out;
} else {
gaugeTemp.data.title = strings.temp_title_in;
}
} else {
gaugeTemp.data.title = strings.temp_title_out;
}
gaugeTemp.gauge.setTitleString(gaugeTemp.data.title);
if (data.ver) {gaugeTemp.update();}
}
if (gaugeDew) {
switch ($('input[name="rad_dew"]:checked').val()) {
case 'dew':
gaugeDew.data.title = strings.dew_title;
break;
case 'app':
gaugeDew.data.title = strings.apptemp_title;
break;
case 'feel':
gaugeDew.data.title = strings.feel_title;
break;
case 'wnd':
gaugeDew.data.title = strings.chill_title;
break;
case 'hea':
gaugeDew.data.title = strings.heat_title;
break;
case 'hum':
gaugeDew.data.title = strings.humdx_title;
break;
// no default
}
gaugeDew.gauge.setTitleString(gaugeDew.data.title);
if (data.ver) {gaugeDew.update();}
}
// rain
if (gaugeRain) {
gaugeRain.data.title = strings.rain_title;
gaugeRain.gauge.setTitleString(gaugeRain.data.title);
if (data.ver) {gaugeRain.update();}
}
// rrate
if (gaugeRRate) {
gaugeRRate.data.title = strings.rrate_title;
gaugeRRate.gauge.setTitleString(gaugeRRate.data.title);
if (data.ver) {gaugeRRate.update();}
}
// humidity
if (gaugeHum) {
if (config.showIndoorTempHum) {
if ($('#rad_hum1').is(':checked')) {
gaugeHum.data.title = strings.hum_title_out;
} else {
gaugeHum.data.title = strings.hum_title_in;
}
} else {
gaugeHum.data.title = strings.hum_title_out;
}
gaugeHum.gauge.setTitleString(gaugeHum.data.title);
if (data.ver) {gaugeHum.update();}
}
// barometer
if (gaugeBaro) {
gaugeBaro.data.title = strings.baro_title;
gaugeBaro.gauge.setTitleString(gaugeBaro.data.title);
if (data.ver) {gaugeBaro.update();}
}
// wind
if (gaugeWind) {
gaugeWind.data.title = strings.wind_title;
gaugeWind.gauge.setTitleString(gaugeWind.data.title);
if (data.ver) {gaugeWind.update();}
}
if (gaugeDir) {
gaugeDir.gauge.setPointSymbols(strings.compass);
gaugeDir.data.titles = [strings.latest_web, strings.tenminavg_web];
gaugeDir.gauge.setLcdTitleStrings(gaugeDir.data.titles);
if (data.ver) {gaugeDir.update();}
}
if (gaugeUV) {
gaugeUV.gauge.setTitleString(strings.uv_title);
if (data.ver) {gaugeUV.update();}
}
if (gaugeSolar) {
gaugeSolar.gauge.setTitleString(strings.solar_title);
if (data.ver) {gaugeSolar.update();}
}
if (gaugeRose) {
gaugeRose.setTitle(strings.windrose);
gaugeRose.setCompassStrings(strings.compass);
gaugeRose.setOdoTitle(strings[getWindrunUnits(displayUnits.wind)]);
if (data.ver) {gaugeRose.update();}
}
if (gaugeCloud) {
// Cloudbase
gaugeCloud.data.units = data.cloudunit === 'm' ? strings.metres : strings.feet;
gaugeCloud.gauge.setTitleString(strings.cloudbase_title);
gaugeCloud.gauge.setUnitString(gaugeCloud.data.units);
if (data.ver) {gaugeCloud.update();}
}
},
//
// return windrun units based on the windspeed units
//
getWindrunUnits = function (spdUnits) {
var retVal;
switch (spdUnits) {
case 'mph':
retVal = 'miles';
break;
case 'kts':
retVal = 'n_miles';
break;
case 'km/h':
// falls through
case 'm/s':
// falls through
default:
retVal = 'km';
break;
}
return retVal;
},
//
// performs a simple cloudbase calculation for those weather programs that don't supply it
//
calcCloudbase = function (temp, tempunit, dew, cloudbaseunit) {
var sprd = temp - dew;
var cb = sprd * (tempunit[1] === 'C' ? 400 : 227.3); // cloud base in feet
if (cloudbaseunit === 'm') {
cb = ft2m(cb);
}
return cb;
},
//
// create a shadow effect for the gauge using CSS
//
gaugeShadow = function (size) {
var offset = Math.floor(size * 0.015);
return {
'box-shadow' : offset + 'px ' + offset + 'px ' + offset + 'px ' + gaugeGlobals.shadowColour,
'border-radius': Math.floor(size / 2) + 'px'
};
},
//
// generate a colour gradient based on start and end values
//
gradient = function (startCol, endCol, fraction) {
var redOrigin, grnOrigin, bluOrigin,
gradientSizeRed, gradientSizeGrn, gradientSizeBlu;
redOrigin = parseInt(startCol.substr(0, 2), 16);
grnOrigin = parseInt(startCol.substr(2, 2), 16);
bluOrigin = parseInt(startCol.substr(4, 2), 16);
gradientSizeRed = parseInt(endCol.substr(0, 2), 16) - redOrigin; // Graduation Size Red
gradientSizeGrn = parseInt(endCol.substr(2, 2), 16) - grnOrigin;
gradientSizeBlu = parseInt(endCol.substr(4, 2), 16) - bluOrigin;
return (redOrigin + (gradientSizeRed * fraction)).toFixed(0) + ',' +
(grnOrigin + (gradientSizeGrn * fraction)).toFixed(0) + ',' +
(bluOrigin + (gradientSizeBlu * fraction)).toFixed(0);
},
//
// returns the next highest number in the step sequence
//
nextHighest = function (value, step) {
return +value == 0 ? step : Math.ceil(+value / step) * step;
},
//
// returns the next lowest number in the step sequence
//
nextLowest = function (value, step) {
return +value == 0 ? -step : Math.floor(+value / step) * step;
};
// ########################################################
// End of gauges() var declarations
// ########################################################
//
// Execution starts here
//
// test for canvas support before we do anything else, especially reference steelseries which will cause the script to abort!
if (!document.createElement('canvas').getContext) {
// failed, no canvas support detected
$('body').html(strings.canvasnosupport);
setTimeout(function () {
window.location = config.oldGauges;
}, 3000);
return false;
} else {
//
// Called when the document object has loaded
// This starts the whole script.
//
$(document).ready(function () {
// Kick it all off - false for web page, true for dashboard
init(config.dashboardMode);
});
}
return {
setLang : setLang,
setUnits : setUnits,
processData: processData,
config : config,
init : init
};
}());
// ===============================================================================================================================
// ===============================================================================================================================
// ===============================================================================================================================
/*!
* Image w/ description tooltip v2.0 - For FF1+ IE6+ Opr8+
* Created: April 23rd, 2010. This notice must stay intact for usage
* Author: Dynamic Drive at http://www.dynamicdrive.com/
* Visit http://www.dynamicdrive.com/ for full source code
* Modified: M Crossley June 2011, January 2012
* v2.-
*/
var ddimgtooltip;
ddimgtooltip = {
tiparray: (function () {
var style = {background: '#FFFFFF', color: 'black', border: '2px ridge darkblue'},
i = 12, // set to number of tooltips required
tooltips = [];
for (;i--;) {
tooltips[i] = [null, ' ', style];
}
return tooltips;
}()),
tooltipoffsets: [20, -30], // additional x and y offset from mouse cursor for tooltips
tipDelay: 1000,
delayTimer: 0,
tipprefix: 'imgtip', // tooltip DOM ID prefixes
createtip: function ($, tipid, tipinfo) {
if ($('#' + tipid).length === 0) { // if this tooltip doesn't exist yet
return $('<div id="' + tipid + '" class="ddimgtooltip" />')
.html(
((tipinfo[1]) ? '<div class="tipinfo" id="' + tipid + '_txt">' + tipinfo[1] + '</div>' : '') +
(tipinfo[0] !== null ? '<div style="text-align:center"><img class="tipimg" id="' + tipid +
'_img" src="' + tipinfo[0] + '" /></div>' : '')
)
.css(tipinfo[2] || {})
.appendTo(document.body);
}
return null;
},
positiontooltip: function ($, $tooltip, e) {
var x = e.pageX + this.tooltipoffsets[0],
y = e.pageY + this.tooltipoffsets[1],
tipw = $tooltip.outerWidth(),
tiph = $tooltip.outerHeight(),
wWidth = $(window).width(),
wHght = $(window).height(),
dTop = $(document).scrollTop();
x = (x + tipw > $(document).scrollLeft() + wWidth) ? x - tipw - (ddimgtooltip.tooltipoffsets[0] * 2) : x;
y = (y + tiph > dTop + wHght) ? dTop + wHght - tiph - 10 : y;
// last ditch attempt to keep the graphs 'on page'
x = Math.max(x, 0);
if (tipw >= wWidth) {
$($tooltip.attr('id') + '_img').css({width: wWidth - 20});
$('#' + $tooltip.attr('id') + '_img').css({width: wWidth - 20});
y = e.pageY + 5;
}
$tooltip.css({left: x, top: y});
},
delaybox: function ($, $tooltip) {
if (this.showTips) {
ddimgtooltip.delayTimer = setTimeout(
function () {
ddimgtooltip.showbox($tooltip);
}, ddimgtooltip.tipDelay);
}
},
showbox: function (tooltip) {
if (this.showTips) {
// $(tooltip).show();
$(tooltip).fadeIn();
}
},
hidebox: function ($, $tooltip) {
clearTimeout(ddimgtooltip.delayTimer);
// $tooltip.hide();
$tooltip.fadeOut();
},
showTips: false,
init: function (targetselector) {
var tiparray = ddimgtooltip.tiparray,
$targets = $(targetselector);
if ($targets.length === 0) {
return;
}
$targets.each(function () {
var $target = $(this),
tipsuffix, tipid,
$tooltip;
var ind = ($target.attr('id').match(/_(\d+)/) || [])[1] || ''; // match d of attribute id='tip_d'
tipsuffix = parseInt(ind, 10); // get d as integer
tipid = this.tipid = ddimgtooltip.tipprefix + tipsuffix; // construct this tip's ID value and remember it
$tooltip = ddimgtooltip.createtip($, tipid, tiparray[tipsuffix]);
$target.mouseenter(function (e) {
var $tooltip = $('#' + this.tipid);
// ddimgtooltip.showbox($, $tooltip, e);
ddimgtooltip.delaybox($, $tooltip, e);
});
$target.mouseleave(function () {
var $tooltip = $('#' + this.tipid);
ddimgtooltip.hidebox($, $tooltip);
});
$target.mousemove(function (e) {
var $tooltip = $('#' + this.tipid);
ddimgtooltip.positiontooltip($, $tooltip, e);
});
if ($tooltip) { // add mouseenter to this tooltip (only if event hasn't already been added)
$tooltip.mouseenter(function () {
ddimgtooltip.hidebox($, $(this));
});
}
});
}
};
// if String doesn't offer a .trim() method, add it
String.prototype.trim = String.prototype.trim || function trim() {
return this.replace(/^\s+|\s+$/g, '');
};