1
0
mirror of https://github.com/peterantypas/maiana.git synced 2025-05-28 05:10:40 -07:00

Merge branch 'wx_app'

This commit is contained in:
Peter Antypas 2022-02-03 05:49:02 -08:00
commit 1e41cd05f0
13 changed files with 3258 additions and 0 deletions

1
latest/Apps/maiana-update/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
__pycache__

3
latest/Apps/maiana-update/.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 (maiana-update) (2)" project-jdk-type="Python SDK" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/maiana-update.iml" filepath="$PROJECT_DIR$/.idea/maiana-update.iml" />
</modules>
</component>
</project>

6
latest/Apps/maiana-update/.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,124 @@
from threading import Thread
import wx
import os
import binascii
import sys
from enum import Enum
EVT_FWUPDATE_ID = wx.NewId()
class EventType(Enum):
DFU_ENABLED = 1
TRANSFER_STARTED = 2
TRANSFER_PROGRESS = 3
TRANSFER_COMPLETE = 4
ERROR = 5
class FwUpdateEvent(wx.PyEvent):
def __init__(self, eventType, data):
wx.PyEvent.__init__(self)
self.SetEventType(EVT_FWUPDATE_ID)
self.eventType = eventType
self.data = data
class FWUpdateThread(Thread):
def __init__(self, window, port, filename):
Thread.__init__(self)
self.daemon = True
self.window = window
self.port = port
self.filesize = 0
self.crc32 = 0
try:
self.file = open(filename, "rb")
except:
print("Unable to open file {0}".format(filename))
sys.exit(2)
self.filesize = os.stat(filename).st_size
# print filesize
self.data = self.file.read()
self.crc32 = (binascii.crc32(self.data) & 0xFFFFFFFF)
self.file.seek(0)
def is_unit_running(self):
print("Checking if unit is running")
s = self.port.readline().strip().decode('utf-8')
if len(s) > 0:
# print s
tokens = s.split(',')
if len(tokens) > 3:
return True
return False
def drain_port(self):
self.port.flushInput()
s = self.port.readline()
while len(s) > 0:
s = self.port.readline()
def enable_dfu(self):
if self.is_unit_running():
print("Unit is running, switching to DFU mode")
self.port.write(b'dfu\r\n')
self.drain_port()
for x in range(5):
self.port.write(b'\r\n')
s = self.port.readline().strip()
if s.find(b"MAIANA bootloader") >= 0:
wx.PostEvent(self.window, FwUpdateEvent(EventType.DFU_ENABLED, None))
return True
wx.PostEvent(self.window, FwUpdateEvent(EventType.ERROR, b'Could not enter DFU mode'))
return False
def begin_transfer(self):
self.drain_port()
command = "load {0} {1:x}\r\n".format(self.filesize, self.crc32).encode('utf-8')
self.port.write(command)
print(command)
s = self.port.readline().strip()
if s == b"READY":
wx.PostEvent(self.window, FwUpdateEvent(EventType.TRANSFER_STARTED, None))
return True
wx.PostEvent(self.window, FwUpdateEvent(EventType.ERROR, 'Failed:{}'.format(s)))
return False
def run(self):
if not self.enable_dfu():
print("Could not get unit into DFU mode")
return
print("Unit is in DFU mode")
if not self.begin_transfer():
print("Unable to begin transfer, restart the unit and retry")
return
print("Starting transfer")
bytes = self.file.read(2048)
resp = ''
bytesSent = 0
while len(bytes) > 0:
self.port.write(bytes)
resp = self.port.readline().strip()
if resp.find(b"OK") < 0:
break
bytesSent += len(bytes)
progress = bytesSent/self.filesize
wx.PostEvent(self.window, FwUpdateEvent(EventType.TRANSFER_PROGRESS, progress))
bytes = self.file.read(2048)
wx.PostEvent(self.window, FwUpdateEvent(EventType.TRANSFER_COMPLETE, None))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
import wx
from mainwindow import MainWindow
if __name__ == '__main__':
app = wx.App()
window = MainWindow()
window.Show(True)
app.MainLoop()

