# @name AQI Air Quality # @desc AQI Value from aqicn.org (WAQI API) # @author zap21 / claude # @version 1.2 # @config station text "Station Code" default="germany/hamburg/flughafen" # @config token text "API Token" default="YOUR_TOKEN" maxlen=64 # @config every number "Request Interval" default=10 min=1 max=1440 unit=min # @config ic text "Icon ID" default="74824" # get TOKEN from https://aqicn.org/api/ # get Station Code (or name) from https://aqicn.org/ class Waqi var url, period var aqi # last known AQI value, nil until first successful request var label, tint var ic var ticks, in_flight var last_status # last HTTP error code def duration() return 3000 # linger for 3 s (durationMS) end def init() self.url = "http://api.waqi.info/feed/" + store.get("station") + "/?token=" + store.get("token") self.period = store.get("every") * 60 self.ic = store.get("ic") #self.aqi = store.get("aqi") self.tint = self.aqi == nil ? 0xFFFFFF : self.color_for(self.aqi) self.label = self.aqi == nil ? nil : "qi:" + str(self.aqi) self.ticks = 0 self.in_flight = false self.last_status = 0 end def color_for(v) if v < 0 return 0xFFFFFF elif v <= 50 return 0x009966 elif v <= 100 return 0xFFDE33 elif v <= 150 return 0xFF9933 elif v <= 200 return 0xCC0033 elif v <= 300 return 0x660099 else return 0x7E0023 end end def on_body(body, status) self.in_flight = false self.last_status = status if body == nil return end # no success, show old value var m = re.search("\"aqi\":([0-9]+)", body) # "aqi":6,... -> 6 if m == nil return end var v = int(num(m[1])) self.aqi = v self.tint = self.color_for(v) self.label = "qi:" + str(v) #store.set("aqi", v) # store if valid end def loop() if self.ticks <= 0 self.ticks = self.period if !self.in_flight self.in_flight = true http.get(self.url, / b, st -> self.on_body(b, st), {'find': "\"aqi\":", 'keep': 16}) end end self.ticks -= 1 end def draw() clear() if self.label == nil if self.last_status != 0 text(1, 6, "e:" + str(self.last_status), 0xFF0000) # show error code else text(1, 6, "...", 0x666666) # no value yet end return end if !icon(self.ic, 0, 0) rect_fill(0, 0, 8, 8, 0x222222) # fallback if icon is missing end var area = width() - 9 # width minus icon size var x = 9 + (area - text_ink_width(self.label)) / 2 # centered text if x < 9 x = 9 end # stay away from the icon text(x, 6, self.label, self.tint) end def on_button(btn) if btn == "select" self.ticks = 0 end # force refresh end end return Waqi()