diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 81242899..a2b605d9 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -23,6 +23,7 @@ import companion import bpc import td import eddn +import edsm import loadout import coriolis import flightlog @@ -34,6 +35,7 @@ l10n.Translations().install() EDDB = eddb.EDDB() SHIPYARD_RETRY = 5 # retry pause for shipyard data [s] +EDSM_POLL = 0.1 class HyperlinkLabel(ttk.Label): @@ -75,6 +77,7 @@ class AppWindow: self.holdofftime = config.getint('querytime') + companion.holdoff self.session = companion.Session() + self.edsm = edsm.EDSM() self.w = master self.w.title(applongname) @@ -110,7 +113,7 @@ class AppWindow: ttk.Label(frame, text=_('Station:')).grid(row=2, column=0, sticky=tk.W) # Main window self.cmdr = ttk.Label(frame, width=-20) - self.system = HyperlinkLabel(frame, width=-20, urlfn = self.system_url) + self.system = HyperlinkLabel(frame, compound=tk.RIGHT, urlfn = self.system_url) self.station = HyperlinkLabel(frame, width=-20, urlfn = self.station_url) self.button = ttk.Button(frame, text=_('Update'), command=self.getandsend, default=tk.ACTIVE, state=tk.DISABLED) # Update button in main window self.status = ttk.Label(frame, width=-25) @@ -238,6 +241,7 @@ class AppWindow: self.cmdr['text'] = data.get('commander') and data.get('commander').get('name') or '' self.system['text'] = data.get('lastSystem') and data.get('lastSystem').get('name') or '' + self.system['image'] = None self.station['text'] = data.get('commander') and data.get('commander').get('docked') and data.get('lastStarport') and data.get('lastStarport').get('name') or (EDDB.system(self.system['text'] and '-' or '')) config.set('querytime', querytime) @@ -253,9 +257,14 @@ class AppWindow: elif (config.getint('output') & config.OUT_EDDN) and data['commander'].get('docked') and not data['lastStarport'].get('ships') and not retrying: # API is flakey about shipyard info - retry if missing (<1s is usually sufficient - 5s for margin). - self.w.after(SHIPYARD_RETRY * 1000, lambda:self.getandsend(retrying=True)) + self.w.after(int(SHIPYARD_RETRY * 1000), lambda:self.getandsend(retrying=True)) # Stuff we can do while waiting for retry + + self.edsm.start_lookup(self.system['text']) + self.system['image'] = self.edsm.result['img'] + self.w.after(int(EDSM_POLL * 1000), self.edsmpoll) + if config.getint('output') & config.OUT_LOG: flightlog.export(data) if config.getint('output') & config.OUT_SHIP_EDS: @@ -273,6 +282,10 @@ class AppWindow: h.write(json.dumps(data, indent=2, sort_keys=True)) if not retrying: + self.edsm.start_lookup(self.system['text']) + self.system['image'] = self.edsm.result['img'] + self.w.after(int(EDSM_POLL * 1000), self.edsmpoll) + if config.getint('output') & config.OUT_LOG: flightlog.export(data) if config.getint('output') & config.OUT_SHIP_EDS: @@ -332,8 +345,15 @@ class AppWindow: self.cooldown() + def edsmpoll(self): + result = self.edsm.result + if result['done']: + self.system['image'] = result['img'] + else: + self.w.after(int(EDSM_POLL * 1000), self.edsmpoll) + def system_url(self, text): - return text and 'http://www.edsm.net/needed-distances?systemName=%s' % urllib.quote(text) + return text and self.edsm.result['url'] def station_url(self, text): if text: diff --git a/README.md b/README.md index e2990e21..00e88c24 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Click on the system name to go to its [Elite: Dangerous Star Map](http://www.eds Click on the station name to go to its [Elite: Dangerous Database](http://eddb.io/) (“eddb”) entry in your web broswer. -  +  Installation diff --git a/edsm.py b/edsm.py new file mode 100644 index 00000000..f69b17e8 --- /dev/null +++ b/edsm.py @@ -0,0 +1,62 @@ +import requests +import threading +from sys import platform +import urllib + +import Tkinter as tk + +if __debug__: + from traceback import print_exc + +class EDSM: + + _TIMEOUT = 10 + + def __init__(self): + self.result = { 'img': None, 'url': None, 'done': True } + EDSM._IMG_WAIT_MAC = tk.PhotoImage(data = 'R0lGODlhDgAQAKEBAAAAAP///////////yH5BAEKAAIALAAAAAAOABAAAAIrlAWpx6jZzoPRvQqC3qBlzjGfNnbSFpQmQibcOqKpKIe0vIpTZS3Y/rscCgA7') # wristwatch + EDSM._IMG_WAIT_WIN = tk.PhotoImage(data = 'R0lGODlhDgAQAKEBAAAAAP///////////yH5BAEKAAIALAAAAAAOABAAAAIuFI4JwurcgpxhQUOnhUD2Xl1R5YmcZl5fqoYsVqYgKs527ZHu+ZGb4UhwgghGAQA7') # hourglass + EDSM._IMG_KNOWN = tk.PhotoImage(data = 'R0lGODlhDgAOAMIEAFWjVVWkVWS/ZGfFZwAAAAAAAAAAAAAAACH5BAEKAAQALAAAAAAOAA4AAAMsSLrcHEIEp8C4GDSLu15dOCyB2E2EYGKCoq5DS5QwSsDjwomfzlOziA0ITAAAOw==') # green circle + EDSM._IMG_UNKNOWN = tk.PhotoImage(data = 'R0lGODlhDgAOAMIEAM16BM57BfCPBfiUBgAAAAAAAAAAAAAAACH5BAEKAAQALAAAAAAOAA4AAAMsSLrcHEIEp8C4GDSLu15dOCyB2E2EYGKCoq5DS5QwSsDjwomfzlOziA0ITAAAOw==') # orange circle + EDSM._IMG_NOTFOUND = tk.PhotoImage(data = 'R0lGODlhDgAOAKECAGVLJ+ddWO5fW+5fWyH5BAEKAAMALAAAAAAOAA4AAAImnI+JEAFqgJj0LYqFNTkf2VVGEFLBWE7nAJZbKlzhFnX00twQVAAAOw==') # red circle + EDSM._IMG_ERROR = tk.PhotoImage(data = 'R0lGODlhDgAOAIABAAAAAP///yH5BAEKAAEALAAAAAAOAA4AAAIcjAOpx+rAUGrzVHujWRrDvmWdOH5geKZqSmpkAQA7') # BBC Mode 7 '?' + + def start_lookup(self, system_name): + self.cancel_lookup() + self.result = { 'img': None, 'url': 'http://www.edsm.net/needed-distances?systemName=%s' % urllib.quote(system_name), 'done': False } # default URL + self.thread = threading.Thread(target = self.worker, name = 'EDSM worker', args = (system_name, self.result)) + self.thread.daemon = True + self.thread.start() + + def cancel_lookup(self): + self.thread = None # orphan any existing thread + self.result = { 'img': None, 'url': None, 'done': True } # orphan existing thread's results + + def worker(self, system_name, result): + try: + r = requests.get('http://www.edsm.net/api-v1/system?sysname=%s&coords=1' % urllib.quote(system_name), timeout=EDSM._TIMEOUT) + r.raise_for_status() + data = r.json() + + if data == -1: + # System not present - create it + result['img'] = EDSM._IMG_NOTFOUND + result['done'] = True # give feedback immediately + requests.get('http://www.edsm.net/api-v1/url?sysname=%s' % urllib.quote(system_name), timeout=EDSM._TIMEOUT) # creates system + elif data.get('coords'): + # Prefer to send user to "Show distances" page for systems with known coordinates + result['img'] = EDSM._IMG_KNOWN + result['done'] = True # give feedback immediately + try: + r = requests.get('http://www.edsm.net/api-v1/url?sysname=%s' % urllib.quote(system_name), timeout=EDSM._TIMEOUT) + r.raise_for_status() + data = r.json() + result['url'] = data['url']['show-system'].replace('\\','') + except: + if __debug__: print_exc() + else: + result['img'] = EDSM._IMG_UNKNOWN + except: + if __debug__: print_exc() + result['img'] = EDSM._IMG_ERROR + result['done'] = True diff --git a/img/mac.png b/img/mac.png index 73f3f429..69f8622b 100644 Binary files a/img/mac.png and b/img/mac.png differ