mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-04-20 11:54:23 +02:00
468 lines
12 KiB
Markdown
468 lines
12 KiB
Markdown
|
Creates a button on the bar which displays the current weather condition and temperature.
|
||
|
Clicking the button opens a popup with forecast information for the next few days.
|
||
|
|
||
|
Weather information is fetched from [wttr.in](https://wttr.in) via an external script.
|
||
|
You will need to set up the script to be run as a service.
|
||
|
|
||
|

|
||
|
|
||
|
## Configuration
|
||
|
|
||
|
<details>
|
||
|
<summary>JSON</summary>
|
||
|
|
||
|
```json
|
||
|
{
|
||
|
"end": [
|
||
|
{
|
||
|
"type": "custom",
|
||
|
"class": "weather",
|
||
|
"bar": [
|
||
|
{
|
||
|
"type": "button",
|
||
|
"label": "#weather_current",
|
||
|
"on_click": "popup:toggle"
|
||
|
}
|
||
|
],
|
||
|
"popup": [
|
||
|
{
|
||
|
"type": "box",
|
||
|
"orientation": "vertical",
|
||
|
"widgets": [
|
||
|
{
|
||
|
"type": "label",
|
||
|
"name": "header",
|
||
|
"label": "Forecast"
|
||
|
},
|
||
|
{
|
||
|
"type": "box",
|
||
|
"widgets": [
|
||
|
{
|
||
|
"type": "box",
|
||
|
"name": "dates",
|
||
|
"orientation": "vertical",
|
||
|
"widgets": [
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-date",
|
||
|
"label": "#weather_date_0"
|
||
|
},
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-date",
|
||
|
"label": "#weather_date_1"
|
||
|
},
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-date",
|
||
|
"label": "#weather_date_2"
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"type": "box",
|
||
|
"name": "temps",
|
||
|
"orientation": "vertical",
|
||
|
"widgets": [
|
||
|
{
|
||
|
"type": "box",
|
||
|
"widgets": [
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-high",
|
||
|
"label": " #weather_high_0"
|
||
|
},
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-avg",
|
||
|
"label": " #weather_avg_0"
|
||
|
},
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-low",
|
||
|
"label": " #weather_low_0"
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"type": "box",
|
||
|
"widgets": [
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-high",
|
||
|
"label": " #weather_high_1"
|
||
|
},
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-avg",
|
||
|
"label": " #weather_avg_1"
|
||
|
},
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-low",
|
||
|
"label": " #weather_low_1"
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"type": "box",
|
||
|
"widgets": [
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-high",
|
||
|
"label": " #weather_high_2"
|
||
|
},
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-avg",
|
||
|
"label": " #weather_avg_2"
|
||
|
},
|
||
|
{
|
||
|
"type": "label",
|
||
|
"class": "weather-low",
|
||
|
"label": " #weather_low_2"
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
```
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary>TOML</summary>
|
||
|
|
||
|
```toml
|
||
|
[[end]]
|
||
|
type = "custom"
|
||
|
class = "weather"
|
||
|
|
||
|
[[end.bar]]
|
||
|
type = "button"
|
||
|
label = "#weather_current"
|
||
|
on_click = "popup:toggle"
|
||
|
|
||
|
[[end.popup]]
|
||
|
type = "box"
|
||
|
orientation = "vertical"
|
||
|
|
||
|
[[end.popup.widgets]]
|
||
|
type = "label"
|
||
|
name = "header"
|
||
|
label = "Forecast"
|
||
|
|
||
|
[[end.popup.widgets]]
|
||
|
type = "box"
|
||
|
|
||
|
[[end.popup.widgets.widgets]]
|
||
|
type = "box"
|
||
|
name = "dates"
|
||
|
orientation = "vertical"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-date"
|
||
|
label = "#weather_date_0"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-date"
|
||
|
label = "#weather_date_1"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-date"
|
||
|
label = "#weather_date_2"
|
||
|
|
||
|
[[end.popup.widgets.widgets]]
|
||
|
type = "box"
|
||
|
name = "temps"
|
||
|
orientation = "vertical"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets]]
|
||
|
type = "box"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-high"
|
||
|
label = " #weather_high_0"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-avg"
|
||
|
label = " #weather_avg_0"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-low"
|
||
|
label = " #weather_low_0"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets]]
|
||
|
type = "box"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-high"
|
||
|
label = " #weather_high_1"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-avg"
|
||
|
label = " #weather_avg_1"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-low"
|
||
|
label = " #weather_low_1"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets]]
|
||
|
type = "box"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-high"
|
||
|
label = " #weather_high_2"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-avg"
|
||
|
label = " #weather_avg_2"
|
||
|
|
||
|
[[end.popup.widgets.widgets.widgets.widgets]]
|
||
|
type = "label"
|
||
|
class = "weather-low"
|
||
|
label = " #weather_low_2"
|
||
|
```
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary>YAML</summary>
|
||
|
|
||
|
```yaml
|
||
|
end:
|
||
|
- type: custom
|
||
|
class: weather
|
||
|
bar:
|
||
|
- type: button
|
||
|
label: '#weather_current'
|
||
|
on_click: popup:toggle
|
||
|
popup:
|
||
|
- type: box
|
||
|
orientation: vertical
|
||
|
widgets:
|
||
|
- type: label
|
||
|
name: header
|
||
|
label: Forecast
|
||
|
- type: box
|
||
|
widgets:
|
||
|
- type: box
|
||
|
name: dates
|
||
|
orientation: vertical
|
||
|
widgets:
|
||
|
- type: label
|
||
|
class: weather-date
|
||
|
label: '#weather_date_0'
|
||
|
- type: label
|
||
|
class: weather-date
|
||
|
label: '#weather_date_1'
|
||
|
- type: label
|
||
|
class: weather-date
|
||
|
label: '#weather_date_2'
|
||
|
- type: box
|
||
|
name: temps
|
||
|
orientation: vertical
|
||
|
widgets:
|
||
|
- type: box
|
||
|
widgets:
|
||
|
- type: label
|
||
|
class: weather-high
|
||
|
label: ' #weather_high_0'
|
||
|
- type: label
|
||
|
class: weather-avg
|
||
|
label: ' #weather_avg_0'
|
||
|
- type: label
|
||
|
class: weather-low
|
||
|
label: ' #weather_low_0'
|
||
|
- type: box
|
||
|
widgets:
|
||
|
- type: label
|
||
|
class: weather-high
|
||
|
label: ' #weather_high_1'
|
||
|
- type: label
|
||
|
class: weather-avg
|
||
|
label: ' #weather_avg_1'
|
||
|
- type: label
|
||
|
class: weather-low
|
||
|
label: ' #weather_low_1'
|
||
|
- type: box
|
||
|
widgets:
|
||
|
- type: label
|
||
|
class: weather-high
|
||
|
label: ' #weather_high_2'
|
||
|
- type: label
|
||
|
class: weather-avg
|
||
|
label: ' #weather_avg_2'
|
||
|
- type: label
|
||
|
class: weather-low
|
||
|
label: ' #weather_low_2'
|
||
|
```
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary>Corn</summary>
|
||
|
|
||
|
|
||
|
```corn
|
||
|
let {
|
||
|
$weather = {
|
||
|
type = "custom"
|
||
|
class = "weather"
|
||
|
|
||
|
bar = [ { type = "button" label = "#weather_current" on_click = "popup:toggle" } ]
|
||
|
popup = [ {
|
||
|
type = "box"
|
||
|
orientation = "vertical"
|
||
|
|
||
|
widgets = [
|
||
|
{ type = "label" name = "header" label = "Forecast" }
|
||
|
{
|
||
|
type = "box"
|
||
|
widgets = [
|
||
|
{ type = "box" name="dates" orientation = "vertical" widgets = [
|
||
|
{ type = "label" class="weather-date" label = "#weather_date_0" }
|
||
|
{ type = "label" class="weather-date" label = "#weather_date_1" }
|
||
|
{ type = "label" class="weather-date" label = "#weather_date_2" }
|
||
|
]}
|
||
|
{ type = "box" name="temps" orientation = "vertical" widgets = [
|
||
|
{
|
||
|
type = "box"
|
||
|
widgets = [
|
||
|
{ type = "label" class="weather-high" label = " #weather_high_0" }
|
||
|
{ type = "label" class="weather-avg" label = " #weather_avg_0" }
|
||
|
{ type = "label" class="weather-low" label = " #weather_low_0" }
|
||
|
]
|
||
|
}
|
||
|
{
|
||
|
type = "box"
|
||
|
widgets = [
|
||
|
{ type = "label" class="weather-high" label = " #weather_high_1" }
|
||
|
{ type = "label" class="weather-avg" label = " #weather_avg_1" }
|
||
|
{ type = "label" class="weather-low" label = " #weather_low_1" }
|
||
|
]
|
||
|
}
|
||
|
{
|
||
|
type = "box"
|
||
|
widgets = [
|
||
|
{ type = "label" class="weather-high" label = " #weather_high_2" }
|
||
|
{ type = "label" class="weather-avg" label = " #weather_avg_2" }
|
||
|
{ type = "label" class="weather-low" label = " #weather_low_2" }
|
||
|
]
|
||
|
}
|
||
|
] }
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
} ]
|
||
|
}
|
||
|
} in {
|
||
|
end = [ $weather ]
|
||
|
}
|
||
|
```
|
||
|
|
||
|
</details>
|
||
|
|
||
|
## Script
|
||
|
|
||
|
Run the following script on a timer. Ensure to fill out your city name.
|
||
|
|
||
|
```js
|
||
|
#!/usr/bin/env zx
|
||
|
|
||
|
const location = "Canterbury";
|
||
|
|
||
|
// JS uses Sunday as first day
|
||
|
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
|
||
|
|
||
|
// bar logic
|
||
|
|
||
|
|
||
|
const data = await fetch(`https://wttr.in/${location}?format=%c %t|%m %t|%S|%s`)
|
||
|
.then(r => r.text());
|
||
|
|
||
|
const [day, night, sunrise, sunset] = data.replaceAll("+", "").split("|");
|
||
|
const [sunriseH, sunriseM, sunriseS] = sunrise.split(":");
|
||
|
const [sunsetH, sunsetM, sunsetS] = sunset.split(":");
|
||
|
|
||
|
const currentTime = new Date();
|
||
|
|
||
|
const sunriseTime = new Date(currentTime);
|
||
|
sunriseTime.setHours(sunriseH);
|
||
|
sunriseTime.setMinutes(sunriseM);
|
||
|
sunriseTime.setSeconds(sunriseS);
|
||
|
|
||
|
const sunsetTime = new Date(currentTime);
|
||
|
sunsetTime.setHours(sunsetH);
|
||
|
sunsetTime.setMinutes(sunsetM);
|
||
|
sunsetTime.setSeconds(sunsetS);
|
||
|
|
||
|
let value = day;
|
||
|
if(currentTime < sunriseTime || currentTime > sunsetTime) value = night;
|
||
|
|
||
|
await $`ironbar set weather_current ${value}`;
|
||
|
|
||
|
// popup logic
|
||
|
|
||
|
const forecast = await fetch(`https://wttr.in/${location}?format=j1`).then(r => r.json());
|
||
|
|
||
|
for (const i in forecast.weather) {
|
||
|
const report = forecast.weather[i];
|
||
|
|
||
|
const day = weekday[new Date(report.date).getDay()];
|
||
|
|
||
|
await $`ironbar set weather_date_${i} ${day}`;
|
||
|
await $`ironbar set weather_avg_${i} ${report.avgtempC.padStart(2, "0")}`;
|
||
|
await $`ironbar set weather_high_${i} ${report.maxtempC.padStart(2, "0")}`;
|
||
|
await $`ironbar set weather_low_${i} ${report.mintempC.padStart(2, "0")}`;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Styling
|
||
|
|
||
|
```css
|
||
|
.popup-weather #header {
|
||
|
font-size: 1.8em;
|
||
|
padding-bottom: 0.4em;
|
||
|
margin-bottom: 0.6em;
|
||
|
border-bottom: 1px solid @color-border;
|
||
|
}
|
||
|
|
||
|
.popup-weather .weather-date {
|
||
|
font-size: 1.5em;
|
||
|
padding-right: 1em;
|
||
|
}
|
||
|
|
||
|
.popup-weather .weather-avg {
|
||
|
margin-left: 0.5em;
|
||
|
margin-right: 0.5em;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
this is a hack to align the different font sizes on left/right
|
||
|
you may need to adjust for different fonts
|
||
|
*/
|
||
|
.popup-weather #temps label {
|
||
|
padding-top: 0.2em;
|
||
|
margin-bottom: 0.7em;
|
||
|
}
|
||
|
```
|