#!/usr/bin/env python3 # This file is part of OpenPlotter. # Copyright (C) 2022 by Sailoog # # Openplotter is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # any later version. # Openplotter is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Openplotter. If not, see . import wx, os, webbrowser, subprocess, time, datetime, ujson, serial, requests, re, sys import wx.richtext as rt from openplotterSettings import conf from openplotterSettings import language from openplotterSettings import platform from openplotterSignalkInstaller import connections from .version import version class MyFrame(wx.Frame): def __init__(self): self.conf = conf.Conf() self.conf_folder = self.conf.conf_folder self.platform = platform.Platform() self.currentdir = os.path.dirname(os.path.abspath(__file__)) self.currentLanguage = self.conf.get('GENERAL', 'lang') self.language = language.Language(self.currentdir,'openplotter-maiana',self.currentLanguage) if self.conf.get('GENERAL', 'debug') == 'yes': self.debug = True else: self.debug = False wx.Frame.__init__(self, None, title=_('MAIANA AIS transponder')+' '+version, size=(800,444)) self.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) icon = wx.Icon(self.currentdir+"/data/openplotter-maiana.png", wx.BITMAP_TYPE_PNG) self.SetIcon(icon) self.CreateStatusBar() font_statusBar = self.GetStatusBar().GetFont() font_statusBar.SetWeight(wx.BOLD) self.GetStatusBar().SetFont(font_statusBar) self.toolbar1 = wx.ToolBar(self, style=wx.TB_TEXT) toolHelp = self.toolbar1.AddTool(101, _('Help'), wx.Bitmap(self.currentdir+"/data/help.png")) self.Bind(wx.EVT_TOOL, self.OnToolHelp, toolHelp) if not self.platform.isInstalled('openplotter-doc'): self.toolbar1.EnableTool(101,False) toolSettings = self.toolbar1.AddTool(102, _('Settings'), wx.Bitmap(self.currentdir+"/data/settings.png")) self.Bind(wx.EVT_TOOL, self.OnToolSettings, toolSettings) self.toolbar1.AddSeparator() aproveSK = self.toolbar1.AddTool(105, _('Approve'), wx.Bitmap(self.currentdir+"/data/sk.png")) self.Bind(wx.EVT_TOOL, self.onAproveSK, aproveSK) connectionSK = self.toolbar1.AddTool(106, _('Allowed'), wx.Bitmap(self.currentdir+"/data/sk.png")) self.Bind(wx.EVT_TOOL, self.onConnectionSK, connectionSK) self.toolbar1.AddSeparator() self.connInit = _('MAIANA Signal K connection') self.SKconn = wx.ComboBox(self.toolbar1, 103, self.connInit, choices=[], size=(250,-1), style=wx.CB_DROPDOWN) toolSKconn = self.toolbar1.AddControl(self.SKconn) self.Bind(wx.EVT_COMBOBOX, self.onSKconn, toolSKconn) showSK = self.toolbar1.AddTool(104, _('Connections'), wx.Bitmap(self.currentdir+"/data/sk.png")) self.Bind(wx.EVT_TOOL, self.onShowSK, showSK) self.notebook = wx.Notebook(self) self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onTabChange) self.settings = wx.Panel(self.notebook) self.firmware = wx.Panel(self.notebook) self.notebook.AddPage(self.settings, _('Settings')) self.notebook.AddPage(self.firmware, _('Firmware')) self.il = wx.ImageList(24, 24) img0 = self.il.Add(wx.Bitmap(self.currentdir+"/data/settings2.png", wx.BITMAP_TYPE_PNG)) img1 = self.il.Add(wx.Bitmap(self.currentdir+"/data/driver.png", wx.BITMAP_TYPE_PNG)) self.notebook.AssignImageList(self.il) self.notebook.SetPageImage(0, img0) self.notebook.SetPageImage(1, img1) vbox = wx.BoxSizer(wx.VERTICAL) vbox.Add(self.toolbar1, 0, wx.EXPAND) vbox.Add(self.notebook, 1, wx.EXPAND) self.SetSizer(vbox) self.pageSettings() self.pageFirmware() maxi = self.conf.get('GENERAL', 'maximize') if maxi == '1': self.Maximize() self.Centre() self.onRead() def ShowStatusBar(self, w_msg, colour): self.GetStatusBar().SetForegroundColour(colour) self.SetStatusText(w_msg) def ShowStatusBarRED(self, w_msg): self.ShowStatusBar(w_msg, (130,0,0)) def ShowStatusBarGREEN(self, w_msg): self.ShowStatusBar(w_msg, (0,130,0)) def ShowStatusBarBLACK(self, w_msg): self.ShowStatusBar(w_msg, wx.BLACK) def ShowStatusBarYELLOW(self, w_msg): self.ShowStatusBar(w_msg,(255,140,0)) def onTabChange(self, event): try: self.SetStatusText('') except:pass def OnToolHelp(self, event): url = "/usr/share/openplotter-doc/maiana/maiana_app.html" webbrowser.open(url, new=2) def OnToolSettings(self, event=0): subprocess.call(['pkill', '-f', 'openplotter-settings']) subprocess.Popen('openplotter-settings') def onAproveSK(self,e): if self.platform.skPort: url = self.platform.http+'localhost:'+self.platform.skPort+'/admin/#/security/access/requests' webbrowser.open(url, new=2) def onConnectionSK(self,e): if self.platform.skPort: url = self.platform.http+'localhost:'+self.platform.skPort+'/admin/#/security/devices' webbrowser.open(url, new=2) def onShowSK(self, event): if self.platform.skPort: url = self.platform.http+'localhost:'+self.platform.skPort+'/admin/#/serverConfiguration/connections/-' webbrowser.open(url, new=2) def restartRead(self): subprocess.call(['pkill','-f','openplotter-maiana-read']) subprocess.Popen('openplotter-maiana-read') time.sleep(1) def onRead(self): self.ShowStatusBarYELLOW(_('Reading MAIANA device settings...')) self.mmsi.SetValue('') self.vesselName.SetValue('') self.callSign.SetValue('') self.vesselType.SetValue('') self.LOA.SetValue('') self.beam.SetValue('') self.portOffset.SetValue('') self.bowOffset.SetValue('') self.logger.Clear() self.logger2.Clear() self.device = self.conf.get('MAIANA', 'device') self.toolbar1.EnableTool(105,False) self.toolbar2.EnableTool(202,False) self.toolbar3.EnableTool(302,False) self.toolbar3.EnableTool(303,False) self.toolbar3.ToggleTool(304,False) if self.conf.get('MAIANA', 'noiseDetect') == '1': self.toolbar3.ToggleTool(304,True) deviceOld = self.device availableIDs = [] selected = '' self.tx = False skConnections = connections.Connections('MAIANA') result = skConnections.checkConnection() if result[0] == 'pending': self.toolbar1.EnableTool(105,True) self.ShowStatusBarYELLOW(result[1]+_(' Press "Approve" and then "Refresh".')) return elif result[0] == 'error': self.ShowStatusBarRED(result[1]) return elif result[0] == 'repeat': self.ShowStatusBarYELLOW(result[1]+_(' Press "Refresh".')) return elif result[0] == 'permissions': self.ShowStatusBarYELLOW(result[1]+_(' Press "Allowed".')) return elif result[0] == 'approved': self.ShowStatusBarGREEN(result[1]) try: setting_file = self.platform.skDir+'/settings.json' with open(setting_file) as data_file: data = ujson.load(data_file) except: data = {} if 'pipedProviders' in data: data = data['pipedProviders'] else: data = [] for i in data: enabled = '' skID = '' dataType = '' device = '' baudrate = '' connectionType = '' suppress0183event = False try: enabled = i['enabled'] skID = i['id'] dataType = i['pipeElements'][0]['options']['type'] dataSubOptions = i['pipeElements'][0]['options']['subOptions'] device = dataSubOptions['device'] baudrate = dataSubOptions['baudrate'] connectionType = dataSubOptions['type'] if 'suppress0183event' in dataSubOptions: suppress0183event = dataSubOptions['suppress0183event'] if enabled and connectionType == 'serial' and baudrate == 38400 and dataType == 'NMEA0183' and not suppress0183event: availableIDs.append(skID) if device == self.device: selected = skID except: pass self.SKconn.Clear() self.SKconn.AppendItems(availableIDs) if selected: self.SKconn.SetValue(selected) else: self.device = '' self.conf.set('MAIANA', 'device', self.device) self.SKconn.SetValue(self.connInit) self.ShowStatusBarRED(_('Select the Signal K connection for the MAIANA device')) if deviceOld != self.device: if self.device: self.restartRead() else: subprocess.call(['pkill','-f','openplotter-maiana-read']) else: if self.device: test = subprocess.check_output(['ps','aux']).decode(sys.stdin.encoding) if not 'openplotter-maiana-read' in test: self.restartRead() else: subprocess.call(['pkill','-f','openplotter-maiana-read']) if self.device: ser = serial.Serial(self.device, 38400) ser.write('sys?\r\n'.encode("utf-8")) ser.write('station?\r\n'.encode("utf-8")) ser.write('tx?\r\n'.encode("utf-8")) time.sleep(0.5) try: resp = requests.get(self.platform.http+'localhost:'+self.platform.skPort+'/signalk/v1/api/vessels/self/MAIANA/', verify=False) data = ujson.loads(resp.content) except: data = {} if 'hardwareRevision' in data: try: ts = datetime.datetime.utcnow().timestamp() timestamp = data['hardwareRevision']['timestamp'] ts2 = time.mktime(datetime.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%fZ").timetuple()) if ts - ts2 > 3: self.ShowStatusBarRED(_('Cannot connect with the device, try again')) print('#############################') return hardwareRevision = data['hardwareRevision']['value'] hardwareRevision = hardwareRevision.split('.') if int(hardwareRevision[0]) < 11: self.ShowStatusBarRED(_('The hardware version of your MAIANA device is too old')) return if int(hardwareRevision[0]) == 11 and int(hardwareRevision[1]) < 3: self.ShowStatusBarRED(_('The hardware version of your MAIANA device is too old')) return firmwareRevision = data['firmwareRevision']['value'] firmwareRevision = firmwareRevision.split('.') if int(firmwareRevision[0]) < 3: self.ShowStatusBarRED(_('The firmware version of your MAIANA device is too old')) return if int(firmwareRevision[0]) == 3 and int(firmwareRevision[1]) < 3: self.ShowStatusBarRED(_('The firmware version of your MAIANA device is too old')) return if int(firmwareRevision[0]) == 3 and int(firmwareRevision[1]) == 3 and int(firmwareRevision[2]) < 1: self.ShowStatusBarRED(_('The firmware version of your MAIANA device is too old')) return self.toolbar3.EnableTool(302,True) self.toolbar3.EnableTool(303,True) if int(firmwareRevision[0]) >= 4: self.toolbar2.EnableTool(202,True) except Exception as e: if self.debug: print(str(e)) self.ShowStatusBarRED(_('Cannot connect with the device, try again')) return else: self.ShowStatusBarRED(_('Cannot connect with the device, try again')) return self.ShowStatusBarGREEN(_('Done')) self.logger.BeginFontSize(10) self.logger.WriteText(_('Hardware revision')) if 'hardwareRevision' in data: self.logger.WriteText(': '+data['hardwareRevision']['value']) self.hardwareRevision = data['hardwareRevision']['value'] self.logger.Newline() self.logger.WriteText(_('Firmware revision')) if 'firmwareRevision' in data: self.logger.WriteText(': '+data['firmwareRevision']['value']) self.logger.Newline() self.logger.WriteText(_('Type of MCU')) if 'MCUtype' in data: self.logger.WriteText(': '+data['MCUtype']['value']) self.MCUtype = data['MCUtype']['value'] self.logger.Newline() self.logger.WriteText(_('Serial number')) if 'serialNumber' in data: self.logger.WriteText(': '+data['serialNumber']['value']) self.logger.Newline() self.logger2.BeginFontSize(10) self.logger2.WriteText(_('Transmitter hardware module')) if 'transmission' in data: if 'hardwarePresent' in data['transmission']: if data['transmission']['hardwarePresent']['value'] == 1: self.logger2.BeginTextColour((0, 130, 0)) self.logger2.WriteText(': '+_('present')) else: self.logger2.BeginTextColour((130, 0, 0)) self.logger2.WriteText(': '+_('not present')) self.logger2.EndTextColour() self.logger2.Newline() self.logger2.WriteText(_('Hardware TX switch')) if 'transmission' in data: if 'hardwareSwitch' in data['transmission']: if data['transmission']['hardwareSwitch']['value'] == 1: self.logger2.BeginTextColour((0, 130, 0)) self.logger2.WriteText(': '+_('ON')) else: self.logger2.BeginTextColour((130, 0, 0)) self.logger2.WriteText(': '+_('OFF')) self.logger2.EndTextColour() self.logger2.Newline() self.logger2.WriteText(_('Software TX switch')) if 'transmission' in data: if 'softwareSwitch' in data['transmission']: if data['transmission']['softwareSwitch']['value'] == 1: self.logger2.BeginTextColour((0, 130, 0)) self.tx = True self.logger2.WriteText(': '+_('ON')) self.toolbar3.SetToolNormalBitmap(302,wx.Bitmap(self.currentdir+"/data/switch-on.png")) else: self.tx = False self.logger2.BeginTextColour((130, 0, 0)) self.logger2.WriteText(': '+_('OFF')) self.toolbar3.SetToolNormalBitmap(302,wx.Bitmap(self.currentdir+"/data/switch-off.png")) self.logger2.EndTextColour() self.logger2.Newline() self.logger2.WriteText(_('Station data')) if 'transmission' in data: if 'stationData' in data['transmission']: if data['transmission']['stationData']['value'] == 1: self.logger2.BeginTextColour((0, 130, 0)) self.logger2.WriteText(': '+_('provided')) else: self.logger2.BeginTextColour((130, 0, 0)) self.logger2.WriteText(': '+_('not provided')) self.logger2.EndTextColour() self.logger2.Newline() self.logger2.WriteText(_('Status')) if 'transmission' in data: if 'status' in data['transmission']: if data['transmission']['status']['value'] == 1: self.logger2.BeginTextColour((0, 130, 0)) self.logger2.WriteText(': '+_('transmitting')) else: self.logger2.BeginTextColour((130, 0, 0)) self.logger2.WriteText(': '+_('not transmitting')) self.logger2.EndTextColour() self.logger2.Newline() self.logger2.WriteText(_('Channel A latest transmitted message')) self.logger2.WriteText(': ') self.logger2.Newline() if 'channelA' in data: if 'transmittedMessageType' in data['channelA']: if data['channelA']['transmittedMessageType']['value']: self.logger2.WriteText(' '+_('Type')) self.logger2.WriteText(': '+data['channelA']['transmittedMessageType']['value']) self.logger2.Newline() self.logger2.WriteText(' '+_('Time')) self.logger2.WriteText(': '+data['channelA']['transmittedMessageType']['timestamp']) self.logger2.Newline() self.logger2.WriteText(_('Channel B latest transmitted message')) self.logger2.WriteText(': ') self.logger2.Newline() if 'channelB' in data: if 'transmittedMessageType' in data['channelB']: if data['channelB']['transmittedMessageType']['value']: self.logger2.WriteText(' '+_('Type')) self.logger2.WriteText(': '+data['channelB']['transmittedMessageType']['value']) self.logger2.Newline() self.logger2.WriteText(' '+_('Time')) self.logger2.WriteText(': '+data['channelB']['transmittedMessageType']['timestamp']) self.logger2.Newline() self.logger2.WriteText(_('Channel A noise floor')) self.logger2.WriteText(': ') if 'channelA' in data: if 'noiseFloor' in data['channelA']: self.logger2.WriteText(str(data['channelA']['noiseFloor']['value'])) self.logger2.Newline() self.logger2.WriteText(_('Channel B noise floor')) self.logger2.WriteText(': ') if 'channelB' in data: if 'noiseFloor' in data['channelB']: self.logger2.WriteText(str(data['channelB']['noiseFloor']['value'])) if 'station' in data: if 'MMSI' in data['station']: self.mmsi.SetValue(data['station']['MMSI']['value']) if 'callSign' in data['station']: self.callSign.SetValue(data['station']['callSign']['value']) if 'vesselName' in data['station']: self.vesselName.SetValue(data['station']['vesselName']['value']) if 'vesselType' in data['station']: if data['station']['vesselType']['value'] == 30: self.vesselType.SetSelection(0) elif data['station']['vesselType']['value'] == 34: self.vesselType.SetSelection(1) elif data['station']['vesselType']['value'] == 36: self.vesselType.SetSelection(2) elif data['station']['vesselType']['value'] == 37: self.vesselType.SetSelection(3) if 'LOA' in data['station']: self.LOA.SetValue(str(data['station']['LOA']['value'])) if 'beam' in data['station']: self.beam.SetValue(str(data['station']['beam']['value'])) if 'bowOffset' in data['station']: self.bowOffset.SetValue(str(data['station']['bowOffset']['value'])) if 'portOffset' in data['station']: self.portOffset.SetValue(str(data['station']['portOffset']['value'])) def onSKconn(self, event): deviceOld = self.conf.get('MAIANA', 'device') selectedID = self.SKconn.GetValue() try: setting_file = self.platform.skDir+'/settings.json' with open(setting_file) as data_file: data = ujson.load(data_file) except: data = {} if 'pipedProviders' in data: data = data['pipedProviders'] else: data = [] for i in data: skID = '' device = '' try: skID = i['id'] dataSubOptions = i['pipeElements'][0]['options']['subOptions'] device = dataSubOptions['device'] if selectedID == skID: self.device = device self.conf.set('MAIANA', 'device', self.device) except: pass if deviceOld != self.device: if self.device: self.restartRead() else: subprocess.call(['pkill','-f','openplotter-maiana-read']) else: if self.device: test = subprocess.check_output(['ps','aux']).decode(sys.stdin.encoding) if not 'openplotter-maiana-read' in test: self.restartRead() else: subprocess.call(['pkill','-f','openplotter-maiana-read']) self.onRead() def pageSettings(self): self.logger2 = rt.RichTextCtrl(self.settings, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_DONTWRAP|wx.LC_SORT_ASCENDING) self.logger2.SetMargins((10,10)) mmsiLabel = wx.StaticText(self.settings, label=_('MMSI')) self.mmsi = wx.TextCtrl(self.settings) vesselNameLabel = wx.StaticText(self.settings, label=_('Vessel name')) self.vesselName = wx.TextCtrl(self.settings) callSignLabel = wx.StaticText(self.settings, label=_('Call sign')) self.callSign = wx.TextCtrl(self.settings) vesselTypeLabel = wx.StaticText(self.settings, label=_('Vessel type')) self.vesselType = wx.ComboBox(self.settings, 701, choices=['Fishing','Diving','Sailing','Pleasure craft'], style=wx.CB_DROPDOWN) LOAlabel = wx.StaticText(self.settings, label=_('LOA')) self.LOA = wx.TextCtrl(self.settings) beamLabel = wx.StaticText(self.settings, label=_('Beam')) self.beam = wx.TextCtrl(self.settings) portOffsetLabel = wx.StaticText(self.settings, label=_('Port Offset')) self.portOffset = wx.TextCtrl(self.settings) bowOffsetLabel = wx.StaticText(self.settings, label=_('Bow Offset')) self.bowOffset = wx.TextCtrl(self.settings) unitsLabel = wx.StaticText(self.settings, label=_('Units: meters')) self.toolbar3 = wx.ToolBar(self.settings, style=wx.TB_TEXT) toolRefresh = self.toolbar3.AddTool(301, _('Refresh'), wx.Bitmap(self.currentdir+"/data/refresh.png")) self.Bind(wx.EVT_TOOL, self.OnToolRefresh, toolRefresh) self.toolbar3.AddSeparator() toolTX = self.toolbar3.AddTool(302, _('Software TX switch'), wx.Bitmap(self.currentdir+"/data/switch-off.png")) self.Bind(wx.EVT_TOOL, self.OnToolTX, toolTX) self.toolbar3.AddSeparator() toolNoise = self.toolbar3.AddCheckTool(304, _('Detect noise'), wx.Bitmap(self.currentdir+"/data/notifications.png")) self.Bind(wx.EVT_TOOL, self.OnToolNoise, toolNoise) self.toolbar3.AddSeparator() toolSave = self.toolbar3.AddTool(303, _('Save station data'), wx.Bitmap(self.currentdir+"/data/apply.png")) self.Bind(wx.EVT_TOOL, self.OnToolSave, toolSave) hbox1 = wx.BoxSizer(wx.VERTICAL) hbox1.Add(self.logger2, 1, wx.EXPAND, 0) hbox2 = wx.BoxSizer(wx.VERTICAL) hbox2.Add(mmsiLabel, 0, wx.ALL | wx.EXPAND, 2) hbox2.Add(self.mmsi, 0, wx.ALL | wx.EXPAND, 2) hbox2.Add(vesselNameLabel, 0, wx.ALL | wx.EXPAND, 2) hbox2.Add(self.vesselName, 0, wx.ALL | wx.EXPAND, 2) hbox2.Add(LOAlabel, 0, wx.ALL | wx.EXPAND, 2) hbox2.Add(self.LOA, 0, wx.ALL | wx.EXPAND, 2) hbox2.Add(portOffsetLabel, 0, wx.ALL | wx.EXPAND, 2) hbox2.Add(self.portOffset, 0, wx.ALL | wx.EXPAND, 2) hbox2.AddSpacer(10) hbox2.Add(unitsLabel, 0, wx.ALL | wx.EXPAND, 5) hbox3 = wx.BoxSizer(wx.VERTICAL) hbox3.Add(callSignLabel, 0, wx.ALL | wx.EXPAND, 2) hbox3.Add(self.callSign, 0, wx.ALL | wx.EXPAND, 2) hbox3.Add(vesselTypeLabel, 0, wx.ALL | wx.EXPAND, 2) hbox3.Add(self.vesselType, 0, wx.ALL | wx.EXPAND, 2) hbox3.Add(beamLabel, 0, wx.ALL | wx.EXPAND, 2) hbox3.Add(self.beam, 0, wx.ALL | wx.EXPAND, 2) hbox3.Add(bowOffsetLabel, 0, wx.ALL | wx.EXPAND, 2) hbox3.Add(self.bowOffset, 0, wx.ALL | wx.EXPAND, 2) hbox4 = wx.BoxSizer(wx.HORIZONTAL) hbox4.Add(hbox1, 2, wx.ALL | wx.EXPAND, 5) hbox4.Add(hbox2, 1, wx.ALL | wx.EXPAND, 5) hbox4.Add(hbox3, 1, wx.ALL | wx.EXPAND, 5) vbox = wx.BoxSizer(wx.VERTICAL) vbox.Add(self.toolbar3, 0) vbox.Add(hbox4, 1, wx.ALL | wx.EXPAND, 0) self.settings.SetSizer(vbox) def OnToolNoise(self,e): if self.toolbar3.GetToolState(304): self.conf.set('MAIANA', 'noiseDetect', '1') else: self.conf.set('MAIANA', 'noiseDetect', '0') def OnToolSave(self, event): mmsi = self.mmsi.GetValue() if not re.match('^[0-9]{9,9}$', mmsi): self.ShowStatusBarRED(_('Invalid MMSI')) return vesselName = self.vesselName.GetValue() vesselName = vesselName.upper() if not re.match('^[0-9A-Z]{1,20}$', vesselName): self.ShowStatusBarRED(_('Invalid vessel name')) return callSign = self.callSign.GetValue() if not re.match('^[0-9A-Z]{0,7}$', callSign): self.ShowStatusBarRED(_('Invalid call sign')) return vesselType = self.vesselType.GetSelection() if vesselType == 0: vesselType = '30' elif vesselType == 1: vesselType = '34' elif vesselType == 2: vesselType = '36' elif vesselType == 3: vesselType = '37' else: self.ShowStatusBarRED(_('Invalid vessel type')) return try: LOA = int(self.LOA.GetValue()) except: self.ShowStatusBarRED(_('Invalid LOA')) return try: beam = int(self.beam.GetValue()) except: self.ShowStatusBarRED(_('Invalid Beam')) return try: bowOffset = float(self.bowOffset.GetValue()) except: self.ShowStatusBarRED(_('Invalid bow offset')) return try: portOffset = float(self.portOffset.GetValue()) except: self.ShowStatusBarRED(_('Invalid port offset')) return command = 'station '+str(mmsi)+','+str(vesselName)+','+str(callSign)+','+str(vesselType)+','+str(LOA)+','+str(beam)+','+str(portOffset)+','+str(bowOffset)+'\r\n' ser = serial.Serial(self.device, 38400) ser.write(command.encode("utf-8")) self.onRead() def OnToolTX(self, event): ser = serial.Serial(self.device, 38400) if self.tx: ser.write('tx off\r\n'.encode("utf-8")) else: ser.write('tx on\r\n'.encode("utf-8")) self.onRead() def OnToolRefresh(self, event): self.onRead() ############################################################################ def pageFirmware(self): self.toolbar2 = wx.ToolBar(self.firmware, style=wx.TB_TEXT) toolRefresh = self.toolbar2.AddTool(201, _('Refresh'), wx.Bitmap(self.currentdir+"/data/refresh.png")) self.Bind(wx.EVT_TOOL, self.OnToolRefresh, toolRefresh) self.toolbar2.AddSeparator() toolDownload= self.toolbar2.AddTool(203, _('Download firmware'), wx.Bitmap(self.currentdir+"/data/download.png")) self.Bind(wx.EVT_TOOL, self.OnToolDownload, toolDownload) toolFile= self.toolbar2.AddTool(202, _('Update firmware'), wx.Bitmap(self.currentdir+"/data/file.png")) self.Bind(wx.EVT_TOOL, self.OnToolFile, toolFile) self.logger = rt.RichTextCtrl(self.firmware, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_DONTWRAP|wx.LC_SORT_ASCENDING) self.logger.SetMargins((10,10)) vbox = wx.BoxSizer(wx.VERTICAL) vbox.Add(self.toolbar2, 0, wx.EXPAND, 0) vbox.Add(self.logger, 1, wx.EXPAND, 0) self.firmware.SetSizer(vbox) def OnToolDownload(self,e): url = "https://github.com/peterantypas/maiana/tree/master/latest/Firmware/Transponder/Binaries" webbrowser.open(url, new=2) def OnToolFile(self,e): file_path = False dlg = wx.FileDialog(self, message=_('Choose a file'), defaultDir='~', defaultFile='', wildcard=_('bin files') + ' (*.bin)|*.bin|' + _('All files') + ' (*.*)|*.*', style=wx.FD_OPEN | wx.FD_CHANGE_DIR) if dlg.ShowModal() == wx.ID_OK: file_path = dlg.GetPath() dlg.Destroy() if file_path: try: fileName = file_path.split('/') fileName = fileName[-1] fileName = fileName.split('-') MCUtype = fileName[1].upper() if MCUtype != self.MCUtype: self.ShowStatusBarRED(_('MCU type mismatch: ')+MCUtype) return hardwareRevision = fileName[2].replace('hw','') hardwareRevision2 = self.hardwareRevision.split('.') del hardwareRevision2[-1] hardwareRevision2 = '.'.join(hardwareRevision2) if hardwareRevision != hardwareRevision2: self.ShowStatusBarRED(_('Hardware revision mismatch: ')+hardwareRevision) return except Exception as e: self.ShowStatusBarRED(_('Error processing file: ')+str(e)) return self.SetStatusText('') dlg = wx.MessageDialog(None, _( 'Your MAIANA device firmware will be updated, please do not disconnect or tamper with it during the update.\n\nDo you want to go ahead?'), _('Question'), wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) if dlg.ShowModal() == wx.ID_YES: self.logger.Clear() self.logger.WriteText(_("Stopping Signal K server")) self.logger.Newline() command = self.platform.admin+' python3 '+self.currentdir+'/fwupdate.py '+self.device+' '+file_path popen = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=True) for line in popen.stdout: if not 'Warning' in line and not 'WARNING' in line: self.logger.WriteText(line) self.ShowStatusBarYELLOW(_('Updating firmware, please wait... ')+line) self.logger.ShowPosition(self.logger.GetLastPosition()) self.logger.WriteText(_("Starting Signal K server")) self.SetStatusText('') dlg.Destroy() ################################################################################ def main(): try: platform2 = platform.Platform() if not platform2.postInstall(version,'maiana'): subprocess.Popen(['openplotterPostInstall', platform2.admin+' maianaPostInstall']) return except: pass app = wx.App() MyFrame().Show() time.sleep(1) app.MainLoop() if __name__ == '__main__': main()