ネットワークの接続状況をシステムトレイに表示する

最近、システムトレイのワイヤレスネットワーク接続のアイコンが全然信用できなかったりするので、ネットワークの接続状況をシステムトレイに表示するスクリプトをでっち上げてみた。要 Python + wxPython + dnspython。
見ればわかるとおり、DNSのレスポンスを heart beat 代わりに使って 10 秒ごとに接続状況をチェックしてアイコンの色を変化させるだけ。
まぁ、こんなスクリプト公開しても需要なんてなさそうだけどな。

参考

import wx
import dns.resolver
import sys

ID_ICON_TIMER = wx.NewId()
INTERVAL = 10000                # in msec
DNS_TIMEOUT = 5                 # in sec

class MyTaskBarIcon(wx.TaskBarIcon):
    def __init__(self, frame):
        wx.TaskBarIcon.__init__(self)
        self.frame = frame

    def CreatePopupMenu(self):
        return self._create_menu()

    def OnClose(self, _):
        self.frame.Close(1)

    def _create_menu(self):
        menu = wx.Menu()
        id = wx.NewId()
        menu.Append(id, "Exit")
        wx.EVT_MENU(self, id, self.OnClose)
        return menu


class TaskBarApp(wx.Frame):
    def __init__(self, parent, id, title):
        style = wx.FRAME_NO_TASKBAR | wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Frame.__init__(self, parent, -1, title, size = (1, 1),
                          style = style)

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

        self.timer = wx.Timer(self, ID_ICON_TIMER)
        self.Bind(wx.EVT_TIMER, self.CheckConnection, self.timer, ID_ICON_TIMER)
        self.timer.Start(INTERVAL)

        self.resolver = dns.resolver.get_default_resolver()
        self.resolver.lifetime = DNS_TIMEOUT

        self.tbicon = MyTaskBarIcon(self)

        self.Show(True)
        self.CheckConnection(None)

    def CheckConnection(self, _):
        image = wx.EmptyImage(16, 16)
        text = 'Connection: '
        try:
            self.resolver.query("www.google.com")
            image.SetData('\x11\xff\x11' * 256)
            text += 'OK'
        except dns.resolver.Timeout:
            image.SetData('\xff\x11\x11' * 256)
            text += 'NG'
        
        bmp = image.ConvertToBitmap()
        bmp.SetMask(wx.Mask(bmp, wx.WHITE))

        icon = wx.EmptyIcon()
        icon.CopyFromBitmap(bmp)
        self.tbicon.SetIcon(icon, text)

    def OnClose(self, _):
        self.tbicon.Destroy()
        self.Destroy()


class MyApp(wx.App):
    def OnInit(self):
        frame = TaskBarApp(None, -1, ' ')
        frame.Center(wx.BOTH)
        frame.Show(False)
        return True

def main(argv=None):
    if argv is None:
        argv = sys.argv
    app = MyApp(0)
    app.MainLoop()

if __name__ == '__main__':
    main()