Exemple #1
0
class HondaECU_ControlPanel(wx.Frame):
    def __init__(self,
                 version_full,
                 nobins=False,
                 restrictions=None,
                 force_restrictions=False):
        self.nobins = nobins
        self.restrictions = restrictions
        self.force_restrictions = force_restrictions
        self.run = True
        self.active_ftdi_device = None
        self.ftdi_devices = {}
        self.__clear_data()

        if getattr(sys, 'frozen', False):
            self.basepath = sys._MEIPASS
        else:
            self.basepath = os.path.dirname(os.path.realpath(__file__))

        self.version_full = version_full
        self.version_short = self.version_full.split("-")[0]

        self.apps = {
            "flash": {
                "label":
                "Flash",
                "icon":
                "images/chip2.png",
                "conflicts": ["data", "hrc"],
                "panel":
                HondaECU_FlashPanel,
                "disabled":
                True,
                "enable": [
                    ECUSTATE.OK, ECUSTATE.RECOVER_OLD, ECUSTATE.RECOVER_NEW,
                    ECUSTATE.WRITEx00, ECUSTATE.WRITEx30, ECUSTATE.READ
                ],
            },
            "tunehelper": {
                "label": "Tune",
                "icon": "images/bike.png",
                "panel": HondaECU_TunePanelHelper,
            },
            "info": {
                "label": "ECU Info",
                "icon": "images/info2.png",
                "conflicts": ["flash", "hrc"],
                "panel": HondaECU_InfoPanel,
            },
            "data": {
                "label": "Data Logging",
                "icon": "images/monitor.png",
                "conflicts": ["flash", "hrc"],
                "panel": HondaECU_DatalogPanel,
                "disabled": True,
                "enable": [ECUSTATE.OK],
            },
            "dtc": {
                "label": "Trouble Codes",
                "icon": "images/warning.png",
                "conflicts": ["flash", "hrc"],
                "panel": HondaECU_ErrorPanel,
                "disabled": True,
                "enable": [ECUSTATE.OK],
            },
            # "hrcsettings": {
            # 	"label":"HRC Settings",
            # 	"icon":"images/cog.png",
            # 	"conflicts":["flash","data","dtc","info"],
            # 	"panel":HondaECU_HRCDataSettingsPanel,
            # 	"disabled":True,
            # 	"enable": [ECUSTATE.OK],
            # },
        }
        self.appanels = {}

        wx.Frame.__init__(self,
                          None,
                          title="HondaECU %s :: Control Panel" %
                          (self.version_short),
                          style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER,
                          size=(500, 300))

        ib = wx.IconBundle()
        ib.AddIcon(os.path.join(self.basepath, "images", "honda.ico"))
        self.SetIcons(ib)

        self.menubar = wx.MenuBar()
        self.SetMenuBar(self.menubar)
        fileMenu = wx.Menu()
        self.menubar.Append(fileMenu, '&File')
        self.devicesMenu = wx.Menu()
        fileMenu.AppendSubMenu(self.devicesMenu, "Devices")
        fileMenu.AppendSeparator()
        quitItem = wx.MenuItem(fileMenu, wx.ID_EXIT, '&Quit\tCtrl+Q')
        self.Bind(wx.EVT_MENU, self.OnClose, quitItem)
        fileMenu.Append(quitItem)
        helpMenu = wx.Menu()
        self.menubar.Append(helpMenu, '&Help')
        debugItem = wx.MenuItem(helpMenu, wx.ID_ANY, 'Show debug log')
        self.Bind(wx.EVT_MENU, self.OnDebug, debugItem)
        helpMenu.Append(debugItem)
        helpMenu.AppendSeparator()
        detectmapItem = wx.MenuItem(helpMenu, wx.ID_ANY, 'Detect map id')
        self.Bind(wx.EVT_MENU, self.OnDetectMap, detectmapItem)
        helpMenu.Append(detectmapItem)
        checksumItem = wx.MenuItem(helpMenu, wx.ID_ANY,
                                   'Validate bin checksum')
        self.Bind(wx.EVT_MENU, self.OnBinChecksum, checksumItem)
        helpMenu.Append(checksumItem)

        self.statusbar = self.CreateStatusBar(1)
        self.statusbar.SetSize((-1, 28))
        self.statusbar.SetStatusStyles([wx.SB_SUNKEN])
        self.SetStatusBar(self.statusbar)

        self.outerp = wx.Panel(self)
        self.wrappanel = wx.Panel(self.outerp)
        wrapsizer = wx.WrapSizer(wx.HORIZONTAL)
        self.appbuttons = {}
        for a, d in self.apps.items():
            icon = wx.Image(os.path.join(self.basepath, d["icon"]),
                            wx.BITMAP_TYPE_ANY).ConvertToBitmap()
            enablestates = None
            if "enable" in d:
                enablestates = d["enable"]
            self.appbuttons[a] = HondaECU_AppButton(a,
                                                    enablestates,
                                                    self.wrappanel,
                                                    wx.ID_ANY,
                                                    icon,
                                                    label=d["label"])
            if "disabled" in d and d["disabled"]:
                self.appbuttons[a].Disable()
            wrapsizer.Add(self.appbuttons[a], 0)
            self.Bind(wx.EVT_BUTTON, self.OnAppButtonClicked,
                      self.appbuttons[a])
        self.wrappanel.SetSizer(wrapsizer)

        self.outersizer = wx.BoxSizer(wx.VERTICAL)
        self.outersizer.Add(self.wrappanel, 1, wx.EXPAND)
        self.outerp.SetSizer(self.outersizer)

        self.mainsizer = wx.BoxSizer(wx.VERTICAL)
        self.mainsizer.Add(self.outerp, 1, wx.EXPAND)
        self.SetSizer(self.mainsizer)

        self.Bind(wx.EVT_CLOSE, self.OnClose)

        self.debuglog = HondaECU_LogPanel(self)

        dispatcher.connect(self.USBMonitorHandler,
                           signal="USBMonitor",
                           sender=dispatcher.Any)
        dispatcher.connect(self.AppPanelHandler,
                           signal="AppPanel",
                           sender=dispatcher.Any)
        dispatcher.connect(self.KlineWorkerHandler,
                           signal="KlineWorker",
                           sender=dispatcher.Any)
        dispatcher.connect(self.TunePanelHelperHandler,
                           signal="TunePanelHelper",
                           sender=dispatcher.Any)

        self.usbmonitor = USBMonitor(self)
        self.klineworker = KlineWorker(self)

        self.Layout()
        self.mainsizer.Fit(self)
        self.Center()
        self.Show()

        self.usbmonitor.start()
        self.klineworker.start()

    def __clear_data(self):
        self.ecuinfo = {}

    def TunePanelHelperHandler(self, xdf, bin, metainfo, htf=None):
        if htf != None:
            tar = tarfile.open(htf, "r:xz")
            xdfs = None
            binorig = None
            binmod = None
            metainfo = None
            for f in tar.getnames():
                if f == "metainfo.json":
                    metainfo = json.load(tar.extractfile(f))
                else:
                    b, e = os.path.splitext(f)
                    if e == ".xdf":
                        xdfs = tar.extractfile(f).read()
                    elif e == ".bin":
                        x, y = os.path.splitext(b)
                        if y == ".orig":
                            binorig = tar.extractfile(f).read()
                        elif y == ".mod":
                            binmod = tar.extractfile(f).read()
            if xdfs != None and binorig != None and binmod != None and metainfo != None:
                tp = TunePanel(self, metainfo, xdfs, binorig, binmod)
        else:
            fbin = open(bin, "rb")
            byts = bytearray(fbin.read(os.path.getsize(bin)))
            fbin.close()
            fbin = open(xdf, "rb")
            xdfs = fbin.read(os.path.getsize(xdf))
            fbin.close()
            tp = TunePanel(self, metainfo, xdfs, byts)

    def KlineWorkerHandler(self, info, value):
        if info in ["ecmid", "flashcount", "dtc", "dtccount", "state"]:
            self.ecuinfo[info] = value
            if info == "state":
                for a, d in self.apps.items():
                    if "enable" in d:
                        if value in d["enable"]:
                            self.appbuttons[a].Enable()
                        else:
                            self.appbuttons[a].Disable()
        elif info == "data":
            if not info in self.ecuinfo:
                self.ecuinfo[info] = {}
            self.ecuinfo[info][value[0]] = value[1:]

    def OnClose(self, event):
        self.run = False
        self.usbmonitor.join()
        self.klineworker.join()
        for w in wx.GetTopLevelWindows():
            w.Destroy()

    def OnDetectMap(self, event):
        with wx.FileDialog(self,
                           "Open ECU dump file",
                           wildcard="ECU dump (*.bin)|*.bin",
                           style=wx.FD_OPEN
                           | wx.FD_FILE_MUST_EXIST) as fileDialog:
            if fileDialog.ShowModal() == wx.ID_CANCEL:
                return
            pathname = fileDialog.GetPath()
            ecupn = os.path.splitext(os.path.split(pathname)[-1])[0]
            for i in ECM_IDs.values():
                if ecupn == i["pn"] and "keihinaddr" in i:
                    fbin = open(pathname, "rb")
                    nbyts = os.path.getsize(pathname)
                    byts = bytearray(fbin.read(nbyts))
                    fbin.close()
                    idadr = int(i["keihinaddr"], 16)
                    self.statusbar.SetStatusText(
                        "Map ID: " + byts[idadr:(idadr + 7)].decode("ascii"),
                        0)
                    return
            self.statusbar.SetStatusText("Map ID: unknown", 0)

    def OnBinChecksum(self, event):
        with wx.FileDialog(self,
                           "Open ECU dump file",
                           wildcard="ECU dump (*.bin)|*.bin",
                           style=wx.FD_OPEN
                           | wx.FD_FILE_MUST_EXIST) as fileDialog:
            if fileDialog.ShowModal() == wx.ID_CANCEL:
                return
            pathname = fileDialog.GetPath()
            fbin = open(pathname, "rb")
            nbyts = os.path.getsize(pathname)
            byts = bytearray(fbin.read(nbyts))
            fbin.close()
            self.statusbar.SetStatusText(
                "Checksum: %s" %
                ("good" if checksum8bitHonda(byts) == 0 else "bad"), 0)
            return

    def OnDebug(self, event):
        self.debuglog.Show()

    def OnAppButtonClicked(self, event):
        b = event.GetEventObject()
        if not b.appid in self.appanels:
            enablestates = None
            if "enable" in self.apps[b.appid]:
                enablestates = self.apps[b.appid]["enable"]
            self.appanels[b.appid] = self.apps[b.appid]["panel"](
                self, b.appid, self.apps[b.appid], enablestates)
            self.appbuttons[b.appid].Disable()
        self.appanels[b.appid].Raise()

    def USBMonitorHandler(self, action, vendor, product, serial):
        dirty = False
        if action == "add":
            if not serial in self.ftdi_devices:
                self.ftdi_devices[serial] = (vendor, product)
                dirty = True
        elif action == "remove":
            if serial in self.ftdi_devices:
                if serial == self.active_ftdi_device:
                    dispatcher.send(signal="FTDIDevice",
                                    sender=self,
                                    action="deactivate",
                                    vendor=vendor,
                                    product=product,
                                    serial=serial)
                    self.active_ftdi_device = None
                    self.__clear_data()
                del self.ftdi_devices[serial]
                dirty = True
        if len(self.ftdi_devices) > 0:
            if not self.active_ftdi_device:
                self.active_ftdi_device = list(self.ftdi_devices.keys())[0]
                dispatcher.send(signal="FTDIDevice",
                                sender=self,
                                action="activate",
                                vendor=vendor,
                                product=product,
                                serial=serial)
                dirty = True
        else:
            pass
        if dirty:
            for i in self.devicesMenu.GetMenuItems():
                self.devicesMenu.Remove(i)
            for s in self.ftdi_devices:
                rb = self.devicesMenu.AppendRadioItem(
                    wx.ID_ANY, "%s : %s : %s" %
                    (self.ftdi_devices[s][0], self.ftdi_devices[s][1], s))
                self.Bind(wx.EVT_MENU, self.OnDeviceSelected, rb)
            if self.active_ftdi_device:
                self.statusbar.SetStatusText(
                    "%s : %s : %s" %
                    (self.ftdi_devices[self.active_ftdi_device][0],
                     self.ftdi_devices[self.active_ftdi_device][1],
                     self.active_ftdi_device), 0)
                self.devicesMenu.FindItemByPosition(
                    list(self.ftdi_devices.keys()).index(
                        self.active_ftdi_device)).Check()
            else:
                self.statusbar.SetStatusText("", 0)

    def OnDeviceSelected(self, event):
        s = list(self.ftdi_devices.keys())[[
            m.IsChecked() for m in event.GetEventObject().GetMenuItems()
        ].index(True)]
        if s != self.active_ftdi_device:
            if self.active_ftdi_device != None:
                dispatcher.send(
                    signal="FTDIDevice",
                    sender=self,
                    action="deactivate",
                    vendor=self.ftdi_devices[self.active_ftdi_device],
                    product=self.ftdi_devices[self.active_ftdi_device],
                    serial=self.active_ftdi_device)
            self.__clear_data()
            self.active_ftdi_device = s
            dispatcher.send(signal="FTDIDevice",
                            sender=self,
                            action="activate",
                            vendor=self.ftdi_devices[self.active_ftdi_device],
                            product=self.ftdi_devices[self.active_ftdi_device],
                            serial=self.active_ftdi_device)
            self.statusbar.SetStatusText(
                "%s : %s : %s" %
                (self.ftdi_devices[self.active_ftdi_device][0],
                 self.ftdi_devices[self.active_ftdi_device][1],
                 self.active_ftdi_device), 0)

    def AppPanelHandler(self, appid, action):
        if action == "close":
            if appid in self.appanels:
                del self.appanels[appid]
                self.appbuttons[appid].Enable()
