FlowAWTRIX 3
OWM forecast (openweathermap)
On an AWTRIX display

On your display
openweathermap forecast
- Works with
- AWTRIX NG
- Topic
- Miscellaneous
- Includes
- Script
Choose your display in the next step.
Flow description
needs a openweathermap.org api_keys it is "free"
jkWnhf8DrABT.ax
# @name Weather OWM
# @desc Temperature, humidity, and weather conditions from OpenWeatherMap
# @author the mighty MiMo
# @version 2.6
# @config city text "City" default="Arlöv" help="Spaces and å, ä, ö are encoded automatically"
# @config key text "API key" default="" help="OpenWeatherMap API key"
# @config every number "Refresh" default=10 min=1 max=120 unit=min help="Minutes between fetches"
# @config show_icon bool "Weather icon" default=true help="8x8 symbol (sun/cloud/rain/snow/thunder)"
# @config show_hum bool "Humidity" default=true help="Show % next to the temperature"
# @config show_desc bool "Description" default=true help="Scroll e.g. 'clear sky'"
# @config show_wind bool "Wind" default=true help="Include m/s in the scroll line"
import json
import string
class WeatherOWM
var url # built once from the settings
var key # OpenWeatherMap API key, empty if not set yet
var temp # latest temperature in °C, nil until the first answer
var hum # humidity in %
var sky # 0 clear, 1 clouds, 2 rain, 3 snow, 4 thunder
var label # temperature as a string, e.g. "16°"
var desc # OWM description, e.g. "clear sky"
var windtxt # e.g. "5 m/s wind"
var line # finished scroll line, built from the flags
var ticks # loop() until the next fetch
var period # seconds between fetches
var in_flight # true while a request is running
var page # 0 = numbers, 1 = scrolling text
var shown_at # now_ms() when the app came up
var o_icon, o_hum, o_desc, o_wind # on/off settings
def init()
self.key = store.get("key", "")
self.url = "https://api.openweathermap.org/data/2.5/weather?q=" +
self.enc(store.get("city")) +
"&appid=" + self.key +
"&units=metric&lang=en"
self.period = store.get("every") * 60
self.o_icon = store.get("show_icon")
self.o_hum = store.get("show_hum")
self.o_desc = store.get("show_desc")
self.o_wind = store.get("show_wind")
self.temp = store.get("temp")
self.hum = store.get("hum")
self.sky = store.get("sky", 0)
self.desc = store.get("desc", "")
self.windtxt = store.get("windtxt", "")
self.label = self.temp == nil ? nil : self.format(self.temp)
self.build_line()
self.ticks = 0
self.in_flight = false
self.page = 0
self.shown_at = 0
if size(self.key) == 0
log("OWM: no API key set - open the app settings")
end
end
# build the scroll line from the settings that are on
def build_line()
var out = ""
if self.o_desc && size(self.desc) > 0
out = self.desc
end
if self.o_wind && size(self.windtxt) > 0
if size(out) > 0 out += " · " end
out += self.windtxt
end
self.line = out
end
# percent-encode what may not go raw into a URL
def enc(s)
var t = string.replace(s, " ", "+")
t = string.replace(t, "å", "%C3%A5")
t = string.replace(t, "ä", "%C3%A4")
t = string.replace(t, "ö", "%C3%B6")
t = string.replace(t, "Å", "%C3%85")
t = string.replace(t, "Ä", "%C3%84")
t = string.replace(t, "Ö", "%C3%96")
return t
end
def format(t)
var half = t >= 0 ? 0.5 : -0.5
return str(int(t + half)) + "°"
end
# map the OpenWeatherMap condition id to one of the five symbols
def classify(id)
if id >= 200 && id < 300 return 4 end
if id >= 300 && id < 600 return 2 end
if id >= 600 && id < 700 return 3 end
if id == 800 return 0 end
return 1
end
def on_body(body, status)
self.in_flight = false
if body == nil
log("OWM: no response (status " + str(status) + ")")
return
end
if status != 200
log("OWM: HTTP " + str(status))
return
end
var data = json.load(body)
if !isinstance(data, map) return end
var m = data.find("main")
if !isinstance(m, map) return end
var t = m.find("temp")
if t == nil return end
# condition id and description, e.g. 800 "clear sky"
var id = 800
var d = ""
var w = data.find("weather")
if isinstance(w, list) && size(w) > 0
if isinstance(w[0], map)
id = int(w[0].find("id", 800))
d = w[0].find("description", "")
end
end
# wind in m/s
var wind = ""
var wi = data.find("wind")
if isinstance(wi, map)
var ws = wi.find("speed")
if ws != nil
wind = str(int(ws + 0.5)) + " m/s wind"
end
end
self.temp = t
self.hum = m.find("humidity")
self.sky = self.classify(id)
self.label = self.format(t)
self.desc = d
self.windtxt = wind
self.build_line()
store.set("temp", t)
if self.hum != nil store.set("hum", self.hum) end
store.set("sky", self.sky)
store.set("desc", self.desc)
store.set("windtxt", self.windtxt)
var hs = self.hum == nil ? "?" : str(self.hum)
log("OWM ok: " + self.label + " hum " + hs + "% | " + self.line)
end
def loop()
if self.ticks <= 0
self.ticks = self.period
if !self.in_flight && size(self.key) > 0
self.in_flight = true
http.get(self.url, / b, st -> self.on_body(b, st))
end
end
self.ticks -= 1
end
def on_show()
self.page = 0
self.shown_at = now_ms()
end
# 8x8 symbol drawn from rectangles and circles
def glyph()
if self.sky == 0
circle_fill(3, 3, 2, 0xFFAA00)
pixel(3, 0, 0xFF6600) pixel(0, 3, 0xFF6600)
pixel(6, 3, 0xFF6600) pixel(3, 6, 0xFF6600)
return
end
circle_fill(2, 4, 1, 0x8899AA)
circle_fill(5, 3, 2, 0x8899AA)
rect_fill(1, 4, 6, 2, 0x8899AA)
if self.sky == 2
pixel(2, 7, 0x3388FF) pixel(4, 6, 0x3388FF) pixel(6, 7, 0x3388FF)
elif self.sky == 3
pixel(2, 7, 0xCCEEFF) pixel(4, 6, 0xCCEEFF) pixel(6, 7, 0xCCEEFF)
elif self.sky == 4
pixel(4, 6, 0xFFDD00) pixel(3, 7, 0xFFDD00)
end
end
def draw()
clear()
if self.label == nil
text(1, 6, "...", 0x666666)
return
end
# page 1: scrolling weather description
if self.page == 1 && size(self.line) > 0
scroll_text(self.line, 0x99CCFF)
return
end
# page 0: symbol + temperature + humidity
var left = 1
if self.o_icon
self.glyph()
left = 9
end
var hstr = ""
if self.o_hum && self.hum != nil
hstr = str(self.hum) + "%"
end
var w1 = text_ink_width(self.label)
var w2 = size(hstr) == 0 ? 0 : text_ink_width(hstr)
var start = left + (width() - left - w1 - w2 - 2) / 2
var c = 0x00FF00
if self.temp >= 28
c = 0xFF4000
elif self.temp <= 0
c = 0x00AAFF
end
var adv = text(start, 6, self.label, c)
if size(hstr) > 0
text(start + adv + 2, 6, hstr, 0x4488FF)
end
# after 4 s: show the scroll line (if one is selected)
if size(self.line) > 0 && now_ms() - self.shown_at > 4000
self.page = 1
end
end
def on_button(btn)
if btn == "select"
self.ticks = 0
end
end
end
return WeatherOWM()
Community
Discussion 0
Ask a question, suggest a change or share how you use it.
No comments yet. Start the conversation.
More flows for AWTRIX NG Scripts or Miscellaneous
Something wrong with this flow? Report it.
Have an idea?
Sign in to ask questions and join the conversation.