Läuft die Voice Acoustic VA-Remotecontrol (AllDSP AllControl) nativ unter Linux auf echtem wxGTK 3.0 — ohne Wine und ohne dekompilierten App-Code. Ausgeführt wird das unveränderte Python-2.7-Bytecode aus dem macOS-.app; C-Extensions (wxGTK/numpy/ scipy/PortAudio) kommen nativ aus Debian stretch. Enthält: va/ (Original-.pyc + pure-Python-Libs + Assets + launch.py mit den drei Linux-Fixes), Dockerfile/run.sh/entrypoint.sh, reference/ (dekompilierter Quellcode zum Debuggen) und README/STATUS. img.cache (378 MB, regenerierbar) ist per .gitignore ausgeschlossen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3988 lines
180 KiB
Python
3988 lines
180 KiB
Python
# uncompyle6 version 3.9.3
|
|
# Python bytecode version base 2.6 (62161)
|
|
# Decompiled from: Python 3.9.25 (main, Oct 31 2025, 23:16:49)
|
|
# [GCC 14.2.0]
|
|
# Embedded file name: network_customized.pyc
|
|
# Compiled at: 2025-05-20 14:45:18
|
|
import mytime, wx, wx.lib.scrolledpanel as scrolled, os, data_model, traceback, one_unit, subprocess, ConfigParser, main, base64
|
|
from subprocess import Popen, PIPE
|
|
import protocol, select_keys, configure_group, d_ethernet, mytime, string, future, sys, my_menu, copy, zipfile
|
|
from email.mime.multipart import MIMEMultipart
|
|
from email.mime.text import MIMEText
|
|
email_server = 'smtp.strato.de'
|
|
email_user = 'swsw@alldsp.com'
|
|
email_password = 'h8d-6fe-hza-Snn'
|
|
mac_names = 'posix'
|
|
definedConfirmUpdate = True
|
|
if os.name in mac_names:
|
|
newline = '\n'
|
|
else:
|
|
newline = '\r\n'
|
|
|
|
def do_nothing(e):
|
|
return
|
|
|
|
|
|
def getString(strID):
|
|
return one_unit.getString(strID)
|
|
|
|
|
|
check_images = False
|
|
import datetime
|
|
|
|
class myBitmap(wx.Bitmap):
|
|
|
|
def __init__(self, img):
|
|
if check_images:
|
|
print datetime.datetime.now(), 'Generating', img
|
|
mytime.sleep(1)
|
|
res = wx.Bitmap.__init__(self, img)
|
|
if check_images:
|
|
one_unit.tryYield()
|
|
mytime.sleep(1)
|
|
one_unit.tryYield()
|
|
mytime.sleep(1)
|
|
print datetime.datetime.now(), 'Done'
|
|
return res
|
|
|
|
|
|
class NotStaticBitmap(wx.Panel):
|
|
|
|
def __init__(self, parent, id=-1, bmp=None, size=None, pos=(0, 0)):
|
|
if bmp != None:
|
|
if size == None:
|
|
size = bmp.GetSize()
|
|
if size == None:
|
|
size = (1, 1)
|
|
wx.Panel.__init__(self, parent, -1, size=size)
|
|
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
|
(width, height) = size
|
|
self.bmp = bmp
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
self.parent = parent
|
|
return
|
|
|
|
def OnPaint(self, event):
|
|
self.parent.parent.painted = True
|
|
dc = wx.AutoBufferedPaintDC(self)
|
|
if self.bmp:
|
|
dc.DrawBitmap(self.bmp, 0, 0)
|
|
return
|
|
|
|
|
|
class MultiTextEntryDialog(wx.Dialog):
|
|
|
|
def __init__(self, parent, title, caption):
|
|
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER
|
|
super(MultiTextEntryDialog, self).__init__(parent, -1, title, style=style)
|
|
text = wx.StaticText(self, -1, caption)
|
|
input = wx.TextCtrl(self, -1, style=wx.TE_MULTILINE)
|
|
input.SetInitialSize((400, 300))
|
|
buttons = self.CreateButtonSizer(wx.OK | wx.CANCEL)
|
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
sizer.Add(text, 0, wx.ALL, 5)
|
|
sizer.Add(input, 1, wx.EXPAND | wx.ALL, 5)
|
|
sizer.Add(buttons, 0, wx.EXPAND | wx.ALL, 5)
|
|
self.SetSizerAndFit(sizer)
|
|
self.input = input
|
|
return
|
|
|
|
def SetValue(self, value):
|
|
self.input.SetValue(value)
|
|
return
|
|
|
|
def GetValue(self):
|
|
return self.input.GetValue()
|
|
|
|
|
|
class MyButton(wx.BitmapButton):
|
|
|
|
def __init__(self, parent, id, img, handlers={}):
|
|
self.parent = parent
|
|
self.bitmapdir = self.parent.bitmapdir
|
|
self.base_img = self.parent.type + '_' + img
|
|
self.name = img
|
|
self.state = 'default'
|
|
self.executing = False
|
|
self.img_lib = {}
|
|
self.enabled = True
|
|
self.handlers = handlers
|
|
self.show = True
|
|
self.parent = parent
|
|
if img == 'locate' and self.parent.MAC.startswith('VN::'):
|
|
self.img = myBitmap(os.path.join(self.bitmapdir, 'GroupHeader_delete_default.png'))
|
|
else:
|
|
self.img = myBitmap(os.path.join(self.bitmapdir, self.base_img + '_default.png'))
|
|
self.img_lib['default'] = self.img
|
|
self.size = self.img.GetSize()
|
|
self.pos = self.parent.params[img + '_button_pos']
|
|
return
|
|
|
|
def SetState(self, state):
|
|
if state == self.state:
|
|
return
|
|
self.state = state
|
|
try:
|
|
img = self.img_lib[state]
|
|
except:
|
|
if os.path.exists(os.path.join(self.bitmapdir, self.base_img + '_' + state + '.png')):
|
|
img = myBitmap(os.path.join(self.bitmapdir, self.base_img + '_' + state + '.png'))
|
|
self.img_lib[state] = img
|
|
else:
|
|
try:
|
|
img = self.img_lib['default']
|
|
except:
|
|
return
|
|
|
|
if self.img != img:
|
|
self.img = img
|
|
self.parent.paint()
|
|
self.parent.Refresh(False)
|
|
return
|
|
|
|
def Enable(self, val):
|
|
if self.enabled == val:
|
|
if val:
|
|
if self.state != 'default':
|
|
self.SetState('default')
|
|
elif self.state != 'disabled':
|
|
self.SetState('disabled')
|
|
return
|
|
self.enabled = val
|
|
if val:
|
|
self.SetState('default')
|
|
else:
|
|
self.SetState('disabled')
|
|
return
|
|
|
|
def Show(self, val):
|
|
self.show = val
|
|
self.Refresh(False)
|
|
return
|
|
|
|
def Refresh(self, erase=False):
|
|
self.parent.changed = True
|
|
self.parent.Refresh(erase)
|
|
self.parent.parent.parent.changed = True
|
|
self.parent.parent.parent.Refresh(erase)
|
|
return
|
|
|
|
def HitTest(self, pos):
|
|
if self.enabled == False:
|
|
return False
|
|
x = pos[0]
|
|
y = pos[1]
|
|
if x < self.pos[0]:
|
|
return False
|
|
if x > self.pos[0] + self.size[0]:
|
|
return False
|
|
if y < self.pos[1]:
|
|
return False
|
|
if y > self.pos[1] + self.size[1]:
|
|
return False
|
|
return True
|
|
|
|
def Fire(self, event):
|
|
if self.executing:
|
|
return
|
|
self.executing = True
|
|
try:
|
|
op = self.handlers[event]
|
|
op()
|
|
except:
|
|
if event == 'OnDoubleClick':
|
|
try:
|
|
op = self.handlers['OnLeftDown']
|
|
op()
|
|
return
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
op = self.handlers[self.handlers.keys()[0]]
|
|
op()
|
|
except:
|
|
pass
|
|
|
|
self.executing = False
|
|
return
|
|
|
|
|
|
class GroupPanel(wx.Panel):
|
|
|
|
def __init__(self, parent, parent2, group):
|
|
self.parent = parent2
|
|
self.scrollPnl = parent
|
|
self.group = group
|
|
self.in_vu = None
|
|
self.params = self.parent.params
|
|
self.UnitStart = 0
|
|
self.out_vu = None
|
|
self.members = 0
|
|
self.last_change_time = 0
|
|
wx.Panel.__init__(self, parent, -1)
|
|
self.font = self.parent.font
|
|
self.bitmapdir = self.parent.bitmapdir
|
|
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
|
self.columns = self.parent.columns
|
|
self.width = 0
|
|
self.height = 0
|
|
self.do_redraw = False
|
|
self.row = 0
|
|
self.header_height = 0
|
|
self.clients = 0
|
|
self.header = None
|
|
if self.group != 'all_units':
|
|
img = os.path.join(self.bitmapdir, 'GroupHeader_header.png')
|
|
if os.path.exists(img):
|
|
separator = myBitmap(img)
|
|
self.header = NotStaticBitmap(self, -1, separator, pos=wx.DefaultPosition)
|
|
(w, h) = self.header.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
else:
|
|
img = os.path.join(self.bitmapdir, 'MainHeader_header.png')
|
|
if os.path.exists(img):
|
|
separator = myBitmap(img)
|
|
self.header = NotStaticBitmap(self, -1, separator, pos=wx.DefaultPosition)
|
|
(w, h) = self.header.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
self.HeaderLine = UnitLine(self, self, -1, '', Type='GroupHeader', Group=self.group)
|
|
if self.header != None:
|
|
self.header.SetPosition((0, 0))
|
|
self.HeaderLine.SetPosition((0, self.header.GetSize()[1]))
|
|
self.expand = self.HeaderLine.expand
|
|
(w, h) = self.HeaderLine.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
if os.path.exists(os.path.join(self.bitmapdir, 'GroupHeader_separator.png')):
|
|
separator = myBitmap(os.path.join(self.bitmapdir, 'GroupHeader_separator.png'))
|
|
self.separator = NotStaticBitmap(self, -1, separator, pos=wx.DefaultPosition)
|
|
self.separator.SetPosition((0, self.height))
|
|
(w, h) = self.separator.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
else:
|
|
self.separator = None
|
|
self.line = {}
|
|
self.stored_line = {}
|
|
self.header_height = self.height
|
|
if self.group != 'all_units':
|
|
img = os.path.join(self.bitmapdir, 'GroupHeader_footer.png')
|
|
if os.path.exists(img):
|
|
separator = myBitmap(img)
|
|
self.footer = NotStaticBitmap(self, -1, separator, pos=wx.DefaultPosition)
|
|
(w, h) = self.footer.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
else:
|
|
self.footer = None
|
|
else:
|
|
img = os.path.join(self.bitmapdir, 'MainHeader_footer.png')
|
|
if os.path.exists(img):
|
|
separator = myBitmap(img)
|
|
self.footer = NotStaticBitmap(self, -1, separator, pos=wx.DefaultPosition)
|
|
(w, h) = self.footer.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
else:
|
|
self.footer = None
|
|
self.SetSize((self.width, self.height))
|
|
self.Bind(wx.EVT_MOTION, self.OnMotion)
|
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
|
|
return
|
|
|
|
def OnMouseWheel(self, evt):
|
|
self.parent.OnMouseWheel(evt)
|
|
return
|
|
|
|
def UnitDown(self):
|
|
self.UnitStart -= 1
|
|
if self.UnitStart < 0:
|
|
self.UnitStart = 0
|
|
self.changed = True
|
|
print mytime.displayTime() + ' Unit Down', self.HeaderLine.name, self.UnitStart
|
|
self.do_redraw = True
|
|
return
|
|
|
|
def UnitUp(self):
|
|
self.UnitStart += 1
|
|
if self.UnitStart >= self.members:
|
|
self.UnitStart = self.members - 1
|
|
self.changed = True
|
|
print mytime.displayTime() + ' Unit Up', self.HeaderLine.name, self.UnitStart
|
|
self.do_redraw = True
|
|
return
|
|
|
|
def OnLeftDown(self, e):
|
|
self.parent.OnLeftDown(e, self.GetPosition())
|
|
return
|
|
|
|
def OnMotion(self, event):
|
|
self.parent.OnMotion(event, self.GetPosition())
|
|
return
|
|
|
|
def OnLeftUp(self, event):
|
|
self.parent.OnLeftUp(event)
|
|
return
|
|
|
|
def Update(self):
|
|
self.HeaderLine.Update()
|
|
changed = False
|
|
if self.HeaderLine.expand == True:
|
|
keys = self.parent.parent.peers.units.keys()
|
|
sorted_keys = sorted([_[1] for mac in keys], key=(lambda s: s.lower()))
|
|
keys = []
|
|
if self.group != 'all_units':
|
|
members = one_unit.getMacList(self.group)
|
|
else:
|
|
members = []
|
|
for name in sorted_keys:
|
|
for mac in self.parent.parent.peers.units.keys():
|
|
if self.parent.parent.peers.units[mac].type == '1_1_25' and self.parent.enable_update == False or mac not in members and self.group != 'all_units' or self.parent.parent.peers.units[mac].MAC[:4] in ('DEMO',
|
|
'GRP_',
|
|
'VN::') and self.parent.demo_mode == False and self.group == 'all_units':
|
|
continue
|
|
if mac == 'Startup...' and self.group != 'all_units':
|
|
continue
|
|
if mac == 'Startup...' and mytime.clock() - one_unit.app.bootloader_last_rx > 5 and one_unit.app.global_bootloader_progress in (None,
|
|
'',
|
|
'(2) Finished',
|
|
'(2) Failed!',
|
|
'Finished'):
|
|
continue
|
|
if mac == 'Choose unit....':
|
|
continue
|
|
if self.parent.parent.peers.units[mac].name.strip() == name and mac not in keys:
|
|
keys.append(mac)
|
|
|
|
self.members = 0
|
|
counter = 0
|
|
if self.do_redraw == True:
|
|
self.height = self.header_height
|
|
self.clients = 0
|
|
for mac in self.line.keys():
|
|
if mac == 'Startup...' and mytime.clock() - one_unit.app.bootloader_last_rx > 5:
|
|
print mytime.displayTime() + ' nwc.u0.Removing Startup line'
|
|
self.clients -= 1
|
|
self.line[mac].Show(False)
|
|
(w, h) = self.line[mac].GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
if self.columns > 1:
|
|
index = self.clients % self.columns
|
|
if index > 0:
|
|
h = 0
|
|
self.height -= h
|
|
self.line[mac].Destroy()
|
|
del self.line[mac]
|
|
changed = True
|
|
|
|
if len(self.line) != len(keys):
|
|
self.height = self.header_height
|
|
self.clients = 0
|
|
changed = True
|
|
while True:
|
|
for mac in self.line.keys():
|
|
self.stored_line[mac] = self.line[mac]
|
|
self.line[mac].Show(False)
|
|
del self.line[mac]
|
|
break
|
|
|
|
if len(self.line) == 0:
|
|
break
|
|
|
|
self.clients = 0
|
|
for mac in keys:
|
|
if one_unit.app.application_stopping == True:
|
|
break
|
|
self.members += 1
|
|
try:
|
|
counter += 1
|
|
if self.line[mac].Update() == True:
|
|
changed = True
|
|
if self.do_redraw == True:
|
|
if counter <= self.UnitStart:
|
|
self.line[mac].Show(False)
|
|
else:
|
|
self.line[mac].Show(True)
|
|
y = self.height
|
|
x = 0
|
|
(w, h) = self.line[mac].GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
if self.columns > 1:
|
|
index = self.clients % self.columns
|
|
x = index * self.line[mac].GetSize()[0]
|
|
if index > 0:
|
|
y -= self.line[mac].GetSize()[1]
|
|
h = 0
|
|
self.line[mac].SetPosition((x, y))
|
|
self.row += 1
|
|
self.height += h
|
|
self.clients += 1
|
|
except:
|
|
if mac not in self.line and (self.parent.parent.peers.units[mac].name.strip() != 'Startup...' or mytime.clock() - one_unit.app.bootloader_last_rx < 5) and (self.parent.parent.peers.units[mac].name.strip() != 'No Name' or mytime.clock() - self.parent.parent.peers.units[mac].discover_time > 5) and self.parent.parent.peers.units[mac].MAC[:4] not in 'GRP_':
|
|
if self.footer:
|
|
del self.footer
|
|
try:
|
|
self.line[mac] = self.stored_line[mac]
|
|
self.line[mac].Show(True)
|
|
(w, h) = self.line[mac].GetSize()
|
|
except:
|
|
self.line[mac] = UnitLine(self, self, -1, mac, Group=self.group)
|
|
else:
|
|
y = self.height
|
|
x = 0
|
|
(w, h) = self.line[mac].GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
if self.columns > 1:
|
|
index = self.clients % self.columns
|
|
x = index * self.line[mac].GetSize()[0]
|
|
if index > 0:
|
|
y -= self.line[mac].GetSize()[1]
|
|
h = 0
|
|
self.line[mac].SetPosition((x, y))
|
|
self.clients += 1
|
|
self.row += 1
|
|
if counter >= self.UnitStart:
|
|
self.height += h
|
|
if self.group != 'all_units':
|
|
img = os.path.join(self.bitmapdir, 'GroupHeader_footer.png')
|
|
if os.path.exists(img):
|
|
separator = myBitmap(img)
|
|
self.footer = NotStaticBitmap(self, -1, separator, pos=wx.DefaultPosition)
|
|
(w, h) = self.footer.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
else:
|
|
self.footer = None
|
|
else:
|
|
img = os.path.join(self.bitmapdir, 'MainHeader_footer.png')
|
|
if os.path.exists(img):
|
|
separator = myBitmap(img)
|
|
self.footer = NotStaticBitmap(self, -1, separator, pos=wx.DefaultPosition)
|
|
(w, h) = self.footer.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
else:
|
|
self.footer = None
|
|
changed = True
|
|
|
|
try:
|
|
for mac in self.stored_line.keys():
|
|
if mac not in self.line.keys():
|
|
print mytime.displayTime() + ' nwc.u0.Removed', mac
|
|
del self.stored_line[mac]
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
else:
|
|
while True:
|
|
for mac in self.line.keys():
|
|
self.clients -= 1
|
|
(w, h) = self.line[mac].GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
if self.columns > 1:
|
|
index = self.clients % self.columns
|
|
if index > 0:
|
|
h = 0
|
|
self.height -= h
|
|
self.line[mac].Destroy()
|
|
del self.line[mac]
|
|
changed = True
|
|
break
|
|
|
|
if len(self.line) == 0:
|
|
break
|
|
|
|
if self.HeaderLine.expand != self.expand:
|
|
changed = True
|
|
self.expand = self.HeaderLine.expand
|
|
if self.do_redraw == True or changed == True:
|
|
self.SetSize((self.width, self.height))
|
|
self.last_change_time = mytime.clock()
|
|
self.HeaderLine.changed = True
|
|
self.Refresh(False)
|
|
self.Layout()
|
|
if self.do_redraw == True:
|
|
self.do_redraw = False
|
|
if changed == True:
|
|
self.do_redraw = True
|
|
return changed
|
|
|
|
def refresh_vu(self):
|
|
for mac in self.line.keys():
|
|
self.line[mac].refresh_vu()
|
|
|
|
return
|
|
|
|
|
|
class UnitLine(wx.Panel):
|
|
|
|
def __init__(self, parent, parent2, id, mac, Type='Unit', Group='None'):
|
|
wx.Panel.__init__(self, parent, id, size=(1, 1))
|
|
self.parent = parent2
|
|
self.group = Group
|
|
self.init_finished = False
|
|
self.MAC = mac
|
|
self.LocateTime = -100
|
|
self.my_group_panel = Group
|
|
self.IP = None
|
|
self.display_buffer = wx.EmptyBitmap(1, 1)
|
|
self.editable = []
|
|
self.hw_status = 0
|
|
self.launchTime = mytime.clock() - 2
|
|
self.conf = ''
|
|
self.repaint = True
|
|
self.always_enable_update = self.parent.parent.always_enable_update
|
|
self.power_state = ''
|
|
self.connected_time = mytime.clock()
|
|
self.offline_time = mytime.clock()
|
|
self.repaint_vu = True
|
|
self.first_time = True
|
|
self.ask_for_pin = True
|
|
self.pin_verified = False
|
|
self.verifyingPIN = False
|
|
self.expand = False
|
|
self.dclick = False
|
|
self.number_of_units = 0
|
|
self.number_muted = 0
|
|
self.model_number = None
|
|
self.group_enabled = False
|
|
self.number_off_string = '0'
|
|
self.updating = False
|
|
self.muted = False
|
|
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
|
self.last_enable_update = False
|
|
if self.group == 'all_units' and Type == 'GroupHeader':
|
|
self.expand = True
|
|
self.type = Type
|
|
self.changed = True
|
|
self.dc = None
|
|
self.mark_for_delete = False
|
|
self.groupbox = None
|
|
self.font = self.parent.font
|
|
self.bitmapdir = self.parent.bitmapdir
|
|
font = self.font
|
|
if self.type == 'GroupHeader' and self.group == 'all_units':
|
|
self.bg = myBitmap(os.path.join(self.bitmapdir, 'MainHeader_bg.png'))
|
|
self.params = self.parent.params['Main']
|
|
else:
|
|
self.bg = myBitmap(os.path.join(self.bitmapdir, self.type + '_bg.png'))
|
|
self.params = self.parent.params[self.type]
|
|
if self.MAC in one_unit.app.seriesHeaders:
|
|
self.bg = myBitmap(os.path.join(self.bitmapdir, 'SeriesHeader_bg.png'))
|
|
self.margin_left_img = None
|
|
if self.type == 'Unit':
|
|
if self.group == 'all_units':
|
|
if os.path.exists(os.path.join(self.bitmapdir, 'Main_Unit_margin_left.png')):
|
|
self.margin_left_img = myBitmap(os.path.join(self.bitmapdir, 'Main_Unit_margin_left.png'))
|
|
elif os.path.exists(os.path.join(self.bitmapdir, 'Group_Unit_margin_left.png')):
|
|
self.margin_left_img = myBitmap(os.path.join(self.bitmapdir, 'Group_Unit_margin_left.png'))
|
|
elif self.group == 'all_units':
|
|
if os.path.exists(os.path.join(self.bitmapdir, 'MainHeader_margin_left.png')):
|
|
self.margin_left_img = myBitmap(os.path.join(self.bitmapdir, 'MainHeader_margin_left.png'))
|
|
elif os.path.exists(os.path.join(self.bitmapdir, 'GroupHeader_margin_left.png')):
|
|
self.margin_left_img = myBitmap(os.path.join(self.bitmapdir, 'GroupHeader_margin_left.png'))
|
|
self.margin_right_img = None
|
|
if self.type == 'Unit':
|
|
if self.group == 'all_units':
|
|
if os.path.exists(os.path.join(self.bitmapdir, 'Main_Unit_margin_right.png')):
|
|
self.margin_right_img = myBitmap(os.path.join(self.bitmapdir, 'Main_Unit_margin_right.png'))
|
|
elif os.path.exists(os.path.join(self.bitmapdir, 'Group_Unit_margin_right.png')):
|
|
self.margin_right_img = myBitmap(os.path.join(self.bitmapdir, 'Group_Unit_margin_right.png'))
|
|
if self.margin_left_img:
|
|
margin_left = self.margin_left_img.GetSize()[0]
|
|
else:
|
|
margin_left = 0
|
|
if self.margin_right_img:
|
|
margin_right = self.margin_right_img.GetSize()[0]
|
|
else:
|
|
margin_right = 0
|
|
self.params['margin_left'] = margin_left
|
|
self.params['margin_right'] = margin_right
|
|
self.params['margin_right_pos'] = self.bg.GetSize()[0] + self.params['margin_left']
|
|
self.vu_pos = self.params['vu_pos']
|
|
self.vu_size = self.params['vu_size']
|
|
self.vu_led_size = self.params['vu_led_size']
|
|
self.vu_led_pitch = self.params['vu_led_pitch']
|
|
self.vu_steps = self.params['vu_steps']
|
|
self.vu_colours = self.params['vu_colours']
|
|
self.to_draw = []
|
|
self.last_vu = []
|
|
for i in range(0, len(self.vu_pos)):
|
|
self.last_vu.append(-100)
|
|
self.to_draw.append(0)
|
|
|
|
self.size = (
|
|
self.bg.GetSize()[0] + self.params['margin_left'] + self.params['margin_right'], self.bg.GetSize()[1])
|
|
self.SetSize(self.size)
|
|
if self.params['show_mute'] == True:
|
|
self.mute_button = MyButton(self, 5, 'mute', handlers={'OnLeftDown': (self.OnMute)})
|
|
self.editable.append(self.mute_button)
|
|
if self.params['show_locate'] == True:
|
|
self.locate_button = MyButton(self, 6, 'locate', handlers={'OnLeftDown': (self.OnLocate)})
|
|
self.editable.append(self.locate_button)
|
|
if self.type == 'GroupHeader':
|
|
self.locate_button.SetState('on')
|
|
if self.params['show_power'] == True:
|
|
self.power_button = MyButton(self, 6, 'power', handlers={'OnLeftDown': (self.OnPower)})
|
|
if self.params['power_button_indicator_only'] == False:
|
|
self.editable.append(self.power_button)
|
|
if self.type == 'Unit':
|
|
self.name = self.parent.parent.parent.peers.units[mac].name.strip()
|
|
elif self.type == 'GroupHeader':
|
|
if self.group == 'all_units':
|
|
self.name = 'All Units'
|
|
elif self.params['expand_name']:
|
|
self.name = 'Group: ' + one_unit.app.group_names[self.group].decode('utf-8') + ' (' + str(len(one_unit.app.groups[self.group])) + ' units)'
|
|
else:
|
|
self.name = one_unit.app.group_names[self.group].decode('utf-8')
|
|
if self.type == 'Unit':
|
|
if self.MAC.startswith('DEMO') == True:
|
|
self.IP = 'Demo Unit'
|
|
elif self.MAC.startswith('VN::') == True:
|
|
self.IP = 'Virtual Unit'
|
|
else:
|
|
self.IP = 'Offline'
|
|
if self.type == 'Unit':
|
|
self.link_status = self.parent.parent.parent.peers.units[mac].link_status
|
|
if self.params['show_launch'] == True:
|
|
self.launch_button = MyButton(self, 2, 'launch', handlers={'OnLeftDown': (self.OnLaunch), 'OnDoubleClick': (self.OnLaunchDoubleClick)})
|
|
self.editable.append(self.launch_button)
|
|
if self.MAC[:4] not in ('DEMO', 'GRP_', 'VN::'):
|
|
self.launch_button.Enable(False)
|
|
if self.MAC == 'Startup...':
|
|
self.launch_button.Show(False)
|
|
if self.MAC in one_unit.app.seriesHeaders:
|
|
self.launch_button.Show(False)
|
|
if Group == 'all_units' and self.params['show_update'] == True:
|
|
self.update_button = MyButton(self, 4, 'update', handlers={'OnLeftDown': (self.OnUpdate)})
|
|
self.update_button.Enable(False)
|
|
self.update_button.Show(False)
|
|
self.editable.append(self.update_button)
|
|
elif self.type == 'GroupHeader':
|
|
self.link_status = 'disconnected'
|
|
if self.params['show_launch'] == True:
|
|
if self.group == 'all_units':
|
|
self.launch_button = MyButton(self, 2, 'launch', handlers={'OnLeftDown': (self.OnLaunchDoubleClick), 'OnDoubleClick': (self.OnLaunchDoubleClick)})
|
|
self.editable.append(self.launch_button)
|
|
else:
|
|
self.launch_button = MyButton(self, 2, 'launch', handlers={'OnLeftDown': (self.OnLaunch), 'OnDoubleClick': (self.OnLaunchDoubleClick)})
|
|
self.editable.append(self.launch_button)
|
|
self.delete_button = MyButton(self, 3, 'delete', handlers={'OnLeftDown': (self.OnDelete)})
|
|
self.editable.append(self.delete_button)
|
|
if self.parent.parent.parent.enable_advanced_grouping == True:
|
|
self.configure_button = MyButton(self, 3, 'configure', handlers={'OnLeftDown': (self.OnConfigure)})
|
|
self.editable.append(self.configure_button)
|
|
if self.type == 'Unit':
|
|
self.namebox = wx.TextCtrl(self, -1, self.name, size=self.params['name_size'], pos=self.params['name_pos'], style=wx.BORDER_NONE | wx.TE_PROCESS_ENTER)
|
|
self.namebox.SetFont(self.font)
|
|
self.namebox.Show(False)
|
|
self.namebox.Bind(wx.EVT_TEXT_ENTER, self.OnSetName)
|
|
self.namebox.Bind(wx.EVT_KILL_FOCUS, self.OnSetName)
|
|
self.Bind(wx.EVT_PAINT, self.on_paint)
|
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick)
|
|
self.Bind(wx.EVT_MOTION, self.OnMotion)
|
|
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
|
|
if self.groupbox != None:
|
|
self.groupbox.Bind(wx.EVT_CHOICE, self.on_group_change)
|
|
self.SetMinSize(self.size)
|
|
if self.type == 'GroupHeader':
|
|
if self.params['show_locate'] == True:
|
|
self.locate_button.Show(False)
|
|
if self.params['show_launch'] == True:
|
|
if self.group != 'all_units':
|
|
self.launch_button.SetState('on')
|
|
x = min(self.vu_pos[0][0], self.vu_pos[1][0])
|
|
y = min(self.vu_pos[0][1], self.vu_pos[1][1])
|
|
w = self.vu_pos[1][0] + self.vu_size[0][0] - self.vu_pos[0][0]
|
|
h = self.vu_pos[1][1] + self.vu_size[0][1] - self.vu_pos[0][1]
|
|
self.rect = wx.Rect(x, y, w, h)
|
|
self.SetLinkStatus()
|
|
self.init_finished = True
|
|
self.paint()
|
|
self.Refresh(False)
|
|
return
|
|
|
|
def OnMouseWheel(self, evt):
|
|
self.parent.OnMouseWheel(evt)
|
|
return
|
|
|
|
def OnSetName(self, e):
|
|
if self.namebox.GetValue() == self.name:
|
|
self.namebox.Show(False)
|
|
self.Refresh()
|
|
return
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_ACCESS_RIGHTS, 0, 0)
|
|
try:
|
|
if self.MAC[:4] not in ('DEMO', 'VN::') and one_unit.app.server.peers.get(key, self.MAC) & protocol.arUnitName == 0:
|
|
dlgMessage = getString('nsa')
|
|
dlgTitle = getString('w')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK)
|
|
self.namebox.SetValue(self.name)
|
|
self.namebox.Show(False)
|
|
self.Refresh()
|
|
return
|
|
except:
|
|
self.namebox.SetValue(self.name)
|
|
self.namebox.Show(False)
|
|
self.Refresh()
|
|
return
|
|
else:
|
|
name = self.namebox.GetValue().strip()[:16]
|
|
name = data_model.getValidName(name)
|
|
if self.MAC[:4] not in 'GRP_':
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_SHORT_NAME, 0, 0)
|
|
try:
|
|
one_unit.app.server.peers.units[self.MAC].process.conn.set_by_key(key, name)
|
|
except:
|
|
pass
|
|
else:
|
|
one_unit.app.server.peers.units[self.MAC].name = name
|
|
self.parent.parent.parent.peers.units[self.MAC].name = name
|
|
try:
|
|
self.parent.parent.parent.server.peers.set_by_key(self.MAC, key, name)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
else:
|
|
if self.group != 'all_units':
|
|
one_unit.app.groups[self.group][self.MAC] = (
|
|
name, one_unit.app.groups[self.group][self.MAC][1], one_unit.app.groups[self.group][self.MAC][2])
|
|
one_unit.app.groupconfig.set(self.group, 'members', one_unit.app.groups[self.group])
|
|
try:
|
|
groupconfigfile = open(os.path.join(one_unit.app.asys_config_path, 'grouping.cfg'), 'wb')
|
|
one_unit.app.groupconfig.write(groupconfigfile)
|
|
groupconfigfile.close()
|
|
except:
|
|
dlgMessage = getString('nsa2')
|
|
dlgTitle = getString('e')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK)
|
|
return
|
|
|
|
print mytime.displayTime() + ' Set name of', self.name, 'to', one_unit.app.server.peers.units[self.MAC].name
|
|
|
|
self.namebox.Show(False)
|
|
self.Refresh()
|
|
return
|
|
|
|
def OnLeftDblClick(self, e):
|
|
self.dclick = True
|
|
return
|
|
|
|
def OnLeftDown(self, e):
|
|
self.parent.Raise()
|
|
pos = e.GetPositionTuple()
|
|
for field in self.editable:
|
|
if field.HitTest(pos):
|
|
field.SetState('open')
|
|
self.Refresh()
|
|
if self.dclick == True:
|
|
event = 'OnDoubleClick'
|
|
else:
|
|
event = 'OnLeftDown'
|
|
self.dclick = False
|
|
try:
|
|
field.Fire(event)
|
|
self.Refresh(False)
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
if pos[0] > self.params['name_pos'][0] and pos[0] < self.params['name_pos'][0] + self.params['name_size'][0] and pos[1] > self.params['name_pos'][1] and pos[1] < self.params['name_pos'][1] + self.params['name_size'][1] and self.type == 'Unit':
|
|
self.namebox.Show(True)
|
|
self.namebox.SetFocus()
|
|
self.namebox.SetValue(self.name)
|
|
self.namebox.SelectAll()
|
|
return
|
|
if self.params['full_area_locate'] == True:
|
|
self.OnLocate()
|
|
return
|
|
if self.params['show_launch'] == False and self.type == 'Unit':
|
|
self.Launch()
|
|
return
|
|
self.getOrReleaseMouseCapture(True)
|
|
self.parent.parent.OnLeftDown(e, (self.GetPosition()[0] + self.parent.GetPosition()[0], self.GetPosition()[1] + self.parent.GetPosition()[1]))
|
|
return
|
|
|
|
def OnMotion(self, event):
|
|
self.parent.parent.OnMotion(event, (self.GetPosition()[0] + self.parent.GetPosition()[0], self.GetPosition()[1] + self.parent.GetPosition()[1]))
|
|
return
|
|
|
|
def OnLeftUp(self, event):
|
|
self.getOrReleaseMouseCapture(False)
|
|
self.parent.parent.OnLeftUp(event)
|
|
return
|
|
|
|
def getOrReleaseMouseCapture(self, capture):
|
|
"""
|
|
Captures the mouse for this class object (which keeps a wxWidgets frame or a compatible
|
|
wxWidgets object). The mouse will only be captured or released if the class object hasCapture
|
|
method returns the correct value.
|
|
|
|
@param self: The class object itself
|
|
@param capture: True or false. True get the mouse capture for this class, false release it
|
|
"""
|
|
if capture and not self.HasCapture():
|
|
self.CaptureMouse()
|
|
if not capture and self.HasCapture():
|
|
self.ReleaseMouse()
|
|
return
|
|
|
|
def OnPower(self):
|
|
if self.type == 'Unit' and self.pin_verified == False:
|
|
self.ask_for_pin = True
|
|
self.verifyPIN()
|
|
if self.pin_verified == False:
|
|
self.power_button.SetState(self.power_state)
|
|
return
|
|
if self.power_state == 'on':
|
|
if self.type != 'Unit':
|
|
dlgMessage = getString('gts')
|
|
dlgTitle = getString('pof')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
self.power_button.SetState('on')
|
|
return
|
|
state = False
|
|
self.power_state = 'off'
|
|
if self.params['show_power'] == True:
|
|
self.power_button.SetState('off')
|
|
elif self.type != 'Unit':
|
|
dlgMessage = getString('exs')
|
|
dlgTitle = getString('pon')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
self.power_button.SetState('off')
|
|
return
|
|
self.power_state = 'on'
|
|
state = True
|
|
if self.params['show_power'] == True:
|
|
self.power_button.SetState('on')
|
|
self.paint()
|
|
mytime.sleep(0.1)
|
|
if self.type == 'Unit':
|
|
self.parent.parent.parent.remote_link.PowerSingleUnit(self.MAC, state)
|
|
else:
|
|
if state == False:
|
|
command = protocol.cmdGotoStandby
|
|
text = 'Switching off ' + self.name + '...'
|
|
else:
|
|
command = protocol.cmdExitStandby
|
|
text = 'Switching on ' + self.name + '...'
|
|
keys = []
|
|
if self.group != 'all_units':
|
|
members = one_unit.getMacList(self.group)
|
|
else:
|
|
members = []
|
|
for mac in self.parent.parent.parent.peers.units.keys():
|
|
if mac[:4] in ('DEMO', 'GRP_', 'VN::'):
|
|
continue
|
|
if mac.startswith('Startup'):
|
|
continue
|
|
if mac in members or self.group == 'all_units':
|
|
keys.append(mac)
|
|
|
|
self.memberlist = keys
|
|
self.progress = one_unit.ProgressScreen(self, -1, 'Progress', text)
|
|
self.progress.Show(True)
|
|
hwkey = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0)
|
|
stupid_repeat = 5
|
|
while stupid_repeat < 100 and one_unit.app.application_stopping == False:
|
|
stupid_repeat += 5
|
|
keys = []
|
|
for mac in self.memberlist:
|
|
self.parent.parent.parent.remote_link.direct_link.set_get_key(hwkey, mac)
|
|
try:
|
|
hw_status = int(one_unit.app.server.peers.get(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0), mac)) & 16777215
|
|
except:
|
|
hw_status = 0
|
|
|
|
if hw_status & protocol.confStandby == protocol.confStandby and state == False:
|
|
continue
|
|
if hw_status & protocol.confStandby == 0 and state == True:
|
|
continue
|
|
if mac not in one_unit.app.pin_verified:
|
|
continue
|
|
if one_unit.app.pin_verified[mac] == False:
|
|
continue
|
|
keys.append(mac)
|
|
|
|
if len(keys) == 0:
|
|
print mytime.displayTime() + ' Finished'
|
|
self.progress.Destroy()
|
|
return
|
|
print mytime.displayTime() + ' Setting ' + str(len(keys)) + ' units'
|
|
counter = 1
|
|
for mac in keys:
|
|
counter += 1
|
|
self.progress.Update(counter * 90 / len(keys))
|
|
try:
|
|
self.parent.parent.parent.server.peers.units[mac].process.conn.set_by_key(data_model.Key(protocol.STRUCT_ID_COMMAND, protocol.MEMBER_ID_COMMAND, 0, command), 1)
|
|
except:
|
|
pass
|
|
|
|
if state:
|
|
mytime.sleep(0.2)
|
|
|
|
finished = False
|
|
retry = 0
|
|
while finished == False and retry < 20:
|
|
retry += 1
|
|
finished = True
|
|
for mac in keys:
|
|
try:
|
|
if self.parent.parent.parent.server.peers.units[mac].process.conn.synced == False:
|
|
finished = False
|
|
break
|
|
except:
|
|
pass
|
|
|
|
mytime.sleep(0.1)
|
|
|
|
mytime.sleep(0.5)
|
|
for mac in keys:
|
|
try:
|
|
self.parent.parent.parent.server.peers.units[mac].process.conn.set_by_key(data_model.Key(protocol.STRUCT_ID_COMMAND, protocol.MEMBER_ID_COMMAND, 0, command), 0)
|
|
self.parent.parent.parent.server.peers.units[mac].process.conn.get_list.append(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0))
|
|
except:
|
|
pass
|
|
|
|
mytime.sleep(0.5)
|
|
|
|
print mytime.displayTime() + ' Not finished, Exiting anyway'
|
|
self.progress.Destroy()
|
|
return
|
|
|
|
def OnConfigure(self):
|
|
dial = configure_group.Dialog(self, -1, 'Configure Group', ' ', self.group)
|
|
dial.ShowModal()
|
|
dial.Destroy()
|
|
return
|
|
|
|
def OnMute(self):
|
|
if self.type == 'Unit' and self.pin_verified == False:
|
|
self.ask_for_pin = True
|
|
self.verifyPIN()
|
|
if self.pin_verified == False:
|
|
if self.muted == True:
|
|
if self.params['show_mute'] == True:
|
|
self.mute_button.SetState('on')
|
|
state = 'on'
|
|
elif self.params['show_mute'] == True:
|
|
self.mute_button.SetState('default')
|
|
state = 'default'
|
|
return
|
|
state = None
|
|
if self.muted == False:
|
|
self.muted = True
|
|
muted = True
|
|
if self.params['show_mute'] == True:
|
|
self.mute_button.SetState('on')
|
|
state = 'on'
|
|
else:
|
|
self.muted = False
|
|
muted = False
|
|
if self.params['show_mute'] == True:
|
|
self.mute_button.SetState('default')
|
|
state = 'default'
|
|
self.Refresh(False)
|
|
self.paint()
|
|
if self.type == 'Unit':
|
|
self.parent.parent.parent.remote_link.MuteSingleUnit(self.MAC, muted)
|
|
else:
|
|
self.parent.parent.parent.remote_link.MuteGroup(self.group, self.muted)
|
|
if state != None:
|
|
try:
|
|
for mac in self.parent.line.keys():
|
|
if mac not in one_unit.app.pin_verified:
|
|
continue
|
|
if one_unit.app.pin_verified[mac] == False:
|
|
continue
|
|
self.parent.line[mac].mute_button.SetState(state)
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
return
|
|
|
|
def OnLocate(self):
|
|
if self.type == 'Unit':
|
|
if self.MAC.startswith('VN::'):
|
|
dlgMessage = getString('dvud1') + ' ' + self.name + ' ' + getString('dvud2')
|
|
dlgTitle = getString('dvu')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
return
|
|
one_unit.deleteVirtualUnit(self.MAC)
|
|
return
|
|
print mytime.displayTime() + ' Locating unit', self.MAC, self.name
|
|
self.LocateTime = mytime.clock()
|
|
self.parent.parent.parent.remote_link.LocateUnit(self.MAC)
|
|
else:
|
|
self.OnExpand()
|
|
return
|
|
|
|
def OnUpdate(self):
|
|
if self.params['show_update'] == True and self.params['show_update'] == True:
|
|
if self.update_button.enabled == False:
|
|
return
|
|
else:
|
|
return
|
|
mytime.sleep(0.1)
|
|
confirm_update = definedConfirmUpdate
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_SHORT_NAME, 0, 0)
|
|
print 'nc.OnUpdate', str(one_unit.app.server.peers.get(key, self.MAC)).strip(), self.MAC
|
|
if self.MAC == 'Startup...':
|
|
one_unit.app.enable_bootloader = True
|
|
return
|
|
try:
|
|
name = str(one_unit.app.server.peers.get(key, self.MAC)).strip()
|
|
if name in ('None', 'No Name', 'Recovery Mode', 'Safe Mode') and one_unit.app.mijnpc == True:
|
|
confirm_update = False
|
|
if name in ('Recovery Mode', 'Safe Mode'):
|
|
one_unit.updateBootloaderDial(self.MAC, 'Executing ' + name + ' Update')
|
|
else:
|
|
one_unit.updateBootloaderDial(self.MAC, 'Executing immediate update for ' + name)
|
|
except:
|
|
name = ''
|
|
|
|
if self.parent.parent.parent.peers.units[self.MAC].link_status == 'available':
|
|
if confirm_update == True and self.parent.parent.full_update_rights != 'yes':
|
|
res = wx.MessageBox('The firmware of this unit will be updated. The update process can have multiple ' + 'steps; please do not power off the unit or disconnect the network until it is finished. ' + 'Should the process fail, try again. Note: You are updating the firmware without a backup. ' + 'All presets and settings in the unit will be lost. Continue?', 'Firmware Update', wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
return
|
|
one_unit.tryYield()
|
|
mytime.sleep(0.1)
|
|
self.parent.parent.StartUpdate(self.MAC)
|
|
self.updating = True
|
|
elif self.parent.parent.parent.peers.units[self.MAC].link_status == 'Bootloader':
|
|
if confirm_update == True and self.parent.parent.full_update_rights != 'yes':
|
|
res = wx.MessageBox('The firmware of this unit will be updated. The update process can have multiple ' + 'steps; please do not power off the unit or disconnect the network until it is finished. Should the process fail, try again. ' + 'Continue?', 'Firmware Update', wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
return
|
|
one_unit.app.enable_Bootloader = True
|
|
self.updating = True
|
|
else:
|
|
res = wx.MessageBox('This unit is not connected. Please start the update process again later.', 'Firmware Update', wx.OK)
|
|
return
|
|
|
|
def OnDelete(self):
|
|
self.mark_for_delete = True
|
|
return
|
|
|
|
def on_group_change(self, e):
|
|
self.group_change()
|
|
return
|
|
|
|
def group_change(self):
|
|
mac = self.MAC
|
|
if self.parent.parent.parent.enable_advanced_grouping == False:
|
|
s = self.groupbox.GetStringSelection()
|
|
if s != 'Not Grouped':
|
|
for group_id in one_unit.app.groups.keys():
|
|
if one_unit.app.group_names[group_id] == s:
|
|
s = group_id
|
|
break
|
|
|
|
try:
|
|
one_unit.app.groups[s][mac] = (
|
|
self.parent.parent.parent.peers.units[mac].name, self.parent.parent.parent.peers.units[mac].type, 'Any')
|
|
except:
|
|
print mytime.displayTime() + ' Group consistency check failed'
|
|
else:
|
|
one_unit.app.groupconfig.set(s, 'members', one_unit.app.groups[s])
|
|
for group_id in one_unit.app.groups.keys():
|
|
if group_id == s:
|
|
continue
|
|
try:
|
|
if mac in one_unit.app.groups[group_id].keys():
|
|
del one_unit.app.groups[group_id][mac]
|
|
one_unit.app.groupconfig.set(group_id, 'members', one_unit.app.groups[group_id])
|
|
except:
|
|
print mytime.displayTime() + ' Group consistency check failed'
|
|
|
|
try:
|
|
groupconfigfile = open(os.path.join(one_unit.app.asys_config_path, 'grouping.cfg'), 'wb')
|
|
one_unit.app.groupconfig.write(groupconfigfile)
|
|
groupconfigfile.close()
|
|
except:
|
|
dlgMessage = getString('nsa2')
|
|
dlgTitle = getString('e')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK)
|
|
return
|
|
|
|
return
|
|
|
|
def OnLaunch(self):
|
|
try:
|
|
self.group_type = None
|
|
try:
|
|
if self.group != 'all_units':
|
|
self.group_type = one_unit.app.groupconfig.get(self.group, 'type')
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
return
|
|
else:
|
|
if self.type == 'GroupHeader' and self.group_type in ('Carbon Copy',
|
|
'Advanced',
|
|
'Relative'):
|
|
if self.params['launch_means_expand'] == True:
|
|
self.OnExpand()
|
|
return
|
|
if self.params['show_launch'] == True:
|
|
if self.launch_button.enabled == False:
|
|
print mytime.displayTime() + ' Launch is disabled.'
|
|
return
|
|
if self.pin_verified == False and self.MAC[:4] not in ('DEMO',
|
|
'GRP_',
|
|
'VN::') and self.type == 'Unit':
|
|
self.ask_for_pin = True
|
|
self.verifyPIN()
|
|
self.ask_for_pin = False
|
|
if self.pin_verified == False:
|
|
print mytime.displayTime() + ' PIN dialog cancelled or wrong PIN.'
|
|
return
|
|
if self.type == 'GroupHeader' and self.group != 'all_units':
|
|
for mac in one_unit.getMacList(self.group):
|
|
if (mac not in one_unit.app.pin_verified or one_unit.app.pin_verified[mac] == False) and self.parent.parent.parent.peers.units[mac].link_status in ('available',
|
|
'ready') and mac[:4] not in ('DEMO',
|
|
'GRP_',
|
|
'VN::'):
|
|
wx.MessageBox('PIN not correct for ' + mac + ', launch aborted!', 'Error', wx.OK)
|
|
try:
|
|
self.parent.parent.group_panels['all_units'].line[mac].ask_for_pin = True
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
self.Launch()
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
return
|
|
|
|
def Launch(self, Show=True):
|
|
if mytime.clock() - self.launchTime < 2:
|
|
return
|
|
if one_unit.app.application_stopping == True:
|
|
return
|
|
self.launchTime = mytime.clock()
|
|
if self.type == 'Unit':
|
|
if self.params['show_launch'] == True:
|
|
self.launch_button.SetState('open')
|
|
self.Refresh()
|
|
self.paint()
|
|
mytime.sleep(0.1)
|
|
one_unit.tryYield()
|
|
mytime.sleep(0.1)
|
|
one_unit.tryYield()
|
|
wx.CallAfter(one_unit.executeLaunch, self.MAC)
|
|
if self.parent.parent.replace_network_window == 'yes' and Show == True:
|
|
self.parent.parent.Show(False)
|
|
return
|
|
if self.type == 'GroupHeader':
|
|
if self.params['launch_means_expand'] == True:
|
|
self.OnExpand()
|
|
return
|
|
self.LaunchGroupPanel()
|
|
return
|
|
return
|
|
|
|
def LaunchGroupPanel(self):
|
|
if self.type == 'GroupHeader':
|
|
self.offset = self.parent.parent.getOffset(self.MAC)
|
|
print mytime.displayTime(), 'nww.launch group', self.group_type
|
|
one_unit.app.groupconfig = ConfigParser.ConfigParser()
|
|
if os.path.exists(os.path.join(one_unit.app.asys_config_path, 'grouping.cfg')):
|
|
one_unit.app.groupconfig.read(os.path.join(one_unit.app.asys_config_path, 'grouping.cfg'))
|
|
self.group_type = None
|
|
try:
|
|
if self.group != 'all_units':
|
|
self.group_type = one_unit.app.groupconfig.get(self.group, 'type')
|
|
except:
|
|
pass
|
|
|
|
mac = None
|
|
if self.group == 'all_units':
|
|
return
|
|
if self.group_type == 'Mute':
|
|
return
|
|
mac = leading_mac = one_unit.getLeadingMAC(self.group)
|
|
if leading_mac == None:
|
|
print mytime.displayTime(), 'No members, aborting launch'
|
|
return
|
|
panel = one_unit.app.group_types[self.group_type]
|
|
testKey = mac + '|' + panel
|
|
print mytime.displayTime(), 'ng.olgp.launching with key', testKey
|
|
if testKey in self.parent.parent.children:
|
|
if self.parent.parent.children[testKey] != 'restart':
|
|
self.parent.parent.children[testKey].Show(True)
|
|
self.parent.parent.children[testKey].Raise()
|
|
return
|
|
if True:
|
|
if mac not in self.parent.parent.parent.peers.units.keys():
|
|
unit = one_unit.RemoteUnit()
|
|
unit.name = self.name
|
|
unit.type = self.group_type
|
|
self.parent.parent.parent.supported_unit_ids.append(unit.type)
|
|
unit.MAC = mac
|
|
unit.IP = self.name
|
|
unit.link_status = 'available'
|
|
self.parent.parent.parent.peers.add(unit)
|
|
panel = one_unit.app.group_types[self.group_type]
|
|
IsMvPanel = True
|
|
customTitle = self.name
|
|
print mytime.displayTime() + ' Opening Panel ' + panel + ' for group', self.group
|
|
try:
|
|
self.parent.parent.children[mac].Show(True)
|
|
self.parent.parent.children[mac].Raise()
|
|
except:
|
|
import child_unit
|
|
self.parent.parent.children[mac] = child_unit.Child_frame(self.parent.parent.parent, None, -1, '', IsMvPanel)
|
|
self.parent.parent.children[mac].storeWithKey = testKey
|
|
self.parent.parent.children[mac].init_1(panel, self.offset, mac, True, group=str(self.group), customTitle=customTitle)
|
|
|
|
return
|
|
else:
|
|
return
|
|
|
|
def OnLaunchDoubleClick(self):
|
|
self.OnLaunch()
|
|
return
|
|
|
|
def OnExpand(self):
|
|
if self.expand == False:
|
|
self.expand = True
|
|
if self.params['show_locate'] == True:
|
|
self.locate_button.SetState('on')
|
|
else:
|
|
self.expand = False
|
|
print mytime.displayTime() + ' Compressing', self.name
|
|
if self.params['show_locate'] == True:
|
|
self.locate_button.SetState('default')
|
|
self.Refresh()
|
|
self.paint()
|
|
return
|
|
|
|
def SetLinkStatus(self, standby=0, protect=0, syncing=0, members=0):
|
|
power_state = 'off'
|
|
if self.params['show_power'] == True and (members > 0 or self.type == 'Unit'):
|
|
if self.power_button.enabled == False:
|
|
self.power_button.Enable(True)
|
|
if self.MAC[:4] in ('DEMO', 'GRP_', 'VN::') and self.type == 'Unit':
|
|
self.power_button.SetState('on')
|
|
return
|
|
if self.type == 'GroupHeader':
|
|
if self.link_status == 'available':
|
|
power_state = 'on'
|
|
if standby > 0:
|
|
power_state = 'off'
|
|
if protect > 0:
|
|
power_state = 'fault'
|
|
if syncing > 0:
|
|
power_state = 'syncing'
|
|
elif self.link_status == 'Bootloader':
|
|
power_state = 'bootloader'
|
|
else:
|
|
power_state = 'offline'
|
|
elif self.link_status == 'available':
|
|
power_state = 'on'
|
|
if self.hw_status & protocol.confStandby == protocol.confStandby:
|
|
power_state = 'off'
|
|
if self.hw_status & protocol.confProtect == protocol.confProtect or self.hw_status & protocol.confMemoryTestFailed == protocol.confMemoryTestFailed:
|
|
power_state = 'fault'
|
|
try:
|
|
if self.MAC != '' and (self.parent.parent.parent.server.peers.units[self.MAC].process.conn.full_sync_time == False or self.parent.parent.parent.server.peers.units[self.MAC].process.conn.synced == False):
|
|
power_state = 'syncing'
|
|
except:
|
|
pass
|
|
|
|
elif self.link_status == 'Bootloader':
|
|
power_state = 'bootloader'
|
|
else:
|
|
power_state = 'offline'
|
|
if power_state != self.power_state:
|
|
self.power_button.SetState(power_state)
|
|
self.power_state = power_state
|
|
self.Refresh(False)
|
|
return True
|
|
return False
|
|
self.power_button.Enable(False)
|
|
return
|
|
|
|
def verifyPIN(self):
|
|
peers = self.parent.parent.parent.server.peers
|
|
one_unit.doVerifyPIN(self, peers)
|
|
return
|
|
|
|
def Update(self):
|
|
if mytime.clock() - self.launchTime < 2:
|
|
return
|
|
else:
|
|
if self.GetPosition()[1] + self.parent.GetPosition()[1] > self.parent.parent.GetSize()[1] or not self.IsShownOnScreen():
|
|
try:
|
|
if self.parent.parent.children[self.MAC] != 'restart':
|
|
return
|
|
except:
|
|
return
|
|
|
|
self.changed = False
|
|
if self.type == 'Unit':
|
|
mac = self.MAC
|
|
user = None
|
|
self.current_user = one_unit.getCurrentUser(self.MAC)
|
|
link_status = self.parent.parent.parent.peers.units[mac].link_status
|
|
if self.MAC[:4] in ('DEMO', 'GRP_', 'VN::'):
|
|
link_status = 'available'
|
|
key = data_model.Key(protocol.STRUCT_ID_PRESET_GLOBAL, protocol.MEMBER_ID_CONFIGURATION, 0, 0)
|
|
try:
|
|
conf = int(one_unit.app.server.peers.get(key, self.MAC)) & 16777215
|
|
except:
|
|
conf = 0
|
|
else:
|
|
if conf & protocol.confTwoWay == protocol.confTwoWay:
|
|
self.conf = 'TWO WAY'
|
|
else:
|
|
self.conf = 'STEREO'
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0)
|
|
try:
|
|
hw_status = int(one_unit.app.server.peers.get(key, self.MAC)) & 16777215
|
|
except:
|
|
hw_status = 0
|
|
else:
|
|
self.link_status = link_status
|
|
self.hw_status = hw_status
|
|
if self.SetLinkStatus():
|
|
self.changed = True
|
|
if self.params['show_locate'] == True:
|
|
if mytime.clock() - self.LocateTime < 12:
|
|
on = int(mytime.clock() - self.LocateTime) & 1
|
|
if on:
|
|
self.locate_button.SetState('default')
|
|
else:
|
|
self.locate_button.SetState('on')
|
|
self.changed = True
|
|
elif mytime.clock() - self.LocateTime < 14:
|
|
self.locate_button.SetState('default')
|
|
self.changed = True
|
|
if self.MAC != 'Startup...':
|
|
if self.parent.parent.parent.peers.units[mac].name.strip() != self.name:
|
|
self.name = self.parent.parent.parent.peers.units[mac].name.strip()[:16]
|
|
self.group_change()
|
|
self.changed = True
|
|
if self.MAC[:4] in ('DEMO', 'GRP_', 'VN::'):
|
|
if self.params['show_launch'] == True:
|
|
if self.MAC not in self.parent.parent.children.keys() or self.MAC in self.parent.parent.children.keys() and self.parent.parent.children[self.MAC] == None:
|
|
if self.launch_button.state != 'default':
|
|
self.launch_button.Enable(True)
|
|
self.launch_button.SetState('default')
|
|
else:
|
|
if self.launch_button.state != 'open':
|
|
self.launch_button.Enable(False)
|
|
self.launch_button.SetState('open')
|
|
if self.parent.parent.children[self.MAC] == 'restart':
|
|
if self.MAC[:4] in ('DEMO', 'GRP_', 'VN::'):
|
|
print mytime.displayTime() + ' nww.u1.Restarting', self.MAC
|
|
else:
|
|
print mytime.displayTime() + ' nww.u1.Restarting', self.MAC, '(' + self.parent.parent.parent.peers.units[self.MAC].type + self.model_number + ')'
|
|
one_unit.executeLaunch(self.MAC)
|
|
if self.MAC[:4] not in ('DEMO', 'GRP_', 'VN::'):
|
|
IP = self.parent.parent.parent.peers.units[mac].IP
|
|
if IP == 'Offline':
|
|
self.offline_time = mytime.clock()
|
|
if mytime.clock() - self.connected_time < 5:
|
|
IP = 'Connecting...'
|
|
else:
|
|
self.connected_time = mytime.clock()
|
|
if self.current_user == None and int(mytime.clock()) & 1 == 1:
|
|
inNetwork = False
|
|
for myIP in one_unit.app.my_ip_list:
|
|
if d_ethernet.addressInNetwork(IP, myIP, one_unit.app.subnet_mask_list[myIP]) == True:
|
|
inNetwork = True
|
|
break
|
|
|
|
if inNetwork:
|
|
IP = 'Connecting...'
|
|
else:
|
|
IP = 'Out Of Range'
|
|
if IP != self.IP:
|
|
self.IP = IP
|
|
self.changed = True
|
|
if self.parent.parent.parent.peers.units[mac].link_status != self.link_status or one_unit.app.link_ok == False and self.link_status == 'available':
|
|
self.link_status = self.parent.parent.parent.peers.units[mac].link_status
|
|
if one_unit.app.link_ok == False:
|
|
self.link_status = 'disconnected'
|
|
self.changed = True
|
|
if self.my_group_panel == 'all_units':
|
|
if self.params['show_update'] == True or self.name[:8] == 'Recovery':
|
|
if self.name[:8] == 'Recovery':
|
|
enable_update = True
|
|
else:
|
|
enable_update = self.parent.parent.enable_update
|
|
if self.last_enable_update != enable_update:
|
|
self.last_enable_update = enable_update
|
|
self.changed = True
|
|
self.update_button.Show(self.last_enable_update)
|
|
if self.last_enable_update == True and self.IP != 'Offline' and (self.link_status == 'available' or self.link_status == 'Bootloader') and self.IP[:5] != 'RS485':
|
|
needs_update = True
|
|
model_number = one_unit.app.server.peers.get(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_MODEL_NUMBER, 0, 0), mac)
|
|
last_fw_version = one_unit.app.Version
|
|
last_pic_version = one_unit.app.Version
|
|
try:
|
|
last_pic_version = one_unit.app.pic_version
|
|
except:
|
|
print mytime.displayTime() + ' Default interface version not found'
|
|
|
|
try:
|
|
last_pic_version = one_unit.app.pic_versions[self.parent.parent.parent.peers.units[mac].type]
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
last_fw_version = one_unit.app.fw_version
|
|
except:
|
|
print mytime.displayTime() + ' Default firmware version not found'
|
|
|
|
try:
|
|
last_fw_version = one_unit.app.fw_versions[self.parent.parent.parent.peers.units[mac].type + '_' + str(model_number)]
|
|
except:
|
|
try:
|
|
last_fw_version = one_unit.app.fw_versions[self.parent.parent.parent.peers.units[mac].type]
|
|
except:
|
|
pass
|
|
|
|
if self.parent.parent.parent.peers.units[mac].FWVersion == last_fw_version:
|
|
needs_update = False
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_USER_ACCESS_RIGHTS, 0, 2)
|
|
key2 = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_ACCESS_RIGHTS, 0, 0)
|
|
try:
|
|
if one_unit.app.server.peers.get(key, mac) & protocol.arUpgradeFirmware == protocol.arUpgradeFirmware and one_unit.app.server.peers.get(key2, mac) & protocol.arUpgradeFirmware == 0:
|
|
needs_update = False
|
|
except:
|
|
pass
|
|
|
|
if self.parent.parent.full_update_rights == 'yes':
|
|
needs_update = True
|
|
if self.parent.parent.parent.peers.units[mac].link_type == 'USB' and self.parent.parent.parent.peers.units[mac].type not in one_unit.app.usb_update_supported_list:
|
|
needs_update = False
|
|
if self.name in ('No Name', 'Recovery Mode',
|
|
'Safe Mode'):
|
|
needs_update = True
|
|
if needs_update == True or self.always_enable_update == True or one_unit.app.mijnpc == True:
|
|
self.update_button.Enable(True)
|
|
else:
|
|
self.update_button.Enable(False)
|
|
else:
|
|
self.update_button.Enable(False)
|
|
if self.parent.parent.parent.peers.units[mac].Muted == 'True' and self.power_state != 'off' and self.muted == False:
|
|
self.muted = True
|
|
if self.params['show_mute'] == True:
|
|
self.mute_button.SetState('on')
|
|
if (self.parent.parent.parent.peers.units[mac].Muted == 'False' or self.power_state == 'off') and self.muted == True:
|
|
self.muted = False
|
|
if self.params['show_mute'] == True:
|
|
self.mute_button.SetState('default')
|
|
if self.MAC != 'Startup...':
|
|
if self.MAC in self.parent.parent.children.keys() and self.parent.parent.children[self.MAC] != None:
|
|
if self.params['show_launch'] == True:
|
|
if self.launch_button.state != 'open':
|
|
self.launch_button.Enable(False)
|
|
self.launch_button.SetState('open')
|
|
if self.parent.parent.children[self.MAC] == 'restart':
|
|
one_unit.executeLaunch(self.MAC)
|
|
elif self.params['show_launch'] == True and (self.current_user == None or self.IP == 'Offline' or self.name in ('Recovery Mode',
|
|
'No Name',
|
|
'Safe Mode') or one_unit.app.server.peers.units[self.MAC].process.conn.got_basic_info == False):
|
|
self.launch_button.Enable(False)
|
|
else:
|
|
self.launch_button.Enable(True)
|
|
if mytime.clock() - self.parent.parent.parent.peers.units[self.MAC].discover_time > 3:
|
|
self.verifyPIN()
|
|
elif self.type == 'GroupHeader':
|
|
if self.params['show_launch'] == True:
|
|
mac = 'GRP_' + self.group
|
|
if mac in self.parent.parent.children:
|
|
if self.parent.parent.children[mac] == 'restart':
|
|
self.Launch()
|
|
if mac not in self.parent.parent.children.keys():
|
|
if self.launch_button.state not in ('default', 'on'):
|
|
self.launch_button.Enable(True)
|
|
if self.expand == True:
|
|
self.launch_button.SetState('default')
|
|
else:
|
|
self.launch_button.SetState('on')
|
|
elif self.launch_button.state != 'open':
|
|
self.launch_button.Enable(False)
|
|
self.launch_button.SetState('open')
|
|
link_status = 'available'
|
|
full_hw_status = 0
|
|
if self.group in one_unit.app.groups.keys():
|
|
members = one_unit.getMacList(self.group)
|
|
else:
|
|
all_members = self.parent.parent.parent.peers.units
|
|
members = {}
|
|
for member in all_members.keys():
|
|
if member[:4] not in ('DEMO', 'GRP_', 'VN::') and member != 'Startup...':
|
|
members[member] = all_members[member]
|
|
|
|
members_to_check = len(members)
|
|
number_of_units = 0
|
|
muted = True
|
|
number_muted = 0
|
|
number_standby = 0
|
|
number_protect = 0
|
|
number_syncing = 0
|
|
if self.group != 'all_units':
|
|
if one_unit.app.group_enabled[self.group] != self.group_enabled:
|
|
self.group_enabled = one_unit.app.group_enabled[self.group]
|
|
self.changed = True
|
|
for mac in self.parent.parent.parent.peers.units.keys():
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0)
|
|
try:
|
|
full_hw_status |= int(one_unit.app.server.peers.get(key, mac))
|
|
except:
|
|
pass
|
|
|
|
if self.parent.parent.parent.peers.units[mac].MAC[:4] in ('DEMO',
|
|
'GRP_',
|
|
'VN::'):
|
|
continue
|
|
if self.parent.parent.parent.peers.units[mac].MAC == 'Choose unit....':
|
|
continue
|
|
if mac == 'Startup...':
|
|
if mytime.clock() - one_unit.app.bootloader_last_rx < 1:
|
|
link_status = 'Bootloader'
|
|
continue
|
|
if members_to_check == 0 and self.group != 'all_units':
|
|
break
|
|
if self.group == 'all_units' or mac in members:
|
|
if self.parent.parent.parent.peers.units[mac].link_status != 'available':
|
|
if self.parent.parent.parent.peers.units[mac].link_status in ('disconnected',
|
|
'ready'):
|
|
if link_status in ('available', 'Bootloader', 'ready'):
|
|
link_status = 'disconnected'
|
|
else:
|
|
number_of_units += 1
|
|
if mac != 'Startup...':
|
|
if self.parent.parent.parent.peers.units[mac].Muted == 'False':
|
|
muted = False
|
|
try:
|
|
hw_status = int(one_unit.app.server.peers.get(key, mac)) & 16777215
|
|
except:
|
|
hw_status = 0
|
|
else:
|
|
if hw_status & protocol.confStandby == protocol.confStandby:
|
|
number_standby += 1
|
|
elif self.parent.parent.parent.peers.units[mac].Muted == 'True':
|
|
number_muted += 1
|
|
if hw_status & protocol.confProtect == protocol.confProtect or hw_status & protocol.confMemoryTestFailed == protocol.confMemoryTestFailed:
|
|
number_protect += 1
|
|
try:
|
|
if one_unit.app.server.peers.units[mac].process.conn.full_synced == False:
|
|
number_syncing += 1
|
|
except:
|
|
pass
|
|
|
|
members_to_check -= 1
|
|
|
|
full_hw_status &= 16777215
|
|
self.link_status = link_status
|
|
self.hw_status = full_hw_status
|
|
if self.SetLinkStatus(number_standby, number_protect, number_syncing, len(members)):
|
|
self.changed = True
|
|
if self.group != 'all_units':
|
|
if self.params['expand_name']:
|
|
name = 'Group: ' + one_unit.app.group_names[self.group].decode('utf-8') + ' (' + str(len(one_unit.app.groups[self.group])) + ' units)'
|
|
else:
|
|
name = one_unit.app.group_names[self.group].decode('utf-8')
|
|
else:
|
|
name = 'All Units (' + str(number_of_units) + ' units online)'
|
|
name = name[:28]
|
|
if name != self.name:
|
|
self.name = name
|
|
self.changed = True
|
|
if muted == True and self.muted == False:
|
|
self.muted = True
|
|
if self.params['show_mute'] == True and len(members) > 0:
|
|
self.mute_button.SetState('on')
|
|
if muted == False and self.muted == True:
|
|
self.muted = False
|
|
if self.params['show_mute'] == True:
|
|
self.mute_button.SetState('default')
|
|
number_of_units_string = str(len(members))
|
|
if len(members) != number_of_units:
|
|
number_of_units_string += ' (' + str(len(members) - number_of_units) + ' offline)'
|
|
if self.number_of_units != number_of_units_string:
|
|
self.number_of_units = number_of_units_string
|
|
self.changed = True
|
|
if self.number_muted != number_muted:
|
|
self.number_muted = number_muted
|
|
self.changed = True
|
|
number_off_string = str(number_standby)
|
|
if number_protect > 0:
|
|
number_off_string += ' (' + str(number_protect) + ' in protect state)'
|
|
if self.number_off_string != number_off_string:
|
|
self.number_off_string = number_off_string
|
|
self.changed = True
|
|
if self.changed == True:
|
|
self.paint()
|
|
self.Layout()
|
|
return True
|
|
return False
|
|
|
|
def refresh_vu(self):
|
|
self.paint_vu()
|
|
return
|
|
|
|
def paint_vu(self, dc=None):
|
|
if one_unit.app.application_stopping == True:
|
|
return
|
|
else:
|
|
if self.MAC == None and self.type != 'GroupHeader':
|
|
return
|
|
if self.MAC == 'Startup...':
|
|
return
|
|
if self.MAC[:4] in ('DEMO', 'GRP_', 'VN::'):
|
|
bg = self.params['vu_bg_colour']
|
|
for i in range(0, len(self.vu_pos)):
|
|
(x, y) = self.vu_pos[i]
|
|
(w, h) = self.vu_size[i]
|
|
if bg != None:
|
|
if dc == None:
|
|
dc = wx.MemoryDC(self.display_buffer)
|
|
dc.SetPen(wx.Pen(bg, 1))
|
|
dc.SetBrush(wx.Brush(bg))
|
|
dc.DrawRectangle(x, y, w, h)
|
|
|
|
return
|
|
if self.params['show_VU'] == False:
|
|
return
|
|
if self.type == 'Unit':
|
|
try:
|
|
vu_values = self.parent.parent.vu_list[self.MAC]
|
|
except:
|
|
bg = self.params['vu_bg_colour']
|
|
for i in range(0, len(self.vu_pos)):
|
|
(x, y) = self.vu_pos[i]
|
|
(w, h) = self.vu_size[i]
|
|
if bg != None:
|
|
if dc == None:
|
|
dc = wx.MemoryDC(self.display_buffer)
|
|
dc.SetPen(wx.Pen(bg, 1))
|
|
dc.SetBrush(wx.Brush(bg))
|
|
dc.DrawRectangle(x, y, w, h)
|
|
|
|
return
|
|
|
|
else:
|
|
return
|
|
bg = self.params['vu_bg_colour']
|
|
if dc == None:
|
|
dc = wx.MemoryDC(self.display_buffer)
|
|
painted_vu = False
|
|
for i in range(0, len(self.vu_pos)):
|
|
vu = vu_values[i]
|
|
self.last_vu[i] = vu
|
|
to_draw = 0
|
|
steps = self.vu_steps[i]
|
|
for step in range(len(steps)):
|
|
if vu < steps[step]:
|
|
break
|
|
to_draw += 1
|
|
|
|
if to_draw == self.to_draw[i] and self.repaint_vu == False:
|
|
continue
|
|
painted_vu = True
|
|
self.to_draw[i] = to_draw
|
|
(x, y) = self.vu_pos[i]
|
|
(w, h) = self.vu_size[i]
|
|
(sx, sy) = self.vu_led_size[i]
|
|
(px, py) = self.vu_led_pitch[i]
|
|
colours = self.vu_colours[i]
|
|
if bg != None:
|
|
dc.SetPen(wx.Pen(bg, 1))
|
|
dc.SetBrush(wx.Brush(bg))
|
|
dc.DrawRectangle(x, y, w, h)
|
|
y += h - sy
|
|
if self.link_status == 'available':
|
|
for step in range(to_draw):
|
|
dc.SetPen(wx.Pen(colours[step], 1))
|
|
dc.SetBrush(wx.Brush(colours[step]))
|
|
dc.DrawRectangle(x, y, sx, sy)
|
|
x += px
|
|
y -= py
|
|
|
|
self.repaint_vu = False
|
|
if painted_vu:
|
|
self.RefreshRect(self.rect)
|
|
return
|
|
|
|
def on_paint(self, event):
|
|
dc = wx.BufferedPaintDC(self, self.display_buffer)
|
|
return
|
|
|
|
def paint(self):
|
|
if self.init_finished == False:
|
|
return
|
|
else:
|
|
(w, h) = self.GetSize()
|
|
self.display_buffer = wx.EmptyBitmap(w, h)
|
|
dc = wx.MemoryDC()
|
|
dc.SelectObject(self.display_buffer)
|
|
if self.margin_left_img != None:
|
|
dc.DrawBitmap(self.margin_left_img, 0, 0)
|
|
dc.DrawBitmap(self.bg, self.params['margin_left'], 0)
|
|
if self.margin_right_img != None:
|
|
dc.DrawBitmap(self.margin_right_img, self.params['margin_right_pos'], 0)
|
|
dc.SetTextForeground(self.params['text_colour'])
|
|
dc.SetFont(self.font)
|
|
if self.params['show_mute'] == True:
|
|
dc.DrawBitmap(self.mute_button.img, self.params['mute_button_pos'][0], self.params['mute_button_pos'][1])
|
|
if self.params['show_locate'] == True:
|
|
dc.DrawBitmap(self.locate_button.img, self.params['locate_button_pos'][0], self.params['locate_button_pos'][1])
|
|
if self.type == 'Unit' and self.my_group_panel == 'all_units' and self.params['show_update'] == True:
|
|
if self.update_button.show == True:
|
|
dc.DrawBitmap(self.update_button.img, self.params['update_button_pos'][0], self.params['update_button_pos'][1])
|
|
if self.params['show_power'] == True:
|
|
if self.power_button.show == True:
|
|
dc.DrawBitmap(self.power_button.img, self.params['power_button_pos'][0], self.params['power_button_pos'][1])
|
|
if self.params['show_launch'] == True:
|
|
if self.launch_button.show == True:
|
|
dc.DrawBitmap(self.launch_button.img, self.params['launch_button_pos'][0], self.params['launch_button_pos'][1])
|
|
y = self.params['name_pos'][1]
|
|
if os.name in mac_names:
|
|
y += 3
|
|
if self.type == 'GroupHeader' and self.group != 'all_units':
|
|
dc.DrawBitmap(self.delete_button.img, self.params['delete_button_pos'][0], self.params['delete_button_pos'][1])
|
|
if self.parent.parent.parent.enable_advanced_grouping == True:
|
|
dc.DrawBitmap(self.configure_button.img, self.params['configure_button_pos'][0], self.params['configure_button_pos'][1])
|
|
col = copy.deepcopy(dc.GetTextForeground())
|
|
dc.SetTextForeground(self.params['IP_colour'])
|
|
if self.params['show_group_enabled'] == True:
|
|
if self.group_enabled == True:
|
|
dc.DrawText('Enabled', self.params['name_pos'][0] + self.params['name_size'][0] + 10, y)
|
|
else:
|
|
dc.DrawText('Disabled', self.params['name_pos'][0] + self.params['name_size'][0] + 10, y)
|
|
dc.SetTextForeground(col)
|
|
if self.params['show_name'] == True:
|
|
dc.DrawText(self.name, self.params['name_pos'][0], y)
|
|
y = self.params['MAC_pos'][1]
|
|
if os.name in mac_names:
|
|
y += 3
|
|
if self.type == 'Unit':
|
|
if self.params['show_MAC'] == True:
|
|
dc.DrawText(self.MAC.lower(), self.params['MAC_pos'][0], y)
|
|
y = self.params['IP_pos'][1]
|
|
if os.name in mac_names:
|
|
y += 3
|
|
dc.SetTextForeground(self.params['IP_colour'])
|
|
dc.DrawText(self.IP, self.params['IP_pos'][0], y)
|
|
dc.SetTextForeground(self.params['text_colour_2'])
|
|
if self.params['show_members'] == True:
|
|
dc.DrawText(self.params['show_members_text'] + str(self.number_of_units), self.params['members_pos'][0], self.params['members_pos'][1])
|
|
if self.params['show_quantity_muted'] == True:
|
|
dc.DrawText(str(self.number_muted), self.params['quantity_muted_pos'][0], self.params['quantity_muted_pos'][1])
|
|
if self.params['show_quantity_off'] == True:
|
|
dc.DrawText(self.number_off_string, self.params['quantity_off_pos'][0], self.params['quantity_off_pos'][1])
|
|
dc.SetTextForeground(self.params['text_colour_3'])
|
|
if self.params['show_configuration'] == True:
|
|
dc.DrawText(self.conf, self.params['configuration_pos'][0], self.params['configuration_pos'][1])
|
|
self.repaint_vu = True
|
|
self.paint_vu(dc)
|
|
del dc
|
|
self.changed = False
|
|
self.Refresh(False)
|
|
return
|
|
|
|
|
|
class NetworkWindow(wx.Frame):
|
|
|
|
def __init__(self, parent, id, title, infotext='', bgcolour=(220, 220, 220), fgcolour=(70, 70, 70)):
|
|
size = (548, 1000)
|
|
self.parent = parent
|
|
self.moved = False
|
|
self.painted = False
|
|
self.vu_list = {}
|
|
self.children = {}
|
|
self.__name__ = 'CustomizedNetworkWindow'
|
|
self.windowReference = self.__name__
|
|
self.GroupStart = 0
|
|
self.panel_size = {}
|
|
self.group_panels = {}
|
|
self.initialized = False
|
|
if self.parent.emulate_path != None:
|
|
self.bitmapdir = os.path.normpath(self.parent.emulate_path + 'nww/')
|
|
else:
|
|
self.bitmapdir = os.path.normpath(one_unit.app.cwd + '/nww/')
|
|
self.width = myBitmap(os.path.join(self.bitmapdir, 'Unit_bg.png')).GetSize()[0]
|
|
self.height = 800
|
|
style = wx.MINIMIZE_BOX | wx.DEFAULT_DIALOG_STYLE | wx.CLOSE_BOX
|
|
if os.path.exists(os.path.join(self.bitmapdir, 'network_bg.png')):
|
|
style |= wx.MAXIMIZE_BOX
|
|
self.CanMaximize = True
|
|
else:
|
|
self.CanMaximize = False
|
|
try:
|
|
self.no_border = self.parent.main_config.get('ROOT', no_border)
|
|
except:
|
|
if os.name in mac_names:
|
|
self.no_border = 'no'
|
|
else:
|
|
self.no_border = 'yes'
|
|
|
|
try:
|
|
self.bgcolour = eval(self.parent.main_config.get('ROOT', 'bgcolour'))
|
|
except:
|
|
self.bgcolour = (0, 0, 0)
|
|
|
|
try:
|
|
self.always_enable_update = eval(self.parent.main_config.get('ROOT', 'always_enable_update'))
|
|
except:
|
|
if one_unit.app.mijnpc == True:
|
|
self.always_enable_update = False
|
|
else:
|
|
self.always_enable_update = False
|
|
|
|
if self.no_border == 'yes':
|
|
style = wx.BORDER_NONE
|
|
super(NetworkWindow, self).__init__(parent, wx.ID_ANY, size=size, style=style)
|
|
self.enable_update = False
|
|
self.sending_mail = False
|
|
self.new_group_button_pos = (919, 16)
|
|
self.group_up_button_pos = (903, 223)
|
|
self.group_down_button_pos = (903, 290)
|
|
self.unit_up_button_pos = (903, 403)
|
|
self.unit_down_button_pos = (903, 468)
|
|
self.new_pos = None
|
|
self.do_maximize = False
|
|
self.maximized = False
|
|
self.shown_height = 0
|
|
self.restore = False
|
|
self.type = 'Window'
|
|
try:
|
|
self.columns = int(self.parent.main_config.get('ROOT', 'columns'))
|
|
except:
|
|
self.columns = 1
|
|
|
|
try:
|
|
self.have_bgm = eval(self.parent.main_config.get('ROOT', 'have_bgm'))
|
|
except:
|
|
self.have_bgm = False
|
|
|
|
try:
|
|
self.have_fw_update_all_units = eval(self.parent.main_config.get('ROOT', 'have_fw_update_all_units'))
|
|
except:
|
|
self.have_fw_update_all_units = False
|
|
|
|
self.show_update_in_menu = True
|
|
try:
|
|
self.show_update_in_menu = eval(self.parent.main_config.get('ROOT', 'show_update_in_menu'))
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
self.askForAdminPasswordOnEnableUpdate = eval(self.parent.main_config.get('ROOT', 'askForAdminPasswordOnEnableUpdate'))
|
|
except:
|
|
self.askForAdminPasswordOnEnableUpdate = True
|
|
|
|
try:
|
|
self.full_update_rights = self.parent.main_config.get('ROOT', 'full_update_rights')
|
|
self.enable_update = True
|
|
except:
|
|
self.full_update_rights = 'no'
|
|
|
|
try:
|
|
self.support_virtual_units = eval(one_unit.app.main_config.get('ROOT', 'support_virtual_units'))
|
|
except:
|
|
self.support_virtual_units = True
|
|
|
|
try:
|
|
self.replace_network_window = self.parent.main_config.get('ROOT', 'replace_network_window')
|
|
except:
|
|
self.replace_network_window = 'no'
|
|
|
|
try:
|
|
self.unit_up_down_button = self.parent.main_config.get('ROOT', 'unit_up_down_button')
|
|
except:
|
|
self.unit_up_down_button = 'no'
|
|
|
|
try:
|
|
self.new_group_button = self.parent.main_config.get('ROOT', 'new_group_button')
|
|
except:
|
|
self.new_group_button = 'no'
|
|
|
|
if os.name in mac_names:
|
|
try:
|
|
use_fill_image = eval(self.parent.main_config.get('ROOT', 'use_fill_image'))
|
|
except:
|
|
use_fill_image = False
|
|
|
|
else:
|
|
use_fill_image = False
|
|
self.use_fill_image = use_fill_image
|
|
families = {'FONTFAMILY_DECORATIVE': (wx.FONTFAMILY_DECORATIVE), 'FONTFAMILY_DEFAULT': (wx.FONTFAMILY_DEFAULT),
|
|
'FONTFAMILY_MODERN': (wx.FONTFAMILY_MODERN),
|
|
'FONTFAMILY_ROMAN': (wx.FONTFAMILY_ROMAN),
|
|
'FONTFAMILY_SCRIPT': (wx.FONTFAMILY_SCRIPT),
|
|
'FONTFAMILY_SWISS': (wx.FONTFAMILY_SWISS),
|
|
'FONTFAMILY_TELETYPE': (wx.FONTFAMILY_TELETYPE)}
|
|
weights = {'FONTWEIGHT_BOLD': (wx.FONTWEIGHT_BOLD), 'FONTWEIGHT_LIGHT': (wx.FONTWEIGHT_LIGHT),
|
|
'FONTWEIGHT_NORMAL': (wx.FONTWEIGHT_NORMAL)}
|
|
styles = {'FONTSTYLE_ITALIC': (wx.FONTSTYLE_ITALIC), 'FONTSTYLE_NORMAL': (wx.FONTSTYLE_NORMAL),
|
|
'FONTSTYLE_SLANT': (wx.FONTSTYLE_SLANT)}
|
|
points = 13
|
|
try:
|
|
points = int(self.parent.main_config.get('ROOT', 'network_window_font_points'))
|
|
family = families[self.parent.main_config.get('ROOT', 'network_window_font_family')]
|
|
weight = weights[self.parent.main_config.get('ROOT', 'network_window_font_weight')]
|
|
style = styles[self.parent.main_config.get('ROOT', 'network_window_font_style')]
|
|
except:
|
|
family = wx.FONTFAMILY_SWISS
|
|
weight = wx.FONTWEIGHT_BOLD
|
|
style = wx.FONTSTYLE_NORMAL
|
|
|
|
if os.name not in mac_names:
|
|
points *= 0.8
|
|
points *= 90.0 / one_unit.app.display_dpi
|
|
if os.name not in mac_names and one_unit.app.highDPI == True:
|
|
points /= one_unit.app.displayScale[0]
|
|
self.font = wx.Font(points, family, style, weight)
|
|
self.parent.font = self.font
|
|
one_unit.app.font = self.font
|
|
param_defaults = {'text_colour': (9, 41, 61),
|
|
'text_colour_2': (175, 175, 175),
|
|
'text_colour_3': (52, 200, 255),
|
|
'IP_colour': (9, 41, 61),
|
|
'name_pos': (85, 3),
|
|
'name_size': (130, 14),
|
|
'MAC_pos': (225, 3),
|
|
'IP_pos': (345, 3),
|
|
'mute_button_pos': (3, 3),
|
|
'locate_button_pos': (25, 3),
|
|
'power_button_pos': (47, 3),
|
|
'power_button_indicator_only': False,
|
|
'full_area_locate': False,
|
|
'launch_button_pos': (455, 3),
|
|
'update_button_pos': (477, 3),
|
|
'delete_button_pos': (433, 3),
|
|
'configure_button_pos': (411, 3),
|
|
'vu_pos': (
|
|
(69, 3), (74, 3)),
|
|
'vu_size': (
|
|
(4, 16), (4, 16)),
|
|
'vu_led_size': (
|
|
(4, 3), (4, 3)),
|
|
'vu_led_pitch': (
|
|
(0, 4), (0, 4)),
|
|
'vu_range': (
|
|
(-48, 12), (-48, 12)),
|
|
'vu_slope': None,
|
|
'vu_red': 0,
|
|
'vu_bg_colour': (0, 0, 0),
|
|
'show_MAC': True,
|
|
'show_locate': True,
|
|
'show_group_enabled': True,
|
|
'show_launch': True,
|
|
'show_mute': True,
|
|
'show_power': True,
|
|
'show_VU': True,
|
|
'show_name': True,
|
|
'show_update': True,
|
|
'expand_name': False,
|
|
'show_members': False,
|
|
'show_quantity_muted': False,
|
|
'show_quantity_off': False,
|
|
'members_pos': (0, 0),
|
|
'show_members_text': '',
|
|
'quantity_muted_pos': (0, 0),
|
|
'quantity_off_pos': (0, 0),
|
|
'show_configuration': False,
|
|
'configuration_pos': (0, 0),
|
|
'launch_means_expand': False}
|
|
main_header_params = {}
|
|
group_header_params = {}
|
|
unit_params = {}
|
|
for key in param_defaults.keys():
|
|
try:
|
|
unit_params[key] = eval(self.parent.main_config.get('Network', 'Unit_' + key))
|
|
except:
|
|
unit_params[key] = param_defaults[key]
|
|
|
|
for key in param_defaults.keys():
|
|
try:
|
|
group_header_params[key] = eval(self.parent.main_config.get('Network', 'Header_' + key))
|
|
except:
|
|
group_header_params[key] = unit_params[key]
|
|
|
|
for key in param_defaults.keys():
|
|
try:
|
|
main_header_params[key] = eval(self.parent.main_config.get('Network', 'Main_' + key))
|
|
except:
|
|
main_header_params[key] = group_header_params[key]
|
|
|
|
main_header_params['show_launch'] = False
|
|
self.params = {'Unit': unit_params, 'GroupHeader': group_header_params, 'Main': main_header_params}
|
|
for param_key in self.params.keys():
|
|
param_set = self.params[param_key]
|
|
if 'vu_steps' not in param_set:
|
|
vu_steps = []
|
|
for i in range(len(param_set['vu_pos'])):
|
|
steps = []
|
|
(w, h) = param_set['vu_size'][i]
|
|
(min_val, max_val) = param_set['vu_range'][i]
|
|
(sx, sy) = param_set['vu_led_size'][i]
|
|
(px, py) = param_set['vu_led_pitch'][i]
|
|
w += px - sx
|
|
h += py - sy
|
|
from math import sqrt
|
|
length = sqrt(w * w + h * h)
|
|
size = sqrt(px * px + py * py)
|
|
q = length / size
|
|
step = (max_val - min_val) / (q - 1)
|
|
q = int(round(q))
|
|
for j in range(q):
|
|
steps.append(int(round(min_val + j * step, 0)))
|
|
|
|
vu_steps.append(steps)
|
|
|
|
self.params[param_key]['vu_steps'] = vu_steps
|
|
|
|
for param_key in self.params.keys():
|
|
param_set = self.params[param_key]
|
|
if 'vu_colours' not in param_set:
|
|
vu_colours = []
|
|
for i in range(len(param_set['vu_pos'])):
|
|
colours = []
|
|
steps = self.params[param_key]['vu_steps'][i]
|
|
(min_val, max_val) = param_set['vu_range'][i]
|
|
if param_set['vu_slope'] == None:
|
|
factor = 255.0 / (0 - min_val)
|
|
else:
|
|
factor = param_set['vu_slope']
|
|
red_offset = param_set['vu_red']
|
|
for i in range(len(steps)):
|
|
red = factor * (steps[i] - min_val - red_offset)
|
|
green = 255
|
|
if red > 255:
|
|
green -= red - 255
|
|
red = 255
|
|
if red < 0:
|
|
red = 0
|
|
red = int(round(red, 0))
|
|
if green > 255:
|
|
green = 255
|
|
if green < 0:
|
|
green = 0
|
|
green = int(round(green, 0))
|
|
colours.append((red, green, 0))
|
|
|
|
vu_colours.append(colours)
|
|
|
|
self.params[param_key]['vu_colours'] = vu_colours
|
|
|
|
self.frame_height = wx.SystemSettings.GetMetric(wx.SYS_CAPTION_Y) + wx.SystemSettings.GetMetric(wx.SYS_BORDER_Y) + 5
|
|
self.frame_width = 2 + wx.SystemSettings.GetMetric(wx.SYS_BORDER_X) * 2
|
|
if self.no_border == 'yes':
|
|
self.frame_width = 0
|
|
self.frame_height = 0
|
|
if os.name in mac_names:
|
|
if self.no_border == 'yes':
|
|
self.frame_height = 0
|
|
else:
|
|
self.frame_height = 26
|
|
self.scrollPnl = scrolled.ScrolledPanel(self, -1, style=wx.TAB_TRAVERSAL | wx.BORDER_NONE | wx.TRANSPARENT_WINDOW)
|
|
self.scrollPnlSizer = wx.BoxSizer(wx.VERTICAL)
|
|
self.scrollPnl.parent = self
|
|
self.SetBackgroundColour(self.bgcolour)
|
|
self.scrollPnl.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
|
if os.path.exists(os.path.join(self.bitmapdir, 'network_footer.png')):
|
|
self.footer = myBitmap(os.path.join(self.bitmapdir, 'network_footer.png'))
|
|
else:
|
|
self.footer = None
|
|
self.demo_mode = one_unit.app.demoMode
|
|
self.client_area = wx.Display().GetClientArea()
|
|
self.max_height = self.client_area[3] - 50
|
|
self.start_pos = (self.client_area[0], self.client_area[1])
|
|
self.create_menu()
|
|
self.scrollPnl.SetPosition((0, self.menubar.GetSize()[1]))
|
|
self.group_panels['all_units'] = GroupPanel(self.scrollPnl, self, 'all_units')
|
|
if self.footer != None:
|
|
self.footer_image = NotStaticBitmap(self.scrollPnl, -1, self.footer, pos=wx.DefaultPosition)
|
|
self.footer_image.Bind(wx.EVT_MOTION, self.OnFooterMotion)
|
|
self.footer_image.Bind(wx.EVT_LEFT_DOWN, self.OnFooterLeftDown)
|
|
self.footer_image.Bind(wx.EVT_LEFT_UP, self.OnFooterLeftUp)
|
|
if False:
|
|
self.fill_image = NotStaticBitmap(self.scrollPnl, id=-1, pos=wx.DefaultPosition, size=(800,
|
|
350))
|
|
self.scrollPnlSizer.Add(self.fill_image)
|
|
self.fill_image.Bind(wx.EVT_MOTION, self.OnFillMotion)
|
|
self.fill_image.Bind(wx.EVT_LEFT_DOWN, self.OnFillLeftDown)
|
|
self.fill_image.Bind(wx.EVT_LEFT_UP, self.OnFillLeftUp)
|
|
elif os.name not in mac_names:
|
|
self.SetDoubleBuffered(True)
|
|
self.scrollPnl.SetSizer(self.scrollPnlSizer)
|
|
self.scrollPnl.SetAutoLayout(1)
|
|
self.scrollPnl.SetupScrolling(scroll_x=False, scroll_y=True)
|
|
self.Refresh(False)
|
|
self.Layout()
|
|
self.Centre()
|
|
self.parent = parent
|
|
self.display_buffer = None
|
|
if os.path.exists(os.path.join(self.bitmapdir, 'network_bg.png')):
|
|
self.bg = myBitmap(os.path.join(self.bitmapdir, 'network_bg.png'))
|
|
self.SetSize((self.bg.GetSize()[0], self.bg.GetSize()[1] + 20))
|
|
self.menubar.SetSize((self.bg.GetSize()[0], self.menubar.GetSize()[1]))
|
|
self.scrollPnl.SetSize(self.bg.GetSize())
|
|
self.scrollPnl.SetupScrolling(scroll_x=False, scroll_y=False)
|
|
print mytime.displayTime(), 'nc.Set background bitmap'
|
|
else:
|
|
self.bg = None
|
|
self.menubar.Show(True)
|
|
self.bg_pos = (
|
|
0, self.menubar.GetSize()[1])
|
|
self.changed = True
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
self.SetPosition(self.start_pos)
|
|
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
|
self.response = None
|
|
self.executeClose = False
|
|
self.closing = False
|
|
self.Update()
|
|
if os.name not in mac_names:
|
|
try:
|
|
if os.path.exists(one_unit.app.cwd + '/icon.ico'):
|
|
_icon = wx.Icon(one_unit.app.cwd + '/icon.ico', wx.BITMAP_TYPE_ICO)
|
|
self.SetIcon(_icon)
|
|
except:
|
|
pass
|
|
|
|
self.refresh_timer = wx.Timer(self)
|
|
self.Bind(wx.EVT_TIMER, self.on_refresh_timer, self.refresh_timer)
|
|
self.refresh_timer.Start(2000)
|
|
self.scrollPnl.Bind(wx.EVT_CHILD_FOCUS, do_nothing)
|
|
self.scrollPnl.Bind(wx.EVT_PAINT, self.OnPaintScrollPnl)
|
|
self.Bind(wx.EVT_MOVE, self.on_move)
|
|
self.scrollPnl.Bind(wx.EVT_MOTION, self.OnMotion)
|
|
self.Bind(wx.EVT_SIZE, self.OnSize)
|
|
self.scrollPnl.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.scrollPnl.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick)
|
|
self.scrollPnl.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
|
|
self.currentPoint = [0, 0]
|
|
self.left_down = False
|
|
self.moved_screen = False
|
|
self.menubar.last_size = self.menubar.GetSize()
|
|
self.maximizetime = -3
|
|
self.initialized = True
|
|
self.current_group_in_view = 0
|
|
if os.name not in mac_names:
|
|
if one_unit.app.highDPI == False:
|
|
self.tools.SetLabel(230, getString('nm230a'))
|
|
else:
|
|
self.tools.SetLabel(230, getString('nm230b'))
|
|
if os.name in mac_names:
|
|
self.Show(True)
|
|
self.Raise()
|
|
return
|
|
|
|
def getOffset(self, mac):
|
|
offset_x = self.width + len(self.children) % 10 * self.parent.child_offset_x
|
|
offset_y = len(self.children) % 10 * self.parent.child_offset_y
|
|
while offset_x + 100 > self.client_area[2]:
|
|
step = self.client_area[2] - self.width - 100
|
|
if step <= 0:
|
|
offset_x = 0
|
|
break
|
|
offset_x -= step
|
|
|
|
while offset_y + 100 > self.client_area[3]:
|
|
step = self.client_area[3] - 100
|
|
if step <= 0:
|
|
offset_y = 0
|
|
break
|
|
offset_y -= step
|
|
|
|
if self.replace_network_window == 'yes':
|
|
self.offset = self.GetPosition()
|
|
offset_x = self.offset[0]
|
|
offset_y = self.offset[1]
|
|
if os.name in mac_names:
|
|
offset_y -= 22
|
|
offset = (
|
|
offset_x, offset_y)
|
|
return offset
|
|
|
|
def OnMouseWheel(self, evt):
|
|
delta = -evt.GetWheelRotation()
|
|
if delta == 0:
|
|
return
|
|
self.scrollMe(delta)
|
|
return
|
|
|
|
def scrollMe(self, delta):
|
|
if self.bg != None:
|
|
return
|
|
else:
|
|
return
|
|
if delta > 0:
|
|
self.current_group_in_view += 1
|
|
else:
|
|
self.current_group_in_view -= 1
|
|
if self.current_group_in_view < 0:
|
|
self.current_group_in_view = 0
|
|
if self.current_group_in_view >= len(self.group_panels):
|
|
self.current_group_in_view = len(self.group_panels)
|
|
self.scrollPnl.ScrollChildIntoView(self.group_panels['all_units'])
|
|
else:
|
|
self.scrollPnl.ScrollChildIntoView(self.group_panels[self.sorted_groups[self.current_group_in_view]])
|
|
return
|
|
|
|
def OnFillLeftUp(self, e):
|
|
self.getOrReleaseMouseCapture(False)
|
|
self.OnLeftUp(e)
|
|
return
|
|
|
|
def OnFillLeftDown(self, e):
|
|
self.getOrReleaseMouseCapture(True)
|
|
self.OnLeftDown(e, self.fill_image.GetPosition())
|
|
return
|
|
|
|
def OnFillMotion(self, event):
|
|
self.OnMotion(event, self.fill_image.GetPosition())
|
|
return
|
|
|
|
def OnFooterLeftUp(self, e):
|
|
self.getOrReleaseMouseCapture(False)
|
|
self.OnLeftUp(e)
|
|
return
|
|
|
|
def OnFooterLeftDown(self, e):
|
|
self.getOrReleaseMouseCapture(True)
|
|
self.OnLeftDown(e, self.footer_image.GetPosition())
|
|
return
|
|
|
|
def OnFooterMotion(self, event):
|
|
self.OnMotion(event, self.footer_image.GetPosition())
|
|
return
|
|
|
|
def getOrReleaseMouseCapture(self, capture):
|
|
"""
|
|
Captures the mouse for this class object (which keeps a wxWidgets frame or a compatible
|
|
wxWidgets object). The mouse will only be captured or released if the class object hasCapture
|
|
method returns the correct value.
|
|
|
|
@param self: The class object itself
|
|
@param capture: True or false. True get the mouse capture for this class, false release it
|
|
"""
|
|
if capture and not self.scrollPnl.HasCapture():
|
|
self.scrollPnl.CaptureMouse()
|
|
if not capture and self.scrollPnl.HasCapture():
|
|
self.scrollPnl.ReleaseMouse()
|
|
return
|
|
|
|
def on_move(self, event):
|
|
self.moved = True
|
|
return
|
|
self.changed = True
|
|
self.Refresh(False)
|
|
|
|
def OnSize(self, e):
|
|
if self.initialized == False:
|
|
return
|
|
else:
|
|
client_area = wx.Display().GetClientArea()
|
|
x = client_area[2]
|
|
if self.bg == None:
|
|
width = self.width + self.frame_width
|
|
height = self.height + self.frame_height
|
|
else:
|
|
width = self.bg.GetSize()[0] + self.frame_width
|
|
height = self.bg.GetSize()[1] + self.frame_height
|
|
size = self.GetSize()
|
|
self.scrollPnl.SetPosition(((size[0] - self.scrollPnl.GetSize()[0]) / 2, self.menubar.GetSize()[1]))
|
|
if self.bg:
|
|
self.bg_pos = self.scrollPnl.GetPosition()
|
|
self.changed = True
|
|
self.display_buffer = None
|
|
self.Refresh(False)
|
|
try:
|
|
self.menubar.Refresh()
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
return
|
|
|
|
def Maximize(self, state):
|
|
super(NetworkWindow, self).Maximize(state)
|
|
if state == True:
|
|
print mytime.displayTime() + ' Maximizing'
|
|
self.menubar.last_size = self.menubar.GetSize()
|
|
self.last_bg_pos = self.bg_pos
|
|
client_area = wx.Display().GetClientArea()
|
|
x = client_area[2]
|
|
x -= self.scrollPnl.GetSize()[0]
|
|
x /= 2
|
|
self.menubar.SetSize((client_area[2], self.menubar.GetSize()[1]))
|
|
self.scrollPnl.SetPosition((x, self.menubar.GetSize()[1]))
|
|
self.bg_pos = (x, self.menubar.GetSize()[1])
|
|
self.maximized = True
|
|
self.SetSize((client_area[2], client_area[3]))
|
|
else:
|
|
self.menubar.SetPosition((0, 0))
|
|
self.menubar.SetSize(self.menubar.last_size)
|
|
self.scrollPnl.SetPosition((0, self.menubar.GetSize()[1]))
|
|
self.bg_pos = (0, self.menubar.GetSize()[1])
|
|
self.maximized = False
|
|
self.display_buffer = None
|
|
self.changed = True
|
|
self.Refresh(False)
|
|
return
|
|
|
|
def getEventCoordinates(self, event, offset=(
|
|
0, 0)):
|
|
return (
|
|
event.GetX() + offset[0], event.GetY() + offset[1])
|
|
|
|
def GroupUp(self):
|
|
self.GroupStart -= 1
|
|
if self.GroupStart < 0:
|
|
self.GroupStart = 0
|
|
self.changed = True
|
|
self.Update(True)
|
|
return
|
|
|
|
def GroupDown(self):
|
|
self.GroupStart += 1
|
|
if self.GroupStart > len(one_unit.app.groups):
|
|
self.GroupStart = len(one_unit.app.groups)
|
|
self.changed = True
|
|
self.Update(True)
|
|
return
|
|
|
|
def UnitUp(self):
|
|
self.group_panels['all_units'].UnitDown()
|
|
for group in one_unit.app.groups.keys()[:]:
|
|
self.group_panels[group].UnitDown()
|
|
|
|
self.changed = True
|
|
return
|
|
|
|
def UnitDown(self):
|
|
self.group_panels['all_units'].UnitUp()
|
|
for group in one_unit.app.groups.keys()[:]:
|
|
self.group_panels[group].UnitUp()
|
|
|
|
self.changed = True
|
|
return
|
|
|
|
def OnLeftDblClick(self, event):
|
|
x = event.GetX()
|
|
y = event.GetY()
|
|
if self.new_group_button == 'yes':
|
|
if x > self.new_group_button_pos[0] and x < self.new_group_button_pos[0] + 90 and y > self.new_group_button_pos[1] and y < self.new_group_button_pos[1] + 44:
|
|
self.parent.OnAddGroup(event)
|
|
return
|
|
if self.unit_up_down_button == 'yes':
|
|
if x > self.group_up_button_pos[0] and x < self.group_up_button_pos[0] + 50 and y > self.group_up_button_pos[1] and y < self.group_up_button_pos[1] + 67:
|
|
self.GroupUp()
|
|
return
|
|
if x > self.group_down_button_pos[0] and x < self.group_down_button_pos[0] + 50 and y > self.group_down_button_pos[1] and y < self.group_down_button_pos[1] + 67:
|
|
self.GroupDown()
|
|
return
|
|
if x > self.unit_up_button_pos[0] and x < self.unit_up_button_pos[0] + 50 and y > self.unit_up_button_pos[1] and y < self.unit_up_button_pos[1] + 67:
|
|
self.UnitUp()
|
|
return
|
|
if x > self.unit_down_button_pos[0] and x < self.unit_down_button_pos[0] + 50 and y > self.unit_down_button_pos[1] and y < self.unit_down_button_pos[1] + 67:
|
|
self.UnitDown()
|
|
return
|
|
return
|
|
|
|
def OnLeftDown(self, event, offset=(
|
|
0, 0)):
|
|
x = event.GetX()
|
|
y = event.GetY()
|
|
if self.new_group_button == 'yes':
|
|
if x > self.new_group_button_pos[0] and x < self.new_group_button_pos[0] + 90 and y > self.new_group_button_pos[1] and y < self.new_group_button_pos[1] + 44:
|
|
self.parent.OnAddGroup(event)
|
|
return
|
|
if self.unit_up_down_button == 'yes':
|
|
if x > self.group_up_button_pos[0] and x < self.group_up_button_pos[0] + 50 and y > self.group_up_button_pos[1] and y < self.group_up_button_pos[1] + 67:
|
|
self.GroupUp()
|
|
return
|
|
if x > self.group_down_button_pos[0] and x < self.group_down_button_pos[0] + 50 and y > self.group_down_button_pos[1] and y < self.group_down_button_pos[1] + 67:
|
|
self.GroupDown()
|
|
return
|
|
if x > self.unit_up_button_pos[0] and x < self.unit_up_button_pos[0] + 50 and y > self.unit_up_button_pos[1] and y < self.unit_up_button_pos[1] + 67:
|
|
self.UnitUp()
|
|
return
|
|
if x > self.unit_down_button_pos[0] and x < self.unit_down_button_pos[0] + 50 and y > self.unit_down_button_pos[1] and y < self.unit_down_button_pos[1] + 67:
|
|
self.UnitDown()
|
|
return
|
|
self.left_down = True
|
|
self.currentPoint = self.getEventCoordinates(event, offset)
|
|
return
|
|
|
|
def OnLeftUp(self, event):
|
|
self.getOrReleaseMouseCapture(False)
|
|
self.left_down = False
|
|
if self.moved_screen == True:
|
|
self.moved_screen = False
|
|
self.changed = True
|
|
self.Refresh(False)
|
|
return
|
|
|
|
def OnMotion(self, event, offset=(
|
|
0, 0)):
|
|
point = self.getEventCoordinates(event, offset)
|
|
if event.Dragging() and self.left_down == True and self.IsMaximized() == False:
|
|
screen = self.GetPosition()
|
|
screenpoint = (
|
|
screen[0] + point[0] - self.currentPoint[0], screen[1] + point[1] - self.currentPoint[1])
|
|
self.SetPosition(screenpoint)
|
|
self.moved_screen = True
|
|
return
|
|
|
|
def OnPaintScrollPnl(self, event):
|
|
dc = wx.PaintDC(self.scrollPnl)
|
|
if self.restore == True:
|
|
self.Show(True)
|
|
self.restore = False
|
|
if self.display_buffer == None:
|
|
(w, h) = self.GetSize()
|
|
self.display_buffer = wx.EmptyBitmap(w, h)
|
|
try:
|
|
dc = wx.MemoryDC()
|
|
dc.SelectObject(self.display_buffer)
|
|
except:
|
|
print mytime.displayTime() + ' nww.Buffered Paint DC failed!'
|
|
traceback.print_exc(file=sys.stdout)
|
|
self.display_buffer = None
|
|
dc = wx.PaintDC(self)
|
|
return
|
|
else:
|
|
if self.changed == True:
|
|
self.paint(dc, self.scrollPnl)
|
|
if os.name not in mac_names:
|
|
super(NetworkWindow, self).OnPaint(event)
|
|
self.changed = False
|
|
|
|
return
|
|
|
|
def OnPaint(self, event):
|
|
if self.restore == True:
|
|
self.Show(True)
|
|
self.restore = False
|
|
if self.display_buffer == None:
|
|
(w, h) = self.GetSize()
|
|
self.display_buffer = wx.EmptyBitmap(w, h)
|
|
try:
|
|
dc = wx.MemoryDC()
|
|
dc.SelectObject(self.display_buffer)
|
|
except:
|
|
print mytime.displayTime() + ' nww.Buffered Paint DC failed!'
|
|
traceback.print_exc(file=sys.stdout)
|
|
self.display_buffer = None
|
|
dc = wx.PaintDC(self)
|
|
return
|
|
else:
|
|
if self.changed == True:
|
|
self.paint(dc, self)
|
|
if os.name not in mac_names:
|
|
super(NetworkWindow, self).OnPaint(event)
|
|
self.changed = False
|
|
|
|
return
|
|
|
|
def paint(self, dc, parent):
|
|
if self.bg != None:
|
|
dc.SetBackground(wx.Brush(self.bgcolour))
|
|
dc.Clear()
|
|
dc.DrawBitmap(self.bg, self.bg_pos[0], self.bg_pos[1])
|
|
del dc
|
|
dc = wx.BufferedPaintDC(parent, self.display_buffer)
|
|
return
|
|
|
|
def on_refresh_timer(self, e):
|
|
if self.executeClose:
|
|
self.executeClose = False
|
|
self.close()
|
|
return
|
|
else:
|
|
if self.IsShownOnScreen() == False and self.restore == False:
|
|
self.refresh_timer.Stop()
|
|
self.refresh_timer.Start(100)
|
|
return
|
|
self.refresh_timer.Stop()
|
|
if self.closing == True or one_unit.app.application_stopping == True:
|
|
mytime.sleep(0.01)
|
|
return
|
|
if self.new_pos != None:
|
|
self.SetPosition(self.new_pos)
|
|
self.new_pos = None
|
|
if self.restore == True and one_unit.app.application_stopping == False:
|
|
print mytime.displayTime() + ' nc.restore 1'
|
|
self.changed = True
|
|
self.Show(True)
|
|
self.Refresh(False)
|
|
self.restore = False
|
|
if self.do_maximize == True:
|
|
self.Maximize(True)
|
|
self.do_maximize = False
|
|
self.vu_list = self.parent.remote_link.vu_list
|
|
self.group_panels['all_units'].refresh_vu()
|
|
for panel in self.group_panels.keys():
|
|
self.group_panels[panel].refresh_vu()
|
|
|
|
self.refresh_timer.Start(100)
|
|
return
|
|
|
|
def moveto(self, pos):
|
|
self.new_pos = pos
|
|
return
|
|
|
|
def restore_from_dock(self):
|
|
self.Maximize(False)
|
|
for unit in self.children.values():
|
|
unit.Maximize(False)
|
|
|
|
return
|
|
|
|
def set_restore(self, maximize):
|
|
self.restore = True
|
|
self.do_maximize = maximize
|
|
self.refresh_timer.Start(100)
|
|
print mytime.displayTime() + ' Setting Refresh for network window'
|
|
return
|
|
|
|
def get_sorted_groups(self):
|
|
groups = one_unit.app.groups.keys()
|
|
sorted_groups = []
|
|
group_names = sorted([_[1] for name in one_unit.app.group_names.values()])
|
|
for name in group_names:
|
|
for gr in groups:
|
|
if one_unit.app.group_names[gr] == name:
|
|
sorted_groups.append(gr)
|
|
break
|
|
|
|
for group in groups:
|
|
if group not in sorted_groups:
|
|
sorted_groups.append(group)
|
|
|
|
return sorted_groups
|
|
|
|
def Update(self, force=False):
|
|
if self.new_pos != None:
|
|
self.SetPosition(self.new_pos)
|
|
self.new_pos = None
|
|
if self.restore == True and one_unit.app.application_stopping == False:
|
|
print mytime.displayTime() + ' nc.restore 2'
|
|
self.changed = True
|
|
self.Show(True)
|
|
self.Refresh(False)
|
|
self.restore = False
|
|
if self.closing == True or one_unit.app.application_stopping == True:
|
|
mytime.sleep(0.01)
|
|
return
|
|
else:
|
|
update_panel = force
|
|
last_size = self.GetSize()
|
|
changed = self.group_panels['all_units'].Update()
|
|
sorted_groups = self.get_sorted_groups()
|
|
self.sorted_groups = sorted_groups
|
|
counter = 0
|
|
height = self.group_panels['all_units'].GetSize()[1] + self.menubar.GetSize()[1]
|
|
width = self.group_panels['all_units'].GetSize()[0]
|
|
if self.bg != None:
|
|
width = self.bg.GetSize()[0]
|
|
for group in sorted_groups:
|
|
if one_unit.app.application_stopping == True:
|
|
break
|
|
try:
|
|
if self.group_panels[group].HeaderLine.mark_for_delete == True:
|
|
self.group_panels[group].HeaderLine.mark_for_delete = False
|
|
dlgMessage = getString('dgm')
|
|
dlgTitle = getString('dgt')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
continue
|
|
if len(one_unit.app.groups[group]) != 0:
|
|
dlgMessage = getString('gne')
|
|
dlgTitle = getString('dgt')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
continue
|
|
print mytime.displayTime() + ' Deleting Group', one_unit.app.group_names[group]
|
|
self.group_panels[group].Destroy()
|
|
del self.group_panels[group]
|
|
del one_unit.app.groups[group]
|
|
del one_unit.app.group_names[group]
|
|
del one_unit.app.group_enabled[group]
|
|
del one_unit.app.group_functions[group]
|
|
del one_unit.app.group_type[group]
|
|
del one_unit.app.group_exceptions[group]
|
|
one_unit.app.groupconfig.remove_section(group)
|
|
groupconfigfile = open(os.path.join(one_unit.app.asys_config_path, 'grouping.cfg'), 'wb')
|
|
one_unit.app.groupconfig.write(groupconfigfile)
|
|
groupconfigfile.close()
|
|
changed = True
|
|
update_panel = True
|
|
windowReference = 'Group ' + group
|
|
try:
|
|
self.children[windowReference].shouldBeVisible = False
|
|
self.children[windowReference].destroyWindow()
|
|
except:
|
|
pass
|
|
|
|
elif self.group_panels[group].Update() == True:
|
|
changed = True
|
|
except:
|
|
self.scrollPnlSizer.Detach(self.group_panels['all_units'])
|
|
self.group_panels[group] = GroupPanel(self.scrollPnl, self, group)
|
|
update_panel = True
|
|
changed = True
|
|
|
|
sorted_groups = self.get_sorted_groups()
|
|
for group in one_unit.app.groups.keys()[:]:
|
|
if counter >= self.GroupStart:
|
|
height += self.group_panels[group].GetSize()[1]
|
|
counter += 1
|
|
|
|
if self.footer != None:
|
|
height += self.footer.GetSize()[1]
|
|
if height != self.height:
|
|
changed = True
|
|
self.height = height
|
|
if self.GetTitle() != self.parent.program_title:
|
|
self.SetTitle(self.parent.program_title)
|
|
try:
|
|
if self.menubar.GetTitle() != self.parent.program_title:
|
|
self.menubar.SetTitle(self.parent.program_title)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
if 'all_units' not in self.panel_size or self.group_panels['all_units'].GetSize() != self.panel_size['all_units']:
|
|
update_panel = True
|
|
self.panel_size['all_units'] = self.group_panels['all_units'].GetSize()
|
|
for group in sorted_groups:
|
|
if group not in self.panel_size or self.group_panels[group].GetSize() != self.panel_size[group]:
|
|
update_panel = True
|
|
self.panel_size[group] = self.group_panels[group].GetSize()
|
|
|
|
if changed == True and update_panel == True:
|
|
if False:
|
|
self.scrollPnlSizer.Detach(self.fill_image)
|
|
if self.footer != None:
|
|
self.scrollPnlSizer.Detach(self.footer_image)
|
|
counter = 0
|
|
shown_height = 0
|
|
self.scrollPnlSizer.Detach(self.group_panels['all_units'])
|
|
for group in sorted_groups:
|
|
try:
|
|
self.scrollPnlSizer.Detach(self.group_panels[group])
|
|
if counter >= self.GroupStart:
|
|
self.group_panels[group].Show(True)
|
|
self.scrollPnlSizer.Add(self.group_panels[group])
|
|
shown_height += self.group_panels[group].GetSize()[1]
|
|
else:
|
|
self.group_panels[group].Show(False)
|
|
counter += 1
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
if counter >= self.GroupStart and shown_height + self.group_panels['all_units'].HeaderLine.GetSize()[1] + 50 < self.max_height + 71:
|
|
self.group_panels['all_units'].Show(True)
|
|
self.scrollPnlSizer.Add(self.group_panels['all_units'])
|
|
shown_height += self.group_panels['all_units'].GetSize()[1]
|
|
else:
|
|
self.group_panels['all_units'].Show(False)
|
|
if self.footer != None:
|
|
self.scrollPnlSizer.Add(self.footer_image)
|
|
shown_height += self.footer_image.GetSize()[1]
|
|
if False:
|
|
self.scrollPnlSizer.Add(self.fill_image)
|
|
frame_height = self.frame_height
|
|
self.Freeze()
|
|
if self.bg == None:
|
|
have_scrollbar = False
|
|
height = height + frame_height
|
|
if height > self.client_area[3]:
|
|
have_scrollbar = True
|
|
height = self.client_area[3]
|
|
if height < self.group_panels['all_units'].HeaderLine.GetSize()[1]:
|
|
height = self.group_panels['all_units'].HeaderLine.GetSize()[1]
|
|
if have_scrollbar:
|
|
width += wx.SystemSettings.GetMetric(wx.SYS_HSCROLL_Y)
|
|
self.scrollPnl.SetSize((width, height - self.menubar.GetSize()[1]))
|
|
self.SetSize((width + self.frame_width, height))
|
|
self.width = width
|
|
self.menubar.SetSize((width, self.menubar.GetSize()[1]))
|
|
if self.shown_height != shown_height or self.shown_height != self.scrollPnlSizer.GetSize()[1]:
|
|
self.scrollPnlSizer.Layout()
|
|
self.scrollPnl.FitInside()
|
|
self.scrollPnl.SetPosition((0, self.menubar.GetSize()[1]))
|
|
else:
|
|
self.SetSize((self.bg.GetSize()[0], self.bg.GetSize()[1] + 20))
|
|
self.scrollPnlSizer.Layout()
|
|
self.scrollPnl.FitInside()
|
|
self.changed = True
|
|
self.Refresh(False)
|
|
self.shown_height = shown_height
|
|
self.Thaw()
|
|
return
|
|
|
|
def OnClose(self, e):
|
|
print mytime.displayTime() + ' nc.oc.Closing Network Window'
|
|
self.closing = True
|
|
self.executeClose = True
|
|
one_unit.app.application_stopping = True
|
|
self.Show(False)
|
|
for child in self.children.values():
|
|
try:
|
|
child.Show(False)
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def close(self):
|
|
one_unit.app.application_stopping = True
|
|
print mytime.displayTime(), 'Waiting for all timers to stop'
|
|
one_unit.tryYield()
|
|
loop = 150
|
|
while loop > 0:
|
|
loop -= 1
|
|
mytime.sleep(0.01)
|
|
|
|
loop = 600
|
|
if self.sending_mail == True:
|
|
print mytime.displayTime() + ' Waiting for email process to finish'
|
|
while self.sending_mail == True and loop > 0:
|
|
mytime.sleep(0.1)
|
|
loop -= 1
|
|
|
|
self.parent.Close()
|
|
return
|
|
|
|
def create_menu(self):
|
|
if False:
|
|
self.osxbar = wx.MenuBar()
|
|
osxhelp = wx.Menu()
|
|
osxfile = wx.Menu()
|
|
self.tools = wx.Menu()
|
|
else:
|
|
self.tools = my_menu.my_Menu(self)
|
|
self.menubar = my_menu.my_MenuBar(self)
|
|
file = my_menu.my_Menu(self)
|
|
helpMenu = my_menu.my_Menu(self)
|
|
self.supportProjects = True
|
|
try:
|
|
self.supportProjects = eval(one_unit.app.main_config.get('ROOT', 'support_projects'))
|
|
except:
|
|
pass
|
|
|
|
if self.supportProjects == True:
|
|
file.Append(218, getString('nm218'), 'Create a new project')
|
|
file.Append(219, getString('nm219'), 'Open a project')
|
|
file.Append(220, getString('nm220'), 'Save all Groups as a project')
|
|
file.AppendSeparator()
|
|
file.Append(105, '&' + getString('q') + '\tCtrl+Q', 'Quit the Application')
|
|
if one_unit.app.master_password not in (None, '', 'None'):
|
|
print mytime.displayTime(), 'Currently valid application master password:', one_unit.app.master_password
|
|
self.tools.Append(205, getString('nm205a'), 'Change the Software Password')
|
|
else:
|
|
self.tools.Append(205, getString('nm205b'), 'Set a Software Password')
|
|
try:
|
|
enablePasswordForAllUnits = eval(one_unit.app.main_config.get('ROOT', 'enablePasswordForAllUnits'))
|
|
except:
|
|
enablePasswordForAllUnits = True
|
|
|
|
if enablePasswordForAllUnits:
|
|
self.tools.AppendSeparator()
|
|
self.tools.Append(667, getString('nm667'), 'Enter Password for all units')
|
|
self.tools.AppendSeparator()
|
|
self.tools.Append(207, getString('nm207'), 'Create a new group')
|
|
self.tools.Append(208, getString('nm208'), 'Open a group')
|
|
self.tools.AppendSeparator()
|
|
if one_unit.app.supportLanguages == True:
|
|
self.languageMenu = my_menu.my_Menu(self)
|
|
self.languages = {}
|
|
i = 0
|
|
for language in sorted(one_unit.app.strings.keys()):
|
|
self.languages[i] = language
|
|
radioItem = self.languageMenu.AppendRadioItem(800 + i, getString(language), 'Set language to ' + getString(language))
|
|
self.Bind(wx.EVT_MENU, self.OnLanguage, radioItem)
|
|
i += 1
|
|
|
|
self.tools.AppendMenu(860, 'Language', self.languageMenu)
|
|
for i in self.languages:
|
|
if self.languages[i] == one_unit.app.language:
|
|
self.languageMenu.Check(800 + i, True)
|
|
|
|
self.tools.AppendSeparator()
|
|
if os.name not in mac_names:
|
|
self.tools.Append(230, getString('nm230a'), 'Set High DPI Mode on or off')
|
|
self.tools.Append(209, getString('nm209a'), 'Set Demo Mode on or off')
|
|
if self.show_update_in_menu:
|
|
self.tools.AppendSeparator()
|
|
self.tools.Append(210, getString('nm210a'), 'Set all units to Admin mode and enable the Firmware Update buttons')
|
|
if one_unit.app.showConnectionTest:
|
|
self.tools.AppendSeparator()
|
|
self.tools.Append(212, 'Start Connection Test', 'Run Connection Test')
|
|
if self.have_fw_update_all_units and self.show_update_in_menu:
|
|
self.tools.AppendSeparator()
|
|
self.fw_update_all_item = self.tools.Append(602, getString('nm602'), 'Update the firmware of all units')
|
|
self.Bind(wx.EVT_MENU, self.OnUpdateAll, id=602)
|
|
self.fw_update_all_item.Enable(False)
|
|
if True:
|
|
helpMenu.Append(211, getString('nm211'), 'Request Support')
|
|
helpMenu.AppendSeparator()
|
|
if os.name in mac_names:
|
|
helpMenu.Append(wx.ID_ABOUT, getString('a'), 'Application Information')
|
|
helpMenu.Append(301, getString('a'), 'Application Information')
|
|
self.menubar.Append(file, getString('f'))
|
|
self.menubar.Append(self.tools, getString('t'))
|
|
self.menubar.Append(helpMenu, getString('h'))
|
|
self.Bind(wx.EVT_MENU, self.OnClose, id=105)
|
|
self.Bind(wx.EVT_MENU, self.parent.OnAddGroup, id=207)
|
|
self.Bind(wx.EVT_MENU, self.parent.OnOpenGroup, id=208)
|
|
self.Bind(wx.EVT_MENU, self.OnToggleDemoMode, id=209)
|
|
if os.name not in mac_names:
|
|
self.Bind(wx.EVT_MENU, self.OnToggleDPIMode, id=230)
|
|
self.Bind(wx.EVT_MENU, self.OnNewProject, id=218)
|
|
self.Bind(wx.EVT_MENU, self.OnOpenProject, id=219)
|
|
self.Bind(wx.EVT_MENU, self.OnSaveProject, id=220)
|
|
self.Bind(wx.EVT_MENU, self.parent.OnAbout, id=wx.ID_ABOUT)
|
|
self.Bind(wx.EVT_MENU, self.parent.OnAbout, id=301)
|
|
self.Bind(wx.EVT_MENU, self.parent.OnSetSoftwarePassword, id=205)
|
|
self.Bind(wx.EVT_MENU, self.OnEnableUpdate, id=210)
|
|
self.Bind(wx.EVT_MENU, self.OnSendFeedback, id=211)
|
|
self.Bind(wx.EVT_MENU, self.OnEnterPassword, id=667)
|
|
self.Bind(wx.EVT_MENU, self.OnRunConnectionTest, id=212)
|
|
if self.no_border == 'yes' or os.name in mac_names:
|
|
self.menubar.AppendIcons()
|
|
self.menubar.SetPosition((0, 0))
|
|
self.menubar.SetSize((self.GetSize()[0], 20))
|
|
if False:
|
|
osxfile.Append(105, '&Quit\tCtrl+Q', 'Quit the Application')
|
|
self.osxbar.Append(osxfile, '&File')
|
|
self.osxbar.Append(self.tools, '&Tools')
|
|
osxhelp.Append(211, 'Request Support', 'Request Support')
|
|
osxhelp.AppendSeparator()
|
|
osxhelp.Append(wx.ID_ABOUT, '&About', 'Application Information')
|
|
osxhelp.Append(301, '&About', 'Application Information')
|
|
self.osxbar.Append(osxhelp, '&Help')
|
|
self.SetMenuBar(self.osxbar)
|
|
return
|
|
|
|
def OnEnterPassword(self, e):
|
|
if self.GetPassword() == False:
|
|
return
|
|
self.SetPasswordAllunits(ignore_accessrights=True)
|
|
return
|
|
|
|
def ping(self, ip):
|
|
p = subprocess.Popen([1, 2, 3, 4, 5, ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
res = ''
|
|
while True:
|
|
res = p.stdout.readline() + p.stderr.readline()
|
|
if not res:
|
|
break
|
|
|
|
p.wait()
|
|
resVal = p.returncode
|
|
if resVal == 0:
|
|
uptime = mytime.clock() - self.connectionTestStartTime
|
|
hours = int(uptime / 3600)
|
|
minutes = int((uptime - hours * 3600) / 60)
|
|
seconds = int(uptime - hours * 3600 - minutes * 60)
|
|
txt = mytime.displayTime() + ' Ping to ' + ip + ' OK'
|
|
elif resVal == 1:
|
|
txt = mytime.displayTime() + ' Ping: no response within 1s from ' + ip
|
|
one_unit.app.connectionTestLog.write(txt + newline)
|
|
self.failedPingAttempts += 1
|
|
else:
|
|
txt = mytime.displayTime() + ' ping to ' + ip + ' failed to execute, code: ' + str(resVal)
|
|
print txt
|
|
traceback.print_exc(file=sys.stdout)
|
|
one_unit.app.connectionTestLog.write(txt + newline)
|
|
one_unit.app.connectionTestLog.write(res)
|
|
self.failedPingAttempts += 1
|
|
return
|
|
|
|
def OnRunConnectionTest(self, e):
|
|
if one_unit.app.runConnectionTest == True:
|
|
one_unit.app.runConnectionTest = False
|
|
self.tools.SetLabel(212, 'Start Connection Test')
|
|
self.connectionTestTimer.Destroy()
|
|
print mytime.displayTime(), 'Stopped connection test'
|
|
one_unit.app.connectionTestLog.write(mytime.displayTime() + ' Stopped connection test' + newline)
|
|
one_unit.app.connectionTestLog.close()
|
|
else:
|
|
self.tools.SetLabel(212, 'Stop Connection Test')
|
|
self.connectionTestStartTime = mytime.clock()
|
|
self.failedPingAttempts = 0
|
|
self.connectionTestTimer = wx.Timer(self)
|
|
self.Bind(wx.EVT_TIMER, self.onConnectionTestTimer, self.connectionTestTimer)
|
|
self.connectionTestTimer.Start(1000)
|
|
print mytime.displayTime(), 'Starting connection test'
|
|
if os.name in mac_names:
|
|
desktopPath = os.path.expanduser('~/Desktop')
|
|
else:
|
|
desktopPath = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
|
|
if not os.path.exists(desktopPath + '/ConnectionLogs/'):
|
|
os.mkdir(desktopPath + '/ConnectionLogs/')
|
|
from time import localtime, strftime
|
|
now = strftime('%a_%d_%b_%Y_%H_%M_%S', localtime())
|
|
fName = desktopPath + '/ConnectionLogs/' + now + '.txt'
|
|
one_unit.app.connectionTestLog = open(fName, 'wb')
|
|
one_unit.app.connectionTestLog.write(mytime.displayTime() + ' Starting connection test' + newline)
|
|
print mytime.displayTime(), 'Writing log file to', fName
|
|
one_unit.app.runConnectionTest = True
|
|
return
|
|
|
|
def onConnectionTestTimer(self, e):
|
|
self.connectionTestTimer.Stop()
|
|
if one_unit.app.runConnectionTest == True and os.name not in mac_names:
|
|
for mac in self.parent.peers.units.keys():
|
|
ip = self.parent.peers.units[mac].IP
|
|
if ip.count('.') < 3:
|
|
continue
|
|
self.ping(ip)
|
|
|
|
self.connectionTestTimer.Start(1000)
|
|
return
|
|
|
|
def refreshMenu(self):
|
|
self.SetMenuBar(None)
|
|
self.menubar.Destroy()
|
|
self.menubar = None
|
|
self.create_menu()
|
|
return
|
|
|
|
def OnLanguage(self, e):
|
|
i = e.GetId() - 800
|
|
language = self.languages[i]
|
|
if language not in one_unit.app.strings:
|
|
print mytime.displayTime(), 'ehmmmm.... taal geselecteerd:', language, 'die niet bestaat in onze wereld', one_unit.app.strings.keys()
|
|
return
|
|
print mytime.displayTime(), 'Setting language to', language
|
|
one_unit.app.language = language
|
|
self.refreshMenu()
|
|
for panel in self.children:
|
|
try:
|
|
self.children[panel].refreshMenu()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def OnNewProject(self, e):
|
|
self.clearProject()
|
|
return
|
|
|
|
def clearProject(self):
|
|
if self.support_virtual_units == True:
|
|
dlgMessage = getString('clp1')
|
|
else:
|
|
dlgMessage = getString('clp2')
|
|
dlgTitle = getString('nm218')
|
|
needDelete = False
|
|
for group in self.group_panels.keys():
|
|
if group == 'all_units':
|
|
continue
|
|
needDelete = True
|
|
|
|
for mac in one_unit.app.server.peers.units.keys():
|
|
if mac.startswith('VN::') == True:
|
|
needDelete = True
|
|
|
|
for mac in one_unit.app.main_frame.peers.units.keys():
|
|
if mac.startswith('VN::') == True:
|
|
needDelete = True
|
|
|
|
if needDelete == True:
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
return
|
|
for group in self.group_panels.keys():
|
|
if group == 'all_units':
|
|
continue
|
|
self.group_panels[group].Destroy()
|
|
del self.group_panels[group]
|
|
del one_unit.app.groups[group]
|
|
del one_unit.app.group_names[group]
|
|
del one_unit.app.group_enabled[group]
|
|
del one_unit.app.group_functions[group]
|
|
del one_unit.app.group_type[group]
|
|
del one_unit.app.group_exceptions[group]
|
|
one_unit.app.groupconfig.remove_section(group)
|
|
try:
|
|
self.group_panels[group].HeaderLine.groupConfigPanel.Destroy()
|
|
except:
|
|
pass
|
|
|
|
for mac in one_unit.app.server.peers.units.keys():
|
|
if mac.startswith('VN::') == True:
|
|
del one_unit.app.server.peers.units[mac]
|
|
|
|
for mac in one_unit.app.main_frame.peers.units.keys():
|
|
if mac.startswith('VN::') == True:
|
|
del one_unit.app.main_frame.peers.units[mac]
|
|
|
|
groupconfigfile = open(os.path.join(one_unit.app.asys_config_path, 'grouping.cfg'), 'wb')
|
|
one_unit.app.groupconfig.write(groupconfigfile)
|
|
groupconfigfile.close()
|
|
return
|
|
|
|
def OnOpenProject(self, e):
|
|
projectFileName = None
|
|
wildcard = 'Project File (*.project)|*.project'
|
|
dlg = wx.FileDialog(self, message='Select Project File', wildcard=wildcard, style=wx.OPEN | wx.CHANGE_DIR)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
projectFileName = dlg.GetPath()
|
|
dlg.Destroy()
|
|
if projectFileName == None:
|
|
return
|
|
else:
|
|
self.clearProject()
|
|
one_unit.app.groupconfig.read(projectFileName)
|
|
groupconfigfile = open(os.path.join(one_unit.app.asys_config_path, 'grouping.cfg'), 'wb')
|
|
one_unit.app.groupconfig.write(groupconfigfile)
|
|
groupconfigfile.close()
|
|
one_unit.initGroups()
|
|
one_unit.app.main_frame.addKnownUnits()
|
|
try:
|
|
lastPosition = eval(one_unit.app.groupconfig.get('all_units', 'lastPosition'))
|
|
self.group_panels['all_units'].SetPosition(lastPosition)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
expand = not eval(one_unit.app.groupconfig.get('all_units', 'expand'))
|
|
self.group_panels['all_units'].expand = expand
|
|
self.group_panels['all_units'].HeaderLine.expand = expand
|
|
self.group_panels['all_units'].HeaderLine.OnExpand()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def OnSaveProject(self, e):
|
|
filename = None
|
|
dlg = wx.FileDialog(self, message='Save Project as....', defaultFile='My Project.project', wildcard='Project file (*.project)|*.project', style=wx.SAVE | wx.CHANGE_DIR)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
filename = dlg.GetPath()
|
|
dlg.Destroy()
|
|
if filename != None:
|
|
groupconfigfile = open(filename, 'wb')
|
|
one_unit.app.groupconfig.write(groupconfigfile)
|
|
groupconfigfile.close()
|
|
return
|
|
|
|
def StartUpdate(self, mac):
|
|
try:
|
|
if mytime.clock() - self.lastUpdateTime < 2:
|
|
print mytime.displayTime(), 'ignoring double fw update command'
|
|
return
|
|
except:
|
|
pass
|
|
|
|
self.lastUpdateTime = mytime.clock()
|
|
print mytime.displayTime() + ' Starting update from nww for', mac
|
|
try:
|
|
self.children[mac].updating_from_nww = True
|
|
self.children[mac].executeTask = self.children[mac].StartFirmwareUpdate
|
|
print mytime.displayTime() + ' Sent StartFirmwareUpdate command to child unit for', mac
|
|
except:
|
|
try:
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_MODEL_NUMBER, 0, 0)
|
|
model_number = one_unit.app.server.peers.get(key, mac)
|
|
if model_number == None:
|
|
model_number = ''
|
|
else:
|
|
model_number = '_' + str(int(model_number))
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
model_number = ''
|
|
else:
|
|
print mytime.displayTime() + ' Launching', mac, '(' + self.parent.peers.units[mac].type + model_number + ')'
|
|
import child_unit
|
|
self.children[mac] = child_unit.Child_frame(self.parent, None, -1, '', False)
|
|
self.children[mac].updating_from_nww = True
|
|
self.children[mac].executeTask = self.children[mac].StartFirmwareUpdate
|
|
self.children[mac].init_1(self.parent.peers.units[mac].type + model_number, (0,
|
|
0), mac, False)
|
|
|
|
return
|
|
|
|
def SetPasswordAllunits(self, text='Applying password to all units...', ignore_accessrights=False):
|
|
if one_unit.app.check_password == None:
|
|
return
|
|
else:
|
|
if one_unit.app.check_password.strip() == '':
|
|
return
|
|
print mytime.displayTime() + ' ' + str(text)
|
|
if text is not None:
|
|
self.progress = one_unit.ProgressScreen(self, -1, 'Progress', text)
|
|
self.progress.Show(True)
|
|
self.progress.Update(15)
|
|
mytime.sleep(0.2)
|
|
stupid_repeat = 5
|
|
finished = False
|
|
all_keys = self.parent.peers.units.keys()
|
|
pwkey = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_CHECK_PASSWORD, 0, 0)
|
|
while stupid_repeat < 16 and one_unit.app.application_stopping == False:
|
|
todo = 0
|
|
stupid_repeat += 5
|
|
keys = []
|
|
for mac in all_keys:
|
|
if mac[:4] in ('DEMO', 'GRP_', 'VN::'):
|
|
continue
|
|
if mac.startswith('Startup...'):
|
|
continue
|
|
if mac.strip() == 'b8:96:74:ff:ff:f7' or self.parent.peers.units[mac].name.strip() == 'Recovery Mode':
|
|
print mytime.displayTime(), 'Skipping recovery mode'
|
|
continue
|
|
if self.parent.peers.units[mac].name.strip() == 'No Name':
|
|
print mytime.displayTime(), 'Skipping No Name'
|
|
continue
|
|
todo += 1
|
|
try:
|
|
if ignore_accessrights == False:
|
|
have_ar = int(one_unit.app.server.peers.get(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_ACCESS_RIGHTS, 0, 0), mac)) & protocol.arUpgradeFirmware
|
|
if have_ar == 0:
|
|
self.parent.server.peers.units[mac].process.conn.set_by_key(pwkey, one_unit.app.check_password)
|
|
elif stupid_repeat < 11:
|
|
self.parent.server.peers.units[mac].process.conn.set_by_key(pwkey, one_unit.app.check_password)
|
|
except:
|
|
continue
|
|
|
|
if ignore_accessrights == False:
|
|
if have_ar != 0:
|
|
continue
|
|
keys.append(mac)
|
|
|
|
if len(keys) == 0 or ignore_accessrights == True and finished == True:
|
|
print mytime.displayTime() + ' Finished'
|
|
if text is not None:
|
|
self.progress.Destroy()
|
|
return
|
|
if text is not None:
|
|
update_progress = stupid_repeat * 3
|
|
self.progress.Update(update_progress)
|
|
mytime.sleep(0.5)
|
|
finished = False
|
|
retry = 0
|
|
while finished == False and retry < 20:
|
|
retry += 1
|
|
finished = True
|
|
for mac in keys:
|
|
try:
|
|
if self.parent.server.peers.units[mac].process.conn.synced == False:
|
|
finished = False
|
|
break
|
|
except:
|
|
pass
|
|
|
|
mytime.sleep(0.5)
|
|
|
|
mytime.sleep(0.5)
|
|
|
|
print mytime.displayTime() + ' Not finished, Exiting anyway'
|
|
if text is not None:
|
|
self.progress.Destroy()
|
|
return
|
|
|
|
def PowerOffAndSetPasswordAllunits(self, text='Switching off all units...', verify=True, power_off=True):
|
|
print mytime.displayTime() + ' ' + str(text)
|
|
hwkey = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0)
|
|
if text is not None:
|
|
self.progress = one_unit.ProgressScreen(self, -1, 'Progress', text)
|
|
self.progress.Show(True)
|
|
stupid_repeat = 5
|
|
all_keys = self.parent.peers.units.keys()
|
|
pwkey = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_CHECK_PASSWORD, 0, 0)
|
|
while stupid_repeat < 30:
|
|
if one_unit.app.application_stopping == True:
|
|
return
|
|
stupid_repeat += 5
|
|
keys = []
|
|
for mac in all_keys:
|
|
if mac[:4] in ('DEMO', 'GRP_', 'VN::'):
|
|
continue
|
|
if mac.startswith('Startup...'):
|
|
continue
|
|
if mac.strip() == 'b8:96:74:ff:ff:f7' or self.parent.peers.units[mac].name.strip() == 'Recovery Mode':
|
|
print mytime.displayTime(), 'Skipping recovery mode'
|
|
continue
|
|
self.parent.remote_link.direct_link.set_get_key(hwkey, mac)
|
|
try:
|
|
have_ar = int(one_unit.app.server.peers.get(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_ACCESS_RIGHTS, 0, 0), mac)) & protocol.arUpgradeFirmware
|
|
if have_ar == 0:
|
|
self.parent.server.peers.units[mac].process.conn.set_by_key(pwkey, one_unit.app.check_password)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
hw_status = int(one_unit.app.server.peers.get(hwkey, mac)) & 16777215
|
|
except:
|
|
hw_status = 0
|
|
|
|
if hw_status & protocol.confStandby == protocol.confStandby or power_off == False:
|
|
continue
|
|
keys.append(mac)
|
|
|
|
if len(keys) == 0:
|
|
print mytime.displayTime() + ' Finished'
|
|
if text is not None:
|
|
self.progress.Destroy()
|
|
return
|
|
counter = 1
|
|
for mac in keys:
|
|
counter += 1
|
|
if text is not None:
|
|
self.progress.Update(counter * 90 / len(keys))
|
|
try:
|
|
if power_off == True and stupid_repeat < 16:
|
|
self.parent.server.peers.units[mac].process.conn.set_by_key(data_model.Key(protocol.STRUCT_ID_COMMAND, protocol.MEMBER_ID_COMMAND, 0, protocol.cmdGotoStandby), 1)
|
|
except:
|
|
pass
|
|
|
|
finished = False
|
|
retry = 0
|
|
while finished == False and retry < 20 and verify == True:
|
|
retry += 1
|
|
finished = True
|
|
for mac in keys:
|
|
try:
|
|
if self.parent.server.peers.units[mac].process.conn.synced == False:
|
|
finished = False
|
|
break
|
|
except:
|
|
pass
|
|
|
|
mytime.sleep(0.1)
|
|
|
|
mytime.sleep(0.1)
|
|
if verify == False:
|
|
if text is not None:
|
|
self.progress.Destroy()
|
|
return
|
|
for mac in keys:
|
|
try:
|
|
if power_off == True:
|
|
self.parent.server.peers.units[mac].process.conn.set_by_key(data_model.Key(protocol.STRUCT_ID_COMMAND, protocol.MEMBER_ID_COMMAND, 0, protocol.cmdGotoStandby), 0)
|
|
self.parent.server.peers.units[mac].process.conn.get_list.append(hwkey)
|
|
except:
|
|
pass
|
|
|
|
one_unit.tryYield()
|
|
mytime.sleep(1)
|
|
|
|
print mytime.displayTime() + ' Not finished, Exiting anyway'
|
|
if text is not None:
|
|
self.progress.Destroy()
|
|
loop = 100
|
|
print mytime.displayTime() + ' Start memory test...'
|
|
while loop > 0 and not one_unit.app.application_stopping:
|
|
no_ok = 0
|
|
no_nok = 0
|
|
for mac in keys:
|
|
try:
|
|
self.parent.remote_link.direct_link.set_get_key(hwkey, mac)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
try:
|
|
hw_status = int(one_unit.app.server.peers.get(hwkey, mac)) & 16777215
|
|
except:
|
|
hw_status = 0
|
|
|
|
if hw_status & protocol.confMemoryTestFailed == protocol.confMemoryTestFailed:
|
|
no_nok += 1
|
|
else:
|
|
no_ok += 1
|
|
|
|
print mytime.displayTime() + 'memory test result: ' + str(no_ok) + ' OK, ' + str(no_nok) + ' NOK'
|
|
if no_nok == 0:
|
|
break
|
|
one_unit.tryYield()
|
|
mytime.sleep(1)
|
|
one_unit.tryYield()
|
|
loop -= 1
|
|
|
|
return
|
|
|
|
def GetPassword(self, txt1='Enter Password', txt2='Enter a valid Password. Please note that \nif you backup and restore presets, parameters \nmay be limited by the access level that is \nselected by the password you enter.'):
|
|
dial = wx.PasswordEntryDialog(self, txt2, txt1)
|
|
dial.CentreOnParent()
|
|
if dial.ShowModal() == wx.ID_OK:
|
|
res = dial.GetValue()
|
|
else:
|
|
res = None
|
|
dial.Destroy()
|
|
if res == None:
|
|
return False
|
|
else:
|
|
try:
|
|
res = str(res)
|
|
res = res[:8]
|
|
except:
|
|
res = None
|
|
|
|
one_unit.app.check_password = res
|
|
return True
|
|
|
|
def OnUpdateAll(self, e):
|
|
WAIT_LOOPS = 300
|
|
dlgMessage = 'The firmware of all units will be verified and updated if needed. If you do not have the needed access rights for a unit, the process will fail for that unit. The update process can have multiple steps; please do not power off the unit or disconnect the network until it is finished. Should the process fail, try again. Please make sure to make a backup of your settings before you continue; this process does not automatically restore your settings and presets after the update. Continue?'
|
|
dlgTitle = 'Firmware Update All Units'
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
return
|
|
else:
|
|
update_ok = []
|
|
self.load_dff_started = False
|
|
loop = 0
|
|
break_counter = 0
|
|
to_update = []
|
|
hwkey = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0)
|
|
break_counter = 0
|
|
dial = dialog.Dialog(self, -1, 'Firmware Update', 'Initializing...', Wrap=300, OK_Enable=False)
|
|
dial.Show()
|
|
mytime.sleep(0.2)
|
|
update_started = False
|
|
update_in_progress = []
|
|
wait_counter = 0
|
|
updating_units = 0
|
|
needs_pic_update = False
|
|
one_unit.app.updating_all = True
|
|
while loop < 5 and one_unit.app.application_stopping == False:
|
|
if update_started == False:
|
|
self.PowerOffAndSetPasswordAllunits(None)
|
|
if one_unit.app.application_stopping == True:
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
wait_time = 100
|
|
loop += 1
|
|
keys = self.parent.peers.units.keys()
|
|
to_update = []
|
|
update_in_progress = []
|
|
for key in keys:
|
|
if key[:4] in ('DEMO', 'GRP_', 'VN::'):
|
|
continue
|
|
if key == 'Startup...':
|
|
continue
|
|
if key not in one_unit.app.server.peers.units:
|
|
continue
|
|
try:
|
|
hw_status = int(one_unit.app.server.peers.get(hwkey, key)) & 16777215
|
|
except:
|
|
hw_status = 0
|
|
|
|
if key not in update_ok:
|
|
to_update.append(key)
|
|
if hw_status & protocol.confProtect == protocol.confProtect:
|
|
to_update.append(key)
|
|
if hw_status & protocol.confMemoryTestFailed == protocol.confMemoryTestFailed:
|
|
to_update.append(key)
|
|
|
|
print mytime.displayTime() + ' Checking ' + str(len(to_update)) + ' units'
|
|
if True:
|
|
if len(to_update) > 0:
|
|
txt = 'Checking ' + str(len(to_update)) + ' units'
|
|
else:
|
|
txt = 'All units up to date.'
|
|
loop = 100
|
|
try:
|
|
dial.Update(txt)
|
|
except:
|
|
dial = dialog.Dialog(self, -1, 'Firmware Update', txt, Wrap=300, OK_Enable=False, OK_Only=True)
|
|
dial.Show()
|
|
else:
|
|
start_time = mytime.clock()
|
|
updating_units = 0
|
|
for mac in to_update:
|
|
if mac[:4] not in ('DEMO', 'GRP_', 'VN::'):
|
|
needs_update = True
|
|
needs_pic_update = True
|
|
last_fw_version = one_unit.app.Version
|
|
last_pic_version = one_unit.app.Version
|
|
model_number = one_unit.app.server.peers.get(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_MODEL_NUMBER, 0, 0), mac)
|
|
try:
|
|
last_pic_version = one_unit.app.pic_version
|
|
except:
|
|
print mytime.displayTime() + ' Default interface version not found'
|
|
else:
|
|
try:
|
|
last_pic_version = one_unit.app.pic_versions[self.parent.peers.units[mac].type]
|
|
except:
|
|
pass
|
|
else:
|
|
try:
|
|
last_fw_version = one_unit.app.fw_version
|
|
except:
|
|
print mytime.displayTime() + ' Default firmware version not found'
|
|
else:
|
|
try:
|
|
last_fw_version = one_unit.app.fw_versions[self.parent.peers.units[mac].type + '_' + str(model_number)]
|
|
except:
|
|
pass
|
|
else:
|
|
if True:
|
|
needs_pic_update = False
|
|
else:
|
|
print mytime.displayTime() + ' Interface not up-to-date on', mac, self.parent.peers.units[mac].PICVersion, '->', last_pic_version
|
|
if self.parent.peers.units[mac].FWVersion == last_fw_version:
|
|
needs_update = False
|
|
else:
|
|
print mytime.displayTime() + ' Firmware not up-to-date on', mac, self.parent.peers.units[mac].FWVersion, '->', last_fw_version
|
|
try:
|
|
hw_status = int(one_unit.app.server.peers.get(hwkey, mac)) & 16777215
|
|
except:
|
|
hw_status = 0
|
|
else:
|
|
try:
|
|
if one_unit.app.server.peers.units[mac].process.conn.Connected == False:
|
|
print mytime.displayTime() + ' Connecting...', mac
|
|
needs_update = True
|
|
except:
|
|
print mytime.displayTime() + ' Unit not connected', mac
|
|
needs_update = True
|
|
else:
|
|
if hw_status & protocol.confMemoryTestFailed == protocol.confMemoryTestFailed:
|
|
print mytime.displayTime() + ' Memory test failed on', mac
|
|
needs_update = True
|
|
if needs_update == False and mac not in update_ok:
|
|
update_ok.append(mac)
|
|
print mytime.displayTime() + ' Firmware up-to-date on ', mac
|
|
|
|
for mac in to_update:
|
|
if mac[:4] not in ('DEMO', 'GRP_', 'VN::'):
|
|
if mac in update_ok:
|
|
continue
|
|
if needs_update:
|
|
updating_units += 1
|
|
try:
|
|
self.parent.remote_link.direct_link.set_get_key(hwkey, mac)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
print mytime.displayTime() + ' Could not get hw key for', mac
|
|
|
|
if updating_units == 0:
|
|
break
|
|
dial2 = dialog.Dialog(self, -1, 'Firmware Update', str(updating_units) + ' units will be updated. Continue?', Wrap=300)
|
|
dial2.ShowModal()
|
|
response = dial2.response
|
|
dial2.Destroy()
|
|
if response != 'OK':
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
for mac in to_update:
|
|
if mac[:4] not in ('DEMO', 'GRP_', 'VN::'):
|
|
if mac in update_ok:
|
|
continue
|
|
if needs_update:
|
|
print mytime.displayTime() + ' Starting batch update of ', mac
|
|
one_unit.tryYield()
|
|
one_unit.app.image_filename[mac] = None
|
|
print mytime.displayTime(), 'nc.oua.1'
|
|
self.parent.remote_link.StartMainUpdate(mac, ignore_version=True)
|
|
print mytime.displayTime(), 'nc.oua.2'
|
|
update_in_progress.append(mac)
|
|
mytime.sleep(0.1)
|
|
update_started = True
|
|
try:
|
|
if dial.IsShownOnScreen() == False:
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
|
|
print mytime.displayTime() + ' Firmware Update All Aborted'
|
|
one_unit.app.updating_all = False
|
|
return
|
|
except:
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
|
|
print mytime.displayTime() + ' Firmware Update All Aborted'
|
|
one_unit.app.updating_all = False
|
|
return
|
|
else:
|
|
if one_unit.app.application_stopping == True:
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
else:
|
|
loop = 100
|
|
break
|
|
|
|
wait = 0
|
|
while wait < wait_time and wait_time > 1:
|
|
mytime.sleep(0.01)
|
|
one_unit.tryYield()
|
|
wait += 1
|
|
|
|
try:
|
|
if dial.IsShownOnScreen() == False:
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
|
|
print mytime.displayTime() + ' Firmware Update All Aborted'
|
|
one_unit.app.updating_all = False
|
|
return
|
|
except:
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
|
|
print mytime.displayTime() + ' Firmware Update All Aborted'
|
|
one_unit.app.updating_all = False
|
|
return
|
|
else:
|
|
if update_started == True:
|
|
update_running = False
|
|
update_verified = []
|
|
for mac in update_in_progress:
|
|
if mac in update_verified:
|
|
continue
|
|
my_update_running = False
|
|
try:
|
|
if one_unit.app.bootloader_progress[mac] != None:
|
|
update_running = True
|
|
my_update_running = True
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
if self.parent.peers.units[mac].link_status != 'available':
|
|
update_running = True
|
|
my_update_running = True
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
hw_status = int(one_unit.app.server.peers.get(hwkey, mac)) & 16777215
|
|
except:
|
|
hw_status = 0
|
|
|
|
if hw_status & protocol.confInitRunning == protocol.confInitRunning:
|
|
update_running = True
|
|
my_update_running = True
|
|
if my_update_running == False:
|
|
if hw_status & protocol.confMemoryTestFailed == protocol.confMemoryTestFailed:
|
|
print mytime.displayTime() + ' nc.oua.Memory test failed on', mac
|
|
else:
|
|
update_verified.append(mac)
|
|
continue
|
|
try:
|
|
self.parent.remote_link.direct_link.set_get_key(hwkey, mac)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
if update_running == False and wait_counter < 280:
|
|
wait_time = 1
|
|
if wait_counter > WAIT_LOOPS - 11:
|
|
wait_time = 100
|
|
if wait_time == 100:
|
|
print mytime.displayTime() + ' nc.oua.Update started, waiting...', str(WAIT_LOOPS - wait_counter)
|
|
try:
|
|
dial.Update('Updating ' + str(updating_units) + ' units, time remaining: ' + str(WAIT_LOOPS - wait_counter))
|
|
except:
|
|
break
|
|
else:
|
|
one_unit.tryYield()
|
|
wait_counter += 1
|
|
if wait_counter > WAIT_LOOPS:
|
|
update_started = False
|
|
wait_counter = 0
|
|
continue
|
|
to_update = []
|
|
for key in keys:
|
|
if key == 'Startup...':
|
|
continue
|
|
if key not in update_ok and key[:4] not in ('DEMO', 'GRP_',
|
|
'VN::') and key in one_unit.app.server.peers.units:
|
|
to_update.append(key)
|
|
|
|
if one_unit.app.application_stopping == True:
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
to_update = []
|
|
for key in keys:
|
|
if key == 'Startup...':
|
|
continue
|
|
if key not in update_ok and key[:4] not in ('DEMO', 'GRP_', 'VN::') and key in one_unit.app.server.peers.units:
|
|
to_update.append(key)
|
|
|
|
try:
|
|
dial.Destroy()
|
|
except:
|
|
pass
|
|
|
|
if False:
|
|
txt = 'Please update the interface of each unit to the latest version, and try again.'
|
|
print mytime.displayTime() + ' PIC version not up to date, aborting.'
|
|
dial = dialog.Dialog(self, -1, 'Firmware Update', txt, Wrap=300, OK_Enable=True, OK_Only=True)
|
|
dial.ShowModal()
|
|
dial.Destroy()
|
|
else:
|
|
txt = 'Firmware is up to date on ' + str(len(update_ok)) + ' units:'
|
|
for mac in update_ok:
|
|
txt += ' ' + mac + ','
|
|
|
|
txt = txt[:-1]
|
|
print mytime.displayTime() + ' ' + txt
|
|
if len(to_update) == 0:
|
|
txt = 'All units up to date.'
|
|
else:
|
|
txt = 'Failed to update ' + str(len(to_update)) + ' units:'
|
|
for mac in to_update:
|
|
txt += ' ' + mac + ','
|
|
|
|
txt = txt[:-1]
|
|
txt = txt + '. Please power cycle, make sure you have the needed access rights to update the firmware of each unit, and try again. Only units that were not updated correctly will be updated again.'
|
|
print mytime.displayTime() + ' ' + txt
|
|
dial = dialog.Dialog(self, -1, 'Firmware Update', txt, Wrap=300, OK_Only=True)
|
|
dial.ShowModal()
|
|
dial.Destroy()
|
|
one_unit.app.updating_all = False
|
|
for mac in to_update:
|
|
self.parent.remote_link.direct_link.set_get_key(hwkey, mac)
|
|
print mytime.displayTime() + ' Updating hardware status for', mac
|
|
|
|
for mac in update_ok:
|
|
self.parent.remote_link.direct_link.set_get_key(hwkey, mac)
|
|
print mytime.displayTime() + ' Updating hardware status for', mac
|
|
|
|
return
|
|
|
|
def isOneunitOnline(self):
|
|
for mac in self.parent.peers.units:
|
|
if self.parent.peers.units[mac].name.strip() not in ('No Name', 'Recovery Mode'):
|
|
return True
|
|
|
|
return False
|
|
|
|
def OnEnableUpdate(self, e):
|
|
if self.enable_update == False:
|
|
if self.askForAdminPasswordOnEnableUpdate == True and self.isOneunitOnline() == True:
|
|
if self.GetPassword() == False:
|
|
return
|
|
self.SetPasswordAllunits()
|
|
self.enable_update = True
|
|
self.demo_mode = False
|
|
self.tools.SetLabel(209, getString('nm209a'))
|
|
self.tools.SetLabel(210, getString('nm210b'))
|
|
if self.have_fw_update_all_units:
|
|
self.fw_update_all_item.Enable()
|
|
elif self.askForAdminPasswordOnEnableUpdate == True:
|
|
if self.GetPassword('Enter User Password', 'Enter a valid User Password') == False:
|
|
return
|
|
self.SetPasswordAllunits(ignore_accessrights=True)
|
|
self.enable_update = False
|
|
self.tools.SetLabel(210, getString('nm210a'))
|
|
if self.have_fw_update_all_units:
|
|
self.fw_update_all_item.Enable(False)
|
|
return
|
|
|
|
def OnToggleDemoMode(self, e):
|
|
print mytime.displayTime() + ' toggle demo mode'
|
|
if self.demo_mode == False:
|
|
one_unit.app.check_password = one_unit.app.demo_user_password
|
|
self.demo_mode = True
|
|
self.tools.SetLabel(209, getString('nm209b'))
|
|
self.enable_update = False
|
|
try:
|
|
self.tools.SetLabel(210, getString('nm210a'))
|
|
except:
|
|
pass
|
|
else:
|
|
one_unit.app.enable_vu_demo = True
|
|
else:
|
|
one_unit.app.check_password = ''
|
|
self.demo_mode = False
|
|
try:
|
|
self.tools.SetLabel(209, getString('nm209a'))
|
|
except:
|
|
pass
|
|
|
|
one_unit.app.enable_vu_demo = False
|
|
return
|
|
|
|
def OnToggleDPIMode(self, e):
|
|
print mytime.displayTime() + ' toggle DPI mode'
|
|
if one_unit.app.highDPI == False:
|
|
one_unit.app.highDPI = True
|
|
self.tools.SetLabel(230, getString('nm230b'))
|
|
else:
|
|
one_unit.app.highDPI = False
|
|
self.tools.SetLabel(230, getString('nm230a'))
|
|
dlgMessage = getString('rstm')
|
|
dlgTitle = getString('rstt')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK)
|
|
return
|
|
|
|
def CreateAboutText(self, mac):
|
|
additional_text = ''
|
|
additional_text += '\tName: ' + self.parent.peers.units[mac].name.strip() + newline
|
|
additional_text += '\tSerial Number: ' + self.parent.peers.units[mac].Serial + newline
|
|
additional_text += '\tConnected By: ' + self.parent.peers.units[mac].IP + newline
|
|
try:
|
|
additional_text += '\tConnection Quality: ' + str(one_unit.app.server.peers.units[mac].process.avg_response_time) + newline
|
|
except:
|
|
additional_text += '\tConnection Quality: No Information' + newline
|
|
|
|
additional_text += '\tMAC Address: ' + mac + newline
|
|
ok = ' (Update Available)'
|
|
version = one_unit.app.fw_version
|
|
model_number = one_unit.app.server.peers.get(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_MODEL_NUMBER, 0, 0), mac)
|
|
try:
|
|
version = one_unit.app.fw_versions[self.parent.peers.units[mac].type + '_' + str(model_number)]
|
|
print mytime.displayTime() + ' Unit-specific firmware version:', version
|
|
except:
|
|
pass
|
|
|
|
if version == self.parent.peers.units[mac].FWVersion:
|
|
ok = ' (OK)'
|
|
FWVersion = self.parent.peers.units[mac].FWVersion
|
|
if self.parent.peers.units[mac].BuildNumber > 0:
|
|
FWVersion += '.' + str(self.parent.peers.units[mac].BuildNumber)
|
|
else:
|
|
FWVersion += ' (Unknown Build Number)'
|
|
additional_text += '\tFirmware Version: ' + FWVersion + ok + newline
|
|
ok = ' (Update Available)'
|
|
version = one_unit.app.pic_version
|
|
try:
|
|
version = one_unit.app.pic_versions[self.full_unit_type]
|
|
except:
|
|
pass
|
|
|
|
if version == self.parent.peers.units[mac].PICVersion or self.parent.peers.units[mac].IP[:3] == 'USB':
|
|
ok = ' (OK)'
|
|
additional_text += '\tInterface Version: ' + self.parent.peers.units[mac].PICVersion + ok + newline
|
|
userkey = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_CURRENT_USER, 0, 0)
|
|
additional_text += '\tHardware Version: ' + self.parent.peers.units[mac].HWVersion + newline
|
|
additional_text += '\tProduction Date: ' + self.parent.peers.units[mac].ProductionDate + newline
|
|
try:
|
|
additional_text += '\tFactory Type String: \t' + self.parent.peers.units[mac].originalSwID.split(':')[0] + newline
|
|
additional_text += '\tFirmware Type String: \t' + self.parent.peers.units[mac].originalSwID.split(':')[1] + newline
|
|
additional_text += '\tCustomer Type String: \t' + self.parent.peers.units[mac].type.replace('_', '.') + '.' + str(model_number) + newline
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0)
|
|
val = one_unit.app.server.peers.get(key, mac)
|
|
errortext = newline + 'Error List:' + newline
|
|
if val == None:
|
|
errortext += '\tNo Information'
|
|
else:
|
|
val = int(val)
|
|
if val & 1 == 0:
|
|
errortext += '\tInitialization Not Finished' + newline
|
|
if val & 2 > 0:
|
|
errortext += '\tMemory Test Failed' + newline
|
|
if val & 8 > 0:
|
|
errortext += '\tCODEC Failed' + newline
|
|
if val & 16 > 0:
|
|
errortext += '\tDSP Not Synchronized' + newline
|
|
if val & 32 > 0:
|
|
errortext += '\tHardware Protection State' + newline
|
|
if errortext == newline + 'Error List:' + newline:
|
|
errortext += '\tNo Errors' + newline
|
|
load = (val & 2130706432) >> 24
|
|
errortext += '\tProcessor Load: ' + str(load) + '%' + newline
|
|
additional_text += errortext
|
|
additional_text += newline + one_unit.app.server.peers.units[mac].foundHardwareString
|
|
return additional_text
|
|
|
|
def OnSendFeedback(self, e):
|
|
try:
|
|
externalSupportLink = one_unit.app.main_config.get('ROOT', 'externalSupportLink')
|
|
import webbrowser
|
|
webbrowser.open(externalSupportLink, new=2)
|
|
return
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
dlgMessage = one_unit.app.main_config.get('ROOT', 'support_dialog')
|
|
dlgTitle = 'Request Support'
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK)
|
|
return
|
|
except:
|
|
pass
|
|
|
|
print mytime.displayTime(), 'Creating Support Request...'
|
|
keys = self.parent.peers.units.keys()
|
|
for mac in keys:
|
|
if mac.startswith('DEMO'):
|
|
continue
|
|
print mytime.displayTime() + ' ********************* Unit information for ' + mac + ' ************************'
|
|
print self.CreateAboutText(mac)
|
|
|
|
product = ''
|
|
while len(product) < 3:
|
|
box1 = wx.TextEntryDialog(None, 'About which product do you have a question?', 'Request Support', '')
|
|
if box1.ShowModal() == wx.ID_OK:
|
|
product = box1.GetValue()
|
|
box1.Destroy()
|
|
else:
|
|
box1.Destroy()
|
|
print mytime.displayTime() + ' Cancelled'
|
|
return
|
|
|
|
comment = ''
|
|
while len(comment) < 50:
|
|
box1 = MultiTextEntryDialog(None, 'Request Support', 'Please enter your question here. To help us help you, some' + newline + 'information about your system and used products will be attached. ' + newline + 'No personal information will be sent.' + newline + 'Please describe your request with at least 50 characters.')
|
|
box1.SetValue(comment)
|
|
box1.CenterOnScreen()
|
|
if box1.ShowModal() == wx.ID_OK:
|
|
box1.Destroy()
|
|
comment = box1.GetValue()
|
|
if len(comment) < 50:
|
|
wx.MessageBox('Please describe your request with at least 50 characters.', 'Error', wx.OK)
|
|
else:
|
|
box1.Destroy()
|
|
print mytime.displayTime() + ' Cancelled'
|
|
return
|
|
|
|
sendername = ''
|
|
while len(sendername) < 2:
|
|
box1 = wx.TextEntryDialog(None, 'Please enter your name.', 'Request Support', '')
|
|
if box1.ShowModal() == wx.ID_OK:
|
|
box1.Destroy()
|
|
sendername = box1.GetValue()
|
|
else:
|
|
box1.Destroy()
|
|
print mytime.displayTime() + ' Cancelled'
|
|
return
|
|
|
|
senderemail = 'No email provided'
|
|
while senderemail.find('@') < 0 or senderemail.find('.') < 0:
|
|
box1 = wx.TextEntryDialog(None, 'Please enter your email. This email address will be used to contact you.', 'Request Support', '')
|
|
if box1.ShowModal() == wx.ID_OK:
|
|
senderemail = box1.GetValue()
|
|
box1.Destroy()
|
|
else:
|
|
box1.Destroy()
|
|
print mytime.displayTime() + ' Cancelled'
|
|
return
|
|
|
|
outer = MIMEMultipart()
|
|
name = one_unit.app.name
|
|
try:
|
|
name = one_unit.app.main_config.get('ROOT', 'support_from')
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
sendto = one_unit.app.main_config.get('ROOT', 'support_email')
|
|
except:
|
|
sendto = 'sw_support@alldsp.com'
|
|
|
|
if one_unit.app.mijnpc == True:
|
|
sendto = 'sw_support@alldsp.com'
|
|
outer['Subject'] = 'Support request from ' + name + ' user'
|
|
outer['To'] = sendto
|
|
outer['From'] = senderemail
|
|
outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'
|
|
msg = MIMEText('Message from: ' + sendername.encode('utf-8') + newline + newline)
|
|
outer.attach(msg)
|
|
msg = MIMEText('About: ' + product.encode('utf-8') + newline + newline + comment.encode('utf-8') + newline + newline)
|
|
outer.attach(msg)
|
|
try:
|
|
fp = open(one_unit.app.logfilename, 'rb')
|
|
msg = fp.read()
|
|
fp.close()
|
|
try:
|
|
msg = base64.b64decode(msg)
|
|
except:
|
|
print mytime.displayTime(), 'Error: Could not decode last log file.'
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
msg = base64.b64encode(msg)
|
|
self.log_1 = msg
|
|
msg = MIMEText(msg)
|
|
msg.add_header('Content-Disposition', 'attachment', filename='Last Log from ' + sendername.encode('utf-8') + '.dfl')
|
|
outer.attach(msg)
|
|
except:
|
|
print mytime.displayTime(), 'Error: Could not read last log file.'
|
|
self.log_1 = base64.b64encode('Could not read last log file.')
|
|
|
|
try:
|
|
if one_unit.app.mijnpc == False:
|
|
string = one_unit.app.logfile.getvalue()
|
|
else:
|
|
lines = os.popen('pwd').readlines()
|
|
string = 'Current log from my PC' + newline
|
|
for line in lines:
|
|
string += line + newline
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
string = 'Could not read current log!'
|
|
|
|
msg = base64.b64encode(string)
|
|
self.log_2 = msg
|
|
msg = MIMEText(msg)
|
|
msg.add_header('Content-Disposition', 'attachment', filename='Current Log from ' + sendername.encode('utf-8') + '.dfl')
|
|
outer.attach(msg)
|
|
self.outer = outer
|
|
self.sender = sendername
|
|
if True:
|
|
wx.MessageBox('Please save the support request as a zip file and email it to your support contact.', 'Support Request', wx.OK)
|
|
dlg = wx.FileDialog(self, message='Save Request as....', defaultDir=one_unit.app.library_path, defaultFile='Support Request.zip', wildcard='Zipped container (*.zip)|*.zip', style=wx.SAVE | wx.CHANGE_DIR)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
filename = dlg.GetPath()
|
|
zfile = zipfile.ZipFile(filename, 'w')
|
|
zfile.writestr('Last.dfl', self.log_1)
|
|
zfile.writestr('Current.dfl', self.log_2)
|
|
zfile.writestr('info.txt', self.outer.as_string())
|
|
zfile.close()
|
|
dlg.Destroy()
|
|
self.sending_mail = False
|
|
return
|
|
|
|
|
|
|
|
# okay decompiling pycode/network_customized.pyc
|