Exemple #2
0
class HondaECU_ControlPanel(wx.Frame):
    def __init__(self,
                 version_full,
                 nobins=False,
                 restrictions=None,
                 force_restrictions=False):
        self.prefsdir = user_data_dir("HondaECU", "MCUInnovationsInc")
        if not os.path.exists(self.prefsdir):
            os.makedirs(self.prefsdir)
        self.configfile = os.path.join(self.prefsdir, 'hondaecu.ini')
        self.config = configparser.ConfigParser()
        if os.path.isfile(self.configfile):
            self.config.read(self.configfile)
        if not "retries" in self.config['DEFAULT']:
            self.config['DEFAULT'] = {'retries': '1'}
        self.nobins = nobins
        self.restrictions = restrictions
        self.force_restrictions = force_restrictions
        self.run = True
        self.active_ftdi_device = None
        self.ftdi_devices = {}
        self.__clear_data()

        if getattr(sys, 'frozen', False):
            self.basepath = sys._MEIPASS
        else:
            self.basepath = os.path.dirname(os.path.realpath(__file__))

        self.version_full = version_full
        self.version_short = self.version_full.split("-")[0]

        self.apps = {
            "flash": {
                "label": "Flash",
                "panel": HondaECU_FlashPanel,
            },
            # "hrc": {
            # 	"label":"HRC Data Settings",
            # 	"panel":HondaECU_HRCDataSettingsPanel,
            # },
            "data": {
                "label": "Data Logging",
                "panel": HondaECU_DatalogPanel,
            },
            "dtc": {
                "label": "Trouble Codes",
                "panel": HondaECU_ErrorPanel,
            },
        }
        self.appanels = {}

        wx.Frame.__init__(self,
                          None,
                          title="HondaECU %s" % (self.version_short),
                          style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER,
                          size=(500, 300))

        ib = wx.IconBundle()
        ib.AddIcon(os.path.join(self.basepath, "images", "honda.ico"))
        self.SetIcons(ib)

        self.menubar = wx.MenuBar()
        self.SetMenuBar(self.menubar)
        fileMenu = wx.Menu()
        self.menubar.Append(fileMenu, '&File')
        quitItem = wx.MenuItem(fileMenu, wx.ID_EXIT, '&Quit\tCtrl+Q')
        self.Bind(wx.EVT_MENU, self.OnClose, quitItem)
        fileMenu.Append(quitItem)
        helpMenu = wx.Menu()
        self.menubar.Append(helpMenu, '&Help')
        debugItem = wx.MenuItem(helpMenu, wx.ID_ANY, 'Show debug log')
        self.Bind(wx.EVT_MENU, self.OnDebug, debugItem)
        helpMenu.Append(debugItem)
        helpMenu.AppendSeparator()
        detectmapItem = wx.MenuItem(helpMenu, wx.ID_ANY, 'Detect map id')
        self.Bind(wx.EVT_MENU, self.OnDetectMap, detectmapItem)
        helpMenu.Append(detectmapItem)
        checksumItem = wx.MenuItem(helpMenu, wx.ID_ANY,
                                   'Validate bin checksum')
        self.Bind(wx.EVT_MENU, self.OnBinChecksum, checksumItem)
        helpMenu.Append(checksumItem)

        self.statusicons = [
            wx.Image(os.path.join(self.basepath, "images/bullet_black.png"),
                     wx.BITMAP_TYPE_ANY).ConvertToBitmap(),
            wx.Image(os.path.join(self.basepath, "images/bullet_yellow.png"),
                     wx.BITMAP_TYPE_ANY).ConvertToBitmap(),
            wx.Image(os.path.join(self.basepath, "images/bullet_green.png"),
                     wx.BITMAP_TYPE_ANY).ConvertToBitmap(),
            wx.Image(os.path.join(self.basepath, "images/bullet_blue.png"),
                     wx.BITMAP_TYPE_ANY).ConvertToBitmap(),
            wx.Image(os.path.join(self.basepath, "images/bullet_purple.png"),
                     wx.BITMAP_TYPE_ANY).ConvertToBitmap(),
            wx.Image(os.path.join(self.basepath, "images/bullet_red.png"),
                     wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        ]
        self.statusbar = ESB.EnhancedStatusBar(self, -1)
        self.SetStatusBar(self.statusbar)
        self.statusbar.SetSize((-1, 28))
        self.statusicon = wx.StaticBitmap(self.statusbar)
        self.statusicon.SetBitmap(self.statusicons[0])
        self.ecmidl = wx.StaticText(self.statusbar)
        self.flashcountl = wx.StaticText(self.statusbar)
        self.dtccountl = wx.StaticText(self.statusbar)
        self.statusbar.SetFieldsCount(4)
        self.statusbar.SetStatusWidths([32, 170, 130, 110])
        self.statusbar.AddWidget(self.statusicon, pos=0)
        self.statusbar.AddWidget(self.ecmidl,
                                 pos=1,
                                 horizontalalignment=ESB.ESB_ALIGN_LEFT)
        self.statusbar.AddWidget(self.flashcountl,
                                 pos=2,
                                 horizontalalignment=ESB.ESB_ALIGN_LEFT)
        self.statusbar.AddWidget(self.dtccountl,
                                 pos=3,
                                 horizontalalignment=ESB.ESB_ALIGN_LEFT)
        self.statusbar.SetStatusStyles(
            [wx.SB_SUNKEN, wx.SB_SUNKEN, wx.SB_SUNKEN, wx.SB_SUNKEN])

        self.outerp = wx.Panel(self)

        self.adapterboxp = wx.Panel(self.outerp)
        self.adapterboxsizer = wx.StaticBoxSizer(wx.VERTICAL, self.adapterboxp,
                                                 "FTDI Devices:")
        self.adapterboxp.SetSizer(self.adapterboxsizer)
        self.adapterlist = wx.Choice(self.adapterboxp,
                                     wx.ID_ANY,
                                     size=(-1, 32))
        self.adapterboxsizer.Add(self.adapterlist,
                                 1,
                                 wx.ALL | wx.EXPAND,
                                 border=10)

        self.labelbook = LB.LabelBook(self.outerp,
                                      agwStyle=LB.INB_FIT_LABELTEXT
                                      | LB.INB_LEFT | LB.INB_DRAW_SHADOW
                                      | LB.INB_GRADIENT_BACKGROUND)

        self.bookpages = {}
        maxdims = [0, 0]
        for a, d in self.apps.items():
            enablestates = None
            if "enable" in self.apps[a]:
                enablestates = self.apps[a]["enable"]
            self.bookpages[a] = d["panel"](self, a, self.apps[a], enablestates)
            x, y = self.bookpages[a].GetSize()
            if x > maxdims[0]:
                maxdims[0] = x
            if y > maxdims[1]:
                maxdims[1] = y
            self.labelbook.AddPage(self.bookpages[a], d["label"], False)
        for k in self.bookpages.keys():
            self.bookpages[k].SetMinSize(maxdims)

        self.modelp = wx.Panel(self.outerp, style=wx.BORDER_SUNKEN)
        self.modelbox = wx.BoxSizer(wx.VERTICAL)
        self.modell = wx.StaticText(self.modelp,
                                    label="",
                                    style=wx.ALIGN_CENTRE_HORIZONTAL
                                    | wx.ALIGN_CENTRE_VERTICAL)
        self.ecupnl = wx.StaticText(self.modelp,
                                    label="",
                                    style=wx.ALIGN_CENTRE_HORIZONTAL
                                    | wx.ALIGN_CENTRE_VERTICAL)
        font1 = self.GetFont().Bold()
        font2 = self.GetFont().Bold()
        font1.SetPointSize(font1.GetPointSize() * 1.25)
        font2.SetPointSize(font2.GetPointSize() * 2)
        self.modell.SetFont(font2)
        self.ecupnl.SetFont(font1)
        self.modelbox.AddSpacer(5)
        self.modelbox.Add(self.modell, 0, wx.CENTER)
        self.modelbox.Add(self.ecupnl, 0, wx.CENTER)
        self.modelbox.AddSpacer(5)
        self.modelp.SetSizer(self.modelbox)

        self.outersizer = wx.BoxSizer(wx.VERTICAL)
        self.outersizer.Add(self.adapterboxp, 0, wx.EXPAND | wx.ALL, 5)
        self.outersizer.Add(self.modelp, 0, wx.EXPAND | wx.ALL, 5)
        self.outersizer.Add(self.labelbook, 2, wx.EXPAND | wx.ALL, 5)
        self.outerp.SetSizer(self.outersizer)

        self.mainsizer = wx.BoxSizer(wx.VERTICAL)
        self.mainsizer.Add(self.outerp, 1, wx.EXPAND)
        self.mainsizer.SetSizeHints(self)
        self.SetSizer(self.mainsizer)

        self.adapterlist.Bind(wx.EVT_CHOICE, self.OnAdapterSelected)
        self.Bind(wx.EVT_CLOSE, self.OnClose)

        self.debuglog = HondaECU_LogPanel(self)

        dispatcher.connect(self.USBMonitorHandler,
                           signal="USBMonitor",
                           sender=dispatcher.Any)
        dispatcher.connect(self.AppPanelHandler,
                           signal="AppPanel",
                           sender=dispatcher.Any)
        dispatcher.connect(self.KlineWorkerHandler,
                           signal="KlineWorker",
                           sender=dispatcher.Any)

        self.usbmonitor = USBMonitor(self)
        self.klineworker = KlineWorker(self)

        self.Layout()
        self.Center()
        self.Show()

        self.usbmonitor.start()
        self.klineworker.start()

        self.powercycle = PowerCycleDialog(None)

    def __clear_data(self):
        self.ecuinfo = {}

    def __clear_widgets(self):
        self.ecmidl.SetLabel("")
        self.flashcountl.SetLabel("")
        self.dtccountl.SetLabel("")
        self.modell.SetLabel("")
        self.ecupnl.SetLabel("")
        self.statusicon.SetBitmap(self.statusicons[0])
        self.statusbar.OnSize(None)

    def KlineWorkerHandler(self, info, value):
        if info in ["ecmid", "flashcount", "dtc", "dtccount", "state"]:
            self.ecuinfo[info] = value
            if info == "state":
                self.statusicon.SetToolTip(
                    wx.ToolTip("state: %s" % (str(value).split(".")[-1])))
                if value in [ECUSTATE.OFF, ECUSTATE.UNKNOWN]:  #BLACK
                    self.__clear_widgets()
                    # self.statusicon.SetBitmap(self.statusicons[0])
                elif value in [ECUSTATE.RECOVER_NEW,
                               ECUSTATE.RECOVER_OLD]:  #YELLOW
                    self.statusicon.SetBitmap(self.statusicons[1])
                elif value in [ECUSTATE.OK]:  #GREEN
                    self.statusicon.SetBitmap(self.statusicons[2])
                elif value in [ECUSTATE.FLASH]:  #BLUE
                    self.statusicon.SetBitmap(self.statusicons[3])
                elif value in [ECUSTATE.SECURE]:  #PURPLE
                    self.statusicon.SetBitmap(self.statusicons[4])
                # elif value in [ECUSTATE.POSTWRITEx00,ECUSTATE.POSTWRITEx12]: #RED
                # 	self.statusicon.SetBitmap(self.statusicons[5])
            elif info == "ecmid":
                if len(value) > 0:
                    ecmid = " ".join(["%02x" % i for i in value])
                    self.ecmidl.SetLabel("   ECM ID: %s" % ecmid)
                    if value in ECM_IDs:
                        model = "%s (%s)" % (ECM_IDs[value]["model"],
                                             ECM_IDs[value]["year"])
                        pn = ECM_IDs[value]["pn"]
                    else:
                        model = "Unknown Model"
                        pn = "-"
                        for m in ECM_IDs.keys():
                            if m[:3] == value[:3]:
                                model = "%s (%s)" % (ECM_IDs[m]["model"],
                                                     ECM_IDs[m]["year"])
                                break
                    self.modell.SetLabel(model)
                    self.ecupnl.SetLabel(pn)
                    self.Layout()
            elif info == "flashcount":
                if value >= 0:
                    self.flashcountl.SetLabel("   Flash Count: %d" % value)
            elif info == "dtccount":
                if value >= 0:
                    self.dtccountl.SetLabel("   DTC Count: %d" % value)
            self.statusbar.OnSize(None)
        elif info == "data":
            if not info in self.ecuinfo:
                self.ecuinfo[info] = {}
            self.ecuinfo[info][value[0]] = value[1:]

    def OnClose(self, event):
        with open(self.configfile, 'w') as configfile:
            self.config.write(configfile)
        self.run = False
        self.usbmonitor.join()
        self.klineworker.join()
        for w in wx.GetTopLevelWindows():
            w.Destroy()

    def OnDetectMap(self, event):
        with wx.FileDialog(self,
                           "Open ECU dump file",
                           wildcard="ECU dump (*.bin)|*.bin",
                           style=wx.FD_OPEN
                           | wx.FD_FILE_MUST_EXIST) as fileDialog:
            if fileDialog.ShowModal() == wx.ID_CANCEL:
                return
            pathname = fileDialog.GetPath()
            ecupn = os.path.splitext(os.path.split(pathname)[-1])[0]
            for i in ECM_IDs.values():
                if ecupn == i["pn"] and "keihinaddr" in i:
                    fbin = open(pathname, "rb")
                    nbyts = os.path.getsize(pathname)
                    byts = bytearray(fbin.read(nbyts))
                    fbin.close()
                    idadr = int(i["keihinaddr"], 16)
                    wx.MessageDialog(
                        None,
                        "Map ID: " + byts[idadr:(idadr + 7)].decode("ascii"),
                        "", wx.CENTRE | wx.STAY_ON_TOP).ShowModal()
                    return
            wx.MessageDialog(None, "Map ID: unknown", "",
                             wx.CENTRE | wx.STAY_ON_TOP).ShowModal()

    def OnBinChecksum(self, event):
        with wx.FileDialog(self,
                           "Open ECU dump file",
                           wildcard="ECU dump (*.bin)|*.bin",
                           style=wx.FD_OPEN
                           | wx.FD_FILE_MUST_EXIST) as fileDialog:
            if fileDialog.ShowModal() == wx.ID_CANCEL:
                return
            pathname = fileDialog.GetPath()
            fbin = open(pathname, "rb")
            nbyts = os.path.getsize(pathname)
            byts = bytearray(fbin.read(nbyts))
            fbin.close()
            wx.MessageDialog(
                None, "Checksum: %s" %
                ("good" if checksum8bitHonda(byts) == 0 else "bad"), "",
                wx.CENTRE | wx.STAY_ON_TOP).ShowModal()
            return

    def OnDebug(self, event):
        self.debuglog.Show()

    def OnAppButtonClicked(self, event):
        b = event.GetEventObject()
        if not b.appid in self.appanels:
            enablestates = None
            if "enable" in self.apps[b.appid]:
                enablestates = self.apps[b.appid]["enable"]
            self.appanels[b.appid] = self.apps[b.appid]["panel"](
                self, b.appid, self.apps[b.appid], enablestates)
            self.appbuttons[b.appid].Disable()
        self.appanels[b.appid].Raise()

    def USBMonitorHandler(self, action, device, config):
        dirty = False
        if action == "error":
            if platform.system() == "Windows":
                wx.MessageDialog(
                    None, "libusb error: make sure libusbk is installed", "",
                    wx.CENTRE | wx.STAY_ON_TOP).ShowModal()
        elif action == "add":
            if not device in self.ftdi_devices:
                self.ftdi_devices[device] = config
                dirty = True
        elif action == "remove":
            if device in self.ftdi_devices:
                if device == self.active_ftdi_device:
                    dispatcher.send(
                        signal="FTDIDevice",
                        sender=self,
                        action="deactivate",
                        device=self.active_ftdi_device,
                        config=self.ftdi_devices[self.active_ftdi_device])
                    self.active_ftdi_device = None
                    self.__clear_data()
                del self.ftdi_devices[device]
                dirty = True
        if len(self.ftdi_devices) > 0:
            if not self.active_ftdi_device:
                self.active_ftdi_device = list(self.ftdi_devices.keys())[0]
                dispatcher.send(
                    signal="FTDIDevice",
                    sender=self,
                    action="activate",
                    device=self.active_ftdi_device,
                    config=self.ftdi_devices[self.active_ftdi_device])
                dirty = True
        else:
            pass
        if dirty:
            self.adapterlist.Clear()
            for device in self.ftdi_devices:
                cfg = self.ftdi_devices[device]
                self.adapterlist.Append(
                    "Bus %03d Device %03d: %s %s %s" %
                    (cfg.bus, cfg.address,
                     usb.util.get_string(cfg, cfg.iManufacturer),
                     usb.util.get_string(cfg, cfg.iProduct),
                     usb.util.get_string(cfg, cfg.iSerialNumber)))
            if self.active_ftdi_device:
                self.adapterlist.SetSelection(
                    list(self.ftdi_devices.keys()).index(
                        self.active_ftdi_device))

    def OnAdapterSelected(self, event):
        device = list(
            self.ftdi_devices.keys())[self.adapterlist.GetSelection()]
        if device != self.active_ftdi_device:
            if self.active_ftdi_device != None:
                dispatcher.send(
                    signal="FTDIDevice",
                    sender=self,
                    action="deactivate",
                    device=self.active_ftdi_device,
                    config=self.ftdi_devices[self.active_ftdi_device])
            self.__clear_data()
            self.active_ftdi_device = device
            dispatcher.send(signal="FTDIDevice",
                            sender=self,
                            action="activate",
                            device=self.active_ftdi_device,
                            config=self.ftdi_devices[self.active_ftdi_device])

    def AppPanelHandler(self, appid, action):
        if action == "close":
            if appid in self.appanels:
                del self.appanels[appid]
                self.appbuttons[appid].Enable()