diff --git a/apps/owmweather/ChangeLog b/apps/owmweather/ChangeLog
new file mode 100644
index 000000000..5560f00bc
--- /dev/null
+++ b/apps/owmweather/ChangeLog
@@ -0,0 +1 @@
+0.01: New App!
diff --git a/apps/owmweather/README.md b/apps/owmweather/README.md
new file mode 100644
index 000000000..694724c4a
--- /dev/null
+++ b/apps/owmweather/README.md
@@ -0,0 +1,13 @@
+# Open Weather Map weather provider
+
+This updates [Weather](https://banglejs.com/apps/#weather) with data from the Open Weather Map API
+
+## Usage
+
+Just install and configure the app. This needs an internet-enabled Gadgetbridge version.
+Install [My Location](https://banglejs.com/apps/#mylocation) to change the location for the weather requests.
+Install one of the text input libraries to modify the API key in the settings
+
+## Creator
+
+[halemmerich](https://github.com/halemmerich)
diff --git a/apps/owmweather/app.png b/apps/owmweather/app.png
new file mode 100644
index 000000000..bbfc0ace0
Binary files /dev/null and b/apps/owmweather/app.png differ
diff --git a/apps/owmweather/boot.js b/apps/owmweather/boot.js
new file mode 100644
index 000000000..64d2df3e9
--- /dev/null
+++ b/apps/owmweather/boot.js
@@ -0,0 +1,28 @@
+(function() {
+ let waiting = false;
+ let settings = require("Storage").readJSON("owmweather.json", 1) || {
+ enabled: false
+ };
+
+ function completion(){
+ waiting = false;
+ }
+
+ if (settings.enabled) {
+ let weather = require("Storage").readJSON('weather.json') || {};
+ let lastUpdate;
+ if (weather && weather.weather && weather.weather.time) lastUpdate = weather.weather.time;
+ if (!lastUpdate || lastUpdate + settings.refresh * 1000 * 60 < Date.now()){
+ if (!waiting){
+ waiting = true;
+ require("owmweather").pull(completion);
+ }
+ }
+ setInterval(() => {
+ if (!waiting && NRF.getSecurityStatus().connected){
+ waiting = true;
+ require("owmweather").pull(completion);
+ }
+ }, settings.refresh * 1000 * 60);
+ }
+})();
diff --git a/apps/owmweather/default.json b/apps/owmweather/default.json
new file mode 100644
index 000000000..9d8998867
--- /dev/null
+++ b/apps/owmweather/default.json
@@ -0,0 +1 @@
+{"enabled":false,"refresh":180}
diff --git a/apps/owmweather/interface.html b/apps/owmweather/interface.html
new file mode 100644
index 000000000..f629a5be9
--- /dev/null
+++ b/apps/owmweather/interface.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+ Set OWM API key
+
+
+
+
+
+
+
+
diff --git a/apps/owmweather/lib.js b/apps/owmweather/lib.js
new file mode 100644
index 000000000..6ba52b498
--- /dev/null
+++ b/apps/owmweather/lib.js
@@ -0,0 +1,53 @@
+function parseWeather(response) {
+ let owmData = JSON.parse(response);
+
+ let isOwmData = owmData.coord && owmData.weather && owmData.main;
+
+ if (isOwmData) {
+ let json = require("Storage").readJSON('weather.json') || {};
+ let weather = {};
+ weather.time = Date.now();
+ weather.hum = owmData.main.humidity;
+ weather.temp = owmData.main.temp;
+ weather.code = owmData.weather[0].id;
+ weather.wdir = owmData.wind.deg;
+ weather.wind = owmData.wind.speed;
+ weather.loc = owmData.name;
+ weather.txt = owmData.weather[0].main;
+
+ if (weather.wdir != null) {
+ let deg = weather.wdir;
+ while (deg < 0 || deg > 360) {
+ deg = (deg + 360) % 360;
+ }
+ weather.wrose = ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'n'][Math.floor((deg + 22.5) / 45)];
+ }
+
+ json.weather = weather;
+ require("Storage").writeJSON('weather.json', json);
+ require("weather").emit("update", json.weather);
+ return undefined;
+ } else {
+ return /*LANG*/"Not OWM data";
+ }
+}
+
+exports.pull = function(completionCallback) {
+ let location = require("Storage").readJSON("mylocation.json", 1) || {
+ "lat": 51.50,
+ "lon": 0.12,
+ "location": "London"
+ };
+ let settings = require("Storage").readJSON("owmweather.json", 1);
+ let uri = "https://api.openweathermap.org/data/2.5/weather?lat=" + location.lat.toFixed(2) + "&lon=" + location.lon.toFixed(2) + "&exclude=hourly,daily&appid=" + settings.apikey;
+ if (Bangle.http){
+ Bangle.http(uri, {timeout:10000}).then(event => {
+ let result = parseWeather(event.resp);
+ if (completionCallback) completionCallback(result);
+ }).catch((e)=>{
+ if (completionCallback) completionCallback(e);
+ });
+ } else {
+ if (completionCallback) completionCallback(/*LANG*/"No http method found");
+ }
+};
diff --git a/apps/owmweather/metadata.json b/apps/owmweather/metadata.json
new file mode 100644
index 000000000..d0229656d
--- /dev/null
+++ b/apps/owmweather/metadata.json
@@ -0,0 +1,22 @@
+{ "id": "owmweather",
+ "name": "Open Weather Map weather provider",
+ "shortName":"OWM Weather",
+ "version":"0.01",
+ "description": "Pulls weather from OWM API",
+ "icon": "app.png",
+ "type": "bootloader",
+ "tags": "boot,tool,weather",
+ "supports" : ["BANGLEJS2"],
+ "interface": "interface.html",
+ "readme": "README.md",
+ "data": [
+ {"name":"owmweather.json"},
+ {"name":"weather.json"}
+ ],
+ "storage": [
+ {"name":"owmweather.default.json","url":"default.json"},
+ {"name":"owmweather.boot.js","url":"boot.js"},
+ {"name":"owmweather","url":"lib.js"},
+ {"name":"owmweather.settings.js","url":"settings.js"}
+ ]
+}
diff --git a/apps/owmweather/settings.js b/apps/owmweather/settings.js
new file mode 100644
index 000000000..a4d21dd7c
--- /dev/null
+++ b/apps/owmweather/settings.js
@@ -0,0 +1,84 @@
+(function(back) {
+ function writeSettings(key, value) {
+ var s = require('Storage').readJSON(FILE, true) || {};
+ s[key] = value;
+ require('Storage').writeJSON(FILE, s);
+ readSettings();
+ }
+
+ function readSettings(){
+ settings = Object.assign(
+ require('Storage').readJSON("owmweather.default.json", true) || {},
+ require('Storage').readJSON(FILE, true) || {}
+ );
+ }
+
+ var FILE="owmweather.json";
+ var settings;
+ readSettings();
+
+ function buildMainMenu(){
+ var mainmenu = {
+ '': { 'title': 'OWM weather' },
+ '< Back': back,
+ "Enabled": {
+ value: !!settings.enabled,
+ onchange: v => {
+ writeSettings("enabled", v);
+ }
+ },
+ "Refresh every": {
+ value: settings.refresh / 60,
+ min: 1,
+ max: 48,
+ step: 1,
+ format: v=>v+"h",
+ onchange: v => {
+ writeSettings("refresh",Math.round(v * 60));
+ }
+ },
+ "Force refresh": ()=>{
+ if (!settings.apikey){
+ E.showAlert("API key is needed","Hint").then(()=>{
+ E.showMenu(buildMainMenu());
+ });
+ } else {
+ E.showMessage("Reloading weather");
+ require("owmweather").pull((e)=>{
+ if (e) {
+ E.showAlert(e,"Error").then(()=>{
+ E.showMenu(buildMainMenu());
+ });
+ } else {
+ E.showAlert("Success").then(()=>{
+ E.showMenu(buildMainMenu());
+ });
+ }
+ });
+ }
+ }
+ };
+
+ mainmenu["API key"] = function (){
+ if (require("textinput")){
+ require("textinput").input({text:settings.apikey}).then(result => {
+ if (result != "") {
+ print("Result is", result);
+ settings.apikey = result;
+ writeSettings("apikey",result);
+ }
+ E.showMenu(buildMainMenu());
+ });
+ } else {
+ E.showPrompt("Install a text input lib"),then(()=>{
+ E.showMenu(buildMainMenu());
+ });
+ }
+ };
+
+
+ return mainmenu;
+ }
+
+ E.showMenu(buildMainMenu());
+});