opench-meteo (empty) → 0.1.0.0
raw patch · 7 files changed
+225/−0 lines, 7 filesdep +aesondep +basedep +data-defaultsetup-changed
Dependencies added: aeson, base, data-default, text, time
Files
- ChangeLog.md +5/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- opench-meteo.cabal +32/−0
- src/Data/Meteo/Swiss.hs +16/−0
- src/Data/Meteo/Swiss/Types.hs +112/−0
- src/Data/Meteo/Swiss/Urls.hs +28/−0
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for opench-meteo++## 0.1.0.0 -- 2017-03-25++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017, Hans Roland Senn++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Hans Roland Senn nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ opench-meteo.cabal view
@@ -0,0 +1,32 @@+-- Initial opench-meteo.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/++name: opench-meteo+version: 0.1.0.0+synopsis: A Haskell implementation of the Swiss Meteo Net data API+description: OpenData SMN is a REST API for <http://www.meteoswiss.admin.ch/home/measurement-and-forecasting-systems/land-based-stations/automatisches-messnetz.html SwissMetNet > data.+ The module Data.Meteo.Swiss contains the main documentation.+homepage: https://github.com/hansroland/opench+license: BSD3+license-file: LICENSE+author: Roland Senn+maintainer: rsx@bluewin.ch+copyright: Copyright by Roland Senn +category: Data+build-type: Simple+extra-source-files: ChangeLog.md+cabal-version: >=1.10++library+ exposed-modules: Data.Meteo.Swiss+ other-modules: Data.Meteo.Swiss.Types+ , Data.Meteo.Swiss.Urls+ other-extensions: OverloadedStrings+ build-depends: base >=4.8 && < 4.10+ , aeson >=0.8 && <1.1+ , data-default >= 0.5 && < 0.8+ , text >=1.2 && <1.3+ , time >=1.5 && <1.7+ hs-source-dirs: src+ default-language: Haskell2010+ ghc-options: -Wall
+ src/Data/Meteo/Swiss.hs view
@@ -0,0 +1,16 @@+-- | A Haskell implementation of the Swiss Meteo Net data API+--+-- OpenData SMN is a REST API for <http://www.meteoswiss.admin.ch/home/measurement-and-forecasting-systems/land-based-stations/automatisches-messnetz.html SwissMetNet > data.+-- It's developed in the open supporting the <http://opendata.ch/ OpenData.ch > initiative. +-- Free OpenData hosting is provided by <http://netcetera.com/ Netcetera > at <http://data.netcetera.com/smn >.+--+-- The actual data for 10 min intervals is provided by opendata.swiss, the Swiss open government data portal.++module Data.Meteo.Swiss + (+ module Data.Meteo.Swiss.Types+ , module Data.Meteo.Swiss.Urls+ ) + where+import Data.Meteo.Swiss.Types+import Data.Meteo.Swiss.Urls
+ src/Data/Meteo/Swiss/Types.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Data types for the Swiss Meteo Net API+module Data.Meteo.Swiss.Types+ (+ -- * Types+ SmnRecord (..)+ , SmnStation(..)+ ) where++import Data.Aeson+import qualified Data.Text as T+import Data.Time+import Data.Default+import Data.Aeson.Types (Parser) +import Data.String (IsString)+import Control.Monad (mzero)++-- | A Swiss Meteo Network data SmnRecord.+-- It contains the meteo information of a 10 min interval of a Swiss meteo station.+-- +-- /Note:/ All 'Text' fields may contain empty strings.+data SmnRecord = SmnRecord + { smnStation :: Maybe SmnStation -- ^ Info about the station+ , smnCode :: T.Text -- ^ 3-char all upper-case station code,+ , smnDateTime :: Maybe UTCTime -- ^ Time in UTC,+ , smnTemperature :: T.Text -- ^ Air temperature 2 m above ground; current value,+ , smnSunshine :: T.Text -- ^ Sunshine duration; ten minutes total,+ , smnPrecipitation :: T.Text -- ^ Precipitation; ten minutes total,+ , smnWindDirection :: T.Text -- ^ Wind direction; ten minutes mean,+ , smnWindSpeed :: T.Text -- ^ Wind speed; ten minutes mean,+ , smnQnhPressure :: T.Text -- ^ Pressure reduced to sea level according to standard atmosphere (QNH); current value,+ , smnGustPeak :: T.Text -- ^ Gust peak (one second); maximum,+ , smnHumidity :: T.Text -- ^ Relative air humidity 2 m above ground; current value,+ , smnQfePressure :: T.Text -- ^ Pressure at station level (QFE); current value,+ , smnQffPressure :: T.Text -- ^ Pressure reduced to sea level (QFF); current value+ }+ deriving Show++instance FromJSON SmnRecord where + parseJSON (Object v) = SmnRecord+ <$> v .:? "station"+ <*> v .:?! "code" + <*> v .:? "dateTime"+ <*> v .:?! "temperature"+ <*> v .:?! "sunshine"+ <*> v .:?! "precipitation"+ <*> v .:?! "windDirection"+ <*> v .:?! "windSpeed"+ <*> v .:?! "qnhPressure"+ <*> v .:?! "gustPeak"+ <*> v .:?! "humidity"+ <*> v .:?! "qfePressure"+ <*> v .:?! "qffPressure"+ parseJSON _ = mzero++instance Default SmnRecord where+ def = SmnRecord + { smnStation = def+ , smnCode = "" + , smnDateTime = Nothing+ , smnTemperature = ""+ , smnSunshine = ""+ , smnPrecipitation = ""+ , smnWindDirection = ""+ , smnWindSpeed = ""+ , smnQnhPressure = ""+ , smnGustPeak = ""+ , smnHumidity = ""+ , smnQfePressure = ""+ , smnQffPressure = ""+ }++-- | A Swiss Meteo Network data station.+--+-- /Note:/ All 'Text' fields may contain empty strings.+data SmnStation = SmnStation + { staCode :: T.Text -- ^ 3-char all upper-case station code,+ , staName :: T.Text -- ^ Original name in local language,+ , staCh1903Y :: Maybe Int -- ^ CH1903 (Swiss grid) y-axis value,+ , staCh1903X :: Maybe Int -- ^ CH1903 (Swiss grid) x-axis value,+ , staLat :: Maybe Double -- ^ WGS84 latitude,+ , staLng :: Maybe Double -- ^ WGS84 longitude,+ , staElevation :: Maybe Int -- ^ meters above sea level+ }+ deriving Show++instance FromJSON SmnStation where + parseJSON (Object v) = SmnStation+ <$> v .:?! "code"+ <*> v .:?! "name"+ <*> v .:? "ch1903Y"+ <*> v .:? "ch1903X"+ <*> v .:? "lat"+ <*> v .:? "lng"+ <*> v .:? "elevation"+ parseJSON _ = mzero++instance Default SmnStation where+ def = SmnStation + { staCode = ""+ , staName = ""+ , staCh1903Y = Nothing+ , staCh1903X = Nothing+ , staLat = Nothing+ , staLng = Nothing+ , staElevation = Nothing+ }+ +-- little helper combinator to parse and convert null values to empty Text strings.+(.:?!) :: (Data.String.IsString a, FromJSON a) => Object -> T.Text -> Parser a+(.:?!) v k = v .: k .!= ""
+ src/Data/Meteo/Swiss/Urls.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE OverloadedStrings #-}++-- | URLs for the Swiss Meteo Net API+module Data.Meteo.Swiss.Urls+ (+ -- * Functions that return URLs+ urlDataAll+ , urlDataStat+ , urlDocuStat + )+where++import qualified Data.Text as T+import Data.Monoid ((<>))++-- | Return the URL to retrieve all meteo data from all stations for the last 10 minutes.+urlDataAll :: T.Text+urlDataAll = "http://opendata.netcetera.com:80/smn/smn/"++-- | Return the URL to retrieve the meteo data for a given station for the last 10 minutes.+urlDataStat :: T.Text -- ^ 3-char all upper-case station code+ -> T.Text+urlDataStat stat = "http://opendata.netcetera.com:80/smn/smn/" <> stat++-- | Return the URL to retrieve the documentation sheet for a given station+urlDocuStat :: T.Text -- ^ 3-char all upper-case station code + -> T.Text+urlDocuStat stat = "http://www.meteoschweiz.admin.ch/product/input/smn-stations/docs/" <> stat <> ".pdf"