View File

@ -0,0 +1,132 @@
import serial
import sys
import glob
import time
import re
from enum import Enum
class MaianaStatus(Enum):
UNKNOWN = 0
RUNNING = 1
DFU = 2
class MaianaClient:
VESSEL_TYPES = [30, 34, 36, 37]
@staticmethod
def serial_ports():
""" Lists serial port names
:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of the serial ports available on the system
"""
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty\..*')
else:
raise EnvironmentError('Unsupported platform')
result = []
for port in ports:
# print port
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, Exception):
pass
return result
@staticmethod
def determineStatus(port):
port.flushInput()
port.flushOutput()
s = port.readline().strip()
port.write(b'\r\n')
for i in range(5):
s = port.readline().strip()
if s.find(b"bootloader") > -1:
return MaianaStatus.DFU
else:
tokens = s.decode('utf-8').split(',')
if (tokens[0][0] == '$' or tokens[0][0] == '!') and len(tokens) >= 2:
return MaianaStatus.RUNNING
return MaianaStatus.UNKNOWN
@staticmethod
def sendCmdWithResponse(port, cmd, resp):
port.flushInput()
port.flushOutput()
port.write(cmd + b'\r\n')
for i in range(25):
s = port.readline().strip()
#print(s)
if s == b'':
break
if resp in s:
return s
return None
@staticmethod
def loadSys(port):
for i in range(2):
try:
sysline = MaianaClient.sendCmdWithResponse(port, b'sys?', b'$PAISYS')
if sysline is None:
return {}
systokens = re.split(',|\\*', sysline.decode('utf-8'))
sysd = {'fw': systokens[2], 'hw': systokens[1], 'cpu': systokens[4]}
return sysd
except:
pass
return {}
@staticmethod
def loadStation(port):
for i in range(2):
try:
stationline = MaianaClient.sendCmdWithResponse(port, b'station?', b'$PAISTN')
if stationline is None:
return {}
stationtokens = re.split(',|\\*', stationline.decode('utf-8'))
stad = {'mmsi': int(stationtokens[1]), 'name': stationtokens[2], 'callsign': stationtokens[3],
'type': int(stationtokens[4]), 'len': int(stationtokens[5]), 'beam': int(stationtokens[6]),
'portoffset': int(stationtokens[7]), 'bowoffset': int(stationtokens[8])}
return stad
except:
pass
return {}
@staticmethod
def setStationData(port, data):
line = 'station {},{},{},{},{},{},{},{}\r\n'.format(
data['mmsi'],
data['name'],
data['callsign'],
data['type'],
data['len'],
data['beam'],
data['portoffset'],
data['bowoffset']
)
resp = MaianaClient.sendCmdWithResponse(port, line.encode('utf-8'), b'$PAISTN')
#print(resp)
if resp:
resp = MaianaClient.sendCmdWithResponse(port, b'reboot', b'$PAISTN')
#print(resp)
return not resp is None
return False

View File

