109 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from owrx.config import PropertyManager
 | |
| from urllib import request
 | |
| import json
 | |
| from datetime import datetime, timedelta
 | |
| import logging
 | |
| import threading
 | |
| from owrx.map import Map, LatLngLocation
 | |
| from owrx.bands import Bandplan
 | |
| 
 | |
| logger = logging.getLogger(__name__)
 | |
| 
 | |
| 
 | |
| class DmrCache(object):
 | |
|     sharedInstance = None
 | |
| 
 | |
|     @staticmethod
 | |
|     def getSharedInstance():
 | |
|         if DmrCache.sharedInstance is None:
 | |
|             DmrCache.sharedInstance = DmrCache()
 | |
|         return DmrCache.sharedInstance
 | |
| 
 | |
|     def __init__(self):
 | |
|         self.cache = {}
 | |
|         self.cacheTimeout = timedelta(seconds=86400)
 | |
| 
 | |
|     def isValid(self, key):
 | |
|         if not key in self.cache:
 | |
|             return False
 | |
|         entry = self.cache[key]
 | |
|         return entry["timestamp"] + self.cacheTimeout > datetime.now()
 | |
| 
 | |
|     def put(self, key, value):
 | |
|         self.cache[key] = {"timestamp": datetime.now(), "data": value}
 | |
| 
 | |
|     def get(self, key):
 | |
|         if not self.isValid(key):
 | |
|             return None
 | |
|         return self.cache[key]["data"]
 | |
| 
 | |
| 
 | |
| class DmrMetaEnricher(object):
 | |
|     def __init__(self):
 | |
|         self.threads = {}
 | |
| 
 | |
|     def downloadRadioIdData(self, id):
 | |
|         cache = DmrCache.getSharedInstance()
 | |
|         try:
 | |
|             logger.debug("requesting DMR metadata for id=%s", id)
 | |
|             res = request.urlopen("https://www.radioid.net/api/dmr/user/?id={0}".format(id), timeout=30).read()
 | |
|             data = json.loads(res.decode("utf-8"))
 | |
|             cache.put(id, data)
 | |
|         except json.JSONDecodeError:
 | |
|             cache.put(id, None)
 | |
|         del self.threads[id]
 | |
| 
 | |
|     def enrich(self, meta):
 | |
|         if not PropertyManager.getSharedInstance()["digital_voice_dmr_id_lookup"]:
 | |
|             return None
 | |
|         if not "source" in meta:
 | |
|             return None
 | |
|         id = meta["source"]
 | |
|         cache = DmrCache.getSharedInstance()
 | |
|         if not cache.isValid(id):
 | |
|             if not id in self.threads:
 | |
|                 self.threads[id] = threading.Thread(target=self.downloadRadioIdData, args=[id], daemon=True)
 | |
|                 self.threads[id].start()
 | |
|             return None
 | |
|         data = cache.get(id)
 | |
|         if "count" in data and data["count"] > 0 and "results" in data:
 | |
|             return data["results"][0]
 | |
|         return None
 | |
| 
 | |
| 
 | |
| class YsfMetaEnricher(object):
 | |
|     def __init__(self, parser):
 | |
|         self.parser = parser
 | |
| 
 | |
|     def enrich(self, meta):
 | |
|         if "source" in meta and "lat" in meta and "lon" in meta:
 | |
|             # TODO parsing the float values should probably happen earlier
 | |
|             loc = LatLngLocation(float(meta["lat"]), float(meta["lon"]))
 | |
|             Map.getSharedInstance().updateLocation(meta["source"], loc, "YSF", self.parser.getBand())
 | |
|         return None
 | |
| 
 | |
| 
 | |
| class MetaParser(object):
 | |
|     def __init__(self, handler):
 | |
|         self.handler = handler
 | |
|         self.enrichers = {"DMR": DmrMetaEnricher(), "YSF": YsfMetaEnricher(self)}
 | |
|         self.band = None
 | |
| 
 | |
|     def setDialFrequency(self, freq):
 | |
|         self.band = Bandplan.getSharedInstance().findBand(freq)
 | |
| 
 | |
|     def getBand(self):
 | |
|         return self.band
 | |
| 
 | |
|     def parse(self, meta):
 | |
|         fields = meta.split(";")
 | |
|         meta = {v[0]: "".join(v[1:]) for v in map(lambda x: x.split(":"), fields) if v[0] != ""}
 | |
| 
 | |
|         if "protocol" in meta:
 | |
|             protocol = meta["protocol"]
 | |
|             if protocol in self.enrichers:
 | |
|                 additional_data = self.enrichers[protocol].enrich(meta)
 | |
|                 if additional_data is not None:
 | |
|                     meta["additional"] = additional_data
 | |
|         self.handler.write_metadata(meta)
 | 
