google_takeout: add semantic location history (#278)
* google_takeout: add semantic location history
This commit is contained in:
parent
a4c713664e
commit
9d231a8ea9
3 changed files with 96 additions and 0 deletions
|
@ -89,6 +89,14 @@ class location:
|
|||
export_path: Paths = ''
|
||||
accuracy: float
|
||||
|
||||
class google_takeout_semantic:
|
||||
# a value between 0 and 100, 100 being the most confident
|
||||
# set to 0 to include all locations
|
||||
# https://locationhistoryformat.com/reference/semantic/#/$defs/placeVisit/properties/locationConfidence
|
||||
require_confidence: float = 40
|
||||
# default accuracy for semantic locations
|
||||
accuracy: float = 100
|
||||
|
||||
|
||||
from my.core.compat import Literal
|
||||
class time:
|
||||
|
|
|
@ -16,6 +16,7 @@ logger = LazyLogger(__name__, level="warning")
|
|||
def locations() -> Iterator[Location]:
|
||||
# can add/comment out sources here to disable them, or use core.disabled_modules
|
||||
yield from _takeout_locations()
|
||||
yield from _takeout_semantic_locations()
|
||||
yield from _gpslogger_locations()
|
||||
yield from _ip_locations()
|
||||
|
||||
|
@ -26,6 +27,17 @@ def _takeout_locations() -> Iterator[Location]:
|
|||
yield from google_takeout.locations()
|
||||
|
||||
|
||||
@import_source(module_name="my.location.google_takeout_semantic")
|
||||
def _takeout_semantic_locations() -> Iterator[Location]:
|
||||
from . import google_takeout_semantic
|
||||
|
||||
for event in google_takeout_semantic.locations():
|
||||
if isinstance(event, Exception):
|
||||
logger.error(f"google_takeout_semantic: {event}")
|
||||
continue
|
||||
yield event
|
||||
|
||||
|
||||
@import_source(module_name="my.location.gpslogger")
|
||||
def _gpslogger_locations() -> Iterator[Location]:
|
||||
from . import gpslogger
|
||||
|
|
76
my/location/google_takeout_semantic.py
Normal file
76
my/location/google_takeout_semantic.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
"""
|
||||
Extracts semantic location history using google_takeout_parser
|
||||
"""
|
||||
|
||||
# This is a separate module to prevent ImportError and a new config block from breaking
|
||||
# previously functional my.location.google_takeout locations
|
||||
|
||||
REQUIRES = ["git+https://github.com/seanbreckenridge/google_takeout_parser"]
|
||||
|
||||
from typing import Iterator, List
|
||||
|
||||
from my.google.takeout.parser import events, _cachew_depends_on as _parser_cachew_depends_on
|
||||
from google_takeout_parser.models import PlaceVisit as SemanticLocation
|
||||
|
||||
from my.core import dataclass, make_config
|
||||
from my.core.common import mcachew, LazyLogger, Stats
|
||||
from my.core.error import Res
|
||||
from .common import Location
|
||||
|
||||
logger = LazyLogger(__name__)
|
||||
|
||||
from my.config import location as user_config
|
||||
|
||||
@dataclass
|
||||
class semantic_locations_config(user_config.google_takeout_semantic):
|
||||
# a value between 0 and 100, 100 being the most confident
|
||||
# set to 0 to include all locations
|
||||
# https://locationhistoryformat.com/reference/semantic/#/$defs/placeVisit/properties/locationConfidence
|
||||
require_confidence: int = 40
|
||||
# default accuracy for semantic locations
|
||||
accuracy: float = 100
|
||||
|
||||
|
||||
config = make_config(semantic_locations_config)
|
||||
|
||||
|
||||
# add config to cachew dependency so it recomputes on config changes
|
||||
def _cachew_depends_on() -> List[str]:
|
||||
dep = _parser_cachew_depends_on()
|
||||
dep.insert(0, f"require_confidence={config.require_confidence} accuracy={config.accuracy}")
|
||||
return dep
|
||||
|
||||
|
||||
|
||||
@mcachew(
|
||||
depends_on=_cachew_depends_on,
|
||||
logger=logger,
|
||||
)
|
||||
def locations() -> Iterator[Res[Location]]:
|
||||
require_confidence = config.require_confidence
|
||||
if require_confidence < 0 or require_confidence > 100:
|
||||
yield ValueError("location.google_takeout.semantic_require_confidence must be between 0 and 100")
|
||||
return
|
||||
|
||||
for g in events():
|
||||
if isinstance(g, SemanticLocation):
|
||||
if g.visitConfidence < require_confidence:
|
||||
logger.debug(f"Skipping {g} due to low confidence ({g.visitConfidence}))")
|
||||
continue
|
||||
yield Location(
|
||||
lon=g.lng,
|
||||
lat=g.lat,
|
||||
dt=g.dt,
|
||||
# can accuracy be inferred from visitConfidence?
|
||||
# there's no exact distance value in the data, its a 0-100% confidence value...
|
||||
accuracy=config.accuracy,
|
||||
elevation=None,
|
||||
datasource="google_takeout_semantic",
|
||||
)
|
||||
|
||||
|
||||
|
||||
def stats() -> Stats:
|
||||
from my.core import stat
|
||||
|
||||
return {**stat(locations)}
|
Loading…
Add table
Reference in a new issue