initial commit

main
_ 2025-01-15 01:40:24 +00:00
commit 8c6c46a26e
8 changed files with 2276 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/untracked

1513
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

13
Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "weather_dot_gov_rs"
version = "0.1.0"
edition = "2021"
[dependencies]
quick-xml = { version = "0.37.2", features = ["overlapped-lists", "serialize"] }
serde = { version = "1.0.217", features = ["derive"] }
[dev-dependencies]
anyhow = "1.0.95"
reqwest = "0.12.12"
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] }

169
data/empire_city.xml Normal file
View File

@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<dwml version="1.0" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">
<head>
<product concise-name="dwmlByDay" operational-mode="developmental" srsName="WGS 1984">
<creation-date refresh-frequency="PT1H">2025-01-14T18:08:11-05:00</creation-date>
<category>current observations and forecast</category>
</product>
<source>
<production-center>New York, NY</production-center>
<credit>https://www.weather.gov/okx/</credit>
<more-information>https://www.nws.noaa.gov/forecasts/xml/</more-information>
</source>
</head>
<data type="forecast">
<location>
<location-key>point1</location-key>
<description>New York, NY</description>
<point latitude="40.71" longitude="-74.01"/>
<city state="NY">New York</city>
<height datum="mean sea level">7</height>
</location>
<moreWeatherInformation applicable-location="point1">https://forecast.weather.gov/MapClick.php?lat=40.71&amp;lon=-74.01</moreWeatherInformation>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p12h-n14-1</layout-key>
<start-valid-time period-name="Tonight">2025-01-14T19:00:00-05:00</start-valid-time>
<start-valid-time period-name="Wednesday">2025-01-15T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Wednesday Night">2025-01-15T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Thursday">2025-01-16T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Thursday Night">2025-01-16T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Friday">2025-01-17T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Friday Night">2025-01-17T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Saturday">2025-01-18T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Saturday Night">2025-01-18T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Sunday">2025-01-19T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Sunday Night">2025-01-19T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="M.L.King Day">2025-01-20T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Monday Night">2025-01-20T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Tuesday">2025-01-21T06:00:00-05:00</start-valid-time>
</time-layout>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p24h-n7-1</layout-key>
<start-valid-time period-name="Tonight">2025-01-14T19:00:00-05:00</start-valid-time>
<start-valid-time period-name="Wednesday Night">2025-01-15T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Thursday Night">2025-01-16T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Friday Night">2025-01-17T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Saturday Night">2025-01-18T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Sunday Night">2025-01-19T18:00:00-05:00</start-valid-time>
<start-valid-time period-name="Monday Night">2025-01-20T18:00:00-05:00</start-valid-time>
</time-layout>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p24h-n7-2</layout-key>
<start-valid-time period-name="Wednesday">2025-01-15T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Thursday">2025-01-16T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Friday">2025-01-17T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Saturday">2025-01-18T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Sunday">2025-01-19T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="M.L.King Day">2025-01-20T06:00:00-05:00</start-valid-time>
<start-valid-time period-name="Tuesday">2025-01-21T06:00:00-05:00</start-valid-time>
</time-layout>
<parameters applicable-location="point1">
<temperature type="minimum" units="Fahrenheit" time-layout="k-p24h-n7-1">
<name>Daily Minimum Temperature</name>
<value>26</value>
<value>24</value>
<value>27</value>
<value>34</value>
<value>34</value>
<value>24</value>
<value>17</value>
</temperature>
<temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n7-2">
<name>Daily Maximum Temperature</name>
<value>33</value>
<value>32</value>
<value>39</value>
<value>43</value>
<value>39</value>
<value>30</value>
<value>24</value>
</temperature>
<probability-of-precipitation type="12 hour" units="percent" time-layout="k-p12h-n14-1">
<name>12 Hourly Probability of Precipitation</name>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value>20</value>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value>60</value>
<value>40</value>
<value xsi:nil="true"/>
<value>30</value>
<value>30</value>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
</probability-of-precipitation>
<weather time-layout="k-p12h-n14-1">
<name>Weather Type, Coverage, Intensity</name>
<weather-conditions weather-summary="Mostly Clear"/>
<weather-conditions weather-summary="Sunny"/>
<weather-conditions weather-summary="Mostly Clear"/>
<weather-conditions weather-summary="Partly Sunny"/>
<weather-conditions weather-summary="Slight Chance Snow Showers"/>
<weather-conditions weather-summary="Sunny"/>
<weather-conditions weather-summary="Partly Cloudy"/>
<weather-conditions weather-summary="Mostly Cloudy then Rain Likely"/>
<weather-conditions weather-summary="Chance Rain"/>
<weather-conditions weather-summary="Mostly Sunny"/>
<weather-conditions weather-summary="Chance Snow"/>
<weather-conditions weather-summary="Chance Snow"/>
<weather-conditions weather-summary="Partly Cloudy"/>
<weather-conditions weather-summary="Mostly Sunny"/>
</weather>
<conditions-icon type="forecast-NWS" time-layout="k-p12h-n14-1">
<name>Conditions Icon</name> <icon-link>https://forecast.weather.gov/newimages/medium/nfew.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/few.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nfew.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/bkn.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nsn20.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/few.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nsct.png</icon-link>
<icon-link>https://forecast.weather.gov/DualImage.php?i=bkn&amp;j=ra&amp;jp=60</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nra40.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/sct.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nsn30.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/sn30.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nsct.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/sct.png</icon-link>
</conditions-icon>
<wordedForecast time-layout="k-p12h-n14-1" dataSource="okxNetcdf" wordGenerator="markMitchell">
<name>Text Forecast</name>
<text>Mostly clear, with a low around 26. Wind chill values between 15 and 20. West wind around 14 mph. </text>
<text>Sunny, with a high near 33. Wind chill values between 15 and 25. Northwest wind 13 to 16 mph, with gusts as high as 28 mph. </text>
<text>Mostly clear, with a low around 24. Wind chill values between 15 and 20. West wind 7 to 10 mph. </text>
<text>Partly sunny, with a high near 32. Wind chill values between 15 and 25. Southwest wind 9 to 13 mph. </text>
<text>A 20 percent chance of snow showers before 1am. Mostly cloudy, with a low around 27. West wind 8 to 10 mph. </text>
<text>Sunny, with a high near 39.</text>
<text>Partly cloudy, with a low around 34.</text>
<text>Rain likely after 1pm. Mostly cloudy, with a high near 43. Chance of precipitation is 60%.</text>
<text>A 40 percent chance of rain before 1am. Mostly cloudy, with a low around 34.</text>
<text>Mostly sunny, with a high near 39.</text>
<text>A 30 percent chance of snow. Mostly cloudy, with a low around 24.</text>
<text>A 30 percent chance of snow. Partly sunny, with a high near 30.</text>
<text>Partly cloudy, with a low around 17.</text>
<text>Mostly sunny, with a high near 24.</text>
</wordedForecast>
</parameters>
</data>
<data type="current observations">
<location>
<location-key>point1</location-key>
<point latitude="40.78" longitude="-73.97"/>
<area-description>New York City, Central Park, NY</area-description>
<height datum="mean sea level" height-units="feet">154</height>
</location>
<moreWeatherInformation applicable-location="point1">https://www.nws.noaa.gov/data/obhistory/KNYC.html</moreWeatherInformation> <time-layout time-coordinate="local"> <layout-key>k-p1h-n1-1</layout-key> <start-valid-time period-name="current">2025-01-14T18:51:00-05:00</start-valid-time> </time-layout> <parameters applicable-location="point1"> <temperature type="apparent" units="Fahrenheit" time-layout="k-p1h-n1-1"> <value>30</value> </temperature> <temperature type="dew point" units="Fahrenheit" time-layout="k-p1h-n1-1"> <value>6</value> </temperature> <humidity type="relative" time-layout="k-p1h-n1-1"> <value>36</value> </humidity> <weather time-layout="k-p1h-n1-1"> <name>Weather Type, Coverage, Intensity</name> <weather-conditions weather-summary="Mostly Cloudy"/> <weather-conditions> <value> <visibility units="statute miles">10.00</visibility> </value> </weather-conditions> </weather> <conditions-icon type="forecast-NWS" time-layout="k-p1h-n1-1"> <name>Conditions Icon</name> <icon-link>https://forecast.weather.gov/newimages/medium/nbkn.png</icon-link> </conditions-icon> <direction type="wind" units="degrees true" time-layout="k-p1h-n1-1"> <value>270</value> </direction> <wind-speed type="gust" units="knots" time-layout="k-p1h-n1-1"> <value>17</value> </wind-speed> <wind-speed type="sustained" units="knots" time-layout="k-p1h-n1-1"> <value>9</value> </wind-speed> <pressure type="barometer" units="inches of mercury" time-layout="k-p1h-n1-1"> <value>30.01</value> </pressure> </parameters></data></dwml>