@ -0,0 +1,291 @@
# -*- coding: utf-8 -*-
###########################################################################
## Python code generated with wxFormBuilder (version 3.10.1-39-g978478d5-dirty)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################
import wx
import wx.xrc
###########################################################################
## Class MainFrame
###########################################################################
class MainFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"MAIANA Transponder Manager ver 0.1", pos = wx.DefaultPosition, size = wx.Size( 605,300 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
self.m_notebook2 = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_StatusPnl = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
gSizer1 = wx.GridSizer( 5, 2, 0, 0 )
self.m_staticText1 = wx.StaticText( self.m_StatusPnl, wx.ID_ANY, u"Serial Port", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText1.Wrap( -1 )
gSizer1.Add( self.m_staticText1, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer4 = wx.BoxSizer( wx.HORIZONTAL )
m_SerialPortChoiceChoices = []
self.m_SerialPortChoice = wx.Choice( self.m_StatusPnl, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_SerialPortChoiceChoices, 0 )
self.m_SerialPortChoice.SetSelection( 0 )
self.m_SerialPortChoice.SetMinSize( wx.Size( 150,-1 ) )
bSizer4.Add( self.m_SerialPortChoice, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_SerialBtn = wx.Button( self.m_StatusPnl, wx.ID_ANY, u"Connect", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_SerialBtn.Enable( False )
bSizer4.Add( self.m_SerialBtn, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
gSizer1.Add( bSizer4, 1, wx.EXPAND, 5 )
self.m_staticText7 = wx.StaticText( self.m_StatusPnl, wx.ID_ANY, u"CPU", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText7.Wrap( -1 )
gSizer1.Add( self.m_staticText7, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_CPULbl = wx.StaticText( self.m_StatusPnl, wx.ID_ANY, u"(unknown)", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_CPULbl.Wrap( -1 )
self.m_CPULbl.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, wx.EmptyString ) )
gSizer1.Add( self.m_CPULbl, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText3 = wx.StaticText( self.m_StatusPnl, wx.ID_ANY, u"Hardware Revision", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText3.Wrap( -1 )
gSizer1.Add( self.m_staticText3, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_HWRevLbl = wx.StaticText( self.m_StatusPnl, wx.ID_ANY, u"(unknown)", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_HWRevLbl.Wrap( -1 )
self.m_HWRevLbl.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, wx.EmptyString ) )
gSizer1.Add( self.m_HWRevLbl, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText5 = wx.StaticText( self.m_StatusPnl, wx.ID_ANY, u"Firmware Revision", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText5.Wrap( -1 )
gSizer1.Add( self.m_staticText5, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_FWRevLbl = wx.StaticText( self.m_StatusPnl, wx.ID_ANY, u"(unknown)", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_FWRevLbl.Wrap( -1 )
self.m_FWRevLbl.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, wx.EmptyString ) )
gSizer1.Add( self.m_FWRevLbl, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_StatusPnl.SetSizer( gSizer1 )
self.m_StatusPnl.Layout()
gSizer1.Fit( self.m_StatusPnl )
self.m_notebook2.AddPage( self.m_StatusPnl, u"Status", True )
self.m_StationPnl = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
self.m_StationPnl.Enable( False )
gSizer2 = wx.GridSizer( 0, 4, 0, 0 )
self.m_staticText101 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, u"MMSI", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText101.Wrap( -1 )
gSizer2.Add( self.m_staticText101, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_MMSIText = wx.TextCtrl( self.m_StationPnl, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( 100,-1 ), 0 )
gSizer2.Add( self.m_MMSIText, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText11 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, u"Call Sign", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText11.Wrap( -1 )
gSizer2.Add( self.m_staticText11, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_CallsignText = wx.TextCtrl( self.m_StationPnl, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
gSizer2.Add( self.m_CallsignText, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText12 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, u"Name", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText12.Wrap( -1 )
gSizer2.Add( self.m_staticText12, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_NameText = wx.TextCtrl( self.m_StationPnl, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_NameText.SetMaxLength( 20 )
self.m_NameText.SetMinSize( wx.Size( 140,-1 ) )
gSizer2.Add( self.m_NameText, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText13 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, u"Vessel Type", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText13.Wrap( -1 )
gSizer2.Add( self.m_staticText13, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
m_VesselTypeChoiceChoices = [ u"Fishing", u"Diving", u"Sailing", u"Pleasure" ]
self.m_VesselTypeChoice = wx.Choice( self.m_StationPnl, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_VesselTypeChoiceChoices, 0 )
self.m_VesselTypeChoice.SetSelection( 0 )
gSizer2.Add( self.m_VesselTypeChoice, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self._ = wx.StaticText( self.m_StationPnl, wx.ID_ANY, u"Length (m)", wx.DefaultPosition, wx.DefaultSize, 0 )
self._.Wrap( -1 )
gSizer2.Add( self._, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_LengthText = wx.TextCtrl( self.m_StationPnl, wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
gSizer2.Add( self.m_LengthText, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText15 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, u"Beam (m)", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText15.Wrap( -1 )
gSizer2.Add( self.m_staticText15, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_BeamText = wx.TextCtrl( self.m_StationPnl, wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
gSizer2.Add( self.m_BeamText, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText17 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, u"Port Offset (m)", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText17.Wrap( -1 )
gSizer2.Add( self.m_staticText17, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_PortOffsetText = wx.TextCtrl( self.m_StationPnl, wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
gSizer2.Add( self.m_PortOffsetText, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText16 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, u"Bow Offset (m)", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText16.Wrap( -1 )
gSizer2.Add( self.m_staticText16, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_BowOffsetText = wx.TextCtrl( self.m_StationPnl, wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
gSizer2.Add( self.m_BowOffsetText, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText18 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText18.Wrap( -1 )
gSizer2.Add( self.m_staticText18, 0, wx.ALL, 5 )
self.m_staticText19 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText19.Wrap( -1 )
gSizer2.Add( self.m_staticText19, 0, wx.ALL, 5 )
self.m_staticText20 = wx.StaticText( self.m_StationPnl, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText20.Wrap( -1 )
gSizer2.Add( self.m_staticText20, 0, wx.ALL, 5 )
self.m_StationSaveBtn = wx.Button( self.m_StationPnl, wx.ID_ANY, u"Save", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_StationSaveBtn.Enable( False )
gSizer2.Add( self.m_StationSaveBtn, 0, wx.ALL|wx.ALIGN_BOTTOM, 5 )
self.m_StationPnl.SetSizer( gSizer2 )
self.m_StationPnl.Layout()
gSizer2.Fit( self.m_StationPnl )
self.m_notebook2.AddPage( self.m_StationPnl, u"Station Data", False )
self.m_FWUpdatePnl = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
self.m_FWUpdatePnl.Enable( False )
bSizer41 = wx.BoxSizer( wx.VERTICAL )
gSizer4 = wx.GridSizer( 1, 2, 0, 0 )
gSizer4.SetMinSize( wx.Size( -1,90 ) )
self.m_staticText28 = wx.StaticText( self.m_FWUpdatePnl, wx.ID_ANY, u"Binary File:", wx.DefaultPosition, wx.Size( 80,-1 ), 0 )
self.m_staticText28.Wrap( -1 )
gSizer4.Add( self.m_staticText28, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_FWBinaryPicker = wx.FilePickerCtrl( self.m_FWUpdatePnl, wx.ID_ANY, wx.EmptyString, u"Select a file", u"*.bin", wx.DefaultPosition, wx.Size( -1,-1 ), wx.FLP_CHANGE_DIR|wx.FLP_DEFAULT_STYLE|wx.FLP_FILE_MUST_EXIST|wx.FLP_OPEN )
gSizer4.Add( self.m_FWBinaryPicker, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 5 )
bSizer41.Add( gSizer4, 1, wx.EXPAND, 5 )
gSizer5 = wx.GridSizer( 1, 2, 0, 0 )
self.m_FWProgress = wx.Gauge( self.m_FWUpdatePnl, wx.ID_ANY, 100, wx.DefaultPosition, wx.Size( 350,-1 ), wx.GA_HORIZONTAL )
self.m_FWProgress.SetValue( 0 )
gSizer5.Add( self.m_FWProgress, 0, wx.ALL, 5 )
self.m_FWUpdateBtn = wx.Button( self.m_FWUpdatePnl, wx.ID_ANY, u"Update", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_FWUpdateBtn.Enable( False )
gSizer5.Add( self.m_FWUpdateBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )
bSizer41.Add( gSizer5, 1, wx.EXPAND, 5 )
self.m_FWUpdateStatusLbl = wx.StaticText( self.m_FWUpdatePnl, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_FWUpdateStatusLbl.Wrap( -1 )
self.m_FWUpdateStatusLbl.SetMinSize( wx.Size( 520,-1 ) )
bSizer41.Add( self.m_FWUpdateStatusLbl, 0, wx.ALL, 5 )
self.m_FWUpdatePnl.SetSizer( bSizer41 )
self.m_FWUpdatePnl.Layout()
bSizer41.Fit( self.m_FWUpdatePnl )
self.m_notebook2.AddPage( self.m_FWUpdatePnl, u"FW Update", False )
bSizer1.Add( self.m_notebook2, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.m_SerialPortChoice.Bind( wx.EVT_CHOICE, self.onSerialPortSelection )
self.m_SerialBtn.Bind( wx.EVT_BUTTON, self.onSerialBtnClick )
self.m_MMSIText.Bind( wx.EVT_TEXT, self.onStationEdit )
self.m_CallsignText.Bind( wx.EVT_TEXT, self.onStationEdit )
self.m_NameText.Bind( wx.EVT_TEXT, self.onStationEdit )
self.m_VesselTypeChoice.Bind( wx.EVT_CHOICE, self.onStationEdit )
self.m_LengthText.Bind( wx.EVT_TEXT, self.onStationEdit )
self.m_BeamText.Bind( wx.EVT_TEXT, self.onStationEdit )
self.m_PortOffsetText.Bind( wx.EVT_TEXT, self.onStationEdit )
self.m_BowOffsetText.Bind( wx.EVT_TEXT, self.onStationEdit )
self.m_StationSaveBtn.Bind( wx.EVT_BUTTON, self.onStationSaveBtnClick )
self.m_FWBinaryPicker.Bind( wx.EVT_FILEPICKER_CHANGED, self.onFWBinarySelection )
self.m_FWUpdateBtn.Bind( wx.EVT_BUTTON, self.onFWUpdateBtnClick )
def __del__( self ):
pass
# Virtual event handlers, override them in your derived class
def onSerialPortSelection( self, event ):
event.Skip()
def onSerialBtnClick( self, event ):
event.Skip()
def onStationEdit( self, event ):
event.Skip()
def onStationSaveBtnClick( self, event ):
event.Skip()
def onFWBinarySelection( self, event ):
event.Skip()
def onFWUpdateBtnClick( self, event ):
event.Skip()

View File

@ -0,0 +1,146 @@
from mainframe import MainFrame
from maianaclient import MaianaClient, MaianaStatus
import serial
import wx
from fwUpdateThread import *
class MainWindow(MainFrame):
def __init__(self):
MainFrame.__init__(self, None)
self.m_SerialPortChoice.Set(MaianaClient.serial_ports())
self.portname = None
self.port = None
self.data = None
def onSerialPortSelection(self, event):
self.m_SerialBtn.Enable()
def onSerialBtnClick(self, event):
if self.port is None:
try:
self.portname = self.m_SerialPortChoice.GetString(self.m_SerialPortChoice.GetSelection())
self.port = serial.Serial(self.portname, 38400, timeout=1)
except:
wx.MessageBox(b'Unable to open port, it may be in use', 'Error', wx.OK | wx.ICON_ERROR)
return
status = MaianaClient.determineStatus(self.port)
if status == MaianaStatus.UNKNOWN:
pass
elif status == MaianaStatus.DFU:
wx.MessageBox(b'MAIANA is currently in firmware update mode. This is the only task you can perform.',
'DFU warning', wx.OK)
self.enableUI()
self.m_SerialBtn.SetLabel(b'Disconnect')
self.m_StationSaveBtn.Disable()
else:
#Assuming status is RUNNING
self.m_SerialBtn.SetLabel(b'Disconnect')
self.enableUI()
if self.refreshSys():
self.refreshStation()
self.m_StationSaveBtn.Disable()
else:
self.port.close()
self.port = None
self.m_SerialBtn.SetLabel(b'Connect')
self.disableUI()
def onStationSaveBtnClick(self, event):
# Let's validate
if not self.validateStationInputs():
return
newdata = {'mmsi': int(self.m_MMSIText.Value),
'name': self.m_NameText.Value,
'callsign': self.m_CallsignText.Value,
'len': int(self.m_LengthText.Value),
'beam': int(self.m_BeamText.Value),
'portoffset': int(self.m_PortOffsetText.Value),
'bowoffset': int(self.m_BowOffsetText.Value),
'type': MaianaClient.VESSEL_TYPES[self.m_VesselTypeChoice.Selection]}
#print(newdata)
if MaianaClient.setStationData(self.port, newdata):
self.stationdata = newdata
self.m_StationSaveBtn.Disable()
def onFWBinarySelection(self, event):
self.m_FWUpdateBtn.Enable()
def onFWUpdateBtnClick(self, event):
self.Connect(-1, -1, EVT_FWUPDATE_ID, self.onFwUpdateEvent)
thr = FWUpdateThread(self, self.port, self.m_FWBinaryPicker.Path)
thr.start()
self.m_FWUpdateBtn.Disable()
def onFwUpdateEvent(self, evt):
print(evt.eventType, evt.data)
if evt.eventType == EventType.DFU_ENABLED:
self.m_FWUpdateStatusLbl.SetLabel("DFU enabled")
elif evt.eventType == EventType.TRANSFER_STARTED:
self.m_FWUpdateStatusLbl.SetLabel("Transferring")
elif evt.eventType == EventType.TRANSFER_PROGRESS:
self.m_FWProgress.SetValue(evt.data * 100)
elif evt.eventType == EventType.TRANSFER_COMPLETE:
self.m_FWProgress.SetValue(0)
self.m_FWUpdateStatusLbl.SetLabel("Transfer completed")
self.refreshSys()
self.refreshStation()
elif evt.eventType == EventType.ERROR:
self.m_FWUpdateStatusLbl.SetLabel(evt.data)
def enableUI(self):
self.m_StationPnl.Enable()
self.m_FWUpdatePnl.Enable()
def disableUI(self):
self.m_StationPnl.Disable()
self.m_FWUpdatePnl.Disable()
def refreshSys(self):
self.sysdata = MaianaClient.loadSys(self.port)
return self.renderSys()
def refreshStation(self):
self.stationdata = MaianaClient.loadStation(self.port)
return self.renderStation()
def renderSys(self):
if not 'hw' in self.sysdata:
wx.MessageDialog(self, b'There was no response from MAIANA. Please check connections and try again.',
'Timeout', wx.OK | wx.STAY_ON_TOP|wx.CENTRE).ShowModal()
return False
self.m_HWRevLbl.SetLabel(self.sysdata['hw'])
self.m_FWRevLbl.SetLabel(self.sysdata['fw'])
self.m_CPULbl.SetLabel(self.sysdata['cpu'])
return True
def renderStation(self):
if not 'mmsi' in self.stationdata:
wx.MessageDialog(self, b'There was no response from MAIANA. Please check connections and try again.',
'Timeout', wx.OK | wx.STAY_ON_TOP|wx.CENTRE).ShowModal()
return False
self.m_MMSIText.SetValue('{}'.format(self.stationdata['mmsi']))
self.m_NameText.SetValue(self.stationdata['name'])
self.m_CallsignText.SetValue(self.stationdata['callsign'])
self.m_LengthText.SetValue('{}'.format(self.stationdata['len']))
self.m_BeamText.SetValue('{}'.format(self.stationdata['beam']))
self.m_PortOffsetText.SetValue('{}'.format(self.stationdata['portoffset']))
self.m_BowOffsetText.SetValue('{}'.format(self.stationdata['bowoffset']))
t = self.stationdata['type']
i = MaianaClient.VESSEL_TYPES.index(t)
self.m_VesselTypeChoice.SetSelection(i)
return True
def validateStationInputs(self):
return True
def onStationEdit( self, event ):
self.m_StationSaveBtn.Enable()
event.Skip()