Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 20 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,44 +34,36 @@ 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
* press the search button (or keyboard button on Kindle 4) again and type: `~disableScreensaver` and press enter on the keyboard. (On Kindle Paperwhite, type: `~ds` - with new firmware this may not be possible, but see these [instructions](https://github.com/matopeto/kindle-weather-dashboard/issues/16) for a solution)
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`
Expand Down
8 changes: 4 additions & 4 deletions config.html
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ <h1>Kindle Weather Dashboard<br/>Config Page</h1>
</div>
<div>
<label>Night Mode: <br/>
<select name="night" id="night">
<select name="nightMode" id="nightMode">
<option value="">default</option>
<option value="off">off</option>
<option value="auto">sunset - sunrise</option>
Expand All @@ -173,7 +173,7 @@ <h1>Kindle Weather Dashboard<br/>Config Page</h1>
</label>
</div>
<div>
<label>Refresh time (leave it blank for default): <br/><input type="text" name="refreshTime" id="refreshTime"/></label>
<label>Refresh interval in minutes (leave it blank for default): <br/><input type="text" name="refreshInterval" id="refreshInterval"/></label>
</div>
<div>
<label>OWM appid (leave it blank for default): <br/><input type="text" name="appId" id="appId"/></label>
Expand Down Expand Up @@ -204,12 +204,12 @@ <h1>Kindle Weather Dashboard<br/>Config Page</h1>
setIfPresent("lang");
setIfPresent("rotation");
setIfPresent("units");
setIfPresent("night");
setIfPresent("nightMode");
setIfPresent("appId");
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

appId premenovat mozno na apiKey alebo nieco podobne

setIfPresent("utcOffset");
setIfPresent("tempType");
setIfPresent("forecastType");
setIfPresent("refreshTime");
setIfPresent("refreshInterval");
</script>
</body>
</html>
21 changes: 12 additions & 9 deletions config.js.sample
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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".
Expand Down
133 changes: 74 additions & 59 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
refreshForecastWeather();

if (!rtcSleepMode) {
window.setTimeout("refreshData()", refreshTime);
window.setTimeout("refreshData()", refreshInterval * 60 * 1000);
}
}

Expand Down Expand Up @@ -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) {
Expand All @@ -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)
Expand All @@ -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, '\\$&');
};
Expand All @@ -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);

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -443,6 +458,7 @@
_apiParams = getApiParams();
if (_apiParams === null) {
window.location = "config.html";
return;
}

moment.locale(momentLocale());
Expand All @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -559,7 +575,7 @@
}

function isNightMode() {
var mode = getUrlParameter("night") ? getUrlParameter("night") : night_mode;
var mode = nightMode;
if (mode === "on") {
return true;
}
Expand Down Expand Up @@ -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;
Expand Down