1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-15 00:30:33 +03:00

Remove support for edproxy and for flight log file

Flight log to file is redundant and little-used. Suitable replacements
are EDSM integration and/or other apps such as Captain's Log.

edproxy since v2.1 supports sending flight log directly to EDSM, and
integration has no other purpose.
This commit is contained in:
Jonathan Harris 2016-07-25 19:14:12 +01:00
parent 7821f2a454
commit a30d85990b
20 changed files with 49 additions and 448 deletions

View File

@ -41,12 +41,10 @@ import eddn
import edsm import edsm
import loadout import loadout
import coriolis import coriolis
import flightlog
import eddb import eddb
import stats import stats
import prefs import prefs
import plug import plug
from edproxy import edproxy
from hotkey import hotkeymgr from hotkey import hotkeymgr
from monitor import monitor from monitor import monitor
from theme import theme from theme import theme
@ -252,8 +250,6 @@ class AppWindow:
monitor.set_callback('Dock', self.getandsend) monitor.set_callback('Dock', self.getandsend)
monitor.set_callback('Jump', self.system_change) monitor.set_callback('Jump', self.system_change)
monitor.start(self.w) monitor.start(self.w)
edproxy.set_callback(self.system_change)
edproxy.start(self.w)
# First run # First run
if not config.get('username') or not config.get('password'): if not config.get('username') or not config.get('password'):
@ -309,15 +305,6 @@ class AppWindow:
if __debug__: print_exc() if __debug__: print_exc()
self.status['text'] = unicode(e) self.status['text'] = unicode(e)
# Try to obtain exclusive lock on flight log ASAP
if config.getint('output') & config.OUT_LOG_FILE:
try:
flightlog.openlog()
except Exception as e:
if __debug__: print_exc()
if not self.status['text']:
self.status['text'] = unicode(e)
if not getattr(sys, 'frozen', False): if not getattr(sys, 'frozen', False):
self.updater.checkForUpdates() # Sparkle / WinSparkle does this automatically for packaged apps self.updater.checkForUpdates() # Sparkle / WinSparkle does this automatically for packaged apps
@ -390,9 +377,7 @@ class AppWindow:
loadout.export(data) loadout.export(data)
if config.getint('output') & config.OUT_SHIP_CORIOLIS: if config.getint('output') & config.OUT_SHIP_CORIOLIS:
coriolis.export(data) coriolis.export(data)
if config.getint('output') & config.OUT_LOG_FILE: if config.getint('output') & config.OUT_SYS_EDSM:
flightlog.export(data)
if config.getint('output') & config.OUT_LOG_EDSM:
# Catch any EDSM errors here so that they don't prevent station update # Catch any EDSM errors here so that they don't prevent station update
try: try:
self.status['text'] = _('Sending data to EDSM...') self.status['text'] = _('Sending data to EDSM...')
@ -406,7 +391,7 @@ class AppWindow:
self.edsm.link(self.system['text']) self.edsm.link(self.system['text'])
self.edsmpoll() self.edsmpoll()
if not (config.getint('output') & (config.OUT_CSV|config.OUT_TD|config.OUT_BPC|config.OUT_EDDN)): if not (config.getint('output') & (config.OUT_MKT_CSV|config.OUT_MKT_TD|config.OUT_MKT_BPC|config.OUT_MKT_EDDN)):
# no station data requested - we're done # no station data requested - we're done
pass pass
@ -421,25 +406,25 @@ class AppWindow:
# No EDDN output? # No EDDN output?
if (config.getint('output') & config.OUT_EDDN) and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')): # Ignore possibly missing shipyard info if (config.getint('output') & config.OUT_MKT_EDDN) and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')): # Ignore possibly missing shipyard info
if not self.status['text']: if not self.status['text']:
self.status['text'] = _("Station doesn't have anything!") self.status['text'] = _("Station doesn't have anything!")
# No market output? # No market output?
elif not (config.getint('output') & config.OUT_EDDN) and not data['lastStarport'].get('commodities'): elif not (config.getint('output') & config.OUT_MKT_EDDN) and not data['lastStarport'].get('commodities'):
if not self.status['text']: if not self.status['text']:
self.status['text'] = _("Station doesn't have a market!") self.status['text'] = _("Station doesn't have a market!")
else: else:
if data['lastStarport'].get('commodities'): if data['lastStarport'].get('commodities'):
if config.getint('output') & config.OUT_CSV: if config.getint('output') & config.OUT_MKT_CSV:
commodity.export(data, COMMODITY_CSV) commodity.export(data, COMMODITY_CSV)
if config.getint('output') & config.OUT_TD: if config.getint('output') & config.OUT_MKT_TD:
td.export(data) td.export(data)
if config.getint('output') & config.OUT_BPC: if config.getint('output') & config.OUT_MKT_BPC:
commodity.export(data, COMMODITY_BPC) commodity.export(data, COMMODITY_BPC)
if config.getint('output') & config.OUT_EDDN: if config.getint('output') & config.OUT_MKT_EDDN:
old_status = self.status['text'] old_status = self.status['text']
if not old_status: if not old_status:
self.status['text'] = _('Sending data to EDDN...') self.status['text'] = _('Sending data to EDDN...')
@ -507,9 +492,7 @@ class AppWindow:
plug.notify_system_changed(timestamp, system, coordinates) plug.notify_system_changed(timestamp, system, coordinates)
if config.getint('output') & config.OUT_LOG_FILE: if config.getint('output') & (config.OUT_SYS_EDSM | config.OUT_SYS_AUTO) == (config.OUT_SYS_EDSM | OUT_SYS_AUTO):
flightlog.writelog(timestamp, system)
if config.getint('output') & config.OUT_LOG_EDSM:
try: try:
self.status['text'] = _('Sending data to EDSM...') self.status['text'] = _('Sending data to EDSM...')
self.w.update_idletasks() self.w.update_idletasks()
@ -590,7 +573,6 @@ class AppWindow:
def onexit(self, event=None): def onexit(self, event=None):
hotkeymgr.unregister() hotkeymgr.unregister()
flightlog.close()
if platform!='darwin' or self.w.winfo_rooty()>0: # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7 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.set('geometry', '+{1}+{2}'.format(*self.w.geometry().split('+')))
config.close() config.close()

