weather 0.28: Fix UV positioning, hide when 0
parent
7ace5bd00d
commit
787696ddf2
|
|
@ -23,4 +23,5 @@
|
||||||
0.24: Redraw clock_info on update and provide color field for condition
|
0.24: Redraw clock_info on update and provide color field for condition
|
||||||
0.25: Added monochrome parameter to drawIcon in lib
|
0.25: Added monochrome parameter to drawIcon in lib
|
||||||
0.26: Expose update function (for use by iOS integration)
|
0.26: Expose update function (for use by iOS integration)
|
||||||
0.27: Add UV index display
|
0.27: Add UV index display
|
||||||
|
0.28: Fix UV positioning, hide when 0
|
||||||
|
|
@ -7,8 +7,11 @@ It also adds a ClockInfo list to Bangle.js.
|
||||||
You can view the full report through the app:
|
You can view the full report through the app:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## iOS Setup
|
## iOS Setup
|
||||||
Use the iOS shortcut [here](https://www.icloud.com/shortcuts/dbf7159200d945179e0938c15e64f102). The shortcut uses Apple Weather for weather updates, and sends a notification, which is read by Bangle.js. To push weather every hour, or interval, you will need to create a shortcut automation for every time you want to push the weather.
|
|
||||||
|
Use the iOS shortcut [here](https://www.icloud.com/shortcuts/ae5f3d7d6ed3460c98a3396b267aa1c5). The shortcut uses Apple Weather for weather updates, and sends a notification, which is read by Bangle.js. To push weather every hour, or interval, you will need to create a shortcut automation for every time you want to push the weather.
|
||||||
|
|
||||||
## Android Setup
|
## Android Setup
|
||||||
|
|
||||||
1. Install [Gadgetbridge for Android](https://f-droid.org/packages/nodomain.freeyourgadget.gadgetbridge/) on your phone.
|
1. Install [Gadgetbridge for Android](https://f-droid.org/packages/nodomain.freeyourgadget.gadgetbridge/) on your phone.
|
||||||
|
|
@ -51,8 +54,8 @@ When you first load QuickWeather, it will take you through the setup process. Yo
|
||||||
|
|
||||||
**Note:** at one time, the Weather Notification app also worked with Gadgetbridge. However, many users are reporting it's no longer seeing the OpenWeatherMap API key as valid. The app has not received any updates since August of 2020, and may be unmaintained.
|
**Note:** at one time, the Weather Notification app also worked with Gadgetbridge. However, many users are reporting it's no longer seeing the OpenWeatherMap API key as valid. The app has not received any updates since August of 2020, and may be unmaintained.
|
||||||
|
|
||||||
|
|
||||||
## Clock Infos
|
## Clock Infos
|
||||||
|
|
||||||
Tap on any clockInfo when focused to directly open the weather app.
|
Tap on any clockInfo when focused to directly open the weather app.
|
||||||
Adds:
|
Adds:
|
||||||
* Condition ClockInfo with condition icon
|
* Condition ClockInfo with condition icon
|
||||||
|
|
@ -60,6 +63,7 @@ Adds:
|
||||||
* Wind speed ClockInfo.
|
* Wind speed ClockInfo.
|
||||||
* Chance of rain ClockInfo.
|
* Chance of rain ClockInfo.
|
||||||
* Temperature ClockInfo without condition icon.
|
* Temperature ClockInfo without condition icon.
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
* Expiration timespan can be set after which the local weather data is considered as invalid
|
* Expiration timespan can be set after which the local weather data is considered as invalid
|
||||||
|
|
|
||||||
|
|
@ -9,38 +9,9 @@ Bangle.loadWidgets();
|
||||||
var layout = new Layout({type:"v", bgCol: g.theme.bg, c: [
|
var layout = new Layout({type:"v", bgCol: g.theme.bg, c: [
|
||||||
{filly: 1},
|
{filly: 1},
|
||||||
{type: "h", filly: 0, c: [
|
{type: "h", filly: 0, c: [
|
||||||
{type: "v", width: g.getWidth()/2, c: [ // Vertical container for icon + UV
|
{type: "v", width: g.getWidth()/2, c: [ // Vertical container for icon
|
||||||
{type: "custom", fillx: 1, height: g.getHeight()/2 - 30, valign: -1, txt: "unknown", id: "icon",
|
{type: "custom", fillx: 1, height: g.getHeight()/2 - 30, valign: -1, txt: "unknown", id: "icon",
|
||||||
render: l => weather.drawIcon(l, l.x+l.w/2, l.y+l.h/2, l.w/2-10)},
|
render: l => weather.drawIcon(l, l.x+l.w/2, l.y+l.h/2, l.w/2-5)},
|
||||||
{type: "custom", fillx: 1, height: 20, id: "uvDisplay",
|
|
||||||
render: l => {
|
|
||||||
if (!current || current.uv === undefined) return;
|
|
||||||
const uv = Math.min(parseInt(current.uv), 11); // Cap at 11
|
|
||||||
|
|
||||||
// UV color thresholds: [max_value, color] based on WHO standards
|
|
||||||
const colors = [[2,"#0F0"], [5,"#FF0"], [7,"#F80"], [10,"#F00"], [11,"#F0F"]];
|
|
||||||
const color = colors.find(c => uv <= c[0])[1];
|
|
||||||
|
|
||||||
// Setup and measure label
|
|
||||||
g.setFont("6x8").setFontAlign(-1, 0);
|
|
||||||
const label = "UV: ";
|
|
||||||
const labelW = g.stringWidth(label);
|
|
||||||
|
|
||||||
// Calculate centered position (4px block + 1px spacing) * blocks - last spacing
|
|
||||||
const totalW = labelW + uv * 5 - (uv > 0 ? 1 : 0);
|
|
||||||
const x = l.x + (l.w - totalW) / 2;
|
|
||||||
const y = l.y + l.h;
|
|
||||||
|
|
||||||
// Draw label
|
|
||||||
g.setColor(g.theme.fg).drawString(label, x, y);
|
|
||||||
|
|
||||||
// Draw UV blocks
|
|
||||||
g.setColor(color);
|
|
||||||
for (let i = 0; i < uv; i++) {
|
|
||||||
g.fillRect(x + labelW + i * 5, y - 3, x + labelW + i * 5 + 3, y + 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]},
|
]},
|
||||||
{type: "v", fillx: 1, c: [
|
{type: "v", fillx: 1, c: [
|
||||||
{type: "h", pad: 2, c: [
|
{type: "h", pad: 2, c: [
|
||||||
|
|
@ -50,12 +21,43 @@ var layout = new Layout({type:"v", bgCol: g.theme.bg, c: [
|
||||||
{filly: 1},
|
{filly: 1},
|
||||||
{type: "txt", font: "6x8", pad: 2, halign: 1, label: /*LANG*/"Humidity"},
|
{type: "txt", font: "6x8", pad: 2, halign: 1, label: /*LANG*/"Humidity"},
|
||||||
{type: "txt", font: "9%", pad: 2, halign: 1, id: "hum", label: "000%"},
|
{type: "txt", font: "9%", pad: 2, halign: 1, id: "hum", label: "000%"},
|
||||||
{filly: 1},
|
{type: "txt", font: "6x8", pad: [2, 2, 2, 2], halign: -1, label: /*LANG*/"Wind"},
|
||||||
{type: "txt", font: "6x8", pad: 2, halign: -1, label: /*LANG*/"Wind"},
|
{type: "h", pad: [0, 2, 2, 2], halign: -1, c: [
|
||||||
{type: "h", halign: -1, c: [
|
|
||||||
{type: "txt", font: "9%", pad: 2, id: "wind", label: "00"},
|
{type: "txt", font: "9%", pad: 2, id: "wind", label: "00"},
|
||||||
{type: "txt", font: "6x8", pad: 2, valign: -1, id: "windUnit", label: "km/h"},
|
{type: "txt", font: "6x8", pad: 2, valign: -1, id: "windUnit", label: "km/h"},
|
||||||
]},
|
]},
|
||||||
|
{type: "custom", fillx: 1, height: 15, id: "uvDisplay",
|
||||||
|
render: l => {
|
||||||
|
if (!current || current.uv === undefined || current.uv === 0) return;
|
||||||
|
const uv = Math.min(parseInt(current.uv), 11); // Cap at 11
|
||||||
|
|
||||||
|
// UV color thresholds: [max_value, color] based on WHO standards
|
||||||
|
const colors = [[2,"#0F0"], [5,"#FF0"], [7,"#F80"], [10,"#F00"], [11,"#F0F"]];
|
||||||
|
const color = colors.find(c => uv <= c[0])[1];
|
||||||
|
const blockH = 8, blockW = 3;
|
||||||
|
|
||||||
|
// Draw UV title and blocks on same line
|
||||||
|
g.setFont("6x8").setFontAlign(-1, 0);
|
||||||
|
const label = "UV";
|
||||||
|
const labelW = g.stringWidth(label);
|
||||||
|
|
||||||
|
const x = l.x + 2;
|
||||||
|
const y = l.y + l.h / 2;
|
||||||
|
|
||||||
|
// Draw title
|
||||||
|
g.setColor(g.theme.fg).drawString(label, x, y);
|
||||||
|
|
||||||
|
// Draw UV blocks after title
|
||||||
|
g.setColor(color);
|
||||||
|
for (let i = 0; i < uv; i++) {
|
||||||
|
const blockX = x + labelW + 4 + i * (blockW + 2);
|
||||||
|
g.fillRect(blockX, y - blockH/2, blockX + blockW, y + blockW/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset graphics state to prevent interference
|
||||||
|
g.reset();
|
||||||
|
}
|
||||||
|
},
|
||||||
]},
|
]},
|
||||||
]},
|
]},
|
||||||
{filly: 1},
|
{filly: 1},
|
||||||
|
|
@ -91,6 +93,7 @@ function draw() {
|
||||||
layout.loc.label = current.loc;
|
layout.loc.label = current.loc;
|
||||||
layout.updateTime.label = `${formatDuration(Date.now() - current.time)} ago`; // How to autotranslate this and similar?
|
layout.updateTime.label = `${formatDuration(Date.now() - current.time)} ago`; // How to autotranslate this and similar?
|
||||||
layout.update();
|
layout.update();
|
||||||
|
layout.forgetLazyState();
|
||||||
layout.render();
|
layout.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "weather",
|
"id": "weather",
|
||||||
"name": "Weather",
|
"name": "Weather",
|
||||||
"version": "0.27",
|
"version": "0.28",
|
||||||
"description": "Show Gadgetbridge/iOS weather report",
|
"description": "Show Gadgetbridge/iOS weather report",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"screenshots": [{"url":"screenshot.png"}],
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue