packages feed

ttn 0.1.0.0 → 0.2.0.0

raw patch · 2 files changed

+107/−70 lines, 2 files

Files

src/Data/TTN/Types.hs view
@@ -1,29 +1,40 @@ {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# OPTIONS_GHC -Wno-orphans     #-}  module Data.TTN.Types where -import System.Exit (exitFailure, exitSuccess)-import System.IO (stderr, hPutStrLn)-import qualified Data.ByteString.Char8 as B-import System.Environment (getArgs)-import Control.Monad (forM_, mzero, join)-import Control.Applicative-import Data.Aeson(decodeStrict, eitherDecodeStrict,-                  Value(..), FromJSON(..), ToJSON(..),-                  pairs, withText, (.:), (.:?), (.=), object)-import Data.Monoid-import Data.Text (Text, unpack)+import Control.Monad (forM_, mzero)++import Data.Aeson ( decodeStrict+                  , eitherDecodeStrict+                  , Value(..)+                  , FromJSON(..)+                  , ToJSON(..)+                  , pairs+                  , withText+                  , (.:)+                  , (.:?)+                  , (.=)+                  , object)++import Data.ByteString.Char8 (ByteString)+import Data.Text (Text)+ import GHC.Generics  import Data.Time.RFC3339 import Data.Time.LocalTime --- | Workaround for https://github.com/bos/aeson/issues/287.-o .:?? val = fmap join (o .:? val)+import qualified Data.ByteString.Char8+import qualified Data.Text+import qualified System.Exit+import qualified System.IO -data TTNZonedTime = TTNZonedTime { unwrap :: ZonedTime } deriving (Show, Generic)+data TTNZonedTime = TTNZonedTime { unwrap :: ZonedTime }+  deriving (Eq, Show, Generic)  instance ToJSON TTNZonedTime where   toJSON     = toJSON . (formatTimeRFC3339 :: ZonedTime -> Text) . unwrap@@ -35,25 +46,27 @@       Nothing -> fail $ "Parsing RFC3339 value failed, got:" ++ show x       Just t -> return $ TTNZonedTime t +instance Eq ZonedTime where+  ZonedTime t1 tz1 == ZonedTime t2 tz2 = t1 == t2 && tz1 == tz2  -- https://github.com/TheThingsNetwork/ttn/blob/develop/core/types/event.go#L65 data Config = Config {     configFrequency  :: Maybe Double   , configDataRate   :: Maybe Text-  , configCounter    :: Maybe Double+  , configCounter    :: Maybe Integer   , configAirtime    :: Maybe Double   , configPower      :: Maybe Double   , configModulation :: Maybe Text-  } deriving (Show, Generic)+  } deriving (Eq, Show, Generic)  instance FromJSON Config where   parseJSON (Object v) = Config-    <$> v .:?? "frequency"-    <*> v .:?? "data_rate"-    <*> v .:?? "counter"-    <*> v .:?? "airtime"-    <*> v .:?? "power"-    <*> v .:?? "modulation"+    <$> v .:? "frequency"+    <*> v .:? "data_rate"+    <*> v .:? "counter"+    <*> v .:? "airtime"+    <*> v .:? "power"+    <*> v .:? "modulation"   parseJSON _          = mzero  instance ToJSON Config where@@ -80,7 +93,7 @@ data GatewaysElt = GatewaysElt {     gatewaysEltGtwId                  :: Maybe Text   , gatewaysEltGtwTrusted             :: Maybe Bool-  , gatewaysEltTimestamp              :: Maybe Int+  , gatewaysEltTimestamp              :: Maybe Integer   , gatewaysEltFineTimestamp          :: Maybe Int   , gatewaysEltFineTimestampEncrypted :: Maybe Text   , gatewaysEltTime                   :: Maybe TTNZonedTime@@ -94,26 +107,26 @@   , gatewaysEltAltitude               :: Maybe Int   , gatewaysEltAccuracy               :: Maybe Int   , gatewaysEltSource                 :: Maybe Text-  } deriving (Show, Generic)+  } deriving (Eq, Show, Generic)  instance FromJSON GatewaysElt where   parseJSON (Object v) = GatewaysElt-    <$> v .:?? "gtw_id"-    <*> v .:?? "gtw_trusted"-    <*> v .:?? "timestamp"-    <*> v .:?? "fine_timestamp"-    <*> v .:?? "fine_timestamp_encrypted"-    <*> v .:?? "time"-    <*> v .:?? "antenna"+    <$> v .:? "gtw_id"+    <*> v .:? "gtw_trusted"+    <*> v .:? "timestamp"+    <*> v .:? "fine_timestamp"+    <*> v .:? "fine_timestamp_encrypted"+    <*> v .:? "time"+    <*> v .:? "antenna"     <*> v .:   "channel"     <*> v .:   "rssi"     <*> v .:   "snr"     <*> v .:   "rf_chain"-    <*> v .:?? "latitude"-    <*> v .:?? "longitude"-    <*> v .:?? "altitude"-    <*> v .:?? "accuracy"-    <*> v .:?? "source"+    <*> v .:? "latitude"+    <*> v .:? "longitude"+    <*> v .:? "altitude"+    <*> v .:? "accuracy"+    <*> v .:? "source"   parseJSON _          = mzero  instance ToJSON GatewaysElt where@@ -165,17 +178,17 @@   , metadataAirtime    :: Maybe Double   , metadataCodingRate :: Maybe Text   , metadataGateways   :: [GatewaysElt]-  } deriving (Show, Generic)+  } deriving (Eq, Show, Generic)  instance FromJSON Metadata where   parseJSON (Object v) = Metadata <$>-        v .:?? "time"-    <*> v .:?? "frequency"-    <*> v .:?? "modulation"-    <*> v .:?? "data_rate"-    <*> v .:?? "bit_rate"-    <*> v .:?? "airtime"-    <*> v .:?? "coding_rate"+        v .:? "time"+    <*> v .:? "frequency"+    <*> v .:? "modulation"+    <*> v .:? "data_rate"+    <*> v .:? "bit_rate"+    <*> v .:? "airtime"+    <*> v .:? "coding_rate"     <*> v .:   "gateways"   parseJSON _          = mzero @@ -206,7 +219,7 @@     messageDevId :: Text,     messageAppId :: Text,     messagePort  :: Double-  } deriving (Show, Generic)+  } deriving (Eq, Show, Generic)  instance FromJSON Message where   parseJSON (Object v) = Message@@ -234,7 +247,7 @@   , uplinkGatewayId      :: Maybe Text   , uplinkDevId          :: Maybe Text   , uplinkPayload        :: Maybe Text-  , uplinkCounter        :: Maybe Double+  , uplinkCounter        :: Maybe Integer   , uplinkIsRetry        :: Maybe Bool   , uplinkMetadata       :: Maybe Metadata   , uplinkPayloadRaw     :: Maybe Text@@ -243,23 +256,23 @@   , uplinkConfirmed      :: Maybe Bool   , uplinkHardwareSerial :: Maybe Text   , uplinkPort           :: Maybe Double-  } deriving (Show, Generic)+  } deriving (Eq, Show, Generic)  instance FromJSON Uplink where   parseJSON (Object v) = Uplink-    <$> v .:?? "config"-    <*> v .:?? "gateway_id"-    <*> v .:?? "dev_id"-    <*> v .:?? "payload"-    <*> v .:?? "counter"-    <*> v .:?? "is_retry"-    <*> v .:?? "metadata"-    <*> v .:?? "payload_raw"-    <*> v .:?? "message"-    <*> v .:?? "app_id"-    <*> v .:?? "confirmed"-    <*> v .:?? "hardware_serial"-    <*> v .:?? "port"+    <$> v .:? "config"+    <*> v .:? "gateway_id"+    <*> v .:? "dev_id"+    <*> v .:? "payload"+    <*> v .:? "counter"+    <*> v .:? "is_retry"+    <*> v .:? "metadata"+    <*> v .:? "payload_raw"+    <*> v .:? "message"+    <*> v .:? "app_id"+    <*> v .:? "confirmed"+    <*> v .:? "hardware_serial"+    <*> v .:? "port"   parseJSON _          = mzero  instance ToJSON Uplink where@@ -303,7 +316,7 @@       "replace" -> return ScheduleReplace       "first"   -> return ScheduleFirst       "last"    -> return ScheduleLast-      w         -> fail $ "Unknown schedule" ++ (unpack w)+      w         -> fail $ "Unknown schedule" ++ (Data.Text.unpack w)  instance ToJSON Schedule where   toJSON ScheduleReplace = "replace"@@ -327,7 +340,7 @@     <*> v .:   "port"     <*> v .:   "payload_raw"     <*> v .:   "confirmed"-    <*> v .:?? "schedule"+    <*> v .:? "schedule"   parseJSON _          = mzero  instance ToJSON Downlink where@@ -359,26 +372,49 @@   toJSON (Error {..}) = object [ "error" .= errorMsg ]   toEncoding (Error {..}) = pairs ( "error" .= errorMsg ) -parse :: B.ByteString -> Either String Uplink+-- used by ttn-client+data EventType =+    Up+  | Down+  | DownAcked+  | DownSent+  | DownScheduled+  | Activation+  | Create+  | Update+  | Delete+  | Unknown+  deriving (Eq, Ord, Show, Generic)++data Event =+    Event EventType Uplink+  | ClientError String+  deriving (Eq, Show, Generic)++instance FromJSON EventType where+instance ToJSON EventType where+instance FromJSON Event where+instance ToJSON Event where++parse :: ByteString -> Either String Uplink parse = eitherDecodeStrict -parseError :: B.ByteString -> Either String Error+parseError :: ByteString -> Either String Error parseError = eitherDecodeStrict  parseFile :: FilePath -> IO Uplink parseFile filename = do-  input <- B.readFile filename+  input <- Data.ByteString.Char8.readFile filename   case decodeStrict input of     Nothing -> fatal $ case (decodeStrict input :: Maybe Value) of                          Nothing -> "Invalid JSON file: "     ++ filename-                         Just v  -> "Mismatched JSON value from file: " ++ filename+                         Just _v -> "Mismatched JSON value from file: " ++ filename     Just r  -> return (r :: Uplink)   where     fatal :: String -> IO a-    fatal msg = do hPutStrLn stderr msg-                   exitFailure+    fatal msg = do System.IO.hPutStrLn System.IO.stderr msg+                   System.Exit.exitFailure  parseMany :: [String] -> IO () parseMany filenames = do   forM_ filenames (\f -> parseFile f >>= (\p -> p `seq` putStrLn $ "Successfully parsed " ++ f))-  exitSuccess
ttn.cabal view
@@ -1,5 +1,5 @@ name:                ttn-version:             0.1.0.0+version:             0.2.0.0 synopsis:            Things Tracker Network JSON Types description:         Parse JSONs from TTN MQTT API homepage:            https://github.com/sorki/data-ttn@@ -14,6 +14,7 @@ cabal-version:       >=1.10  library+  ghc-options:         -Wall   hs-source-dirs:      src   exposed-modules:     Data.TTN                      , Data.TTN.Types