packages feed

stratux-demo-0.0.12: src/Data/Aviation/Stratux/Demo.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE CPP #-}

module Data.Aviation.Stratux.Demo where

import Control.Applicative(pure, (<*>), (<**>))
import Control.Category((.))
import Control.Concurrent(threadDelay)
import Control.Lens((^.), makeClassy)
import Control.Monad(forever, join)
import Control.Monad.IO.Class(MonadIO(liftIO))
import Control.Monad.Trans.Except(runExceptT)
import Data.Aviation.Stratux
import Data.Bool(Bool, bool)
import Data.Either(either)
import Data.String(String)
import Data.Eq(Eq((==)))
import Data.Function(($))
import Data.Functor((<$>))
import Data.Int(Int)
import Data.List((++))
import Data.Maybe(Maybe(Just, Nothing))
import Data.Ord(Ord)
import Data.Semigroup((<>))
import Data.Text(Text)
import Network.URI(URIAuth(URIAuth))
import Prelude(Show(show))
import System.IO(IO, putStrLn)
import Text.Printf(printf)
import Options.Applicative(Parser, execParser, info, helper, fullDesc, header, option, maybeReader, short, long, value, help, strOption, switch, metavar, auto, showDefault)

hdr ::
  Bool
  -> String
  -> String
hdr nc s =
  bool
    (join ["\ESC[92m\ESC[42m", s, "\ESC[m"])
    s
    nc

val ::
  Bool
  -> String
  -> String
val nc s =
  bool
    (join ["\ESC[38m\ESC[41m", s, "\ESC[m"])
    s
    nc

----

demoSituation ::
  HasSituation s =>
  Bool
  -> s
  -> String
demoSituation nc = 
  let hdr' = hdr nc
      val' = val nc
  in  do  pa <- (^. pressureAlt)
          pc <- (^. pitch)
          rl <- (^. roll)
          hd <- (^. gyroHeading)
          lt <- (^. lat)
          ln <- (^. lon)
          vs <- (^. gpsVertVel)
          ht <- (^. heightAboveEllipsoid)
          cs <- (^. trueCourse)
          gs <- (^. groundSpeed)
          pure (join  [
                  hdr' "p.alt: "
                , val' (printf "%*.2fft" (8 :: Int) pa)
                , hdr' " pitch: "
                , val' (printf "%*.2fdeg" (7 :: Int) pc)
                , hdr' " roll: "
                , val' (printf "%*.2fdeg" (7 :: Int) rl)
                , hdr' " hdg: "
                , val' (printf "%*.2fdeg" (7 :: Int) hd)
                , hdr' " lat: "             
                , val' (printf "%*.4f" (8 :: Int) lt)
                , hdr' " lon: "
                , val' (printf "%*.4f" (9 :: Int) ln)
                , hdr' " v.speed: "
                , val' (printf "%*.2fft/min" (9 :: Int) vs)
                , hdr' " hgt: "
                , val' (printf "%*.2fft" (8 :: Int) ht)
                , hdr' " tr: "
                , val' (printf "%*.2fdeg" (6 :: Int) cs)
                , hdr' " g.speed: "
                , val' (printf "%*dkt" (3 :: Int) gs)                
                ])
         
printloop ::
  MonadIO f =>
  Int
  -> f String
  -> f ()
printloop d x =
  forever $
    do  a <- x
        liftIO (putStrLn a)
        liftIO (threadDelay d)

----

demoAirTraffic ::
  HasTraffic s =>
  Bool
  -> s
  -> String
demoAirTraffic nc =
  let hdr' = hdr nc
      val' = val nc
  in  do  t <- (^. tail)
          s <- (^. signalLevel)
          l <- (^. latitude)
          g <- (^. longitude)
          a <- (^. altitude)
          p <- (^. speed)
          v <- (^. verticalVelocity)
          x <- (^. timestamp)
          pure (join  [
                        hdr' "flight: "
                      , val' (printf "%*s" (6 :: Int) t)
                      , hdr' " power: "
                      , val' (printf "%*.2f dB" (6 :: Int) s)
                      , hdr' " lat: "             
                      , val' (printf "%*.4f" (8 :: Int) l)
                      , hdr' " lon: "
                      , val' (printf "%*.4f" (9 :: Int) g)
                      , hdr' " alt: "
                      , val' (printf "%*dft" (5 :: Int) a)
                      , hdr' " velocity: "
                      , val' (printf "%*dkt" (3 :: Int) p)
                      , hdr' " v/velocity: "
                      , val' (printf "%*dft/min" (6 :: Int) v)
                      , hdr' " time: "
                      , val' (printf "%*s" (27 :: Int) (show x))
                      ])

data DemoType =
  SituationDemo
  | TrafficDemo
  deriving (Eq, Ord)

instance Show DemoType where
  show SituationDemo =
    "situation"
  show TrafficDemo =
    "traffic"

data StratuxConfig =
  StratuxConfig {
    _demohost ::
      String
  , _demoport ::
      Int
  , _delay ::
      Int
  , _dtype ::
      DemoType
  , _nocolours ::
      Bool
  } deriving (Eq, Ord, Show)

parserDemoType ::
  Parser DemoType
parserDemoType =
  option
    (
      maybeReader
        (\s ->
          bool
            (
              bool
                Nothing
                (Just TrafficDemo)
                (s == "traffic")
            )
            (Just SituationDemo)
            (s == "situation")
        )
    )
    (
      short 'm' <>
      long "demo" <>
      value SituationDemo <>
      showDefault <>
      help "which demo" <>
      metavar "<situation|traffic>"
    )

parserStratuxConfig ::
  Parser StratuxConfig
parserStratuxConfig =
  StratuxConfig <$>
    strOption
      (
        short 'h' <>
        long "host" <>
        help "the host name" <>
        metavar "HOSTNAME"
      ) <*>
    option auto
      ( 
        short 'p' <>
        long "port" <>
        help "The host port" <>
        showDefault <>
        value 80 <>
        metavar "INT"
      ) <*>
    option auto
      ( 
        short 'd' <>
        long "delay" <>
        help "The delay between reading from the stratux device (milliseconds)" <>
        showDefault <>
        value 4000 <>
        metavar "INT"
      ) <*>
    parserDemoType <*>
    switch
      (
        short 'c' <>
        long "no-colours" <>
        help "terminal colours off"
      )

makeClassy ''StratuxConfig

run ::
  IO ()
run =
  let execopts =
        execParser
          (info (parserStratuxConfig <**> helper) (
            fullDesc <>
            header ("stratux-demo " <> VERSION_stratux_demo <> "demonstrates situation and traffic given by stratux <https://stratux.me/>")
          )
        )
  in  do  c <- execopts
          case c ^. dtype of
            SituationDemo ->
                printloop
                  (c ^. delay)
                  (either ("Error: " ++) (demoSituation (c ^. nocolours)) <$> runExceptT (getSituation (URIAuth (c ^. demohost) "" (':' : show (c ^. demoport))) "" ""))
            TrafficDemo ->
                trafficApp
                  (c ^. demohost)
                  (c ^. demoport) (
                    either
                      (\e ->
                          putStrLn ("Error: " ++ e))
                      (putStrLn . demoAirTraffic (c ^. nocolours))
                    )
                  ("" :: Text)