# @name Ecowitt API v2 # @desc Holt Ecowitt-Daten direkt von der API; OK wechselt die Seite # @version 2.0 # @config application_key text "Application Key" default="" maxlen=64 # @config api_key text "API Key" default="" maxlen=64 # @config mac text "MAC-Adresse" default="" maxlen=32 # @config every number "Refresh" default=300 min=30 max=3600 unit=s # @config show number "Seite" default=5 min=2 max=30 unit=s # @config scroll_speed slider "Scrolltempo" default=80 min=20 max=200 unit=% # @config temp_unit number "Temp Unit" default=1 min=1 max=2 # @config rain_unit number "Regen Unit" default=12 min=1 max=20 # @config wind_unit number "Wind Unit" default=7 min=1 max=20 import json class EcowittApiV2 var url var every var show var scroll_speed var scroll_opts var ticks var in_flight var items var text_color var page var page_started def init() self.every = store.get("every") self.show = store.get("show") self.scroll_speed = store.get("scroll_speed") self.scroll_opts = {"speed": clamp(self.scroll_speed, 20, 200)} self.ticks = 0 self.in_flight = false self.items = store.get("items") self.text_color = settings.get("textColor") self.page = 0 self.page_started = now_ms() if self.text_color == nil self.text_color = 0xFFFFFF end self.url = self.build_url() if self.items == nil || size(self.items) == 0 self.items = [{"text": "Wetter n/a", "duration": 15000}] end end def build_url() var application_key = store.get("application_key") var api_key = store.get("api_key") var mac = store.get("mac") if type(application_key) != "string" || application_key == "" return nil end if type(api_key) != "string" || api_key == "" return nil end if type(mac) != "string" || mac == "" return nil end return "http://api.ecowitt.net/api/v3/device/real_time?" + "application_key=" + application_key + "&api_key=" + api_key + "&mac=" + mac + "&call_back=all" + "&temp_unitid=" + str(store.get("temp_unit")) + "&rainfall_unitid=" + str(store.get("rain_unit")) + "&wind_speed_unitid=" + str(store.get("wind_unit")) end def clean_text(label) if type(label) != "string" return "-" end var m = re.match("^([-0-9.]+)℃$", label) if m != nil return m[1] + "C" end m = re.match("^([-0-9.]+)°C$", label) if m != nil return m[1] + "C" end return label end def format_now() var h = hour() var m = minute() if h < 0 || m < 0 return nil end var mm = m < 10 ? "0" + str(m) : str(m) return "Gemessen " + str(h) + ":" + mm end def make_item(text, icon_id, duration) return { "text": self.clean_text(text), "icon": icon_id, "duration": duration } end def on_body(body, status) self.in_flight = false if body == nil || status < 200 || status >= 300 return end var root = json.load(body) if !isinstance(root, map) return end var data = root.find("data") if !isinstance(data, map) return end var indoor = data.find("indoor") var outdoor = data.find("outdoor") var wind = data.find("wind") if !isinstance(indoor, map) || !isinstance(outdoor, map) || !isinstance(wind, map) return end var temp_in = indoor.find("temperature") var hum_in = indoor.find("humidity") var temp_out = outdoor.find("temperature") var wind_speed = wind.find("wind_speed") if !isinstance(temp_in, map) || !isinstance(hum_in, map) || !isinstance(temp_out, map) || !isinstance(wind_speed, map) return end var next_items = [] next_items.push(self.make_item( str(temp_in.find("value", "-")) + str(temp_in.find("unit", "")), "68435", 15000 )) next_items.push(self.make_item( str(hum_in.find("value", "-")) + str(hum_in.find("unit", "")), "39041", 15000 )) next_items.push(self.make_item( str(temp_out.find("value", "-")) + str(temp_out.find("unit", "")), "44092", 15000 )) var rainfall = data.find("rainfall_piezo") if isinstance(rainfall, map) var daily = rainfall.find("daily") if isinstance(daily, map) var rain_value = daily.find("value") if num(rain_value) != nil && num(rain_value) > 0 next_items.push(self.make_item( str(rain_value) + str(daily.find("unit", "")), "2720", 15000 )) end end end next_items.push(self.make_item( str(wind_speed.find("value", "-")) + str(wind_speed.find("unit", "")), "1153", 15000 )) var measured = self.format_now() if measured != nil next_items.push(self.make_item(measured, "2438", 15000)) end if size(next_items) == 0 return end self.items = next_items self.page = self.page % size(self.items) store.set("items", self.items) end def loop() if self.url == nil return end if self.ticks <= 0 self.ticks = self.every if !self.in_flight self.in_flight = true http.get(self.url, / b, st -> self.on_body(b, st)) end end self.ticks -= 1 end def duration() if self.items == nil || size(self.items) == 0 return 15000 end return size(self.items) * clamp(self.show, 2, 30) * 1000 end def on_button(btn) if btn != "select" || self.items == nil || size(self.items) == 0 return end var now = now_ms() var show_ms = clamp(self.show, 2, 30) * 1000 self.page = (self.page + int((now - self.page_started) / show_ms) + 1) % size(self.items) self.page_started = now end def draw() clear() if self.url == nil text(1, 6, "API?", self.text_color) return end if self.items == nil || size(self.items) == 0 text(1, 6, "Wetter n/a", self.text_color) return end var show_ms = clamp(self.show, 2, 30) * 1000 var index = (self.page + int((now_ms() - self.page_started) / show_ms)) % size(self.items) var item = self.items[index] if !isinstance(item, map) text(1, 6, "Wetter n/a", self.text_color) return end var label = item.find("text", "-") var icon_name = item.find("icon") var has_icon = type(icon_name) == "string" && icon_name != "" if has_icon if !icon(icon_name, 0, 0) rect_fill(0, 0, 8, 8, 0x222222) end var avail = width() - 9 if text_ink_width(label) > avail scroll_text(9, 6, avail, label, self.text_color, self.scroll_opts) else text(9 + (avail - text_ink_width(label)) / 2, 6, label, self.text_color) end return end if text_ink_width(label) > width() scroll_text(label, self.text_color, self.scroll_opts) else text((width() - text_ink_width(label)) / 2, 6, label, self.text_color) end end end return EcowittApiV2()