{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} module Data.Aviation.Stratux.Types.Traffic( Traffic(..) , HasTraffic(..) , HasUTCTimes(..) ) where import Control.Applicative(Applicative((<*>))) import Control.Category(Category((.), id)) import Control.Lens(makeClassy, lens, Traversal') import Data.Aviation.Stratux.Types.EmitterCategory(EmitterCategory) import Data.Aviation.Stratux.Types.IcaoAddr(IcaoAddr, HasIcaoAddr(icaoAddr), HasWord8s(_Word8s)) import Data.Aviation.Stratux.Types.TargetType(TargetType) import Data.Aeson(FromJSON(parseJSON), ToJSON(toJSON), (.:), withObject, (.=), object) import Data.Bool(Bool) import Data.Eq(Eq) import Data.Int(Int) import Data.Functor((<$>)) import Data.Ord(Ord) import Data.String(String) import Data.Time(UTCTime) import Prelude(Double, Show) -- $setup -- >>> :set -XOverloadedStrings -- >>> import Control.Lens -- >>> import Data.Aeson(decode, encode) -- >>> import Data.Maybe(Maybe) -- >>> import Prelude -- >>> import Data.Aviation.Stratux.Types.EmitterCategory -- >>> import Data.Aviation.Stratux.Types.IcaoAddr -- >>> import Data.Aviation.Stratux.Types.TargetType -- >>> import Data.Time -- https://i.imgur.com/nOqGbfr.png data Traffic = Traffic { icaoAddrTraffic :: IcaoAddr , _tail :: String -- tail , _emitterCategory :: EmitterCategory , _onGround :: Bool -- on-ground , _addressType :: Int -- address type , _targetType :: TargetType , _signalLevel :: Double -- signal level , _positionValid :: Bool -- position valid , _latitude :: Double -- latitude , _longitude :: Double -- longitude , _altitude :: Int -- altitude , _gnssDiffFromBaroAlt :: Int -- GNSS altitude above WGS84 datum , _altIsGnss :: Bool -- AltIsGNSS, Pressure alt = 0; GNSS alt = 1 , _navigationIntegrityCategory :: Int -- Navigation Integrity Category. , _navigationAccuracyCategoryForPosition :: Int -- Navigation Accuracy Category for Position , _track :: Int -- Track degrees true , _speed :: Int -- speed (knots) , _speedValid :: Bool -- speed valid , _verticalVelocity :: Int -- Vertical velocity (feet/minute) , _timestamp :: UTCTime -- Timestamp , _age :: Double -- age , _lastSeen :: UTCTime -- last seen , _lastAltitude :: UTCTime -- last altitude , _lastGnssDiff :: UTCTime -- last GNSS diff , _lastGnssDiffAltitude :: Int -- last GNSS diff altitude , _lastSpeed :: UTCTime -- last speed , _lastSource :: Int -- last source , _extrapolatedPosition :: Bool -- extrapolated position , _bearing :: Double -- Bearing in degrees true to traffic from ownship, if it can be calculated. , _distanceToTrafficFromOwnship :: Double -- Distance to traffic from ownship, if it can be calculated. } deriving (Eq, Ord, Show) makeClassy ''Traffic -- | -- -- >>> decode "{\"Icao_addr\":8153826,\"Tail\":\"SVY22\",\"Emitter_category\":1,\"OnGround\":false,\"Addr_type\":0,\"TargetType\":1,\"SignalLevel\":-30.920514783877277,\"Position_valid\":true,\"Lat\":-27.501154,\"Lng\":153.21422,\"Alt\":12500,\"GnssDiffFromBaroAlt\":650,\"AltIsGNSS\":false,\"NIC\":8,\"NACp\":9,\"Track\":89,\"Speed\":205,\"Speed_valid\":true,\"Vvel\":0,\"Timestamp\":\"2016-05-24T01:13:18.189Z\",\"Age\":40.8,\"Last_seen\":\"0001-01-01T03:30:38.2Z\",\"Last_alt\":\"0001-01-01T03:30:38.55Z\",\"Last_GnssDiff\":\"0001-01-01T03:30:36.75Z\",\"Last_GnssDiffAlt\":12500,\"Last_speed\":\"0001-01-01T03:30:36.75Z\",\"Last_source\":1,\"ExtrapolatedPosition\":false,\"Bearing\":0,\"Distance\":0}" :: Maybe Traffic -- Just (Traffic {icaoAddrTraffic = IcaoAddr {_icaoAddrWord0 = 124, _icaoAddrWord1 = 106, _icaoAddrWord2 = 226}, _tail = "SVY22", _emitterCategory = Light, _onGround = False, _addressType = 0, _targetType = Adsb, _signalLevel = -30.920514783877277, _positionValid = True, _latitude = -27.501154, _longitude = 153.21422, _altitude = 12500, _gnssDiffFromBaroAlt = 650, _altIsGnss = False, _navigationIntegrityCategory = 8, _navigationAccuracyCategoryForPosition = 9, _track = 89, _speed = 205, _speedValid = True, _verticalVelocity = 0, _timestamp = 2016-05-24 01:13:18.189 UTC, _age = 40.8, _lastSeen = 0001-01-01 03:30:38.2 UTC, _lastAltitude = 0001-01-01 03:30:38.55 UTC, _lastGnssDiff = 0001-01-01 03:30:36.75 UTC, _lastGnssDiffAltitude = 12500, _lastSpeed = 0001-01-01 03:30:36.75 UTC, _lastSource = 1, _extrapolatedPosition = False, _bearing = 0.0, _distanceToTrafficFromOwnship = 0.0}) instance FromJSON Traffic where parseJSON = withObject "Traffic" (\x -> Traffic <$> x .: "Icao_addr" <*> x .: "Tail" <*> x .: "Emitter_category" <*> x .: "OnGround" <*> x .: "Addr_type" <*> x .: "TargetType" <*> x .: "SignalLevel" <*> x .: "Position_valid" <*> x .: "Lat" <*> x .: "Lng" <*> x .: "Alt" <*> x .: "GnssDiffFromBaroAlt" <*> x .: "AltIsGNSS" <*> x .: "NIC" <*> x .: "NACp" <*> x .: "Track" <*> x .: "Speed" <*> x .: "Speed_valid" <*> x .: "Vvel" <*> x .: "Timestamp" <*> x .: "Age" <*> x .: "Last_seen" <*> x .: "Last_alt" <*> x .: "Last_GnssDiff" <*> x .: "Last_GnssDiffAlt" <*> x .: "Last_speed" <*> x .: "Last_source" <*> x .: "ExtrapolatedPosition" <*> x .: "Bearing" <*> x .: "Distance") -- | -- -- >>> toJSON (Traffic (IcaoAddr 124 106 226) "SVY22" Light False 0 Adsb (-30.920514783877277) True (-27.501154) 153.21422 12500 650 False 8 9 89 205 True 0 (UTCTime (fromGregorian 1 1 1) 3597) 40.8 (UTCTime (fromGregorian 1 1 1) 259) (UTCTime (fromGregorian 1 1 1) 23) (UTCTime (fromGregorian 1 1 1) 597) 12500 (UTCTime (fromGregorian 2016 5 24) 237) 1 False 0.0 0.0) -- Object (fromList [("OnGround",Bool False),("Bearing",Number 0.0),("ExtrapolatedPosition",Bool False),("NIC",Number 8.0),("Last_alt",String "0001-01-01T00:00:23Z"),("Track",Number 89.0),("Last_speed",String "2016-05-24T00:03:57Z"),("GnssDiffFromBaroAlt",Number 650.0),("Last_seen",String "0001-01-01T00:04:19Z"),("Icao_addr",Number 8153826.0),("SignalLevel",Number -30.920514783877277),("Distance",Number 0.0),("Age",Number 40.8),("Speed_valid",Bool True),("TargetType",Number 1.0),("Lat",Number -27.501154),("Vvel",Number 0.0),("NACp",Number 9.0),("Addr_type",Number 0.0),("Speed",Number 205.0),("AltIsGNSS",Bool False),("Lng",Number 153.21422),("Tail",String "SVY22"),("Last_GnssDiffAlt",Number 12500.0),("Position_valid",Bool True),("Last_source",Number 1.0),("Timestamp",String "0001-01-01T00:59:57Z"),("Last_GnssDiff",String "0001-01-01T00:09:57Z"),("Alt",Number 12500.0),("Emitter_category",Number 1.0)]) instance ToJSON Traffic where toJSON (Traffic icaoAddr_ tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp_ age_ lastSeen_ lastAltitude_ lastGnssDiff_ lastGnssDiffAltitude_ lastSpeed_ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) = object [ "Icao_addr" .= icaoAddr_ , "Tail" .= tail_ , "Emitter_category" .= emitterCategory_ , "OnGround" .= onGround_ , "Addr_type" .= addressType_ , "TargetType" .= targetType_ , "SignalLevel" .= signalLevel_ , "Position_valid" .= positionValid_ , "Lat" .= latitude_ , "Lng" .= longitude_ , "Alt" .= altitude_ , "GnssDiffFromBaroAlt" .= gnssDiffFromBaroAlt_ , "AltIsGNSS" .= altIsGnss_ , "NIC" .= navigationIntegrityCategory_ , "NACp" .= navigationAccuracyCategoryForPosition_ , "Track" .= track_ , "Speed" .= speed_ , "Speed_valid" .= speedValid_ , "Vvel" .= verticalVelocity_ , "Timestamp" .= timestamp_ , "Age" .= age_ , "Last_seen" .= lastSeen_ , "Last_alt" .= lastAltitude_ , "Last_GnssDiff" .= lastGnssDiff_ , "Last_GnssDiffAlt" .= lastGnssDiffAltitude_ , "Last_speed" .= lastSpeed_ , "Last_source" .= lastSource_ , "ExtrapolatedPosition" .= extrapolatedPosition_ , "Bearing" .= bearing_ , "Distance" .= distanceToTrafficFromOwnship_ ] instance HasIcaoAddr Traffic where icaoAddr = lens (\(Traffic x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) -> x) (\(Traffic _ tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp_ age_ lastSeen_ lastAltitude_ lastGnssDiff_ lastGnssDiffAltitude_ lastSpeed_ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) x -> Traffic x tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp_ age_ lastSeen_ lastAltitude_ lastGnssDiff_ lastGnssDiffAltitude_ lastSpeed_ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) instance HasWord8s Traffic where _Word8s = icaoAddr . _Word8s class HasUTCTimes a where utcTimes :: Traversal' a UTCTime instance HasUTCTimes UTCTime where utcTimes = id -- | -- -- >>> (utcTimes %~ addUTCTime 1) (UTCTime (fromGregorian 1 1 1) 600) -- 0001-01-01 00:10:01 UTC instance HasUTCTimes Traffic where utcTimes f (Traffic icaoAddr_ tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp_ age_ lastSeen_ lastAltitude_ lastGnssDiff_ lastGnssDiffAltitude_ lastSpeed_ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) = (\timestamp__ lastSeen__ lastAltitude__ lastGnssDiff__ lastSpeed__ -> Traffic icaoAddr_ tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp__ age_ lastSeen__ lastAltitude__ lastGnssDiff__ lastGnssDiffAltitude_ lastSpeed__ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) <$> f timestamp_ <*> f lastSeen_ <*> f lastAltitude_ <*> f lastGnssDiff_ <*> f lastSpeed_