]> www.average.org Git - loctrkd.git/blobdiff - loctrkd/evstore.py
storage: save both raw and rectified reports
[loctrkd.git] / loctrkd / evstore.py
index 07b6dc4b760b7de08349611e844168ab0e80470a..b0265055dec85cd55785f626e6ae690aeb1599f5 100644 (file)
@@ -1,20 +1,32 @@
 """ sqlite event store """
 
+from datetime import datetime
+from json import dumps
 from sqlite3 import connect, OperationalError
-from typing import Any, List, Tuple
+from typing import Any, Dict, List, Tuple
 
-__all__ = "fetch", "initdb", "stow"
+__all__ = "fetch", "initdb", "stow", "stowloc"
 
 DB = None
 
-SCHEMA = """create table if not exists events (
+SCHEMA = (
+    """create table if not exists events (
     tstamp real not null,
     imei text,
     peeraddr text not null,
     is_incoming int not null default TRUE,
     proto text not null,
     packet blob
-)"""
+)""",
+    """create table if not exists reports (
+    imei text,
+    devtime text not null,
+    accuracy real,
+    latitude real,
+    longitude real,
+    remainder text
+)""",
+)
 
 
 def initdb(dbname: str) -> None:
@@ -26,7 +38,8 @@ def initdb(dbname: str) -> None:
                 is_incoming int not null default TRUE"""
         )
     except OperationalError:
-        DB.execute(SCHEMA)
+        for stmt in SCHEMA:
+            DB.execute(stmt)
 
 
 def stow(**kwargs: Any) -> None:
@@ -54,9 +67,33 @@ def stow(**kwargs: Any) -> None:
     DB.commit()
 
 
+def stowloc(**kwargs: Dict[str, Any]) -> None:
+    assert DB is not None
+    parms = {
+        k: kwargs.pop(k) if k in kwargs else v
+        for k, v in (
+            ("imei", None),
+            ("devtime", str(datetime.now())),
+            ("accuracy", None),
+            ("latitude", None),
+            ("longitude", None),
+        )
+    }
+    parms["remainder"] = dumps(kwargs)
+    DB.execute(
+        """insert or ignore into reports
+                (imei, devtime, accuracy, latitude, longitude, remainder)
+                values
+                (:imei, :devtime, :accuracy, :latitude, :longitude, :remainder)
+        """,
+        parms,
+    )
+    DB.commit()
+
+
 def fetch(
     imei: str, matchlist: List[Tuple[bool, str]], backlog: int
-) -> List[Tuple[bool, float, bytes]]:
+) -> List[Tuple[bool, float, str, bytes]]:
     # matchlist is a list of tuples (is_incoming, proto)
     # returns a list of tuples (is_incoming, timestamp, packet)
     assert DB is not None
@@ -65,7 +102,7 @@ def fetch(
     )
     cur = DB.cursor()
     cur.execute(
-        f"""select is_incoming, tstamp, packet from events
+        f"""select is_incoming, tstamp, proto, packet from events
                     where ({selector}) and imei = ?
                     order by tstamp desc limit ?""",
         tuple(item for sublist in matchlist for item in sublist)