diff --git a/README.md b/README.md index e5a05af5..99520ac9 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Icons source: https://github.com/erikflowers/weather-icons # How to run directly on the Kindle (tested on Kindle PW 3) 1. clone or download repository 2. generate your free API key (AppId) at http://openweathermap.org/appid -3. rename `config.js.sample` to `config.js` and set the parameters you need (all parameters are optional and can be set in the HTML webpage `config.html`, but I recommend setting at least the `api_appId`) +3. rename `config.js.sample` to `config.js` and set the parameters you need (all parameters are optional and can be set in the HTML webpage `config.html`, but I recommend setting at least the `appId`) 4. copy the folder with all files to the root of Kindle storage 5. disable the screensaver on your Kindle: * press the search button (or keyboard button on Kindle 4) on homescreen and type: `;debugOn` and press enter on the keyboard @@ -42,36 +42,28 @@ Icons source: https://github.com/erikflowers/weather-icons 6. launch the browser on your Kindle and go to: `file:///mnt/us/kindle-weather-dashboard/index.html` (where `kindle-weather-dashboard` is the folder in the root of your Kindle storage from step 4) ## Configuration -### with config.js -create a config.js file from config.js.sample and set variables: - -* `api_locParams` - query parameters to set location (e.g. `lat=50&lon=14`, or `q=Paris`) -* `api_appId` - set your `API KEY (appId)` from http://openweathermap.org/appid -* `api_lang` - output language (e.g. `en`, default: `en`) -* `api_units` - units: `metric` (°C), `imperial` (°F), `standard` (K) (default: `metric`) -* or you can set all API parameters at once with the `api_params` variable (e.g. `q=Prague&appid=YOUR_API_KEY&lang=sk&units=metric`). **Note:** when `api_params` is set, `api_locParams`, `api_appId`, `api_lang`, `api_units` and their URL counterparts (`city`, `lat`, `lon`, `appId`, `lang`, `units`) are ignored. -* `rotation` - force rotation (on Kindle Paperwhite) `ll` for left landscape, `lr` for right landscape, and `up` for upside down (default: none) -* `night_mode` - `auto` - based on sunrise and sunset, `on` - always on, `HH-HH` (`22-06`) interval for on/off, `off` or `null` to disable (default: `off`) -* `refreshTime` - refresh rate in milliseconds (default: 30 minutes) -* `utcOffset` - if not set, it is determined by location (default: `auto`), `local` - local machine UTC offset, or custom UTC offset. (Because Kindle doesn't report the correct local time. You may need to change the value after the winter/summer time change) -* `tempType` - use `feelsLike` for current weather and hourly forecast; daily forecast uses actual min/max temps (default: `actual`) -* `forecastType` - `hour` for 3-hour steps or `daily` for daily forecast (default: `hour`) +Parameters can be set in `config.js`, URL query parameters, or through `config.html`. + +Parameters: +* `city` - city name (e.g. `Paris`), default: not set +* `lat`, `lon` - GPS coordinates (e.g. `lat=50.1243111`, `lon=14.4901953`), default: not set +* `appId` - OpenWeather API key, default: not set +* `lang` - output language (e.g. `en`), default: `en` +* `units` - `metric` (°C), `imperial` (°F), `standard` (K), default: `metric` +* `rotation` - `ll`, `lr`, `up`, or not set (no forced rotation), default: not set +* `nightMode` - `off`, `auto`, `on`, or `HH-HH` (e.g. `22-06`), default: `off` +* `refreshInterval` - refresh interval in minutes, default: `30` +* `utcOffset` - auto by location (not set), `local`, or custom UTC offset (`+08:00`), default: auto by location +* `tempType` - `actual` or `feelsLike`, default: `actual` +* `forecastType` - `hour` or `daily`, default: `hour` + +Precedence: +* URL query parameters override values from `config.js`. +* If neither URL nor `config.js` provides a value, built-in defaults are used. +* For location, when both `city` and `lat`/`lon` are set, `lat`/`lon` take priority. See more: http://openweathermap.org/current, http://openweathermap.org/forecast and http://openweathermap.org/forecast16 -### with url query parameters -* `appId` sets the appId -* `city` sets the city (e.g. `city=Paris`) -* `lat`, `lon` set location (e.g. `lat=50&lon=14`) -* `lang` sets language (default: `en`) -* `units` sets units: `metric` (°C), `imperial` (°F), `standard` (K) (default: `metric`) -* `rotation` sets the rotation (default: none) -* `utcOffset` sets UTC offset (default: auto by location) -* `tempType` sets temperature type - `actual` or `feelsLike` (default: `actual`) -* `forecastType` sets forecast type - `hour` or `daily` (default: `hour`) -* `night` sets night mode - `off`, `auto`, `on` (default: `off`) -* `refreshTime` sets refresh interval in minutes (default: 30) - Examples: * Dashboard for Prague, metric units, Slovak language: `http://YOUR_URL/?city=Prague&lang=sk&units=metric&appId=YOUR_API_KEY` * Dashboard for a given GPS location, metric units, default language: `https://YOUR_URL/?lat=50&lon=14&units=metric&appId=YOUR_API_KEY` diff --git a/config.html b/config.html index 876501a3..2267ac26 100644 --- a/config.html +++ b/config.html @@ -164,7 +164,7 @@