169
data/sunset_city.xml Normal file
View File

@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<dwml version="1.0" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">
<head>
<product concise-name="dwmlByDay" operational-mode="developmental" srsName="WGS 1984">
<creation-date refresh-frequency="PT1H">2025-01-14T12:27:51-08:00</creation-date>
<category>current observations and forecast</category>
</product>
<source>
<production-center>San Francisco Bay Area/Monterey, CA</production-center>
<credit>https://www.weather.gov/mtr</credit>
<more-information>https://www.nws.noaa.gov/forecasts/xml/</more-information>
</source>
</head>
<data type="forecast">
<location>
<location-key>point1</location-key>
<description>San Francisco, CA</description>
<point latitude="37.77" longitude="-122.41"/>
<city state="CA">San Francisco</city>
<height datum="mean sea level">131</height>
</location>
<moreWeatherInformation applicable-location="point1">https://forecast.weather.gov/MapClick.php?lat=37.77&amp;lon=-122.41</moreWeatherInformation>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p12h-n14-1</layout-key>
<start-valid-time period-name="Tonight">2025-01-14T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Wednesday">2025-01-15T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Wednesday Night">2025-01-15T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Thursday">2025-01-16T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Thursday Night">2025-01-16T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Friday">2025-01-17T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Friday Night">2025-01-17T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Saturday">2025-01-18T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Saturday Night">2025-01-18T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Sunday">2025-01-19T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Sunday Night">2025-01-19T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="M.L.King Day">2025-01-20T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Monday Night">2025-01-20T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Tuesday">2025-01-21T06:00:00-08:00</start-valid-time>
</time-layout>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p24h-n7-1</layout-key>
<start-valid-time period-name="Tonight">2025-01-14T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Wednesday Night">2025-01-15T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Thursday Night">2025-01-16T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Friday Night">2025-01-17T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Saturday Night">2025-01-18T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Sunday Night">2025-01-19T18:00:00-08:00</start-valid-time>
<start-valid-time period-name="Monday Night">2025-01-20T18:00:00-08:00</start-valid-time>
</time-layout>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p24h-n7-2</layout-key>
<start-valid-time period-name="Wednesday">2025-01-15T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Thursday">2025-01-16T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Friday">2025-01-17T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Saturday">2025-01-18T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Sunday">2025-01-19T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="M.L.King Day">2025-01-20T06:00:00-08:00</start-valid-time>
<start-valid-time period-name="Tuesday">2025-01-21T06:00:00-08:00</start-valid-time>
</time-layout>
<parameters applicable-location="point1">
<temperature type="minimum" units="Fahrenheit" time-layout="k-p24h-n7-1">
<name>Daily Minimum Temperature</name>
<value>44</value>
<value>44</value>
<value>46</value>
<value>45</value>
<value>43</value>
<value>43</value>
<value>43</value>
</temperature>
<temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n7-2">
<name>Daily Maximum Temperature</name>
<value>62</value>
<value>61</value>
<value>58</value>
<value>57</value>
<value>56</value>
<value>58</value>
<value>59</value>
</temperature>
<probability-of-precipitation type="12 hour" units="percent" time-layout="k-p12h-n14-1">
<name>12 Hourly Probability of Precipitation</name>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
</probability-of-precipitation>
<weather time-layout="k-p12h-n14-1">
<name>Weather Type, Coverage, Intensity</name>
<weather-conditions weather-summary="Mostly Clear"/>
<weather-conditions weather-summary="Sunny"/>
<weather-conditions weather-summary="Clear"/>
<weather-conditions weather-summary="Sunny"/>
<weather-conditions weather-summary="Mostly Clear"/>
<weather-conditions weather-summary="Mostly Sunny"/>
<weather-conditions weather-summary="Partly Cloudy"/>
<weather-conditions weather-summary="Mostly Sunny"/>
<weather-conditions weather-summary="Mostly Clear"/>
<weather-conditions weather-summary="Sunny"/>
<weather-conditions weather-summary="Mostly Clear"/>
<weather-conditions weather-summary="Sunny"/>
<weather-conditions weather-summary="Mostly Clear"/>
<weather-conditions weather-summary="Mostly Sunny"/>
</weather>
<conditions-icon type="forecast-NWS" time-layout="k-p12h-n14-1">
<name>Conditions Icon</name> <icon-link>https://forecast.weather.gov/newimages/medium/nfew.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/skc.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nskc.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/skc.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nfew.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/sct.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nsct.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/sct.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nfew.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/few.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nfew.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/few.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nfew.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/sct.png</icon-link>
</conditions-icon>
<wordedForecast time-layout="k-p12h-n14-1" dataSource="mtrNetcdf" wordGenerator="markMitchell">
<name>Text Forecast</name>
<text>Mostly clear, with a low around 44. West wind 5 to 8 mph becoming calm after midnight. </text>
<text>Sunny, with a high near 62. East northeast wind 3 to 5 mph. </text>
<text>Clear, with a low around 44. Light east northeast wind. </text>
<text>Sunny, with a high near 61. Light north northeast wind. </text>
<text>Mostly clear, with a low around 46. Light west southwest wind. </text>
<text>Mostly sunny, with a high near 58.</text>
<text>Partly cloudy, with a low around 45.</text>
<text>Mostly sunny, with a high near 57.</text>
<text>Mostly clear, with a low around 43.</text>
<text>Sunny, with a high near 56.</text>
<text>Mostly clear, with a low around 43.</text>
<text>Sunny, with a high near 58.</text>
<text>Mostly clear, with a low around 43.</text>
<text>Mostly sunny, with a high near 59.</text>
</wordedForecast>
</parameters>
</data>
<data type="current observations">
<location>
<location-key>point1</location-key>
<point latitude="37.77056" longitude="-122.42694"/>
<area-description>SAN FRANCISCO DOWNTOWN, CA</area-description>
<height datum="mean sea level" height-units="feet">150.0</height>
</location>
<moreWeatherInformation applicable-location="point1">https://www.weather.gov/wrh/LocalWeather?wfo=mtr&amp;zone=CAZ006</moreWeatherInformation> <time-layout time-coordinate="local"> <layout-key>k-p1h-n1-1</layout-key> <start-valid-time period-name="current">2025-01-14T16:00:00</start-valid-time> </time-layout> <parameters applicable-location="point1"> <temperature type="apparent" units="Fahrenheit" time-layout="k-p1h-n1-1"> <value>60</value> </temperature> <temperature type="dew point" units="Fahrenheit" time-layout="k-p1h-n1-1"> <value>28</value> </temperature> <humidity type="relative" time-layout="k-p1h-n1-1"> <value>29</value> </humidity> <weather time-layout="k-p1h-n1-1"> <name>Weather Type, Coverage, Intensity</name> <weather-conditions weather-summary="NA"/> <weather-conditions> <value> <visibility units="statute miles">NA</visibility> </value> </weather-conditions> </weather> <conditions-icon type="forecast-NWS" time-layout="k-p1h-n1-1"> <name>Conditions Icon</name> <icon-link>NULL</icon-link> </conditions-icon> <direction type="wind" units="degrees true" time-layout="k-p1h-n1-1"> <value>NA</value> </direction> <wind-speed type="gust" units="knots" time-layout="k-p1h-n1-1"> <value>NA</value> </wind-speed> <wind-speed type="sustained" units="knots" time-layout="k-p1h-n1-1"> <value>NA</value> </wind-speed> <pressure type="barometer" units="inches of mercury" time-layout="k-p1h-n1-1"> <value>NA</value> </pressure> </parameters></data></dwml>

