Support multiple locator methods

This commit is contained in:
Teemu Ikonen
2023-03-10 17:09:06 +02:00
parent 2ff735aeaa
commit 04b48952e9
3 changed files with 57 additions and 44 deletions

View File

@@ -150,9 +150,17 @@ def get_config():
f"Cell resolver '{resolver}' in " f"Cell resolver '{resolver}' in "
f"locator '{locator}' not found in config") f"locator '{locator}' not found in config")
if conf.get('method') not in conf['locator'].keys(): methods = ([conf.get('method')] if conf.get('method') is not None
raise MissingConfigException( else conf.get('methods'))
"Method not defined in config, or it's not in configured locators") if not methods:
raise MissingConfigException("Locator methods not defined in config")
for method in methods:
if method not in conf['locator'].keys():
raise MissingConfigException(
f"Method '{method}' is not in configured locators")
conf['methods'] = methods
if isinstance(conf['datadir'], str): if isinstance(conf['datadir'], str):
if conf['datadir'].startswith('~'): if conf['datadir'].startswith('~'):

View File

@@ -2,7 +2,7 @@ port = 8088
host = "127.0.0.1" host = "127.0.0.1"
datadir = "~/.local/share/ols/" datadir = "~/.local/share/ols/"
# obsdb = "obsdb.db" # DB file (in datadir) to store all incoming observations # obsdb = "obsdb.db" # DB file (in datadir) to store all incoming observations
method = "clustering" # Must be a name of a locator subsection methods = ["clustering"] # Methods are names of locator subsections
debuglevel = "warning" # critical,error,warning,info,debug debuglevel = "warning" # critical,error,warning,info,debug
logtimestamps = true # Set to false if logging to journald logtimestamps = true # Set to false if logging to journald
@@ -14,6 +14,7 @@ logtimestamps = true # Set to false if logging to journald
[locator.clustering] [locator.clustering]
# Aggregates wifi and cell coordinates and calculates a probable location # Aggregates wifi and cell coordinates and calculates a probable location
type = "clustering" type = "clustering"
# Resolvers are resolver subsection names
wifiresolvers = ["wigle"] wifiresolvers = ["wigle"]
cellresolvers = ["wigle"] cellresolvers = ["wigle"]

View File

@@ -12,7 +12,7 @@ from . import config
from . import obsdb from . import obsdb
from . import schemas from . import schemas
locator = None locators = None
observationdb = None observationdb = None
geolocate_validate = fastjsonschema.compile(schemas.geolocate_v1_schema) geolocate_validate = fastjsonschema.compile(schemas.geolocate_v1_schema)
geosubmit_validate = fastjsonschema.compile(schemas.geosubmit_v2_schema) geosubmit_validate = fastjsonschema.compile(schemas.geosubmit_v2_schema)
@@ -25,7 +25,7 @@ async def all_handler(request):
async def locate_handler(request): async def locate_handler(request):
global hint global hint
global locator global locators
global observationdb global observationdb
notfound_error_res = { notfound_error_res = {
@@ -78,12 +78,15 @@ async def locate_handler(request):
observationdb.insert_locate(data) observationdb.insert_locate(data)
try: for locator in locators:
async with asyncio.timeout(20): try:
latlon, accuracy = await locator.locate(data, hint=hint) async with asyncio.timeout(20):
except asyncio.TimeoutError: latlon, accuracy = await locator.locate(data, hint=hint)
log.warning('Locator timeout') except asyncio.TimeoutError:
latlon, accuracy = None, None log.warning('Locator timeout')
latlon, accuracy = None, None
if latlon is not None:
break
if latlon is not None: if latlon is not None:
hint = latlon hint = latlon
@@ -140,7 +143,7 @@ async def submit_handler(request):
def main(): def main():
global locator global locators
global observationdb global observationdb
global log global log
@@ -181,37 +184,38 @@ def main():
log.error(f"Unknown resolver type '{rtype}'") log.error(f"Unknown resolver type '{rtype}'")
return None return None
# FIXME: Add support for multiple locators locators = []
method_conf = conf['locator'][conf['method']] for method in conf['methods']:
mtype = method_conf.get('type') method_conf = conf['locator'][method]
if mtype is None: mtype = method_conf.get('type')
raise config.MissingConfigException if mtype is None:
elif mtype == 'clustering': raise config.MissingConfigException
from .locator.clustering import ClusteringLocator elif mtype == 'clustering':
wlist = method_conf.get('wifiresolvers', []) from .locator.clustering import ClusteringLocator
wifiresolvers = [get_resolver(e) for e in wlist] wlist = method_conf.get('wifiresolvers', [])
clist = method_conf.get('cellresolvers', []) wifiresolvers = [get_resolver(e) for e in wlist]
cellresolvers = [get_resolver(e) for e in clist] clist = method_conf.get('cellresolvers', [])
locator = ClusteringLocator(wifiresolvers, cellresolvers) cellresolvers = [get_resolver(e) for e in clist]
elif mtype == 'strongestcell': locators.append(ClusteringLocator(wifiresolvers, cellresolvers))
from .locator.single import StrongestCellLocator elif mtype == 'strongestcell':
clist = method_conf.get('cellresolvers', []) from .locator.single import StrongestCellLocator
cellresolvers = [get_resolver(e) for e in clist] clist = method_conf.get('cellresolvers', [])
locator = StrongestCellLocator(cellresolvers) cellresolvers = [get_resolver(e) for e in clist]
elif mtype == 'strongestwifi': locators.append(StrongestCellLocator(cellresolvers))
from .locator.single import StrongestWifiLocator elif mtype == 'strongestwifi':
wlist = method_conf.get('wifiresolvers', []) from .locator.single import StrongestWifiLocator
wifiresolvers = [get_resolver(e) for e in wlist] wlist = method_conf.get('wifiresolvers', [])
locator = StrongestWifiLocator(wifiresolvers) wifiresolvers = [get_resolver(e) for e in wlist]
elif mtype == 'm8b': locators.append(StrongestWifiLocator(wifiresolvers))
from .locator.m8b import M8BLocator elif mtype == 'm8b':
locator = M8BLocator(os.path.expanduser(method_conf['datafile'])) from .locator.m8b import M8BLocator
elif mtype == 'web': locators.append(M8BLocator(os.path.expanduser(method_conf['datafile'])))
from .locator.web import WebLocator elif mtype == 'web':
locator = WebLocator(method_conf['locateurl'], method_conf['apikey']) from .locator.web import WebLocator
else: locators.append(WebLocator(method_conf['locateurl'], method_conf['apikey']))
raise ValueError(f'Unknown locator type in config: {mtype}') else:
log.info(f"Using '{mtype}' locator") raise ValueError(f'Unknown locator type in config: {mtype}')
log.info(f"Using '{mtype}' locator")
if conf['obsdb'] is None: if conf['obsdb'] is None:
# Use the dummy obsdb class # Use the dummy obsdb class