From db543c290174caaeb3d0b740066f68d7b76e8090 Mon Sep 17 00:00:00 2001 From: Jonathan Harris <jonathan@marginal.org.uk> Date: Tue, 6 Sep 2016 01:54:13 +0100 Subject: [PATCH] Option to delay sending body data until docked --- EDMarketConnector.py | 7 ++++++ README.md | 1 + config.py | 1 + eddn.py | 57 ++++++++++++++++++++++++++++++++++++++++---- prefs.py | 6 +++++ 5 files changed, 68 insertions(+), 4 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 9e3c7a43..b647addf 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -309,6 +309,12 @@ class AppWindow: if __debug__: print_exc() self.status['text'] = unicode(e) + # Try to obtain exclusive lock on journal cache, even if we don't need it yet + try: + eddn.load() + except Exception as e: + self.status['text'] = unicode(e) + if not getattr(sys, 'frozen', False): self.updater.checkForUpdates() # Sparkle / WinSparkle does this automatically for packaged apps @@ -620,6 +626,7 @@ class AppWindow: if platform!='darwin' or self.w.winfo_rooty()>0: # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7 config.set('geometry', '+{1}+{2}'.format(*self.w.geometry().split('+'))) config.close() + eddn.close() self.updater.close() self.session.close() self.w.destroy() diff --git a/README.md b/README.md index 2da16df2..ca32ec90 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ Some options work by reading the Elite: Dangerous game's “journal” files. If * Sends station commodity market, outfitting and shipyard data to “[EDDN](http://eddn-gateway.elite-markets.net/)” from where you and others can use it via online trading tools such as [eddb](http://eddb.io/), [Elite Trade Net](http://etn.io/), [Inara](http://inara.cz), [ED-TD](http://ed-td.space/), [Thrudd's Trading Tools](http://www.elitetradingtool.co.uk/), [Roguey's](http://roguey.co.uk/elite-dangerous/), etc. * System and scan data * Sends general system information and the results of your detailed planet scans to “[EDDN](http://eddn-gateway.elite-markets.net/)” from where you and others can use it via online prospecting tools such as [eddb](http://eddb.io/), [Inara](http://inara.cz), etc. + * You can choose to delay sending this information to EDDN until you're next safely docked at a station. Otherwise the information is sent as soon as you enter a system or perform a scan. ### EDSM diff --git a/config.py b/config.py index b51ca4f6..b5d60652 100644 --- a/config.py +++ b/config.py @@ -95,6 +95,7 @@ class Config: # OUT_SYS_AUTO = 512 # Now always automatic OUT_MKT_MANUAL = 1024 OUT_SYS_EDDN = 2048 + OUT_SYS_DELAY = 4096 if platform=='darwin': diff --git a/eddn.py b/eddn.py index a986d1d4..21d29caa 100644 --- a/eddn.py +++ b/eddn.py @@ -4,12 +4,20 @@ from collections import OrderedDict import hashlib import json import numbers +from os import SEEK_SET, SEEK_CUR, SEEK_END +from os.path import exists, join from platform import system import re import requests from sys import platform import time +if platform != 'win32': + from fcntl import lockf, LOCK_EX, LOCK_NB + +if __debug__: + from traceback import print_exc + from config import applongname, appversion, config from companion import category_map @@ -25,6 +33,38 @@ class _EDDN: def __init__(self): self.session = requests.Session() + self.replayfile = None # For delayed messages + + def load(self): + # Try to obtain exclusive access to the journal cache + filename = join(config.app_dir, 'replay.jsonl') + try: + try: + # Try to open existing file + self.replayfile = open(filename, 'r+') + except: + if exists(filename): + raise # Couldn't open existing file + else: + self.replayfile = open(filename, 'w+') # Create file + if platform != 'win32': # open for writing is automatically exclusive on Windows + lockf(self.replayfile, LOCK_EX|LOCK_NB) + except: + if __debug__: print_exc() + if self.replayfile: + self.replayfile.close() + self.replayfile = None + raise Exception("Error: Is another copy of this app already running?") # Shouldn't happen - don't bother localizing + + def flush(self): + self.replayfile.seek(0, SEEK_SET) + for line in self.replayfile: + self.send(*json.loads(line, object_pairs_hook=OrderedDict)) + self.replayfile.truncate(0) + + def close(self): + if self.replayfile: + self.replayfile.close() def send(self, cmdr, msg): msg['header'] = { @@ -96,10 +136,19 @@ class _EDDN: }) def export_journal_entry(self, cmdr, is_beta, entry): - self.send(cmdr, { - '$schemaRef' : 'http://schemas.elite-markets.net/eddn/journal/1' + (is_beta and '/test' or ''), - 'message' : entry - }) + if config.getint('output') & config.OUT_SYS_DELAY and self.replayfile and entry['event'] != 'Docked': + self.replayfile.seek(0, SEEK_END) + self.replayfile.write('%s\n' % json.dumps([cmdr.encode('utf-8'), { + '$schemaRef' : 'http://schemas.elite-markets.net/eddn/journal/1' + (is_beta and '/test' or ''), + 'message' : entry + }])) + self.replayfile.flush() + else: + self.flush() + self.send(cmdr, { + '$schemaRef' : 'http://schemas.elite-markets.net/eddn/journal/1' + (is_beta and '/test' or ''), + 'message' : entry + }) # singleton eddn = _EDDN() diff --git a/prefs.py b/prefs.py index 5606e610..6beef4f8 100644 --- a/prefs.py +++ b/prefs.py @@ -11,6 +11,7 @@ from ttkHyperlinkLabel import HyperlinkLabel import myNotebook as nb from config import applongname, config +from eddn import eddn from hotkey import hotkeymgr from l10n import Translations from monitor import monitor @@ -157,6 +158,9 @@ class PreferencesDialog(tk.Toplevel): self.eddn_system = tk.IntVar(value = (output & config.OUT_SYS_EDDN) and 1) self.eddn_system_button = nb.Checkbutton(eddnframe, text=_('Send system and scan data to the Elite Dangerous Data Network'), variable=self.eddn_system, command=self.outvarchanged) # Output setting new in E:D 2.2 self.eddn_system_button.grid(padx=BUTTONX, pady=(5,0), sticky=tk.W) + self.eddn_delay= tk.IntVar(value = (output & config.OUT_SYS_DELAY) and 1) + self.eddn_delay_button = nb.Checkbutton(eddnframe, text=_('Delay sending until docked'), variable=self.eddn_delay, command=self.outvarchanged) # Output setting under 'Send system and scan data to the Elite Dangerous Data Network' new in E:D 2.2 + self.eddn_delay_button.grid(padx=BUTTONX, sticky=tk.W) notebook.add(eddnframe, text='EDDN') # Not translated @@ -318,6 +322,7 @@ class PreferencesDialog(tk.Toplevel): self.eddn_auto_button['state'] = self.eddn_station.get() and logvalid and tk.NORMAL or tk.DISABLED self.eddn_system_button['state']= logvalid and tk.NORMAL or tk.DISABLED + self.eddn_delay_button['state'] = logvalid and eddn.replayfile and self.eddn_system.get() and tk.NORMAL or tk.DISABLED self.edsm_log_button['state'] = logvalid and tk.NORMAL or tk.DISABLED edsm_state = logvalid and self.edsm_log.get() and tk.NORMAL or tk.DISABLED @@ -449,6 +454,7 @@ class PreferencesDialog(tk.Toplevel): (self.out_ship_coriolis.get() and config.OUT_SHIP_CORIOLIS) + (self.eddn_station.get() and config.OUT_MKT_EDDN) + (self.eddn_system.get() and config.OUT_SYS_EDDN) + + (self.eddn_delay.get() and config.OUT_SYS_DELAY) + (self.edsm_log.get() and config.OUT_SYS_EDSM)) config.set('outdir', self.outdir.get().startswith('~') and join(config.home, self.outdir.get()[2:]) or self.outdir.get())