View File

@ -73,9 +73,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Připojeno k {EDPROXY} na {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Čekej {SS}s"; "cooldown {SS}s" = "Čekej {SS}s";
@ -172,9 +169,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Cesta k souboru"; "File location" = "Cesta k souboru";
/* [prefs.py] */
"Flight log in CSV format file" = "Letový záznam ve formátu CSV";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -73,9 +73,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Kompetent"; "Competent" = "Kompetent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Verbunden mit {EDPROXY} bei {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Wartezeit {SS}s"; "cooldown {SS}s" = "Wartezeit {SS}s";
@ -172,9 +169,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Speicherort"; "File location" = "Speicherort";
/* [prefs.py] */
"Flight log in CSV format file" = "Fluglogbuch im CSV-Format";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -73,9 +73,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "cooldown {SS}s"; "cooldown {SS}s" = "cooldown {SS}s";
@ -172,9 +169,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "File location"; "File location" = "File location";
/* [prefs.py] */
"Flight log in CSV format file" = "Flight log in CSV format file";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -73,9 +73,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competente"; "Competent" = "Competente";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Conectado a {EDPROXY} en {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Espere {SS}s"; "cooldown {SS}s" = "Espere {SS}s";
@ -172,9 +169,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Localización de archivos"; "File location" = "Localización de archivos";
/* [prefs.py] */
"Flight log in CSV format file" = "Registro de vuelo en formato CSV";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiador"; "Gladiator" = "Gladiador";

View File

@ -70,9 +70,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Compétent"; "Competent" = "Compétent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connecté à {EDPROXY} sur {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Temps de recharge {SS}s"; "cooldown {SS}s" = "Temps de recharge {SS}s";
@ -169,9 +166,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Emplacement des fichiers"; "File location" = "Emplacement des fichiers";
/* [prefs.py] */
"Flight log in CSV format file" = "Journal de vol au format CSV";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -70,9 +70,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connesso a {EDPROXY} all'indirizzo {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "disponibile tra {SS} secondi"; "cooldown {SS}s" = "disponibile tra {SS} secondi";
@ -169,9 +166,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Percorso del file"; "File location" = "Percorso del file";
/* [prefs.py] */
"Flight log in CSV format file" = "Flight log in formato CSV";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -73,9 +73,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "{ADDR} の {EDPROXY} に接続しました";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "次回更新まであと {SS}秒"; "cooldown {SS}s" = "次回更新まであと {SS}秒";
@ -172,9 +169,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "ファイルの出力先"; "File location" = "ファイルの出力先";
/* [prefs.py] */
"Flight log in CSV format file" = "フライトログをCSV形式で記録する";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -70,9 +70,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Atskaite {SS}"; "cooldown {SS}s" = "Atskaite {SS}";
@ -169,9 +166,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Faila atrašanās vieta"; "File location" = "Faila atrašanās vieta";
/* [prefs.py] */
"Flight log in CSV format file" = "Lidojuma ieraksts SCV formāta failā";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiators"; "Gladiator" = "Gladiators";

View File

@ -73,9 +73,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Verbonden met {EDPROXY} via {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "wachtperiode {SS}s"; "cooldown {SS}s" = "wachtperiode {SS}s";
@ -172,9 +169,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Bestand locatie"; "File location" = "Bestand locatie";
/* [prefs.py] */
"Flight log in CSV format file" = "Vlucht log in CSV bestand formaat";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -70,9 +70,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Połąćzono do {EDPROXY} na {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Oczekiwanie {SS} sek."; "cooldown {SS}s" = "Oczekiwanie {SS} sek.";
@ -169,9 +166,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Położenie pliku"; "File location" = "Położenie pliku";
/* [prefs.py] */
"Flight log in CSV format file" = "Dziennik lotu w formacie CSV";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -70,9 +70,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Специалист"; "Competent" = "Специалист";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "пауза {SS} сек"; "cooldown {SS}s" = "пауза {SS} сек";
@ -169,9 +166,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Сохранять файлы"; "File location" = "Сохранять файлы";
/* [prefs.py] */
"Flight log in CSV format file" = "Журнал полета в формате CSV";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Гладиатор"; "Gladiator" = "Гладиатор";

View File

@ -70,9 +70,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Posodobitev v {SS}s"; "cooldown {SS}s" = "Posodobitev v {SS}s";
@ -169,9 +166,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Lokacija datoteke"; "File location" = "Lokacija datoteke";
/* [prefs.py] */
"Flight log in CSV format file" = "Dnevnik leta v CSV formatu";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Gladiator"; "Gladiator" = "Gladiator";

View File

@ -70,9 +70,6 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Компетентний"; "Competent" = "Компетентний";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Підключено до {EDPROXY}, адреса {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "очикування {SS} сек"; "cooldown {SS}s" = "очикування {SS} сек";
@ -169,9 +166,6 @@
/* Section heading in settings. [prefs.py] */ /* Section heading in settings. [prefs.py] */
"File location" = "Росташування файлу"; "File location" = "Росташування файлу";
/* [prefs.py] */
"Flight log in CSV format file" = "Журнал (log) в CSV форматі";
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Gladiator" = "Гладіатор"; "Gladiator" = "Гладіатор";

View File

@ -70,17 +70,17 @@ elif platform=='linux2':
class Config: class Config:
OUT_EDDN = 1 OUT_MKT_EDDN = 1
OUT_BPC = 2 OUT_MKT_BPC = 2
OUT_TD = 4 OUT_MKT_TD = 4
OUT_CSV = 8 OUT_MKT_CSV = 8
OUT_SHIP_EDS = 16 OUT_SHIP_EDS = 16
OUT_LOG_FILE = 32 # OUT_SYS_FILE = 32 # No longer supported
#OUT_STAT = 64 # No longer available # OUT_STAT = 64 # No longer available
OUT_SHIP_CORIOLIS = 128 OUT_SHIP_CORIOLIS = 128
OUT_LOG_EDSM = 256 OUT_SYS_EDSM = 256
OUT_LOG_AUTO = 512 OUT_SYS_AUTO = 512
OUT_MANUAL = 1024 OUT_MKT_MANUAL = 1024
if platform=='darwin': if platform=='darwin':

View File

@ -1,155 +0,0 @@
#
# Elite: Dangerous Netlog Proxy Server client - https://bitbucket.org/westokyo/edproxy/
#
import json
import socket
import struct
import sys
import threading
from time import time, strptime, mktime
from datetime import datetime
from calendar import timegm
if __debug__:
from traceback import print_exc
from config import config
class _EDProxy:
DISCOVERY_ADDR = '239.45.99.98'
DISCOVERY_PORT = 45551
DISCOVERY_QUERY = 'Query'
DISCOVERY_ANNOUNCE = 'Announce'
SERVICE_NAME = 'edproxy'
SERVICE_HEARTBEAT = 60 # [s]
SERVICE_TIMEOUT = 90 # [s]
MESSAGE_MAX = 1024 # https://bitbucket.org/westokyo/edproxy/src/master/ednet.py?fileviewer=file-view-default#ednet.py-166
MESSAGE_SYSTEM = 'System'
def __init__(self):
self.root = None
self.lock = threading.Lock()
self.addr = None
self.port = None
thread = threading.Thread(target = self._listener)
thread.daemon = True
thread.start()
self.callback = None
self.last_event = None # for communicating the Jump event
# start
self.discover_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.discover()
def set_callback(self, callback):
self.callback = callback
def start(self, root):
self.root = root
self.root.bind_all('<<ProxyJump>>', self.jump) # user-generated
def stop(self):
# Still listening, but stop callbacks
if self.root:
self.root.unbind_all('<<ProxyJump>>')
def status(self):
self.lock.acquire()
if self.addr and self.port:
status = '%s:%d' % (self.addr, self.port)
self.lock.release()
return status
else:
self.lock.release()
self.discover() # Kick off discovery
return None
def jump(self, event):
# Called from Tkinter's main loop
if self.callback and self.last_event:
self.callback(event, *self.last_event)
def close():
self.discover_sock.shutdown()
self.discover_sock = None
# Send a query. _listener should get the response.
def discover(self):
self.discover_sock.sendto(json.dumps({
'type': self.DISCOVERY_QUERY,
'name': self.SERVICE_NAME,
}), (self.DISCOVERY_ADDR, self.DISCOVERY_PORT))
def _listener(self):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
if sys.platform == 'win32':
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
else:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind(('', self.DISCOVERY_PORT))
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, struct.pack('4sL', socket.inet_aton(self.DISCOVERY_ADDR), socket.INADDR_ANY))
while True:
try:
(data, addr) = s.recvfrom(self.MESSAGE_MAX)
msg = json.loads(data)
if msg['name'] == self.SERVICE_NAME and msg['type'] == self.DISCOVERY_ANNOUNCE:
# ignore if already connected to a proxy
if not self.addr or not self.port:
thread = threading.Thread(target = self._worker, args = (msg['ipv4'], int(msg['port'])))
thread.daemon = True
thread.start()
except:
if __debug__: print_exc()
def _worker(self, addr, port):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((addr, port))
s.settimeout(0)
s.sendall(json.dumps({
'Type' : 'Init',
'DateUtc' : datetime.utcnow().isoformat(),
'StartTime' : 'now',
'Register' : [ 'System' ],
}))
except:
if __debug__: print_exc()
return
self.lock.acquire()
self.addr = addr
self.port = port
self.lock.release()
try:
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 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:
timestamp = mktime(strptime(msg['Date'], '%Y-%m-%d %H:%M:%S')) # from local time
self.last_event = (timestamp, msg['System'], None)
self.root.event_generate('<<ProxyJump>>', when="tail")
except:
if __debug__: print_exc()
self.lock.acquire()
self.addr = self.port = None
self.lock.release()
# Kick off discovery for another proxy
self.discover()
# singleton
edproxy = _EDProxy()

19
edsm.py
View File

@ -7,7 +7,6 @@ import urllib
import Tkinter as tk import Tkinter as tk
from config import applongname, appversion, config from config import applongname, appversion, config
import flightlog
if __debug__: if __debug__:
from traceback import print_exc from traceback import print_exc
@ -139,21 +138,3 @@ def writelog(timestamp, system, edsmlookupfn, coordinates=None):
# Message numbers: 1xx = OK, 2xx = fatal error, 3xx = error (but not generated in practice), 4xx = ignorable errors # Message numbers: 1xx = OK, 2xx = fatal error, 3xx = error (but not generated in practice), 4xx = ignorable errors
if msgnum // 100 not in (1,4): if msgnum // 100 not in (1,4):
raise Exception(_('Error: EDSM {MSG}').format(MSG=msg)) raise Exception(_('Error: EDSM {MSG}').format(MSG=msg))
if not config.getint('edsm_historical'):
config.set('edsm_historical', 1)
thread = threading.Thread(target = export_historical, name = 'EDSM export')
thread.daemon = True
thread.start()
# Make best effort to export existing flight log file. Be silent on error.
def export_historical():
try:
for (timestamp, system_name) in flightlog.logs():
r = requests.get('https://www.edsm.net/api-logs-v1/set-log?commanderName=%s&apiKey=%s&systemName=%s&dateVisited=%s&fromSoftware=%s&fromSoftwareVersion=%s' % (urllib.quote(config.get('edsm_cmdrname').encode('utf-8')), urllib.quote(config.get('edsm_apikey')), urllib.quote(system_name), urllib.quote(time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(timestamp))), urllib.quote(applongname), urllib.quote(appversion)), timeout=EDSM._TIMEOUT)
r.raise_for_status()
if r.json()['msgnum'] // 100 == 2:
raise Exception()
except:
if __debug__: print_exc()

View File

@ -1,105 +0,0 @@
# Export poor man's flight log
from collections import defaultdict
import errno
import os
from os.path import join
from sys import platform
import time
from config import config
from companion import ship_map
logfile = None
last_timestamp = last_system = last_ship = None
last_commodities = {}
def openlog():
global logfile
if logfile: return
try:
logfile = open(join(config.get('outdir'), 'Flight Log.csv'), 'a+b')
if platform != 'win32': # open for writing is automatically exclusive on Windows
from fcntl import lockf, LOCK_SH, LOCK_NB
lockf(logfile, LOCK_SH|LOCK_NB)
logfile.seek(0, os.SEEK_END)
if not logfile.tell():
logfile.write('Date,Time,System,Station,Ship,Cargo\r\n')
except EnvironmentError as e:
logfile = None
if e.errno in [errno.EACCES, errno.EAGAIN]:
raise Exception('Can\'t write "Flight Log.csv". Are you editing it in another app?')
else:
raise
except:
logfile = None
raise
def export(data):
querytime = config.getint('querytime') or int(time.time())
commodities = defaultdict(int)
for item in data['ship'].get('cargo',{}).get('items',[]):
if item['commodity'] != 'drones':
commodities[item['commodity']] += item['qty']
writelog(querytime,
data['lastSystem']['name'],
data['commander']['docked'] and data['lastStarport']['name'],
ship_map.get(data['ship']['name'].lower(), data['ship']['name']),
commodities)
def writelog(timestamp, system, station=None, ship=None, commodities={}):
global last_timestamp, last_system, last_ship, last_commodities
if last_system and last_system != system:
_writelog(last_timestamp, last_system, None, last_ship, last_commodities)
if not station:
# If not docked, hold off writing log entry until docked or until system changes
last_timestamp, last_system, last_ship, last_commodities = timestamp, system, ship, commodities
else:
last_system = None
_writelog(timestamp, system, station, ship, commodities)
def _writelog(timestamp, system, station=None, ship=None, commodities={}):
openlog()
logfile.write('%s,%s,%s,%s,%s,%s\r\n' % (
time.strftime('%Y-%m-%d', time.localtime(timestamp)),
time.strftime('%H:%M:%S', time.localtime(timestamp)),
system,
station or '',
ship or '',
','.join([('%d %s' % (commodities[k], k)) for k in sorted(commodities)])))
logfile.flush()
def close():
global last_timestamp, last_system
if last_system:
_writelog(last_timestamp, last_system, None, last_ship, last_commodities)
last_system = None
# return log as list of (timestamp, system_name)
def logs():
entries = []
with open(join(config.get('outdir'), 'Flight Log.csv'), 'rU') as f:
f.readline() # Assume header
for line in f:
if not line.strip(): continue
cols = line.split(',')
assert len(cols) >= 3, cols
entries.append((time.mktime(time.strptime('%sT%s' % (cols[0], cols[1]), '%Y-%m-%dT%H:%M:%S')), cols[2])) # Convert from local time to UTC
return entries

View File

@ -154,7 +154,7 @@ class EDLogs(FileSystemEventHandler):
while True: while True:
if docked and not updated and not config.getint('output') & config.OUT_MANUAL: if docked and not updated and not config.getint('output') & config.OUT_MKT_MANUAL:
self.root.event_generate('<<MonitorDock>>', when="tail") self.root.event_generate('<<MonitorDock>>', when="tail")
updated = True updated = True
if __debug__: if __debug__:
@ -190,7 +190,7 @@ class EDLogs(FileSystemEventHandler):
if __debug__: if __debug__:
print "%s :\t%s %s" % (match.group(2), docked and " docked" or "!docked", updated and " updated" or "!updated") print "%s :\t%s %s" % (match.group(2), docked and " docked" or "!docked", updated and " updated" or "!updated")
if system and not docked and config.getint('output') & config.OUT_LOG_AUTO: if system and not docked and config.getint('output'):
# Convert local time string to UTC date and time # Convert local time string to UTC date and time
visited_struct = strptime(visited, '%H:%M:%S') visited_struct = strptime(visited, '%H:%M:%S')
now = localtime() now = localtime()

View File

@ -11,7 +11,6 @@ from ttkHyperlinkLabel import HyperlinkLabel
import myNotebook as nb import myNotebook as nb
from config import applongname, config from config import applongname, config
from edproxy import edproxy
from hotkey import hotkeymgr from hotkey import hotkeymgr
from l10n import Translations from l10n import Translations
from monitor import monitor from monitor import monitor
@ -114,33 +113,27 @@ class PreferencesDialog(tk.Toplevel):
outframe = nb.Frame(notebook) outframe = nb.Frame(notebook)
outframe.columnconfigure(0, weight=1) outframe.columnconfigure(0, weight=1)
output = config.getint('output') or (config.OUT_EDDN | config.OUT_SHIP_EDS) # default settings output = config.getint('output') or (config.OUT_MKT_EDDN | config.OUT_SHIP_EDS) # default settings
nb.Label(outframe, text=_('Please choose what data to save')).grid(columnspan=2, padx=PADX, sticky=tk.W) nb.Label(outframe, text=_('Please choose what data to save')).grid(columnspan=2, padx=PADX, sticky=tk.W)
self.out_eddn= tk.IntVar(value = (output & config.OUT_EDDN) and 1) self.out_eddn= tk.IntVar(value = (output & config.OUT_MKT_EDDN) and 1)
nb.Checkbutton(outframe, text=_('Send station data to the Elite Dangerous Data Network'), variable=self.out_eddn, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W) nb.Checkbutton(outframe, text=_('Send station data to the Elite Dangerous Data Network'), variable=self.out_eddn, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_csv = tk.IntVar(value = (output & config.OUT_CSV ) and 1) self.out_csv = tk.IntVar(value = (output & config.OUT_MKT_CSV ) and 1)
nb.Checkbutton(outframe, text=_('Market data in CSV format file'), variable=self.out_csv, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W) nb.Checkbutton(outframe, text=_('Market data in CSV format file'), variable=self.out_csv, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_bpc = tk.IntVar(value = (output & config.OUT_BPC ) and 1) self.out_bpc = tk.IntVar(value = (output & config.OUT_MKT_BPC ) and 1)
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) 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) self.out_td = tk.IntVar(value = (output & config.OUT_MKT_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) 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) 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) 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) self.out_ship_coriolis= tk.IntVar(value = (output & config.OUT_SHIP_CORIOLIS) and 1)
nb.Checkbutton(outframe, text=_('Ship loadout in Coriolis format file'), variable=self.out_ship_coriolis, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W) nb.Checkbutton(outframe, text=_('Ship loadout in Coriolis format file'), variable=self.out_ship_coriolis, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_log_file = tk.IntVar(value = (output & config.OUT_LOG_FILE) and 1) self.out_auto = tk.IntVar(value = 0 if output & config.OUT_MKT_MANUAL else 1) # inverted
nb.Checkbutton(outframe, text=_('Flight log in CSV format file'), variable=self.out_log_file, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, pady=(5,0), sticky=tk.W) self.out_auto_button = nb.Checkbutton(outframe, text=_('Automatically update on docking'), variable=self.out_auto, command=self.outvarchanged) # Output setting
self.out_log_auto = tk.IntVar(value = output & config.OUT_LOG_AUTO and 1 or 0) self.out_auto_button.grid(columnspan=2, padx=BUTTONX, pady=(5,0), sticky=tk.W)
self.out_log_auto_button = nb.Checkbutton(outframe, text=_('Automatically make a log entry on entering a system'), variable=self.out_log_auto, command=self.outvarchanged) # Output setting
self.out_log_auto_button.grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_log_auto_text = nb.Label(outframe, foreground='firebrick')
self.out_log_auto_text.grid(columnspan=2, padx=(30,0), sticky=tk.W)
self.outdir_label = nb.Label(outframe, text=_('File location')) # Section heading in settings self.outdir_label = nb.Label(outframe, text=_('File location')) # Section heading in settings
self.outdir_label.grid(padx=BUTTONX, sticky=tk.W) self.outdir_label.grid(padx=BUTTONX, pady=(5,0), sticky=tk.W)
self.outdir = nb.Entry(outframe, takefocus=False) self.outdir = nb.Entry(outframe, takefocus=False)
if config.get('outdir').startswith(config.home): if config.get('outdir').startswith(config.home):
self.outdir.insert(0, '~' + config.get('outdir')[len(config.home):]) self.outdir.insert(0, '~' + config.get('outdir')[len(config.home):])
@ -159,14 +152,13 @@ class PreferencesDialog(tk.Toplevel):
edsmframe.columnconfigure(1, weight=1) edsmframe.columnconfigure(1, weight=1)
HyperlinkLabel(edsmframe, text='Elite Dangerous Star Map', background=nb.Label().cget('background'), url='https://www.edsm.net/', underline=True).grid(columnspan=2, padx=PADX, sticky=tk.W) # Don't translate HyperlinkLabel(edsmframe, text='Elite Dangerous Star Map', background=nb.Label().cget('background'), url='https://www.edsm.net/', underline=True).grid(columnspan=2, padx=PADX, sticky=tk.W) # Don't translate
ttk.Separator(edsmframe, orient=tk.HORIZONTAL).grid(columnspan=2, padx=PADX, pady=PADY, sticky=tk.EW) self.edsm_log = tk.IntVar(value = (output & config.OUT_SYS_EDSM) and 1)
self.out_log_edsm = tk.IntVar(value = (output & config.OUT_LOG_EDSM) and 1) nb.Checkbutton(edsmframe, text=_('Send flight log to Elite Dangerous Star Map'), variable=self.edsm_log, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
nb.Checkbutton(edsmframe, text=_('Send flight log to Elite Dangerous Star Map'), variable=self.out_log_edsm, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W) self.edsm_log_auto = tk.IntVar(value = output & config.OUT_SYS_AUTO and 1 or 0)
self.edsm_log_auto_button = nb.Checkbutton(edsmframe, text=_('Automatically make a log entry on entering a system'), variable=self.out_log_auto, command=self.outvarchanged) # Output setting self.edsm_log_auto_button = nb.Checkbutton(edsmframe, text=_('Automatically make a log entry on entering a system'), variable=self.edsm_log_auto, command=self.outvarchanged) # Output setting
self.edsm_log_auto_button.grid(columnspan=2, padx=BUTTONX, sticky=tk.W) self.edsm_log_auto_button.grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.edsm_log_auto_text = nb.Label(edsmframe, foreground='firebrick')
self.edsm_log_auto_text.grid(columnspan=2, padx=(30,0), sticky=tk.W)
nb.Label(edsmframe).grid(sticky=tk.W) # big spacer
self.edsm_label = HyperlinkLabel(edsmframe, text=_('Elite Dangerous Star Map credentials'), background=nb.Label().cget('background'), url='https://www.edsm.net/settings/api', underline=True) # Section heading in settings self.edsm_label = HyperlinkLabel(edsmframe, text=_('Elite Dangerous Star Map credentials'), background=nb.Label().cget('background'), url='https://www.edsm.net/settings/api', underline=True) # Section heading in settings
self.edsm_label.grid(columnspan=2, padx=PADX, sticky=tk.W) self.edsm_label.grid(columnspan=2, padx=PADX, sticky=tk.W)
@ -270,7 +262,7 @@ class PreferencesDialog(tk.Toplevel):
self.protocol("WM_DELETE_WINDOW", self._destroy) self.protocol("WM_DELETE_WINDOW", self._destroy)
# Selectively disable buttons depending on output settings # Selectively disable buttons depending on output settings
self.proxypoll() self.outvarchanged()
self.themevarchanged() self.themevarchanged()
# disable hotkey for the duration # disable hotkey for the duration
@ -282,39 +274,24 @@ class PreferencesDialog(tk.Toplevel):
self.grab_set() self.grab_set()
def proxypoll(self):
self.outvarchanged()
self.after(1000, self.proxypoll)
def outvarchanged(self): def outvarchanged(self):
local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship_eds.get() or self.out_ship_coriolis.get() or self.out_log_file.get() local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship_eds.get() or self.out_ship_coriolis.get()
self.outdir_label['state'] = local and tk.NORMAL or tk.DISABLED self.outdir_label['state'] = local and tk.NORMAL or tk.DISABLED
self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED
self.outdir['state'] = local and 'readonly' or tk.DISABLED self.outdir['state'] = local and 'readonly' or tk.DISABLED
edsm_state = self.out_log_edsm.get() and tk.NORMAL or tk.DISABLED edsm_state = self.edsm_log.get() and tk.NORMAL or tk.DISABLED
self.edsm_label['state'] = edsm_state self.edsm_label['state'] = edsm_state
self.edsm_cmdr_label['state'] = edsm_state self.edsm_cmdr_label['state'] = edsm_state
self.edsm_apikey_label['state'] = edsm_state self.edsm_apikey_label['state'] = edsm_state
self.edsm_cmdr['state'] = edsm_state self.edsm_cmdr['state'] = edsm_state
self.edsm_apikey['state'] = edsm_state self.edsm_apikey['state'] = edsm_state
proxyaddr = edproxy.status() if monitor.logdir:
self.out_log_auto_text['text'] = '' self.out_auto_button['state'] = tk.NORMAL
self.edsm_log_auto_text['text'] = ''
if monitor.logdir or proxyaddr:
self.out_auto_button['state'] = monitor.logdir and tk.NORMAL or tk.DISABLED # edproxy doesn't send docking status
self.out_log_auto_button['state'] = self.out_log_file.get() and tk.NORMAL or tk.DISABLED
if self.out_log_file.get() and self.out_log_auto.get() and proxyaddr:
self.out_log_auto_text['text'] = _('Connected to {EDPROXY} at {ADDR}').format(EDPROXY = 'edproxy', ADDR = proxyaddr) # Output settings
self.edsm_log_auto_button['state'] = edsm_state self.edsm_log_auto_button['state'] = edsm_state
if self.out_log_edsm.get() and self.out_log_auto.get() and proxyaddr:
self.edsm_log_auto_text['text'] = _('Connected to {EDPROXY} at {ADDR}').format(EDPROXY = 'edproxy', ADDR = proxyaddr) # Output settings
else: else:
self.out_auto_button['state'] = tk.DISABLED self.out_auto_button['state'] = tk.DISABLED
self.out_log_auto_button['state'] = tk.DISABLED
self.edsm_log_auto_button['state'] = tk.DISABLED self.edsm_log_auto_button['state'] = tk.DISABLED
def outbrowse(self): def outbrowse(self):
@ -418,16 +395,15 @@ class PreferencesDialog(tk.Toplevel):
config.set('password', self.password.get().strip()) config.set('password', self.password.get().strip())
config.set('output', config.set('output',
(self.out_eddn.get() and config.OUT_EDDN) + (self.out_eddn.get() and config.OUT_MKT_EDDN) +
(self.out_bpc.get() and config.OUT_BPC) + (self.out_bpc.get() and config.OUT_MKT_BPC) +
(self.out_td.get() and config.OUT_TD) + (self.out_td.get() and config.OUT_MKT_TD) +
(self.out_csv.get() and config.OUT_CSV) + (self.out_csv.get() and config.OUT_MKT_CSV) +
(config.OUT_MANUAL if not self.out_auto.get() else 0) + (config.OUT_MKT_MANUAL if not self.out_auto.get() else 0) +
(self.out_ship_eds.get() and config.OUT_SHIP_EDS) + (self.out_ship_eds.get() and config.OUT_SHIP_EDS) +
(self.out_ship_coriolis.get() and config.OUT_SHIP_CORIOLIS) + (self.out_ship_coriolis.get() and config.OUT_SHIP_CORIOLIS) +
(self.out_log_file.get() and config.OUT_LOG_FILE) + (self.edsm_log.get() and config.OUT_SYS_EDSM) +
(self.out_log_edsm.get() and config.OUT_LOG_EDSM) + (self.edsm_log_auto.get() and config.OUT_SYS_AUTO))
(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()) config.set('outdir', self.outdir.get().startswith('~') and join(config.home, self.outdir.get()[2:]) or self.outdir.get())
config.set('edsm_cmdrname', self.edsm_cmdr.get().strip()) config.set('edsm_cmdrname', self.edsm_cmdr.get().strip())