Added view switcher. Added hard coded metars
This commit is contained in:
@@ -14,3 +14,25 @@ proc format_predictions*(prd: JSONNode): string =
|
|||||||
"No prediction available"
|
"No prediction available"
|
||||||
else:
|
else:
|
||||||
prd["prd"].getElems.map(time => time["prdctdn"].getStr).join(", ")
|
prd["prd"].getElems.map(time => time["prdctdn"].getStr).join(", ")
|
||||||
|
|
||||||
|
proc home_predictions*: string =
|
||||||
|
let client = newHttpClient()
|
||||||
|
const home_nl = "51067"
|
||||||
|
const home_12 = "58995"
|
||||||
|
const home_29 = "56557"
|
||||||
|
|
||||||
|
let nl_predictions = client.get_predictions(home_nl, "NL").format_predictions
|
||||||
|
let twelve_predictions = client.get_predictions(home_12, "12").format_predictions
|
||||||
|
let twenty_nine_predictions = client.get_predictions(home_29, "29").format_predictions
|
||||||
|
|
||||||
|
&"Home\nNL: {nl_predictions}\n12: {twelve_predictions}\n29: {twenty_nine_predictions}"
|
||||||
|
|
||||||
|
proc office_predictions*: string =
|
||||||
|
let client = newHttpClient()
|
||||||
|
const office_nl = "56565"
|
||||||
|
const office_12 = "57111"
|
||||||
|
|
||||||
|
let nl_predictions = client.get_predictions(office_nl, "NL").format_predictions
|
||||||
|
let twelve_predictions = client.get_predictions(office_12, "12").format_predictions
|
||||||
|
|
||||||
|
&"Oakland Office\nNL: {nl_predictions}\n12: {twelve_predictions}"
|
||||||
|
|||||||
56
metar.nim
Normal file
56
metar.nim
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import std/[httpclient, os, sequtils, sugar, strutils, xmlparser, xmltree]
|
||||||
|
import strformat
|
||||||
|
|
||||||
|
proc getMetar(client: HttpClient, code: string): XMLNode =
|
||||||
|
let requestUrl = &"https://aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&hoursBeforeNow=3&mostRecent=true&stationString={code}"
|
||||||
|
let metarData = client.getContent(requestUrl)
|
||||||
|
parseXml(metarData)
|
||||||
|
|
||||||
|
proc childString(node: XMLnode, name: string): string =
|
||||||
|
let node = node.child(name)
|
||||||
|
if node != nil:
|
||||||
|
result = node.innerText
|
||||||
|
else:
|
||||||
|
result = ""
|
||||||
|
|
||||||
|
type SkyCondition* = object
|
||||||
|
skyCover: string
|
||||||
|
cloudBaseAgl: string
|
||||||
|
|
||||||
|
type MetarData* = object
|
||||||
|
rawText*: string
|
||||||
|
stationId*: string
|
||||||
|
observationTime*: string
|
||||||
|
temperature*: string
|
||||||
|
dewPoint*: string
|
||||||
|
windHeading*: string
|
||||||
|
windSpeedKnots*: string
|
||||||
|
visibility*: string
|
||||||
|
altimiter*: string
|
||||||
|
flightCategory*: string
|
||||||
|
skyConditions*: seq[SkyCondition]
|
||||||
|
|
||||||
|
proc newMetarData*(xmlData: XMLNode): MetarData =
|
||||||
|
let metar = xmlData.child("data").child("METAR")
|
||||||
|
|
||||||
|
result = MetarData(
|
||||||
|
rawText: metar.childString("raw_text"),
|
||||||
|
stationId: metar.childString("station_id"),
|
||||||
|
observationTime: metar.childString("observation_time"),
|
||||||
|
temperature: metar.childString("temp_c"),
|
||||||
|
dewPoint: metar.childString("dewpoint_c"),
|
||||||
|
windHeading: metar.childString("wind_dir_degrees"),
|
||||||
|
visibility: metar.childString("visibility_statute_mi"),
|
||||||
|
altimiter: metar.childString("altim_in_hg"),
|
||||||
|
flightCategory: metar.childString("flight_category")
|
||||||
|
)
|
||||||
|
|
||||||
|
for skyConditionXml in metar.findAll("sky_condition"):
|
||||||
|
result.skyConditions.add(
|
||||||
|
SkyCondition(
|
||||||
|
skyCover: skyConditionXml.attr("sky_cover"),
|
||||||
|
cloudBaseAgl: skyconditionXml.attr("cloud_base_ft_agl")))
|
||||||
|
|
||||||
|
proc getMetars*(airports: seq[string]): seq[MetarData] =
|
||||||
|
let client = newHttpClient()
|
||||||
|
airports.map(airportCode => client.getMetar(airportCode)).map(metarXml => newMetarData(metarXml))
|
||||||
99
toolbox.nim
99
toolbox.nim
@@ -1,47 +1,93 @@
|
|||||||
import gintro/[gtk4, gobject, gio, adw]
|
import gintro/[gtk4, gobject, gio, adw]
|
||||||
import std/[httpclient, with]
|
import std/[with]
|
||||||
import strformat
|
|
||||||
import actransit
|
import actransit
|
||||||
|
import metar
|
||||||
|
|
||||||
proc home_predictions: string =
|
const airports = @["khwd", "koak", "klvk", "khaf"]
|
||||||
let client = newHttpClient()
|
|
||||||
const home_nl = "51067"
|
|
||||||
const home_12 = "58995"
|
|
||||||
const home_29 = "56557"
|
|
||||||
|
|
||||||
let nl_predictions = client.get_predictions(home_nl, "NL").format_predictions
|
proc clearMetars(metar_list: gtk4.ListBox) =
|
||||||
let twelve_predictions = client.get_predictions(home_12, "12").format_predictions
|
for i in 1..airports.len:
|
||||||
let twenty_nine_predictions = client.get_predictions(home_29, "29").format_predictions
|
let metar_row = metar_list.get_row_at_index(0)
|
||||||
|
metar_list.remove(metar_row)
|
||||||
|
|
||||||
&"Home\nNL: {nl_predictions}\n12: {twelve_predictions}\n29: {twenty_nine_predictions}"
|
proc addMetars(metar_list: gtk4.ListBox) =
|
||||||
|
let metars = getMetars(airports)
|
||||||
|
|
||||||
proc office_predictions: string =
|
for metar in metars:
|
||||||
let client = newHttpClient()
|
let metar_label = newLabel()
|
||||||
const office_nl = "56565"
|
with metar_label:
|
||||||
const office_12 = "57111"
|
text = metar.rawText.cstring
|
||||||
|
halign = Align.start
|
||||||
|
wrap = true
|
||||||
|
metar_list.append(metar_label)
|
||||||
|
|
||||||
let nl_predictions = client.get_predictions(office_nl, "NL").format_predictions
|
proc button_refresh_signal(b: Button,
|
||||||
let twelve_predictions = client.get_predictions(office_12, "12").format_predictions
|
widgets: tuple[vs: adw.ViewStack, home: Label, office: Label, metar_list: gtk4.ListBox]) =
|
||||||
|
if widgets.vs.get_visible_child_name() == "act_view":
|
||||||
&"Oakland Office\nNL: {nl_predictions}\n12: {twelve_predictions}"
|
widgets.home.text = home_predictions().cstring
|
||||||
|
widgets.office.text = office_predictions().cstring
|
||||||
|
elif widgets.vs.get_visible_child_name() == "metar_view":
|
||||||
|
clearMetars(widgets.metar_list)
|
||||||
|
addMetars(widgets.metar_list)
|
||||||
|
|
||||||
proc activate(app: adw.Application) =
|
proc activate(app: adw.Application) =
|
||||||
let
|
let
|
||||||
window = adw.newApplicationWindow(app)
|
window = adw.newApplicationWindow(app)
|
||||||
|
view_stack = adw.newViewStack()
|
||||||
|
switcher_bar = adw.newViewSwitcherBar()
|
||||||
|
|
||||||
|
bart_box = newBox(Orientation.vertical, 0)
|
||||||
|
|
||||||
|
metar_box = newBox(Orientation.vertical, 0)
|
||||||
|
metar_list = newListBox()
|
||||||
|
|
||||||
|
act_box = newBox(Orientation.vertical, 0)
|
||||||
home_label = newLabel()
|
home_label = newLabel()
|
||||||
office_label = newLabel()
|
office_label = newLabel()
|
||||||
|
|
||||||
refresh_button = newButtonFromIconName("view-refresh")
|
refresh_button = newButtonFromIconName("view-refresh")
|
||||||
header = adw.newHeaderBar()
|
header = adw.newHeaderBar()
|
||||||
mainBox = newBox(Orientation.vertical, 0)
|
main_box = newBox(Orientation.vertical, 0)
|
||||||
with mainBox:
|
|
||||||
|
|
||||||
|
with main_box:
|
||||||
append header
|
append header
|
||||||
|
append view_stack
|
||||||
|
append switcher_bar
|
||||||
|
|
||||||
|
let
|
||||||
|
act_view_page = view_stack.add_titled(act_box, "act_view", "AC Transit")
|
||||||
|
bart_view_page = view_stack.add_titled(bart_box, "bart_view", "BART")
|
||||||
|
metar_view_page = view_stack.add_titled(metar_box, "metar_view", "Metar")
|
||||||
|
|
||||||
|
act_view_page.set_icon_name("go-home")
|
||||||
|
bart_view_page.set_icon_name("view-grid")
|
||||||
|
metar_view_page.set_icon_name("weather-clear")
|
||||||
|
|
||||||
|
with view_stack:
|
||||||
|
set_visible_child_name "act_view"
|
||||||
|
vexpand = true
|
||||||
|
|
||||||
|
with switcher_bar:
|
||||||
|
reveal = true
|
||||||
|
stack = view_stack
|
||||||
|
valign = Align.end
|
||||||
|
|
||||||
|
with act_box:
|
||||||
append home_label
|
append home_label
|
||||||
append office_label
|
append office_label
|
||||||
|
|
||||||
|
with metar_box:
|
||||||
|
append metar_list
|
||||||
|
|
||||||
with header:
|
with header:
|
||||||
pack_end refresh_button
|
pack_end refresh_button
|
||||||
|
|
||||||
|
with metar_list:
|
||||||
|
selectionMode = SelectionMode.none
|
||||||
|
showSeparators = true
|
||||||
|
addMetars(metar_list)
|
||||||
|
|
||||||
with refresh_button:
|
with refresh_button:
|
||||||
iconName = "view-refresh"
|
iconName = "view-refresh"
|
||||||
|
|
||||||
@@ -51,6 +97,7 @@ proc activate(app: adw.Application) =
|
|||||||
marginBottom = 10
|
marginBottom = 10
|
||||||
marginStart = 10
|
marginStart = 10
|
||||||
marginEnd = 10
|
marginEnd = 10
|
||||||
|
halign = Align.start
|
||||||
|
|
||||||
with office_label:
|
with office_label:
|
||||||
text = office_predictions().cstring
|
text = office_predictions().cstring
|
||||||
@@ -58,17 +105,15 @@ proc activate(app: adw.Application) =
|
|||||||
marginBottom = 10
|
marginBottom = 10
|
||||||
marginStart = 10
|
marginStart = 10
|
||||||
marginEnd = 10
|
marginEnd = 10
|
||||||
|
hexpand = true
|
||||||
|
halign = Align.start
|
||||||
|
|
||||||
proc button_refresh_signal(b: Button, labels: tuple[home: Label, office: Label]) =
|
refresh_button.connect("clicked", button_refresh_signal, (view_stack, home_label, office_label, metar_list))
|
||||||
labels.home.text = home_predictions().cstring
|
|
||||||
labels.office.text = office_predictions().cstring
|
|
||||||
|
|
||||||
refresh_button.connect("clicked", button_refresh_signal, (home_label, office_label))
|
|
||||||
|
|
||||||
with window:
|
with window:
|
||||||
title = "Toolbox"
|
title = "Toolbox"
|
||||||
defaultSize = (300, 500)
|
defaultSize = (300, 500)
|
||||||
content = mainBox
|
content = main_box
|
||||||
show()
|
show()
|
||||||
|
|
||||||
proc initAdw(app: adw.Application) =
|
proc initAdw(app: adw.Application) =
|
||||||
|
|||||||
Reference in New Issue
Block a user