From dbb5c4b6b882cd99981eb854386586854a23fdec Mon Sep 17 00:00:00 2001 From: stuebinm Date: Wed, 13 May 2026 00:05:37 +0200 Subject: Server.Frontend.Tracker: dedicated configuration menu There is no back-channel with which we could retrieve the config that is currently on an owntracks client. However, we can send out each config with its own slightly tweaked host url, so that we can detect its provisioning on the incoming requests anyways. Credits for the idea go to Emily. --- lib/API.hs | 2 +- lib/OwnTracks/Configuration.hs | 1 + lib/Persist.hs | 9 ++++ lib/Server/Frontend/Routes.hs | 1 + lib/Server/Frontend/Tracker.hs | 93 ++++++++++++++++++++++++++++++++++++++---- lib/Server/Ingest.hs | 16 +++++++- 6 files changed, 111 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/API.hs b/lib/API.hs index e3e7107..b890ab7 100644 --- a/lib/API.hs +++ b/lib/API.hs @@ -83,7 +83,7 @@ type GtfsRealtimeAPI = "servicealerts" :> QueryFlag "force" :> Get '[Proto] Feed :<|> "vehiclepositions" :> QueryFlag "force" :> Get '[Proto] FeedMessage type OwnTracksAPI = - "pub" :> QueryParam "u" Text :> QueryParam "d" Text :> ReqBody '[JSON] OT.Message :> Post '[JSON] [OT.Command] + "pub" :> QueryParam "u" Text :> QueryParam "d" Text :> QueryParam "version" Int :> ReqBody '[JSON] OT.Message :> Post '[JSON] [OT.Command] type CompleteAPI = diff --git a/lib/OwnTracks/Configuration.hs b/lib/OwnTracks/Configuration.hs index 0cb361d..a10a46e 100644 --- a/lib/OwnTracks/Configuration.hs +++ b/lib/OwnTracks/Configuration.hs @@ -91,6 +91,7 @@ data Configuration = Configuration -- ^ Add extended data attributes to location messages (iOS,Android/boolean) , configHost :: Maybe Text -- ^ MQTT endpoint host (iOS,Android/string) + -- FIXME: structured type here? , configHttpHeaders :: Maybe Text -- ^ extra HTTP headers:field names and field content are separated by a colon (:), multiple fields by a backslash-n (\n) \:\\n\:\... (iOS only/string) , configIgnoreInaccurateLocations :: Maybe Int diff --git a/lib/Persist.hs b/lib/Persist.hs index dbab9bd..6f459fc 100644 --- a/lib/Persist.hs +++ b/lib/Persist.hs @@ -94,6 +94,7 @@ derivePersistFieldJSON "Value" -- We derive these here so that OwnTracks.* can become its own package eventually derivePersistFieldJSON "OwnTracks.Status" derivePersistFieldJSON "OwnTracks.Command" +derivePersistFieldJSON "OwnTracks.Configuration" data CommandStatus = Queued | Sent @@ -144,6 +145,7 @@ Tracker sql=tt_tracker blocked Bool agent Text currentTicket TicketId Maybe + configVersion Int Maybe deriving Eq Show Generic TrackerStatus sql=tt_tracker_status @@ -164,6 +166,13 @@ TrackerCommand sql=tt_tracker_command command OwnTracks.Command deriving Show Eq +TrackerConfig sql=tt_tracker_config + tracker TrackerId + timestamp UTCTime + seen Bool + configuration OwnTracks.Configuration + deriving Show Eq + -- raw frames as received from OBUs Ping json sql=tt_trip_ping ticket TicketId Maybe OnDeleteCascade OnUpdateCascade diff --git a/lib/Server/Frontend/Routes.hs b/lib/Server/Frontend/Routes.hs index d6b82e2..684d69d 100644 --- a/lib/Server/Frontend/Routes.hs +++ b/lib/Server/Frontend/Routes.hs @@ -49,6 +49,7 @@ mkYesodData "Frontend" [parseRoutes| /tracker/#Text TrackerViewR GET /tracker/#Text/delete TrackerDeleteR POST /tracker/#Text/command TrackerCommandR POST +/tracker/#Text/config TrackerConfigR POST /ticker/announce TickerAnnounceR POST /ticker/delete TickerDeleteR POST diff --git a/lib/Server/Frontend/Tracker.hs b/lib/Server/Frontend/Tracker.hs index ddbf5e9..e78e567 100644 --- a/lib/Server/Frontend/Tracker.hs +++ b/lib/Server/Frontend/Tracker.hs @@ -1,20 +1,21 @@ -{-# LANGUAGE BlockArguments #-} -{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE RecordWildCards #-} module Server.Frontend.Tracker (getTrackerViewR, getTrackersR, postTrackersR, postTrackerDeleteR, - postTrackerCommandR) + postTrackerCommandR, postTrackerConfigR) where -import Data.Aeson (decode, Value) -import Data.ByteString (fromStrict) +import Data.Aeson (Value, decode, encode) +import Data.ByteString (fromStrict, toStrict) import Data.Coerce (coerce) import Data.Function ((&)) import Data.Functor ((<&>)) import qualified Data.Map as M import Data.Text (Text) import qualified Data.Text as T -import Data.Text.Encoding (encodeUtf8) +import Data.Text.Encoding (decodeUtf8, encodeUtf8) import Data.Time (getCurrentTime) import qualified Data.UUID as UUID import Database.Esqueleto.Experimental hiding ((<&>)) @@ -24,7 +25,10 @@ import Server.Frontend.Routes (FrontendMessage (..), Handler, import Yesod hiding (delete, update, (=.), (==.)) +import Fmt +import qualified OwnTracks import OwnTracks.Command +import OwnTracks.Configuration (configHost) import OwnTracks.Status @@ -57,6 +61,7 @@ trackerCreateForm = renderDivs $ Tracker <*> pure False <*> areq textField (fieldSettingsLabel MsgTrackerAgent) Nothing <*> pure Nothing + <*> pure Nothing trackerCreateWidget :: Handler Html trackerCreateWidget = do @@ -130,6 +135,70 @@ postTrackerCommandR name = do