Kindle Weather Dashboard
Config Page

- +
@@ -204,12 +204,12 @@

Kindle Weather Dashboard
Config Page

setIfPresent("lang"); setIfPresent("rotation"); setIfPresent("units"); - setIfPresent("night"); + setIfPresent("nightMode"); setIfPresent("appId"); setIfPresent("utcOffset"); setIfPresent("tempType"); setIfPresent("forecastType"); - setIfPresent("refreshTime"); + setIfPresent("refreshInterval"); diff --git a/config.js.sample b/config.js.sample index 5ff10087..cbf5ada8 100644 --- a/config.js.sample +++ b/config.js.sample @@ -1,16 +1,19 @@ -var api_locParams = "lat=50.1243111&lon=14.4901953"; -// or api_locParams = "q=Paris"; -var api_appId = "YOUR_API_KEY"; -var api_lang = "sk" -var api_units = "metric"; +// Location by city name +var city = "Paris"; +// or by GPS coordinates +// var lat = "50.1243111"; +// var lon = "14.4901953"; + +var appId = "YOUR_API_KEY"; +var lang = "sk" +var units = "metric"; -var api_params = null; // Forecast type: "hour" (3h steps) or "daily" var forecastType = "hour"; -// refresh time in miliseconds (default 30 mins) -var refreshTime = 30 * 60 * 1000; +// Refresh interval in minutes (default 30) +var refreshInterval = 30; // Browser in kindle paperwhite doesn't support rotation. // You can override with this parameter 'll' and 'lr' for landscape left/right, 'up' for upside down. @@ -20,7 +23,7 @@ var refreshTime = 30 * 60 * 1000; // "auto" - by sunrise and sunset, // "HH-HH - like: ""22-06", from 22:00 to 06:00 // "on" - night mode all the day :) -var night_mode = "off"; +var nightMode = "off"; // Timezone offset - kindle doesnt report correct local time to the kindle (always it is GMT), // You can set custom GMT offset, in format "+08:00". diff --git a/index.html b/index.html index ed88c0ac..ce5dc187 100644 --- a/index.html +++ b/index.html @@ -93,7 +93,7 @@ refreshForecastWeather(); if (!rtcSleepMode) { - window.setTimeout("refreshData()", refreshTime); + window.setTimeout("refreshData()", refreshInterval * 60 * 1000); } } @@ -156,30 +156,16 @@ } function getApiParams() { - if (getUrlParameter("api_params")) { - var url = getUrlParameter("api_params"); - setsUnitsSymbolFromApiUrl(url) - return url; - } - - if (api_params) { - var url = api_params; - setsUnitsSymbolFromApiUrl(url) - return url; - } - - var appId = getUrlParameter("appId") ? getUrlParameter("appId") : api_appId; - lang = getUrlParameter("lang") ? getUrlParameter("lang") : (api_lang || "en"); + var apiLang = lang; if (typeof(lang) === 'string') { - lang = lang.split(";", 1) + apiLang = lang.split(";", 1) } - var units = getUrlParameter("units") ? getUrlParameter("units") : (api_units || "metric"); - var locParams = api_locParams; - if (getUrlParameter("city")) { - locParams = "q=" + encodeURIComponent(getUrlParameter("city")); - } else if (getUrlParameter("lat") && getUrlParameter("lon")) { - locParams = "lat=" + encodeURIComponent(getUrlParameter("lat")) + "&lon=" + encodeURIComponent(getUrlParameter("lon")); + var locParams = null; + if (lat != null && lat !== "" && lon != null && lon !== "") { + locParams = "lat=" + encodeURIComponent(lat) + "&lon=" + encodeURIComponent(lon); + } else if (city) { + locParams = "q=" + encodeURIComponent(city); } if (!locParams || !appId) { @@ -191,13 +177,13 @@ url += locParams; } if (appId) { - url += "&appid=" + appId; + url += "&appid=" + encodeURIComponent(appId); } - if (lang) { - url += "&lang=" + lang; + if (apiLang) { + url += "&lang=" + encodeURIComponent(apiLang); } if (units) { - url += "&units=" + units; + url += "&units=" + encodeURIComponent(units); } setsUnitsSymbolFromApiUrl(url) @@ -213,6 +199,39 @@ return decodeURIComponent(results[1].replace(/\+/g, ' ')); } + function getUrlStringParameter(name, defaultValue) { + var value = getUrlParameter(name); + return value === null || value === "" ? defaultValue : value; + } + + function getUrlNumberParameter(name, defaultValue) { + var value = getUrlParameter(name); + if (value === null || value === "") { + return defaultValue; + } + + var parsed = Number(value); + return isNaN(parsed) ? defaultValue : parsed; + } + + function getUrlBooleanParameter(name, defaultValue) { + var value = getUrlParameter(name); + if (value === null || value === "") { + return defaultValue; + } + + switch (value.toLowerCase()) { + case "true": + case "1": + return true; + case "false": + case "0": + return false; + default: + return defaultValue; + } + } + RegExp.escape = function (s) { return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); }; @@ -226,7 +245,7 @@ icon.style.webkitTransform = null; temp.innerHTML = feelsLike ? Math.round(data.main.feels_like) : Math.round(data.main.temp); temp.className = feelsLike ? "feelsLike" : ""; - city.innerHTML = data.name; + cityName.innerHTML = data.name; description.innerHTML = data.weather[0].description; lastUpdate.innerHTML = momentWithCorrectUtcOffset(new Date()).format(timeFormat) + "/" + momentWithCorrectUtcOffset(new Date(data.dt * 1000)).format(timeFormat); @@ -299,12 +318,11 @@ var page = null; var temp = null; var icon = null; - var city = null; + var cityName = null; var description = null; var lastUpdate = null; var date = null; var sun = null; - var lang = null; var forecastsCells = null; @@ -348,15 +366,22 @@ var timeFormat = "HH:mm"; // Config parameters. - var api_params, api_appId, api_lang, api_units, api_locParams, rotation, night_mode, refreshTime, utcOffset, tempType, forecastType, rtcSleepMode, rtcWakeDelay; - - utcOffset = getUrlParameter("utcOffset") ? getUrlParameter("utcOffset") : utcOffset; - tempType = getUrlParameter("tempType") ? getUrlParameter("tempType") : tempType; - forecastType = getUrlParameter("forecastType") ? getUrlParameter("forecastType") : forecastType; - refreshTime = getUrlParameter("refreshTime") ? getUrlParameter("refreshTime") * 60 * 1000 : refreshTime; // URL: minutes, config.js: milliseconds - rtcSleepMode = getUrlParameter("rtcSleepMode") ? getUrlParameter("rtcSleepMode") === "true" : !!rtcSleepMode; - rtcWakeDelay = getUrlParameter("rtcWakeDelay") ? getUrlParameter("rtcWakeDelay") * 1000 : rtcWakeDelay; // URL: seconds, config.js: milliseconds - + var city, lat, lon, appId, lang, units, nightMode, rotation, refreshInterval, utcOffset, tempType, forecastType, rtcSleepMode, rtcWakeDelay; + + city = getUrlStringParameter("city", city); + lat = getUrlStringParameter("lat", lat); + lon = getUrlStringParameter("lon", lon); + appId = getUrlStringParameter("appId", appId); + lang = getUrlStringParameter("lang", lang || "en"); + units = getUrlStringParameter("units", units || "metric"); + nightMode = getUrlStringParameter("nightMode", nightMode || "off"); + rotation = getUrlStringParameter("rotation", rotation); + utcOffset = getUrlStringParameter("utcOffset", utcOffset); + tempType = getUrlStringParameter("tempType", tempType || "actual"); + forecastType = getUrlStringParameter("forecastType", forecastType || "hour"); + refreshInterval = getUrlNumberParameter("refreshInterval", refreshInterval || 30); // in minutes + rtcSleepMode = getUrlBooleanParameter("rtcSleepMode", !!rtcSleepMode); + rtcWakeDelay = getUrlNumberParameter("rtcWakeDelay", rtcWakeDelay || 15); // in seconds var dataTimeZone = 0; @@ -366,23 +391,13 @@ var _apiParams = null; - if (!refreshTime) { - refreshTime = 30 * 60 * 1000; // default 30 minutes - } - if (!rtcWakeDelay) { - rtcWakeDelay = 15 * 1000; // default 15 seconds - } - if (!forecastType) { - forecastType = "hour"; - } function rotate() { - var rot = getUrlParameter("rotation") ? getUrlParameter("rotation") : rotation; - + var v = viewport(); var isPortrait = v.height > v.width; - if (isPortrait && rot === "ll") { + if (isPortrait && rotation === "ll") { // landscape left page.className = "landscape"; forcedRotation = true; @@ -396,7 +411,7 @@ page.style.height = v.width + "px"; page.style.width = v.height + "px"; - } else if (isPortrait && rot === "lr") { + } else if (isPortrait && rotation === "lr") { // landscape right page.className = "landscape"; forcedRotation = true; @@ -410,7 +425,7 @@ page.style.height = v.width + "px"; page.style.width = v.height + "px"; - } else if (rot === "up") { + } else if (rotation === "up") { // upside down page.className = isPortrait ? "portrait" : "landscape"; forcedRotation = false; @@ -443,6 +458,7 @@ _apiParams = getApiParams(); if (_apiParams === null) { window.location = "config.html"; + return; } moment.locale(momentLocale()); @@ -453,8 +469,8 @@ temp = document.getElementById("temp"); icon = document.getElementById("icon"); - city = document.getElementById("city"); - city.addEventListener('click', function (event) { + cityName = document.getElementById("city"); + cityName.addEventListener('click', function (event) { event.preventDefault(); window.location.href = window.location.href.replace("/index.html", "/config.html"); return false @@ -498,13 +514,13 @@ setInterval(function() { var now = new Date().getTime(); var sinceRefresh = now - lastRefresh; - if (sinceRefresh > refreshTime && !wakeDelayActive) { + if (sinceRefresh > refreshInterval * 60 * 1000 && !wakeDelayActive) { wakeDelayActive = true; setTimeout(function() { lastRefresh = new Date().getTime(); refreshData(); wakeDelayActive = false; - }, rtcWakeDelay); + }, rtcWakeDelay * 1000); } }, 1000); } @@ -559,7 +575,7 @@ } function isNightMode() { - var mode = getUrlParameter("night") ? getUrlParameter("night") : night_mode; + var mode = nightMode; if (mode === "on") { return true; } @@ -591,9 +607,8 @@ } function momentLocale() { - var lang = getUrlParameter("lang") ? getUrlParameter("lang") : api_lang; if (typeof(lang) === 'string') { - var langs = lang.split(";", 2) + var langs = String(lang).split(";", 2) return langs.length > 1 ? langs[1] : langs[0]; } else { return null;