mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-13 15:57:14 +03:00
parent
25444410ab
commit
e9ef32598d
@ -249,11 +249,11 @@ class AppWindow:
|
||||
hotkeymgr.register(self.w, config.getint('hotkey_code'), config.getint('hotkey_mods'))
|
||||
|
||||
# Install log monitoring
|
||||
monitor.set_callback(self.system_change)
|
||||
monitor.set_callback('Dock', self.getandsend)
|
||||
monitor.set_callback('Jump', self.system_change)
|
||||
monitor.start(self.w)
|
||||
edproxy.set_callback(self.system_change)
|
||||
if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_FILE|config.OUT_LOG_EDSM)):
|
||||
monitor.start(self.w)
|
||||
edproxy.start(self.w)
|
||||
edproxy.start(self.w)
|
||||
|
||||
# First run
|
||||
if not config.get('username') or not config.get('password'):
|
||||
@ -497,7 +497,7 @@ class AppWindow:
|
||||
except:
|
||||
pass
|
||||
|
||||
def system_change(self, timestamp, system, coordinates):
|
||||
def system_change(self, event, timestamp, system, coordinates):
|
||||
|
||||
if self.system['text'] != system:
|
||||
self.system['text'] = system
|
||||
|
@ -28,6 +28,9 @@
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically make a log entry on entering a system" = "Automaticky vytvořit záznam při vstoupení do systému";
|
||||
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically update on docking" = "Automaticky aktualizovat při zadokování";
|
||||
|
||||
/* Cmdr stats. [stats.py] */
|
||||
"Balance" = "Zůstatek";
|
||||
|
||||
|
@ -28,6 +28,9 @@
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically make a log entry on entering a system" = "Automatisch Logbucheintrag bei Systemeintritt anlegen";
|
||||
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically update on docking" = "Automatisch beim Andocken aktualisieren";
|
||||
|
||||
/* Cmdr stats. [stats.py] */
|
||||
"Balance" = "Kontostand";
|
||||
|
||||
|
@ -28,6 +28,9 @@
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically make a log entry on entering a system" = "Automatically make a log entry on entering a system";
|
||||
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically update on docking" = "Automatically update on docking";
|
||||
|
||||
/* Cmdr stats. [stats.py] */
|
||||
"Balance" = "Balance";
|
||||
|
||||
|
@ -28,6 +28,9 @@
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically make a log entry on entering a system" = "Crear automáticamente una entrada en el registro al entrar en un sistema";
|
||||
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically update on docking" = "Actualizar automáticamente al atracar";
|
||||
|
||||
/* Cmdr stats. [stats.py] */
|
||||
"Balance" = "Saldo";
|
||||
|
||||
|
@ -28,6 +28,9 @@
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically make a log entry on entering a system" = "別の星系に移動したら自動的にフライトログを記録する";
|
||||
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically update on docking" = "ドッキングした際に自動でデータを更新する";
|
||||
|
||||
/* Cmdr stats. [stats.py] */
|
||||
"Balance" = "Balance";
|
||||
|
||||
|
@ -28,6 +28,9 @@
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically make a log entry on entering a system" = "Automatisch een log regel aanmaken bij het binnengaan van een stelsel";
|
||||
|
||||
/* Output setting. [prefs.py] */
|
||||
"Automatically update on docking" = "Automatisch bijwerken na landing";
|
||||
|
||||
/* Cmdr stats. [stats.py] */
|
||||
"Balance" = "Balans";
|
||||
|
||||
|
@ -10,7 +10,7 @@ This app downloads commodity market and other station data from the game [Elite:
|
||||
|
||||
Usage
|
||||
--------
|
||||
The user-interface is deliberately minimal - when you land at a station just switch to the app and press the “Update” button or press Enter to automatically download and transmit and/or save your choice of data.
|
||||
The user-interface is deliberately minimal - when you land at a station just switch to the app and press the “Update” button or press Enter to download and transmit and/or save your choice of data.
|
||||
|
||||
Click on the system name to go to its [Elite: Dangerous Star Map](http://www.edsm.net/) (“EDSM”) entry in your web broswer.
|
||||
|
||||
@ -44,7 +44,7 @@ Setup
|
||||
The first time that you run the app you are prompted for your username and password. This is the same username and password
|
||||
combination that you use to log into the Elite: Dangerous launcher, and is required so that the Frontier servers can send the app *your* data and the market data for the station that *you* are docked at.
|
||||
|
||||
You can also choose here what data to save (refer to the next section for details), whether to set up a hotkey so you don't have to switch to the app in order to “Update”, and whether to attach your Cmdr name or a [pseudo-anonymized](http://en.wikipedia.org/wiki/Pseudonymity) ID to the data.
|
||||
You can also choose here what data to save (refer to the next section for details), whether to “Update” automatically on docking and/or with a hotkey, and whether to attach your Cmdr name or a [pseudo-anonymized](http://en.wikipedia.org/wiki/Pseudonymity) ID to the data.
|
||||
|
||||
The first time that you hit “Update” you will be prompted to authenticate with a “verification code”, which you will shortly receive by email from Frontier.
|
||||
Note that each “verification code” is one-time only - if you enter the code incorrectly or quit the app before
|
||||
|
@ -80,6 +80,7 @@ class Config:
|
||||
OUT_SHIP_CORIOLIS = 128
|
||||
OUT_LOG_EDSM = 256
|
||||
OUT_LOG_AUTO = 512
|
||||
OUT_MANUAL = 1024
|
||||
|
||||
if platform=='darwin':
|
||||
|
||||
|
@ -14,6 +14,8 @@ from calendar import timegm
|
||||
if __debug__:
|
||||
from traceback import print_exc
|
||||
|
||||
from config import config
|
||||
|
||||
|
||||
class _EDProxy:
|
||||
|
||||
@ -73,7 +75,7 @@ class _EDProxy:
|
||||
def jump(self, event):
|
||||
# Called from Tkinter's main loop
|
||||
if self.callback and self.last_event:
|
||||
self.callback(*self.last_event)
|
||||
self.callback(event, *self.last_event)
|
||||
|
||||
def close():
|
||||
self.discover_sock.shutdown()
|
||||
@ -131,7 +133,7 @@ class _EDProxy:
|
||||
s.settimeout(None) # was self.SERVICE_TIMEOUT, but heartbeat doesn't appear to work so wait indefinitely
|
||||
while True:
|
||||
msg = json.loads(s.recv(self.MESSAGE_MAX))
|
||||
if msg['Type'] == self.MESSAGE_SYSTEM:
|
||||
if msg['Type'] == self.MESSAGE_SYSTEM and config.getint('output') & config.OUT_LOG_AUTO:
|
||||
if 'DateUtc' in msg:
|
||||
timestamp = timegm(datetime.strptime(msg['DateUtc'], '%Y-%m-%d %H:%M:%S').utctimetuple())
|
||||
else:
|
||||
|
59
monitor.py
59
monitor.py
@ -12,6 +12,9 @@ from datetime import datetime
|
||||
if __debug__:
|
||||
from traceback import print_exc
|
||||
|
||||
from config import config
|
||||
|
||||
|
||||
if platform=='darwin':
|
||||
from AppKit import NSWorkspace
|
||||
from Foundation import NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask
|
||||
@ -72,6 +75,8 @@ else:
|
||||
|
||||
class EDLogs(FileSystemEventHandler):
|
||||
|
||||
_POLL = 5 # New system gets posted to log file before hyperspace ends, so don't need to poll too often
|
||||
|
||||
def __init__(self):
|
||||
FileSystemEventHandler.__init__(self) # futureproofing - not need for current version of watchdog
|
||||
self.root = None
|
||||
@ -79,11 +84,12 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.logfile = None
|
||||
self.observer = None
|
||||
self.thread = None
|
||||
self.callback = None
|
||||
self.callbacks = { 'Jump': None, 'Dock': None }
|
||||
self.last_event = None # for communicating the Jump event
|
||||
|
||||
def set_callback(self, callback):
|
||||
self.callback = callback
|
||||
def set_callback(self, name, callback):
|
||||
if name in self.callbacks:
|
||||
self.callbacks[name] = callback
|
||||
|
||||
def start(self, root):
|
||||
self.root = root
|
||||
@ -94,6 +100,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
return True
|
||||
|
||||
self.root.bind_all('<<MonitorJump>>', self.jump) # user-generated
|
||||
self.root.bind_all('<<MonitorDock>>', self.dock) # user-generated
|
||||
|
||||
# Set up a watchog observer. This is low overhead so is left running irrespective of whether monitoring is desired.
|
||||
if not self.observer:
|
||||
@ -131,6 +138,10 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.logfile = event.src_path
|
||||
|
||||
def worker(self):
|
||||
# Tk isn't thread-safe in general.
|
||||
# event_generate() is the only safe way to poke the main thread from this thread:
|
||||
# https://mail.python.org/pipermail/tkinter-discuss/2013-November/003522.html
|
||||
|
||||
# e.g.:
|
||||
# "{18:00:41} System:"Shinrarta Dezhra" StarPos:(55.719,17.594,27.156)ly NormalFlight\r\n"
|
||||
# or with verboseLogging:
|
||||
@ -140,6 +151,16 @@ class EDLogs(FileSystemEventHandler):
|
||||
# Note that system name may contain parantheses, e.g. "Pipe (stem) Sector PI-T c3-5".
|
||||
regexp = re.compile(r'\{(.+)\} System:"(.+)" StarPos:\((.+),(.+),(.+)\)ly.* (\S+)') # (localtime, system, x, y, z, context)
|
||||
|
||||
# e.g.:
|
||||
# "{14:42:11} GetSafeUniversalAddress Station Count 1 moved 0 Docked Not Landed\r\n"
|
||||
# or:
|
||||
# "... Undocked Landed\r\n"
|
||||
# Don't use the simpler "Commander Put ..." message since its more likely to be delayed.
|
||||
dockre = re.compile(r'\{(.+)\} GetSafeUniversalAddress Station Count \d+ moved \d+ (\S+) ([^\r\n]+)') # (localtime, docked_status, landed_status)
|
||||
|
||||
docked = False # Whether we're docked
|
||||
updated = False # Whether we've sent an update since we docked
|
||||
|
||||
# Seek to the end of the latest log file
|
||||
logfile = self.logfile
|
||||
if logfile:
|
||||
@ -149,6 +170,13 @@ class EDLogs(FileSystemEventHandler):
|
||||
loghandle = None
|
||||
|
||||
while True:
|
||||
|
||||
if docked and not updated and not config.getint('output') & config.OUT_MANUAL:
|
||||
self.root.event_generate('<<MonitorDock>>', when="tail")
|
||||
updated = True
|
||||
if __debug__:
|
||||
print "%s :\t%s %s" % ('Updated', docked and " docked" or "!docked", updated and " updated" or "!updated")
|
||||
|
||||
# Check whether new log file started, e.g. client (re)started.
|
||||
newlogfile = self.logfile
|
||||
if logfile != newlogfile:
|
||||
@ -168,8 +196,18 @@ class EDLogs(FileSystemEventHandler):
|
||||
if system == 'ProvingGround':
|
||||
system = 'CQC'
|
||||
coordinates = (float(x), float(y), float(z))
|
||||
else:
|
||||
match = dockre.match(line)
|
||||
if match:
|
||||
if match.group(2) == 'Undocked':
|
||||
docked = updated = False
|
||||
elif match.group(2) == 'Docked':
|
||||
docked = True
|
||||
# do nothing now in case the API server is lagging, but update on next poll
|
||||
if __debug__:
|
||||
print "%s :\t%s %s" % (match.group(2), docked and " docked" or "!docked", updated and " updated" or "!updated")
|
||||
|
||||
if system:
|
||||
if system and not docked and config.getint('output') & config.OUT_LOG_AUTO:
|
||||
# Convert local time string to UTC date and time
|
||||
visited_struct = strptime(visited, '%H:%M:%S')
|
||||
now = localtime()
|
||||
@ -177,11 +215,10 @@ class EDLogs(FileSystemEventHandler):
|
||||
# Crossed midnight between timestamp and poll
|
||||
now = localtime(time()-12*60*60) # yesterday
|
||||
time_struct = datetime(now.tm_year, now.tm_mon, now.tm_mday, visited_struct.tm_hour, visited_struct.tm_min, visited_struct.tm_sec).timetuple() # still local time
|
||||
# Tk on Windows doesn't like to be called outside of an event handler, so generate an event
|
||||
self.last_event = (mktime(time_struct), system, coordinates)
|
||||
self.root.event_generate('<<MonitorJump>>', when="tail")
|
||||
|
||||
sleep(10) # New system gets posted to log file before hyperspace ends, so don't need to poll too often
|
||||
sleep(self._POLL)
|
||||
|
||||
# Check whether we're still supposed to be running
|
||||
if threading.current_thread() != self.thread:
|
||||
@ -189,8 +226,14 @@ class EDLogs(FileSystemEventHandler):
|
||||
|
||||
def jump(self, event):
|
||||
# Called from Tkinter's main loop
|
||||
if self.callback and self.last_event:
|
||||
self.callback(*self.last_event)
|
||||
if self.callbacks['Jump'] and self.last_event:
|
||||
self.callbacks['Jump'](event, *self.last_event)
|
||||
|
||||
def dock(self, event):
|
||||
# Called from Tkinter's main loop
|
||||
if self.callbacks['Dock']:
|
||||
self.callbacks['Dock'](event)
|
||||
|
||||
|
||||
if platform=='darwin':
|
||||
|
||||
|
14
prefs.py
14
prefs.py
@ -124,6 +124,9 @@ class PreferencesDialog(tk.Toplevel):
|
||||
nb.Checkbutton(outframe, text=_("Market data in Slopey's BPC format file"), variable=self.out_bpc, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
|
||||
self.out_td = tk.IntVar(value = (output & config.OUT_TD ) and 1)
|
||||
nb.Checkbutton(outframe, text=_('Market data in Trade Dangerous format file'), variable=self.out_td, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
|
||||
self.out_auto = tk.IntVar(value = 0 if output & config.OUT_MANUAL else 1) # inverted
|
||||
self.out_auto_button = nb.Checkbutton(outframe, text=_('Automatically update on docking'), variable=self.out_auto, command=self.outvarchanged) # Output setting
|
||||
self.out_auto_button.grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
|
||||
self.out_ship_eds= tk.IntVar(value = (output & config.OUT_SHIP_EDS) and 1)
|
||||
nb.Checkbutton(outframe, text=_('Ship loadout in E:D Shipyard format file'), variable=self.out_ship_eds, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, pady=(5,0), sticky=tk.W)
|
||||
self.out_ship_coriolis= tk.IntVar(value = (output & config.OUT_SHIP_CORIOLIS) and 1)
|
||||
@ -418,9 +421,10 @@ class PreferencesDialog(tk.Toplevel):
|
||||
(self.out_bpc.get() and config.OUT_BPC) +
|
||||
(self.out_td.get() and config.OUT_TD) +
|
||||
(self.out_csv.get() and config.OUT_CSV) +
|
||||
(config.OUT_MANUAL if not self.out_auto.get() else 0) +
|
||||
(self.out_ship_eds.get() and config.OUT_SHIP_EDS) +
|
||||
(self.out_log_file.get() and config.OUT_LOG_FILE) +
|
||||
(self.out_ship_coriolis.get() and config.OUT_SHIP_CORIOLIS) +
|
||||
(self.out_log_file.get() and config.OUT_LOG_FILE) +
|
||||
(self.out_log_edsm.get() and config.OUT_LOG_EDSM) +
|
||||
(self.out_log_auto.get() and config.OUT_LOG_AUTO))
|
||||
config.set('outdir', self.outdir.get().startswith('~') and join(config.home, self.outdir.get()[2:]) or self.outdir.get())
|
||||
@ -451,14 +455,8 @@ class PreferencesDialog(tk.Toplevel):
|
||||
self.callback()
|
||||
|
||||
def _destroy(self):
|
||||
# Re-enable hotkey and log monitoring before exit
|
||||
# Re-enable hotkey monitoring before exit
|
||||
hotkeymgr.register(self.parent, config.getint('hotkey_code'), config.getint('hotkey_mods'))
|
||||
if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_FILE|config.OUT_LOG_EDSM)):
|
||||
monitor.start(self.parent)
|
||||
edproxy.start(self.parent)
|
||||
else:
|
||||
monitor.stop()
|
||||
edproxy.stop()
|
||||
self.parent.wm_attributes('-topmost', config.getint('always_ontop') and 1 or 0)
|
||||
self.destroy()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user