186
data/windy_city.xml Normal file
View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<dwml version="1.0" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">
<head>
<product concise-name="dwmlByDay" operational-mode="developmental" srsName="WGS 1984">
<creation-date refresh-frequency="PT1H">2025-01-14T16:27:37-06:00</creation-date>
<category>current observations and forecast</category>
</product>
<source>
<production-center>Chicago, IL</production-center>
<credit>https://www.weather.gov/lot</credit>
<more-information>https://www.nws.noaa.gov/forecasts/xml/</more-information>
</source>
</head>
<data type="forecast">
<location>
<location-key>point1</location-key>
<point latitude="41.88" longitude="-87.65"/>
<area-description>4 Miles NE Chicago IL</area-description>
<height datum="mean sea level" height-units="feet">594</height>
</location>
<moreWeatherInformation applicable-location="point1">https://forecast.weather.gov/MapClick.php?lat=41.88&amp;lon=-87.65</moreWeatherInformation>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p12h-n14-1</layout-key>
<start-valid-time period-name="Tonight">2025-01-14T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Wednesday">2025-01-15T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Wednesday Night">2025-01-15T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Thursday">2025-01-16T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Thursday Night">2025-01-16T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Friday">2025-01-17T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Friday Night">2025-01-17T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Saturday">2025-01-18T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Saturday Night">2025-01-18T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Sunday">2025-01-19T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Sunday Night">2025-01-19T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="M.L.King Day">2025-01-20T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Monday Night">2025-01-20T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Tuesday">2025-01-21T06:00:00-06:00</start-valid-time>
</time-layout>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p24h-n7-1</layout-key>
<start-valid-time period-name="Tonight">2025-01-14T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Wednesday Night">2025-01-15T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Thursday Night">2025-01-16T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Friday Night">2025-01-17T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Saturday Night">2025-01-18T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Sunday Night">2025-01-19T18:00:00-06:00</start-valid-time>
<start-valid-time period-name="Monday Night">2025-01-20T18:00:00-06:00</start-valid-time>
</time-layout>
<time-layout time-coordinate="local" summarization="12hourly">
<layout-key>k-p24h-n7-2</layout-key>
<start-valid-time period-name="Wednesday">2025-01-15T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Thursday">2025-01-16T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Friday">2025-01-17T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Saturday">2025-01-18T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Sunday">2025-01-19T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="M.L.King Day">2025-01-20T06:00:00-06:00</start-valid-time>
<start-valid-time period-name="Tuesday">2025-01-21T06:00:00-06:00</start-valid-time>
</time-layout>
<parameters applicable-location="point1">
<temperature type="minimum" units="Fahrenheit" time-layout="k-p24h-n7-1">
<name>Daily Minimum Temperature</name>
<value>3</value>
<value>17</value>
<value>25</value>
<value>28</value>
<value>10</value>
<value>-1</value>
<value>-1</value>
</temperature>
<temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n7-2">
<name>Daily Maximum Temperature</name>
<value>21</value>
<value>35</value>
<value>38</value>
<value>31</value>
<value>13</value>
<value>8</value>
<value>13</value>
</temperature>
<probability-of-precipitation type="12 hour" units="percent" time-layout="k-p12h-n14-1">
<name>12 Hourly Probability of Precipitation</name>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value>40</value>
<value>20</value>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value>40</value>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
<value xsi:nil="true"/>
</probability-of-precipitation>
<weather time-layout="k-p12h-n14-1">
<name>Weather Type, Coverage, Intensity</name>
<weather-conditions weather-summary="Clear"/>
<weather-conditions weather-summary="Sunny"/>
<weather-conditions weather-summary="Chance Snow"/>
<weather-conditions weather-summary="Slight Chance Snow then Partly Sunny"/>
<weather-conditions weather-summary="Mostly Cloudy"/>
<weather-conditions weather-summary="Mostly Sunny"/>
<weather-conditions weather-summary="Chance Rain then Chance Rain/Snow"/>
<weather-conditions weather-summary="Mostly Cloudy"/>
<weather-conditions weather-summary="Mostly Cloudy"/>
<weather-conditions weather-summary="Partly Sunny"/>
<weather-conditions weather-summary="Partly Cloudy"/>
<weather-conditions weather-summary="Cold"/>
<weather-conditions weather-summary="Partly Cloudy"/>
<weather-conditions weather-summary="Mostly Sunny"/>
</weather>
<conditions-icon type="forecast-NWS" time-layout="k-p12h-n14-1">
<name>Conditions Icon</name> <icon-link>https://forecast.weather.gov/newimages/medium/nskc.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/few.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nsn40.png</icon-link>
<icon-link>https://forecast.weather.gov/DualImage.php?i=sn&amp;j=bkn&amp;ip=20</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nbkn.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/sct.png</icon-link>
<icon-link>https://forecast.weather.gov/DualImage.php?i=nra&amp;j=nrasn&amp;ip=40&amp;jp=30</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/bkn.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nbkn.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/bkn.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nsct.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/cold.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/nsct.png</icon-link>
<icon-link>https://forecast.weather.gov/newimages/medium/sct.png</icon-link>
</conditions-icon>
<hazards time-layout="">
<name>Watches, Warnings, and Advisories</name>
<hazard-conditions>
<hazard headline="Hazardous Weather Outlook">
<hazardTextURL>https://forecast.weather.gov/showsigwx.php?warnzone=ILZ104&amp;warncounty=ILC031&amp;firewxzone=ILZ014&amp;local_place1=4+Miles+NE+Chicago+IL&amp;product1=Hazardous+Weather+Outlook</hazardTextURL>
</hazard>
</hazard-conditions>
</hazards>
<hazards time-layout="">
<name>Watches, Warnings, and Advisories</name>
<hazard-conditions>
<hazard headline="Hydrologic Outlook">
<hazardTextURL>https://forecast.weather.gov/showsigwx.php?warnzone=ILZ104&amp;warncounty=ILC031&amp;firewxzone=ILZ014&amp;local_place1=4+Miles+NE+Chicago+IL&amp;product1=Hydrologic+Outlook</hazardTextURL>
</hazard>
</hazard-conditions>
</hazards>
<wordedForecast time-layout="k-p12h-n14-1" dataSource="lotNetcdf" wordGenerator="markMitchell">
<name>Text Forecast</name>
<text>Clear, with a low around 3. Wind chill values as low as -7. West northwest wind 5 to 10 mph, with gusts as high as 15 mph. </text>
<text>Sunny, with a high near 21. Wind chill values as low as -8. Southwest wind 5 to 15 mph, with gusts as high as 25 mph. </text>
<text>A 40 percent chance of snow, mainly after midnight. Increasing clouds, with a temperature rising to around 23 by 5am. Southwest wind around 15 mph, with gusts as high as 25 mph. </text>
<text>A 20 percent chance of snow before noon. Mostly cloudy, with a high near 35. West northwest wind 10 to 15 mph, with gusts as high as 25 mph. </text>
<text>Mostly cloudy, with a low around 25. West wind 5 to 10 mph becoming south southwest after midnight. Winds could gust as high as 15 mph. </text>
<text>Mostly sunny, with a high near 38.</text>
<text>A chance of rain before midnight, then a chance of rain and snow. Mostly cloudy, with a low around 28. Chance of precipitation is 40%.</text>
<text>Mostly cloudy, with a high near 31.</text>
<text>Mostly cloudy, with a low around 10.</text>
<text>Partly sunny, with a high near 13.</text>
<text>Partly cloudy, with a low around -1.</text>
<text>Mostly sunny and cold, with a high near 8.</text>
<text>Partly cloudy, with a low around -1.</text>
<text>Mostly sunny, with a high near 13.</text>
</wordedForecast>
</parameters>
</data>
<data type="current observations">
<location>
<location-key>point1</location-key>
<point latitude="41.78" longitude="-87.76"/>
<area-description>Chicago, Chicago Midway Airport, IL</area-description>
<height datum="mean sea level" height-units="feet">617</height>
</location>
<moreWeatherInformation applicable-location="point1">https://www.nws.noaa.gov/data/obhistory/KMDW.html</moreWeatherInformation> <time-layout time-coordinate="local"> <layout-key>k-p1h-n1-1</layout-key> <start-valid-time period-name="current">2025-01-14T17:53:00-06:00</start-valid-time> </time-layout> <parameters applicable-location="point1"> <temperature type="apparent" units="Fahrenheit" time-layout="k-p1h-n1-1"> <value>15</value> </temperature> <temperature type="dew point" units="Fahrenheit" time-layout="k-p1h-n1-1"> <value>1</value> </temperature> <humidity type="relative" time-layout="k-p1h-n1-1"> <value>53</value> </humidity> <weather time-layout="k-p1h-n1-1"> <name>Weather Type, Coverage, Intensity</name> <weather-conditions weather-summary="Fair"/> <weather-conditions> <value> <visibility units="statute miles">10.00</visibility> </value> </weather-conditions> </weather> <conditions-icon type="forecast-NWS" time-layout="k-p1h-n1-1"> <name>Conditions Icon</name> <icon-link>https://forecast.weather.gov/newimages/medium/nsct.png</icon-link> </conditions-icon> <direction type="wind" units="degrees true" time-layout="k-p1h-n1-1"> <value>290</value> </direction> <wind-speed type="gust" units="knots" time-layout="k-p1h-n1-1"> <value>NA</value> </wind-speed> <wind-speed type="sustained" units="knots" time-layout="k-p1h-n1-1"> <value>7</value> </wind-speed> <pressure type="barometer" units="inches of mercury" time-layout="k-p1h-n1-1"> <value>30.42</value> </pressure> </parameters></data></dwml>

