{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE LambdaCase #-} module OwnTracks.Command -- | https://owntracks.org/booklet/tech/json/ (Command(..)) where import Data.Aeson import Data.Aeson.Types (Parser) import Data.ByteString (ByteString) import Data.ByteString.Base64 import Data.Functor ((<&>)) import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8) import Data.Time (UTCTime, defaultTimeLocale, parseTimeM) import Database.Persist import GHC.Generics (Generic) import OwnTracks.Configuration import OwnTracks.Waypoint data Command = Dump -- ^ Triggers the publish of a configuration message (iOS) | GetStatus -- ^ Triggers the publish of a status message to ../status (iOS) | ReportSteps { reportStepsFrom :: Maybe Int, reportStepsTo :: Maybe Int } -- ^ Triggers the report of a steps messages_(iOS)_ | ReportLocation -- ^ Triggers the publish of a location messages (iOS,Android) Don‘t expect device to be online. Send with QoS>0. Device will receive and repond when activated next time | ClearWaypoints -- ^ deletes all waypoints/regions (iOS) | SetWaypoints [Waypoint] -- ^ Imports (merge) and activates new waypoints (iOS,Android) | SetConfiguration Configuration -- ^ Imports and activates new configuration values (iOS,Android) | GetWaypoints -- ^ Triggers publish of a waypoints message (iOS,Android) deriving (Eq, Show, Generic) instance ToJSON Command where toJSON c = object ( "_type" .= String "cmd" : "action" .= String action : others ) where action = case c of Dump -> "dump" GetStatus -> "status" ReportSteps _ _ -> "reportSteps" ReportLocation -> "reportLocation" ClearWaypoints -> "clearWaypoints" SetWaypoints _ -> "setWaypoints" SetConfiguration _ -> "setConfiguration" GetWaypoints -> "waypoints" others = case c of ReportSteps f t -> [ "from" .= f, "to" .= t ] SetWaypoints ws -> [ "waypoints" .= ws ] SetConfiguration c -> [ "configuration" .= c ] _ -> [] instance FromJSON Command where parseJSON (Object v) = do action :: Text <- v .: "action" case action of "dump" -> pure Dump "status" -> pure GetStatus "reportSteps" -> ReportSteps <$> v .: "from" <*> v .: "to" "reportLocation" -> pure ReportLocation "clearWaypoints" -> pure ClearWaypoints "setWaypoints" -> SetWaypoints <$> v .: "waypoints" "setConfiguration" -> SetConfiguration <$> v .: "configuration" "waypoints" -> pure GetWaypoints _ -> fail "unknown action in _type=command" parseJSON _ = fail "Command should be an object"