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>
4320 lines
195 KiB
Python
4320 lines
195 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_graphical.pyc
|
|
# Compiled at: 2025-05-20 14:45:18
|
|
if __name__ == '__main__':
|
|
import main
|
|
main.run()
|
|
import wx, wx.lib.scrolledpanel, os, data_model, traceback, one_unit, subprocess, mytime, ConfigParser, main, base64
|
|
from subprocess import Popen, PIPE
|
|
import protocol, select_keys, configure_group, d_ethernet, mytime, math, string, future, smtplib, inspect, sys, my_menu, copy, zipfile, socket, struct
|
|
from email.mime.multipart import MIMEMultipart
|
|
from email.mime.text import MIMEText
|
|
definedConfirmUpdate = True
|
|
email_server = 'smtp.strato.de'
|
|
email_user = 'swsw@alldsp.com'
|
|
email_password = 'h8d-6fe-hza-Snn'
|
|
mac_names = 'posix'
|
|
confirm_update = True
|
|
|
|
def getString(strID):
|
|
return one_unit.getString(strID)
|
|
|
|
|
|
if os.name in mac_names:
|
|
newline = '\n'
|
|
else:
|
|
newline = '\r\n'
|
|
|
|
def do_nothing(e):
|
|
return
|
|
|
|
|
|
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.img_lib = {}
|
|
self.executing = False
|
|
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()
|
|
self.parent.executedTask = True
|
|
self.parent.parent.executedTask = True
|
|
except:
|
|
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.group = group
|
|
self.in_vu = None
|
|
self.params = self.parent.params
|
|
self.UnitStart = 0
|
|
self.executedTask = False
|
|
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.columns = self.parent.columns
|
|
self.width = 0
|
|
try:
|
|
self.checkOffset = (float(self.group) + 1.0) / 1.0
|
|
except:
|
|
self.checkOffset = 0
|
|
|
|
self.lastCheckTime = self.checkOffset
|
|
self.lastNumberOfUnits = 0
|
|
self.height = 0
|
|
self.do_redraw = False
|
|
self.row = 0
|
|
self.lastMove = mytime.clock()
|
|
self.header_height = 0
|
|
self.mouseDownPosition = None
|
|
self.movedMyself = False
|
|
self.clients = 0
|
|
self.header = None
|
|
self.SetBackgroundColour('#ffffff')
|
|
if self.group != 'all_units':
|
|
self.type = 'GroupHeader'
|
|
img = os.path.join(self.bitmapdir, 'GroupHeader_header.png')
|
|
if os.path.exists(img) == False:
|
|
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
|
|
else:
|
|
self.type = 'Main'
|
|
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.header.Bind(wx.EVT_MOTION, self.OnMotion)
|
|
self.header.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.header.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
|
|
self.HeaderLine = UnitLine(self, self, -1, '', Type='GroupHeader', Group=self.group)
|
|
self.HeaderLine.SetPosition((0, self.height))
|
|
self.expand = self.HeaderLine.expand
|
|
(w, h) = self.HeaderLine.GetSize()
|
|
if self.width < w:
|
|
self.width = w
|
|
self.height += h
|
|
self.lineHeight = h
|
|
if self.group == 'all_units':
|
|
if os.path.exists(os.path.join(self.bitmapdir, 'MainHeader_separator.png')):
|
|
separator = myBitmap(os.path.join(self.bitmapdir, 'MainHeader_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
|
|
elif 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.header_height = self.height
|
|
self.scrollPanel = wx.lib.scrolledpanel.ScrolledPanel(self, -1, size=(self.width, 0), pos=(0, self.height), style=wx.VSCROLL | wx.NO_BORDER)
|
|
self.scrollPanel.SetupScrolling()
|
|
self.scrollPanel.SetAutoLayout(1)
|
|
self.scrollPanel.SetBackgroundColour('#abcdef')
|
|
self.scrollPanelSizer = wx.BoxSizer(wx.VERTICAL)
|
|
self.scrollPanel.SetSizer(self.scrollPanelSizer)
|
|
self.line = {}
|
|
self.stored_line = {}
|
|
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 + 20, 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)
|
|
try:
|
|
lastPosition = eval(one_unit.app.groupconfig.get(self.group, 'lastPosition'))
|
|
except:
|
|
if self.group == 'all_units':
|
|
if os.name in mac_names:
|
|
lastPosition = (0, 0)
|
|
else:
|
|
lastPosition = (0, 20)
|
|
else:
|
|
pos = self.parent.group_panels['all_units'].GetPosition()
|
|
size = self.parent.group_panels['all_units'].GetSize()
|
|
lastPosition = (pos[0] + size[0], pos[1])
|
|
print mytime.displayTime(), 'ng.pos', lastPosition, self.parent.GetSize()
|
|
if lastPosition[0] > self.parent.GetSize()[0] - self.width:
|
|
lastPosition = (
|
|
pos[0] - self.width, lastPosition[1])
|
|
self.Raise()
|
|
|
|
print mytime.displayTime(), 'ng.GP.Setting initial position for group', self.group, 'to', lastPosition
|
|
self.SetPosition(lastPosition)
|
|
self.verifyAndResizeParent()
|
|
try:
|
|
self.expand = not eval(one_unit.app.groupconfig.get(self.group, 'expand'))
|
|
except:
|
|
self.expand = False
|
|
|
|
self.HeaderLine.expand = self.expand
|
|
self.HeaderLine.OnExpand()
|
|
self.emptyHeight = self.height
|
|
self.maxHeight = self.params['GroupHeader']['max_height']
|
|
myPos = self.GetPosition()
|
|
print mytime.displayTime(), 'ng.positie van panel is', myPos
|
|
posVerified = False
|
|
while posVerified == False:
|
|
posVerified = True
|
|
for group in self.parent.group_panels:
|
|
try:
|
|
pos = self.parent.group_panels[group].GetPosition()
|
|
if pos == myPos:
|
|
height = self.parent.group_panels[group].emptyHeight
|
|
myPos = (pos[0], pos[1] + height)
|
|
self.SetPosition(myPos)
|
|
print mytime.displayTime(), 'ng.positie van panel aangepast naar', myPos
|
|
posVerified = False
|
|
break
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
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.getOrReleaseMouseCapture(True)
|
|
self.mouseDownPosition = e.GetPositionTuple()
|
|
self.Raise()
|
|
self.movedMyself = False
|
|
return
|
|
|
|
def OnMotion(self, e):
|
|
if mytime.clock() - self.lastMove < 0.03:
|
|
return
|
|
else:
|
|
if self.mouseDownPosition != None:
|
|
(x, y) = self.GetPosition()
|
|
(mouseX, mouseY) = e.GetPositionTuple()
|
|
dx = mouseX - self.mouseDownPosition[0]
|
|
dy = mouseY - self.mouseDownPosition[1]
|
|
x += dx
|
|
y += dy
|
|
if x < 0:
|
|
x = 0
|
|
if y < 0:
|
|
y = 0
|
|
self.SetPosition((x, y))
|
|
self.lastMove = mytime.clock()
|
|
self.movedMyself = True
|
|
self.verifyAndResizeParent()
|
|
self.scrollVirtualPanel()
|
|
return
|
|
|
|
def scrollVirtualPanel(self):
|
|
(scrollToX, scrollToY) = self.parent.scrollPanel.GetViewStart()
|
|
doScroll = False
|
|
if self.GetPosition()[0] < scrollToX:
|
|
scrollToX = self.GetPosition()[0]
|
|
doScroll = True
|
|
if self.GetPosition()[1] < scrollToY:
|
|
scrollToY = self.GetPosition()[1]
|
|
doScroll = True
|
|
if self.GetPosition()[0] + self.GetSize()[0] - self.parent.scrollPanel.GetSize()[0] + self.parent.moveGroupPanelLimitX > scrollToX:
|
|
scrollToX = self.GetPosition()[0] + self.GetSize()[0] - self.parent.scrollPanel.GetSize()[0] + self.parent.moveGroupPanelLimitX
|
|
doScroll = True
|
|
if self.GetPosition()[1] + self.GetSize()[1] - self.parent.scrollPanel.GetSize()[1] + self.parent.moveGroupPanelLimitY > scrollToY:
|
|
scrollToY = self.GetPosition()[1] + self.GetSize()[1] - self.parent.scrollPanel.GetSize()[1] + self.parent.moveGroupPanelLimitY
|
|
doScroll = True
|
|
if doScroll == True:
|
|
if scrollToX < 0:
|
|
scrollToX = 0
|
|
if scrollToY < 0:
|
|
scrollToY = 0
|
|
self.parent.scrollPanel.Scroll(scrollToX, scrollToY)
|
|
return
|
|
|
|
def verifyAndResizeParent(self):
|
|
if self.GetPosition()[0] + self.GetSize()[0] > self.parent.maxVirtualSizeX:
|
|
self.SetPosition((self.parent.maxVirtualSizeX - self.GetSize()[0], self.GetPosition()[1]))
|
|
if self.GetPosition()[1] + self.GetSize()[1] > self.parent.maxVirtualSizeY:
|
|
self.SetPosition((self.GetPosition()[0], self.parent.maxVirtualSizeY - self.GetSize()[1]))
|
|
doResize = False
|
|
if self.GetPosition()[0] + self.GetSize()[0] + self.parent.scrollBarSizeX > self.parent.virtualPanelSize[0]:
|
|
self.parent.virtualPanelSize = (
|
|
self.GetPosition()[0] + self.GetSize()[0] + self.parent.scrollBarSizeX, self.parent.virtualPanelSize[1])
|
|
doResize = True
|
|
if self.GetPosition()[1] + self.GetSize()[1] + self.parent.scrollBarSizeY > self.parent.virtualPanelSize[1]:
|
|
self.parent.virtualPanelSize = (self.parent.virtualPanelSize[0], self.GetPosition()[1] + self.GetSize()[1] + self.parent.scrollBarSizeY)
|
|
doResize = True
|
|
if doResize:
|
|
self.parent.autoSizePanels()
|
|
return
|
|
|
|
def OnLeftUp(self, event):
|
|
self.getOrReleaseMouseCapture(False)
|
|
self.lastMove = 0
|
|
self.OnMotion(event)
|
|
if self.movedMyself == True:
|
|
self.verifyAndResizeParent()
|
|
self.movedMyself = False
|
|
self.mouseDownPosition = None
|
|
if self.executedTask == False:
|
|
print mytime.displayTime(), 'ng.olu.hiding children'
|
|
one_unit.hideChildren()
|
|
self.executedTask = False
|
|
return
|
|
|
|
def Update(self):
|
|
yPos = self.scrollPanel.GetScrollPos(wx.VERTICAL)
|
|
self.HeaderLine.Update()
|
|
changed = False
|
|
if self.HeaderLine.expand == True:
|
|
self.lastCheckTime = mytime.clock() + self.checkOffset
|
|
self.lastNumberOfUnits = len(self.parent.parent.peers.units)
|
|
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 mac not in members and self.group != 'all_units' or self.parent.parent.peers.units[mac].MAC[:4] in ('DEMO',
|
|
'GRP_') 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.clients = 0
|
|
for mac in self.line.keys():
|
|
if mac not in keys or mac == 'Startup...' and mytime.clock() - one_unit.app.bootloader_last_rx > 5:
|
|
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.line[mac].Destroy()
|
|
del self.line[mac]
|
|
changed = True
|
|
|
|
if len(self.line) != len(keys):
|
|
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
|
|
unitsAdded = 0
|
|
for mac in keys:
|
|
if unitsAdded > 10:
|
|
break
|
|
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.line[mac].GetSize()[1] * self.clients
|
|
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.row += 1
|
|
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:
|
|
try:
|
|
text = str(mytime.clock()) + ' ng.u0a.Adding ' + mac + ': ' + self.parent.parent.peers.units[mac].name.strip() + ' to group panel ' + one_unit.app.group_names[self.group]
|
|
print text
|
|
except:
|
|
print mytime.displayTime() + ' ng.u0b.Adding ' + mac + ':', self.parent.parent.peers.units[mac].name.strip(), 'to group panel', self.group
|
|
else:
|
|
try:
|
|
self.line[mac] = UnitLine(self.scrollPanel, self, -1, mac, Group=self.group)
|
|
unitsAdded += 1
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
else:
|
|
y = self.line[mac].GetSize()[1] * self.clients
|
|
x = 0
|
|
(w, h) = self.line[mac].GetSize()
|
|
self.lineHeight = h
|
|
if w > self.width:
|
|
self.width = w
|
|
self.clients += 1
|
|
self.row += 1
|
|
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
|
|
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
|
|
else:
|
|
self.footer = None
|
|
changed = True
|
|
|
|
try:
|
|
for mac in self.stored_line.keys():
|
|
if mac not in self.line.keys():
|
|
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
|
|
print mytime.displayTime() + ' Deleted unit', mac, self.clients, 'set height to', self.height
|
|
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:
|
|
lineHeight = self.clients * self.lineHeight
|
|
w = self.width
|
|
if self.emptyHeight + lineHeight > self.maxHeight:
|
|
lineHeight = self.maxHeight - self.emptyHeight
|
|
if os.name in mac_names:
|
|
w += 15
|
|
else:
|
|
w += 18
|
|
for mac in self.line:
|
|
self.scrollPanelSizer.Detach(self.line[mac])
|
|
|
|
sorted_keys = sorted([_[2] for mac in self.line], key=(lambda mac: self.parent.parent.peers.units[mac].name.strip().lower()))
|
|
for mac in sorted_keys:
|
|
self.scrollPanelSizer.Add(self.line[mac], border=0)
|
|
|
|
if self.expand == False and self.params[self.type]['minimized_size'] != None:
|
|
size = self.params[self.type]['minimized_size']
|
|
else:
|
|
size = (
|
|
w + 18, self.emptyHeight + lineHeight)
|
|
self.SetSize(size)
|
|
self.scrollPanel.SetSize((w + 18, lineHeight + 1))
|
|
self.scrollPanel.Layout()
|
|
self.scrollPanel.SetSize((w + 1, lineHeight + 1))
|
|
if self.expand == False and self.params[self.type]['minimized_size'] != None:
|
|
size = self.params[self.type]['minimized_size']
|
|
else:
|
|
size = (
|
|
w, self.emptyHeight + lineHeight)
|
|
self.SetSize(size)
|
|
self.last_change_time = mytime.clock()
|
|
self.HeaderLine.changed = True
|
|
self.Refresh(False)
|
|
self.Layout()
|
|
self.scrollPanel.SetScrollPos(wx.VERTICAL, yPos, True)
|
|
if self.do_redraw == True:
|
|
self.do_redraw = False
|
|
if changed == True:
|
|
self.do_redraw = True
|
|
self.verifyAndResizeParent()
|
|
return changed
|
|
|
|
def refresh_vu(self):
|
|
for mac in self.line.keys():
|
|
self.line[mac].refresh_vu()
|
|
|
|
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
|
|
|
|
|
|
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.conf = ''
|
|
self.launchTime = mytime.clock() - 2
|
|
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.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
|
self.model_number = None
|
|
self.group_enabled = False
|
|
self.number_off_string = '0'
|
|
self.updating = False
|
|
self.muted = False
|
|
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']
|
|
elif self.type == 'Unit':
|
|
if self.parent.group == 'all_units':
|
|
self.bg = myBitmap(os.path.join(self.bitmapdir, self.type + '_bg.png'))
|
|
self.params = self.parent.params[self.type]
|
|
else:
|
|
self.bg = myBitmap(os.path.join(self.bitmapdir, 'GroupUnit_bg.png'))
|
|
self.params = self.parent.params['GroupUnit']
|
|
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.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)
|
|
if self.params['show_delete_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.parent.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()
|
|
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:
|
|
traceback.print_exc(file=sys.stdout)
|
|
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.parent.mouseDownPosition = pos
|
|
self.getOrReleaseMouseCapture(True)
|
|
return
|
|
|
|
def OnLeftUp(self, event):
|
|
self.getOrReleaseMouseCapture(False)
|
|
self.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 one_unit.app.softwareLock:
|
|
return
|
|
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
|
|
wx.CallAfter(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)
|
|
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.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':
|
|
for mac in one_unit.getMacList(self.group):
|
|
if mac[:5] != 'Group' and (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 verified yet 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.paint()
|
|
mytime.sleep(0.1)
|
|
print mytime.displayTime() + ' ng.l.Launching', self.MAC
|
|
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':
|
|
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
|
|
members = one_unit.getMacList(self.group)
|
|
if len(members) == 0:
|
|
print mytime.displayTime(), 'No members, aborting launch'
|
|
return
|
|
mac = leading_mac = one_unit.getLeadingMAC(self.group)
|
|
if self.group_type == 'Mute':
|
|
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].shouldBeVisible = True
|
|
self.parent.parent.children[testKey].isVisible = False
|
|
self.parent.parent.children[testKey].raiseOrLower()
|
|
return
|
|
if True:
|
|
if mac not in self.parent.parent.parent.peers.units.keys():
|
|
print mytime.displayTime(), 'nww.lgp.making unit for MAC', mac
|
|
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
|
|
if panel == 'unitType':
|
|
model_number = one_unit.app.server.peers.get(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_MODEL_NUMBER, 0, 0), mac)
|
|
model_firmware = one_unit.app.server.peers.get(data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_MODEL_FIRMWARE, 0, 0), mac)
|
|
print mytime.displayTime(), 'nww.Launching group panel, model number:', model_number, 'model firmware:', model_firmware
|
|
if model_number == None:
|
|
panel = self.parent.parent.parent.peers.units[mac].type
|
|
else:
|
|
panel = self.parent.parent.parent.peers.units[mac].type + '_' + str(model_number)
|
|
customTitle = customTitle.encode('utf-8')
|
|
print mytime.displayTime() + ' Opening Panel ' + panel + ' for group', self.group, 'title', customTitle, 'with leading MAC', leading_mac
|
|
if one_unit.app.server.peers.units[leading_mac].link_status not in ('available',
|
|
'ready'):
|
|
print mytime.displayTime() + ' Reference unit not online, warning'
|
|
dlgMessage = 'Warning: The reference unit for this group ' + leading_mac + ' is not online. This may lead to unexpected results. Continue?'
|
|
dlgTitle = 'Open Group'
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL | wx.ICON_WARNING)
|
|
if res != wx.OK:
|
|
return
|
|
windowReference = 'Group ' + self.group
|
|
try:
|
|
self.parent.parent.children[windowReference].customTitle = customTitle
|
|
self.parent.parent.children[windowReference].ChangeProgramTitle()
|
|
self.parent.parent.children[windowReference].Show(True)
|
|
self.parent.parent.children[windowReference].shouldBeVisible = True
|
|
self.parent.parent.children[windowReference].isVisible = False
|
|
self.parent.parent.children[windowReference].raiseOrLower()
|
|
except:
|
|
import child_unit
|
|
self.parent.parent.children[windowReference] = child_unit.Child_frame(self.parent.parent.parent, None, -1, '', IsMvPanel)
|
|
self.parent.parent.children[windowReference].storeWithKey = windowReference
|
|
print mytime.displayTime, 'Warning: de regel hieronder ziet er niet juist uit, wat is dit? Komt dit voor? Zie functie parameters init_1'
|
|
self.parent.parent.children[windowReference].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')
|
|
if self.group == 'all_units':
|
|
print mytime.displayTime(), 'Minimized size:', self.params['minimized_size']
|
|
self.parent.SetSize(self.params['minimized_size'])
|
|
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' and (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:
|
|
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':
|
|
print mytime.displayTime() + ' nww.u2.Restarting', self.MAC
|
|
self.parent.parent.children[self.MAC] = 'launching'
|
|
wx.CallAfter(one_unit.launchLater, self.MAC)
|
|
else:
|
|
if self.params['show_launch'] == True:
|
|
if 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 one_unit.app.mijnpc == True:
|
|
self.launch_button.Enable(True)
|
|
if mytime.clock() - self.parent.parent.parent.peers.units[self.MAC].discover_time > 1:
|
|
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':
|
|
if self.params['show_delete_button']:
|
|
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:
|
|
maxNameWidth = self.params['name_size'][0]
|
|
name = self.name
|
|
(w, h) = dc.GetTextExtent(name)
|
|
while w > maxNameWidth:
|
|
name = name[:-1]
|
|
(w, h) = dc.GetTextExtent(name)
|
|
|
|
dc.DrawText(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
|
|
if self.params['show_IP'] == True:
|
|
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 = (1000, 750)
|
|
self.parent = parent
|
|
self.__name__ = 'GraphicalNetworkWindow'
|
|
self.windowReference = self.__name__
|
|
self.vu_list = {}
|
|
self.children = {}
|
|
self.GroupStart = 0
|
|
self.painted = False
|
|
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 = size[0]
|
|
self.height = size[1]
|
|
style = wx.MINIMIZE_BOX | wx.DEFAULT_DIALOG_STYLE | wx.CLOSE_BOX
|
|
style |= wx.MAXIMIZE_BOX
|
|
self.CanMaximize = True
|
|
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 | wx.RESIZE_BORDER
|
|
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'
|
|
self.bgName = one_unit.app.bgName
|
|
if self.bgName != None and os.path.exists(self.bgName):
|
|
self.bg = wx.Bitmap(self.bgName)
|
|
else:
|
|
self.bg = wx.EmptyBitmap(self.width, self.height)
|
|
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),
|
|
'show_delete_button': True,
|
|
'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_IP': 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,
|
|
'max_height': (self.GetSize()[1] - 30),
|
|
'minimized_size': None}
|
|
main_header_params = {}
|
|
group_header_params = {}
|
|
unit_params = {}
|
|
group_unit_params = {}
|
|
param_empty_if_default = ('vu_colours', 'vu_steps')
|
|
for key in param_empty_if_default:
|
|
try:
|
|
unit_params[key] = eval(self.parent.main_config.get('Network', 'Unit_' + key))
|
|
except:
|
|
pass
|
|
|
|
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_empty_if_default:
|
|
try:
|
|
group_unit_params[key] = eval(self.parent.main_config.get('Network', 'GroupUnit_' + key))
|
|
except:
|
|
pass
|
|
|
|
for key in param_defaults.keys():
|
|
try:
|
|
group_unit_params[key] = eval(self.parent.main_config.get('Network', 'GroupUnit_' + key))
|
|
except:
|
|
group_unit_params[key] = unit_params[key]
|
|
|
|
for key in param_empty_if_default:
|
|
try:
|
|
group_header_params[key] = eval(self.parent.main_config.get('Network', 'Header_' + key))
|
|
except:
|
|
pass
|
|
|
|
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_empty_if_default:
|
|
try:
|
|
main_header_params[key] = eval(self.parent.main_config.get('Network', 'Main_' + key))
|
|
except:
|
|
pass
|
|
|
|
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, 'GroupUnit': group_unit_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
|
|
length = math.sqrt(w * w + h * h)
|
|
size = math.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
|
|
|
|
print mytime.displayTime() + ' nww.4'
|
|
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 = 22
|
|
self.maxVirtualSizeX = one_unit.app.client_area[2] * 2
|
|
self.maxVirtualSizeY = one_unit.app.client_area[3] * 2
|
|
if False:
|
|
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 = one_unit.app.client_area
|
|
self.max_height = self.client_area[3] - 50
|
|
print mytime.displayTime() + ' nww.8'
|
|
self.create_menu()
|
|
print mytime.displayTime() + ' nww.9'
|
|
panelSize = (self.GetSize()[0], self.GetSize()[1] - self.menubar.GetSize()[1])
|
|
self.virtualPanelSize = panelSize
|
|
panelPos = (0, self.menubar.GetSize()[1])
|
|
self.scrollPanel = wx.ScrolledWindow(self, -1, size=panelSize, pos=panelPos, style=wx.HSCROLL | wx.VSCROLL | wx.NO_BORDER)
|
|
self.scrollPanel.SetBackgroundColour(self.bgcolour)
|
|
self.virtualPanel = wx.Panel(self.scrollPanel)
|
|
self.virtualPanel.SetSize(panelSize)
|
|
if os.name in mac_names:
|
|
self.scrollBarSizeX = 0
|
|
self.scrollBarSizeY = 22
|
|
self.moveGroupPanelLimitX = 0
|
|
self.moveGroupPanelLimitY = 0
|
|
else:
|
|
self.scrollBarSizeX = 14
|
|
self.scrollBarSizeY = 14
|
|
self.moveGroupPanelLimitX = 0
|
|
self.moveGroupPanelLimitY = 0
|
|
self.lastPosition = self.GetPosition()[:]
|
|
self.lastPanelPosition = self.GetPosition()[:]
|
|
self.group_panels['all_units'] = GroupPanel(self.virtualPanel, self, 'all_units')
|
|
if os.name not in mac_names:
|
|
self.SetDoubleBuffered(True)
|
|
self.Refresh(False)
|
|
self.parent = parent
|
|
self.display_buffer = None
|
|
self.SetSize(one_unit.app.nwwSize)
|
|
self.menubar.SetSize((self.bg.GetSize()[0], self.menubar.GetSize()[1]))
|
|
self.menubar.Show(True)
|
|
self.scrollPanel.SetScrollRate(1, 1)
|
|
self.changed = True
|
|
self.virtualPanel.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
print mytime.displayTime(), 'ng.set my position to', one_unit.app.nwwPosition
|
|
self.minPosX = one_unit.app.client_area[0]
|
|
self.minPosY = one_unit.app.client_area[1]
|
|
if one_unit.app.nwwPosition[0] < self.minPosX:
|
|
one_unit.app.nwwPosition = (
|
|
self.minPosX, one_unit.app.nwwPosition[1])
|
|
if one_unit.app.nwwPosition[1] < self.minPosY:
|
|
one_unit.app.nwwPosition = (
|
|
one_unit.app.nwwPosition[0], self.minPosY)
|
|
self.SetPosition(one_unit.app.nwwPosition)
|
|
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
|
self.executeClose = False
|
|
self.response = None
|
|
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(100)
|
|
self.virtualPanel.Bind(wx.EVT_MOTION, self.OnMoveVirtualPanel)
|
|
self.Bind(wx.EVT_SIZE, self.OnSize)
|
|
self.virtualPanel.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.virtualPanel.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick)
|
|
self.virtualPanel.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
|
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick)
|
|
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
|
|
self.leftDownPoint = [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
|
|
Size = self.ClientSize
|
|
self._Buffer = wx.EmptyBitmap(*Size)
|
|
self.execOnSize()
|
|
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()
|
|
self.SetFocus()
|
|
else:
|
|
self.lastSize = one_unit.app.nwwSize
|
|
self.lastPosition = one_unit.app.nwwPosition
|
|
if one_unit.app.nwwMaximized == True:
|
|
self.Maximize(True)
|
|
self.displaySize = (
|
|
wx.Display().GetClientArea()[2], wx.Display().GetClientArea()[3])
|
|
if self.maximized == False:
|
|
newX = self.GetSize()[0]
|
|
newY = self.GetSize()[1]
|
|
if newX > wx.Display().GetClientArea()[2]:
|
|
newX = wx.Display().GetClientArea()[2]
|
|
if newY > wx.Display().GetClientArea()[3]:
|
|
newY = wx.Display().GetClientArea()[3]
|
|
self.SetSize((newX, newY))
|
|
if self.bgName != None and os.path.exists(self.bgName):
|
|
print mytime.displayTime(), 'ng. mijn client size:', self.ClientSize
|
|
self.bg = self.scaleBitmap(self.bg, self.displaySize[0], self.displaySize[1] - self.menubar.GetSize()[1], doScale=True)
|
|
print mytime.displayTime(), 'nwg init done'
|
|
return
|
|
|
|
def getOffset(self, mac):
|
|
offset = self.GetPosition()
|
|
print mytime.displayTime(), 'ng.go.Set default offset to nww position'
|
|
if len(self.children) > 0:
|
|
print mytime.displayTime(), 'ng.go.Getting default offset from child position'
|
|
lastCloseTime = 0
|
|
try:
|
|
for testKey in self.children:
|
|
if testKey.find(mac) >= 0:
|
|
try:
|
|
if self.children[testKey].closeTime > lastCloseTime:
|
|
lastCloseTime = self.children[testKey].closeTime
|
|
print mytime.displayTime(), 'ng.go.Using', testKey, 'close time:', lastCloseTime
|
|
offset = self.children[testKey].myPosition
|
|
except:
|
|
pass
|
|
|
|
except:
|
|
pass
|
|
|
|
print mytime.displayTime(), 'ng.go.returning offset', offset
|
|
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
|
|
|
|
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.HasCapture():
|
|
self.CaptureMouse()
|
|
if not capture and self.HasCapture():
|
|
self.ReleaseMouse()
|
|
return
|
|
|
|
def scaleBitmap(self, bitmap, width, height, doScale=False):
|
|
print mytime.displayTime(), 'ng.scale called with', width, height, doScale, 'for bitmap', bitmap
|
|
if doScale == False:
|
|
return bitmap
|
|
image = wx.ImageFromBitmap(bitmap)
|
|
size = image.GetSize()
|
|
widthRatio = float(size[0]) / float(width)
|
|
heightRatio = float(size[1]) / float(height)
|
|
if widthRatio > heightRatio:
|
|
height = size[1] / widthRatio
|
|
else:
|
|
width = size[0] / heightRatio
|
|
print mytime.displayTime(), 'ng.Scaling image to', width, height
|
|
image = image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
|
|
result = wx.BitmapFromImage(image)
|
|
return result
|
|
|
|
def autoSizePanels(self, doScale=False):
|
|
myPos = self.GetPosition()
|
|
mySize = self.GetSize()
|
|
displayGeometry = wx.Display().GetGeometry()
|
|
if os.name in mac_names and myPos[0] == displayGeometry[0] and myPos[1] == displayGeometry[1] and mySize[0] == displayGeometry[2] and mySize[1] == displayGeometry[3]:
|
|
osxFullScreen = True
|
|
else:
|
|
osxFullScreen = False
|
|
if osxFullScreen == True or self.maximized == True:
|
|
self.scrollPanel.SetSize(mySize)
|
|
if self.virtualPanelSize[0] < self.scrollPanel.GetSize()[0]:
|
|
self.virtualPanelSize = (
|
|
self.scrollPanel.GetSize()[0] - self.scrollBarSizeX, self.virtualPanelSize[1])
|
|
if self.virtualPanelSize[1] < self.scrollPanel.GetSize()[1]:
|
|
self.virtualPanelSize = (
|
|
self.virtualPanelSize[0], self.scrollPanel.GetSize()[1] - self.scrollBarSizeY - self.menubar.GetSize()[1])
|
|
if self.virtualPanelSize[0] > self.maxVirtualSizeX:
|
|
self.virtualPanelSize = (
|
|
self.maxVirtualSizeX, self.virtualPanelSize[1])
|
|
if self.virtualPanelSize[1] > self.maxVirtualSizeY:
|
|
self.virtualPanelSize = (
|
|
self.virtualPanelSize[0], self.maxVirtualSizeY)
|
|
if osxFullScreen:
|
|
panelSize = (mySize[0], mySize[1])
|
|
elif self.maximized == True:
|
|
panelSize = (
|
|
mySize[0] - self.scrollBarSizeX, mySize[1] - self.scrollBarSizeY - self.menubar.GetSize()[1])
|
|
else:
|
|
panelSize = (
|
|
mySize[0] - self.scrollBarSizeX, mySize[1] - self.scrollBarSizeY - self.menubar.GetSize()[1])
|
|
self.scrollPanel.SetSize(panelSize)
|
|
self.virtualPanel.SetSize(self.virtualPanelSize)
|
|
self.scrollPanel.SetVirtualSize(self.virtualPanelSize)
|
|
self.scrollPanel.SetScrollRate(1, 1)
|
|
return
|
|
|
|
def OnSize(self, e):
|
|
self.execOnSize()
|
|
return
|
|
|
|
def execOnSize(self):
|
|
if self.initialized == False:
|
|
return
|
|
size = self.GetSize()
|
|
menuSize = self.menubar.GetSize()
|
|
self.changed = True
|
|
menuSize = (size[0], menuSize[1])
|
|
self.menubar.SetSize(menuSize)
|
|
self.autoSizePanels()
|
|
self.Refresh(False)
|
|
one_unit.app.nwwSize = self.GetSize()
|
|
one_unit.app.nwwPosition = self.GetPosition()
|
|
return
|
|
|
|
def Maximize(self, state):
|
|
if self.maximized == False:
|
|
self.lastSize = self.GetSize()
|
|
self.lastPanelPosition = self.GetPosition()[:]
|
|
self.menubar.last_size = self.menubar.GetSize()
|
|
(c_x, c_y, c_w, c_h) = wx.ClientDisplayRect()
|
|
frameWidth = 7
|
|
frameHeight = 7
|
|
self.menubar.maximizeImage = 'restore.png'
|
|
self.SetSize((c_w + frameWidth * 2, c_h + frameHeight * 2))
|
|
self.SetPosition((c_x - frameWidth, c_y - 7))
|
|
self.maximized = True
|
|
else:
|
|
self.SetPosition(self.lastPanelPosition)
|
|
self.menubar.maximizeImage = 'maximize.png'
|
|
self.SetSize(self.lastSize)
|
|
self.maximized = False
|
|
self.menubar.Refresh()
|
|
self.display_buffer = None
|
|
self.changed = True
|
|
self.do_redraw = True
|
|
self.autoSizePanels(doScale=True)
|
|
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)):
|
|
print mytime.displayTime(), 'ng.OLD'
|
|
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.leftDownPoint = self.getEventCoordinates(event, offset)
|
|
self.leftDownViewPoint = self.scrollPanel.GetViewStart()
|
|
self.leftDownPosition = self.GetPosition()
|
|
self.lastPosition = self.GetPosition()
|
|
one_unit.hideChildren()
|
|
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)
|
|
delta = self.GetPosition() - self.lastPosition
|
|
one_unit.moveChildren(delta)
|
|
else:
|
|
one_unit.hideChildren()
|
|
return
|
|
|
|
def OnMoveVirtualPanel(self, event, offset=(
|
|
0, 0)):
|
|
point = self.getEventCoordinates(event, offset)
|
|
currentViewPoint = self.scrollPanel.GetViewStart()
|
|
if event.Dragging() and self.left_down == True:
|
|
ppu = self.scrollPanel.GetScrollPixelsPerUnit()
|
|
targetX = self.leftDownPoint[0] - point[0] + currentViewPoint[0] * ppu[0]
|
|
targetY = self.leftDownPoint[1] - point[1] + currentViewPoint[1] * ppu[0]
|
|
if targetX < 0:
|
|
targetX = 0
|
|
if targetY < 0:
|
|
targetY = 0
|
|
if targetX > self.virtualPanelSize[0] - self.GetSize()[0]:
|
|
targetX = self.virtualPanelSize[0] - self.GetSize()[0]
|
|
if targetY > self.virtualPanelSize[1] - self.GetSize()[1]:
|
|
targetY = self.virtualPanelSize[1] - self.GetSize()[1]
|
|
targetX /= ppu[0]
|
|
targetY /= ppu[1]
|
|
self.scrollPanel.Scroll(targetX, targetY)
|
|
return
|
|
|
|
def OnMotion(self, event, offset=(
|
|
0, 0)):
|
|
if self.menubar.left_down == False:
|
|
return
|
|
if self.maximized == True:
|
|
return
|
|
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.leftDownPoint[0], screen[1] + point[1] - self.leftDownPoint[1])
|
|
self.SetPosition(screenpoint)
|
|
self.moved_screen = True
|
|
if self.maximized == True:
|
|
self.maximized = False
|
|
delta = self.GetPosition() - self.lastPosition
|
|
self.lastPosition = self.GetPosition()
|
|
one_unit.moveChildren(delta)
|
|
return
|
|
|
|
def OnPaint(self, event):
|
|
dc = wx.PaintDC(self.virtualPanel)
|
|
self.paint(dc, self)
|
|
return
|
|
|
|
def paint(self, dc, parent):
|
|
dc.DrawBitmap(self.bg, 0, 0)
|
|
if self.bgName == None:
|
|
dc.SetTextForeground((128, 128, 128))
|
|
dc.DrawText('Click "Tools - Select Background" to select a background image', self.GetSize()[0] / 2 - 200, self.GetSize()[1] / 2)
|
|
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:
|
|
print mytime.displayTime() + ' restore 1'
|
|
self.changed = True
|
|
self.Show(True)
|
|
self.Refresh(False)
|
|
self.restore = False
|
|
if self.do_maximize == True:
|
|
print mytime.displayTime(), 'ng.doMaximize'
|
|
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 set_restore(self, maximize):
|
|
self.restore = True
|
|
self.do_maximize = maximize
|
|
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:
|
|
self.Show(True)
|
|
print mytime.displayTime() + ' restore 2'
|
|
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:
|
|
mytime.sleep(0.01)
|
|
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)
|
|
try:
|
|
self.group_panels[group].HeaderLine.groupConfigPanel.Destroy()
|
|
except:
|
|
pass
|
|
else:
|
|
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.group_panels[group] = GroupPanel(self.virtualPanel, 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:
|
|
counter = 0
|
|
shown_height = 0
|
|
for group in sorted_groups:
|
|
try:
|
|
self.group_panels[group].Show(True)
|
|
shown_height += self.group_panels[group].GetSize()[1]
|
|
except:
|
|
pass
|
|
|
|
self.group_panels['all_units'].Show(True)
|
|
shown_height += self.group_panels['all_units'].GetSize()[1]
|
|
frame_height = self.frame_height
|
|
self.Freeze()
|
|
self.changed = True
|
|
self.Refresh(False)
|
|
self.shown_height = shown_height
|
|
self.autoSizePanels()
|
|
self.Thaw()
|
|
return
|
|
|
|
def saveGroupPositions(self):
|
|
for group in self.group_panels:
|
|
groupPanel = self.group_panels[group]
|
|
if str(group) not in one_unit.app.groupconfig.sections():
|
|
one_unit.app.groupconfig.add_section(str(group))
|
|
print mytime.displayTime(), 'ng.sgp.Added group config section for', group
|
|
one_unit.app.groupconfig.set(group, 'lastPosition', str(groupPanel.GetPosition()))
|
|
one_unit.app.groupconfig.set(group, 'expand', str(groupPanel.HeaderLine.expand))
|
|
|
|
print mytime.displayTime(), 'ng.sgp.Saved group positions'
|
|
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 = 'Saving program data failed. You do not have sufficient access rights to run this program. Please contact your system administrator.'
|
|
dlgTitle = 'Error'
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK)
|
|
|
|
return
|
|
|
|
def OnClose(self, e):
|
|
print mytime.displayTime() + ' nc.oc.Closing Network Window'
|
|
print mytime.displayTime(), 'Window data: Iconized:', self.IsIconized(), 'maximized:', self.IsMaximized(), self.maximized, 'size:', self.GetSize(), 'position:', self.GetPosition()
|
|
if self.IsIconized() == False:
|
|
if self.maximized == True:
|
|
one_unit.app.nwwSize = self.lastSize
|
|
one_unit.app.nwwPosition = self.lastPanelPosition
|
|
else:
|
|
one_unit.app.nwwSize = self.GetSize()
|
|
one_unit.app.nwwPosition = self.GetPosition()
|
|
one_unit.app.nwwMaximized = self.maximized
|
|
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
|
|
|
|
self.saveGroupPositions()
|
|
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 != None and len(one_unit.app.master_password) > 0:
|
|
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')
|
|
self.tools.AppendSeparator()
|
|
self.tools.Append(666, getString('nm666'), 'Select Background Image')
|
|
self.tools.Append(668, getString('nm668'), 'Remove Background Image')
|
|
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.windowMenu = my_menu.my_Menu(self)
|
|
self.windowMenu.Append(700, 'Main', 'Main Network Window')
|
|
self.menubar.Append(file, getString('f'))
|
|
self.menubar.Append(self.tools, getString('t'))
|
|
self.menubar.Append(self.windowMenu, getString('nm301'))
|
|
self.menubar.Append(helpMenu, getString('h'))
|
|
self.Bind(wx.EVT_MENU, self.OnMainWindow, id=700)
|
|
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)
|
|
self.Bind(wx.EVT_MENU, self.OnNewProject, id=218)
|
|
if os.name not in mac_names:
|
|
self.Bind(wx.EVT_MENU, self.OnToggleDPIMode, id=230)
|
|
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.OnSelectBackground, id=666)
|
|
self.Bind(wx.EVT_MENU, self.OnRemoveBackground, id=668)
|
|
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 True:
|
|
self.menubar.AppendIcons()
|
|
self.menubar.SetPosition((0, 0))
|
|
self.menubar.SetSize((self.GetSize()[0], 20))
|
|
print mytime.displayTime(), 'ng.cm.6', self.menubar.GetSize()
|
|
print mytime.displayTime(), 'ng.cm. de volgende regels moeten er eigenlijk in!!'
|
|
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 OnMainWindow(self, e):
|
|
self.Raise()
|
|
return
|
|
|
|
def updateAllWindowLists(self):
|
|
one_unit.updateWindowList(self)
|
|
for c in self.children.values():
|
|
try:
|
|
one_unit.updateWindowList(c)
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def OnSelectWindow(self, e):
|
|
one_unit.OnSelectWindow(self, e)
|
|
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 = 'All groups and virtual units will be deleted. Continue?'
|
|
else:
|
|
dlgMessage = 'All groups will be deleted. Continue?'
|
|
dlgTitle = 'New Project'
|
|
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()
|
|
self.saveGroupPositions()
|
|
if filename != None:
|
|
groupconfigfile = open(filename, 'wb')
|
|
one_unit.app.groupconfig.write(groupconfigfile)
|
|
groupconfigfile.close()
|
|
return
|
|
|
|
def OnRemoveBackground(self, e):
|
|
bgname = None
|
|
self.bg = wx.EmptyBitmap(self.width, self.height)
|
|
self.bgName = None
|
|
one_unit.app.bgName = None
|
|
self.changed = True
|
|
self.Refresh(False)
|
|
return
|
|
|
|
def OnSelectBackground(self, e):
|
|
bgname = None
|
|
wildcard = 'PNG File (*.png)|*.png|JPEG File (*.jpg)|*.jpg'
|
|
dlg = wx.FileDialog(self, message='Select Background Image', wildcard=wildcard, style=wx.OPEN | wx.CHANGE_DIR)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
bgname = dlg.GetPath()
|
|
dlg.Destroy()
|
|
if bgname != None:
|
|
try:
|
|
self.bg = wx.Bitmap(bgname)
|
|
size = self.GetSize()
|
|
self.bg = self.scaleBitmap(self.bg, self.displaySize[0], self.displaySize[1] - self.menubar.GetSize()[1], doScale=True)
|
|
self.bgName = bgname
|
|
one_unit.app.bgName = bgname
|
|
except:
|
|
print mytime.displayTime(), 'ng.Load Background Failed', bgname
|
|
traceback.print_exc(file=sys.stdout)
|
|
return
|
|
|
|
self.changed = True
|
|
self.Refresh(False)
|
|
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
|
|
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() + ' ng.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':
|
|
continue
|
|
if self.parent.peers.units[mac].name.strip() == '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() + ' ng.oua.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(), 'ng.oua.1'
|
|
self.parent.remote_link.StartMainUpdate(mac, ignore_version=True)
|
|
print mytime.displayTime(), 'ng.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() + ' ng.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() + ' ng.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(ignore_accessrights=True)
|
|
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
|
|
|
|
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_graphical.pyc
|