31
examples/reqwest.rs Normal file
View File

@ -0,0 +1,31 @@
use anyhow::{Context as _, Result};
use std::str::FromStr as _;
#[tokio::main]
async fn main() -> Result<()> {
let mut args = std::env::args();
args.next().context("Expected app name as arg0")?;
let lat = args.next().context("Usage: weather_dot_gov $LAT $LON")?;
let lon = args.next().context("Usage: weather_dot_gov $LAT $LON")?;
let client = reqwest::Client::new();
let req = client
.get("https://forecast.weather.gov/MapClick.php")
.query(&[
("lat", lat.as_str()),
("lon", lon.as_str()),
("unit", "0"),
("lg", "english"),
("FcstType", "dwml"),
])
.header("user-agent", "weather_dot_gov_rs")
.build()?;
let res = client.execute(req).await?;
let body = res.text().await?;
let dwml = weather_dot_gov_rs::Dwml::from_str(&body)?;
println!("{dwml:#?}");
Ok(())
}

193
src/lib.rs Normal file
View File

@ -0,0 +1,193 @@
use serde::Deserialize;
#[derive(Debug, Deserialize, PartialEq)]
pub struct Dwml {
pub head: Head,
pub data: (Forecast, CurrentObservations),
}
impl std::str::FromStr for Dwml {
type Err = quick_xml::DeError;
fn from_str(s: &str) -> Result<Self, quick_xml::DeError> {
quick_xml::de::from_str(s)
}
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Head {
pub product: Product,
pub source: Source,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Forecast {
pub location: Location,
#[serde(rename = "time-layout")]
pub time_layout: (TimeLayout, TimeLayout, TimeLayout),
pub parameters: Parameters,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Location {
#[serde(rename = "area-description")]
pub area_description: Option<String>,
pub description: Option<String>,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct TimeLayout {
#[serde(rename = "@time-coordinate")]
pub time_coordinate: TimeCoordinate,
#[serde(rename = "layout-key")]
pub layout_key: LayoutKey,
#[serde(rename = "start-valid-time")]
pub start_valid_time: Vec<StartValidTime>,
}
#[derive(Debug, Deserialize, PartialEq)]
pub enum TimeCoordinate {
#[serde(rename = "local")]
Local,
}
#[derive(Debug, Deserialize, PartialEq)]
pub enum LayoutKey {
#[serde(rename = "k-p12h-n14-1")]
K12Hourly,
#[serde(rename = "k-p24h-n7-1")]
K24Hourly1,
#[serde(rename = "k-p24h-n7-2")]
K24Hourly2,
#[serde(rename = "k-p1h-n1-1")]
K1Hour,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct StartValidTime {
#[serde(rename = "@period-name")]
pub period_name: String,
#[serde(rename = "$value")]
pub value: String,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct CurrentObservations {
pub location: Location,
#[serde(rename = "time-layout")]
pub time_layout: TimeLayout,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Product {
#[serde(rename = "creation-date")]
pub creation_date: CreationDate,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct CreationDate {
#[serde(rename = "@refresh-frequency")]
pub refresh_frequency: String,
#[serde(rename = "$value")]
pub value: String,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Source {
#[serde(rename = "production-center")]
pub production_center: String,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Parameters {
pub temperature: (Temperature, Temperature),
#[serde(rename = "probability-of-precipitation")]
pub probability_of_precipitation: ProbabilityOfPrecipitation,
pub weather: Weather,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Temperature {
#[serde(rename = "@type")]
pub temp_type: TempType,
#[serde(rename = "@units")]
pub units: TempUnits,
#[serde(rename = "@time-layout")]
pub time_layout: LayoutKey,
pub value: Vec<i32>,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct ProbabilityOfPrecipitation {
#[serde(rename = "@time-layout")]
pub time_layout: LayoutKey,
pub value: Vec<PrecipitationValue>,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct Weather {
#[serde(rename = "@time-layout")]
pub time_layout: LayoutKey,
#[serde(rename = "weather-conditions")]
pub weather_conditions: Vec<WeatherCondition>,
}
#[derive(Debug, Deserialize, PartialEq)]
pub struct WeatherCondition {
#[serde(rename = "@weather-summary")]
pub weather_summary: String,
}
// If only there was a percentage that could convey the concept of
// no precipitation.
#[derive(Debug, Deserialize, PartialEq)]
pub struct PrecipitationValue {
#[serde(rename = "$text")]
pub value: Option<u32>,
}
#[derive(Debug, Deserialize, PartialEq)]
pub enum TempType {
#[serde(rename = "apparent")]
Apparent,
#[serde(rename = "dew point")]
DewPoint,
#[serde(rename = "minimum")]
Minimum,
#[serde(rename = "maximum")]
Maximum,
}
#[derive(Debug, Deserialize, PartialEq)]
pub enum TempUnits {
Celsius,
Fahrenheit,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse() {
let s = include_str!("../data/empire_city.xml");
let _: Dwml = quick_xml::de::from_str(s).unwrap();
let s = include_str!("../data/sunset_city.xml");
let _: Dwml = quick_xml::de::from_str(s).unwrap();
let s = include_str!("../data/windy_city.xml");
let _: Dwml = quick_xml::de::from_str(s).unwrap();
}
}