Exemplo n.º 1
0
class SignalKScope(SignalKScopeBase):
    def __init__(self):
        super(SignalKScope, self).__init__(None)

        self.plot = SignalKPlot()
        self.glContext = wx.glcanvas.GLContext(self.glArea)

        self.client = SignalKClientFromArgs(sys.argv[:2], True, self.on_con)
        self.host_port = self.client.host_port
        self.client.autoreconnect = False
        self.value_list = self.client.list_values()
        self.plot.init(self.value_list)
        self.watches = {}

        watches = sys.argv[2:]
        for name in sorted(self.value_list):
            if self.value_list[name]['type'] != 'SensorValue':
                continue

            i = self.clValues.Append(name)
            self.watches[name] = False
            for arg in watches:
                if arg == name:
                    self.clValues.Check(i, True)
                    self.watches[name] = True
                    watches.remove(name)
        for arg in watches:
            print 'value not found:', arg

        self.on_con(self.client)

        self.timer = wx.Timer(self, wx.ID_ANY)
        self.Bind(wx.EVT_TIMER, self.receive_messages, id=wx.ID_ANY)
        self.timer.Start(100)

        self.sTime.SetValue(self.plot.disptime)
        self.plot_reshape = False

    def on_con(self, client):
        self.plot.add_blank()
        for i in range(self.clValues.GetCount()):
            if self.clValues.IsChecked(i):
                client.watch(self.clValues.GetString(i))
                self.watches[self.clValues.GetString(i)] = True

    def receive_messages(self, event):
        if not self.client:
            try:
                host, port = self.host_port
                self.client = SignalKClient(self.on_con,
                                            host,
                                            port,
                                            autoreconnect=False)
                self.timer.Start(100)
            except socket.error:
                self.timer.Start(1000)
                return

        refresh = False
        while True:
            result = False
            try:
                result = self.client.receive_single()
            except ConnectionLost:
                self.client = False
                return
            except:
                pass
            if not result:
                break

            if self.watches[result[0]]:
                if self.plot.read_data(result):
                    refresh = True

        if refresh:
            self.glArea.Refresh()

    def onValueSelected(self, event):
        self.plot.select(self.clValues.GetStringSelection())

    def onValueToggled(self, event):
        value = self.clValues.IsChecked(event.GetInt())
        self.watches[event.GetString()] = value
        self.client.watch(event.GetString(), value)
        self.plot.add_blank(event.GetString())

    def onPaintGL(self, event):
        dc = wx.PaintDC(self.glArea)
        self.glArea.SetCurrent(self.glContext)
        self.plot.fft_on = self.cbfftw.GetValue()

        if self.plot_reshape:
            apply(self.plot.reshape, self.plot_reshape)
            self.plot_reshape = False

        self.plot.display()
        self.glArea.SwapBuffers()

    def onSizeGL(self, event):
        self.plot_reshape = (event.GetSize().x, event.GetSize().y)

    def onMouseEvents(self, event):
        self.glArea.SetFocus()

        pos = event.GetPosition()
        if event.LeftDown():
            self.lastmouse = pos

        if event.RightDown():
            self.plot.curtrace.center()
            self.glArea.Refresh()

        if event.Dragging():
            offset = pos[1] - self.lastmouse[1]
            self.plot.adjustoffset(offset, self.glArea.GetSize().y)
            self.lastmouse = pos
            self.glArea.Refresh()

        rotation = event.GetWheelRotation() / 60
        if rotation:
            if rotation > 0:
                self.plot.increasescale()
            else:
                self.plot.decreasescale()
            self.glArea.Refresh()

    def onKeyPress(self, event):
        wxglutkeypress(event, self.plot.special, self.plot.key)
        self.cbfftw.SetValue(self.plot.fft_on)
        self.glArea.Refresh()

    def onZero(self, event):
        if self.plot.curtrace:
            self.plot.curtrace.offset = 0
            self.glArea.Refresh()

    def onCenter(self, event):
        if self.plot.curtrace:
            self.plot.curtrace.center()
            self.glArea.Refresh()

    def onScalePlus(self, event):
        self.plot.increasescale()
        self.glArea.Refresh()

    def onScaleMinus(self, event):
        self.plot.decreasescale()
        self.glArea.Refresh()

    def onOffsetPlus(self, event):
        self.plot.curtrace.offset -= self.plot.scale / 10.0
        self.glArea.Refresh()

    def onOffsetMinus(self, event):
        self.plot.curtrace.offset += self.plot.scale / 10.0
        self.glArea.Refresh()

    def onFreeze(self, event):
        self.plot.freeze = event.IsChecked()
        self.glArea.Refresh()

    def onReset(self, event):
        self.plot.reset()
        self.glArea.Refresh()

    def onTime(self, event):
        self.plot.disptime = self.sTime.GetValue()
        self.glArea.Refresh()

    def onClose(self, event):
        self.Close()
Exemplo n.º 2
0
class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="signalk client", size=(1000, 600))

        self.value_list = []
        self.client = SignalKClientFromArgs(sys.argv, True, self.on_con)
        self.host_port = self.client.host_port
        self.client.autoreconnect = False

        ssizer = wx.FlexGridSizer(0, 1, 0, 0)
        ssizer.AddGrowableRow(0)
        ssizer.AddGrowableCol(0)
        ssizer.SetFlexibleDirection(wx.BOTH)
        ssizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)

        self.scrolledWindow = wx.ScrolledWindow(self, wx.ID_ANY,
                                                wx.DefaultPosition,
                                                wx.DefaultSize,
                                                wx.HSCROLL | wx.VSCROLL)
        self.scrolledWindow.SetScrollRate(5, 5)

        sizer = wx.FlexGridSizer(0, 3, 0, 0)
        sizer.AddGrowableCol(2)
        sizer.SetFlexibleDirection(wx.BOTH)
        sizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)

        self.values = {}
        self.controls = {}
        self.sliderrange = {}
        self.value_list = self.client.list_values()
        self.on_con(self.client)

        for name in sorted(self.value_list):
            sizer.Add(wx.StaticText(self.scrolledWindow, wx.ID_ANY, name), 0,
                      wx.ALL, 5)

            self.values[name] = wx.StaticText(self.scrolledWindow, wx.ID_ANY)
            sizer.Add(self.values[name], 0, wx.ALL, 5)

            t = self.value_list[name]['type']

            if t == 'Property':
                tb = wx.TextCtrl(self.scrolledWindow, wx.ID_ANY)
                sizer.Add(tb)
                self.controls[name] = tb

            elif t == 'BooleanProperty':

                def proc():  # encapsulate to fix scope
                    cb = wx.CheckBox(self.scrolledWindow, wx.ID_ANY, '')
                    sizer.Add(cb, 0, wx.EXPAND)
                    self.controls[name] = cb

                    cbname = name

                    def oncheck(event):
                        self.client.set(cbname, cb.GetValue())

                    cb.Bind(wx.EVT_CHECKBOX, oncheck)

                proc()

            elif t == 'RangeProperty':
                useSlider = True

                def proc():
                    r = self.value_list[name]['min'], self.value_list[name][
                        'max']
                    if useSlider:
                        s = wx.Slider(self.scrolledWindow)
                        s.SetRange(0, 1000)
                    else:
                        s = wx.SpinCtrlDouble(self.scrolledWindow)
                        s.SetRange(r[0], r[1])
                        s.SetIncrement(min(1, (r[1] - r[0]) / 100.0))
                        s.SetDigits(-math.log(s.GetIncrement()) /
                                    math.log(10) + 1)
                    sizer.Add(s, 0, wx.EXPAND)
                    self.controls[name] = s
                    sname = name

                    def onspin(event):
                        if useSlider:
                            v = s.GetValue() / 1000.0 * (r[1] - r[0]) + r[0]
                            self.client.set(sname, v)
                        else:
                            self.client.set(sname, s.GetValue())

                    if useSlider:
                        s.Bind(wx.EVT_SLIDER, onspin)
                        self.sliderrange[name] = r
                    else:
                        s.Bind(wx.EVT_SPINCTRLDOUBLE, onspin)

                proc()

            elif t == 'EnumProperty':

                def proc():
                    c = wx.Choice(self.scrolledWindow, wx.ID_ANY)
                    for choice in self.value_list[name]['choices']:
                        c.Append(str(choice))
                    sizer.Add(c, 0, wx.EXPAND)
                    self.controls[name] = c
                    cname = name

                    def onchoice(event):
                        self.client.set(cname, str(c.GetStringSelection()))

                    c.Bind(wx.EVT_CHOICE, onchoice)

                proc()

            elif t == 'ResettableValue':

                def proc():
                    b = wx.Button(self.scrolledWindow, wx.ID_ANY, 'Reset')
                    sizer.Add(b, 0, wx.EXPAND)
                    bname = name

                    def onclick(event):
                        self.client.set(bname, 0)

                    b.Bind(wx.EVT_BUTTON, onclick)

                proc()

            else:
                sizer.Add(wx.StaticText(self.scrolledWindow, wx.ID_ANY, ''))

        self.scrolledWindow.SetSizer(sizer)
        self.scrolledWindow.Layout()

        sizer.Fit(self.scrolledWindow)
        ssizer.Add(self.scrolledWindow, 1, wx.EXPAND | wx.ALL, 5)

        bsizer = wx.FlexGridSizer(1, 0, 0, 0)
        self.bRefresh = wx.Button(self, wx.ID_ANY, 'Refresh')
        self.bRefresh.Bind(wx.EVT_BUTTON, self.Refresh)
        bsizer.Add(self.bRefresh)

        self.bScope = wx.Button(self, wx.ID_ANY, 'Scope')
        self.bScope.Bind(
            wx.EVT_BUTTON, lambda event: subprocess.Popen([
                'python',
                os.path.abspath(os.path.dirname(__file__)) + '/' +
                'scope_wx.py'
            ] + sys.argv[1:]))
        bsizer.Add(self.bScope)

        self.bClose = wx.Button(self, wx.ID_ANY, 'Close')
        self.bClose.Bind(wx.EVT_BUTTON, exit)
        bsizer.Add(self.bClose)

        ssizer.Add(bsizer, 1, wx.EXPAND)

        self.SetSizer(ssizer)
        self.Layout()

        self.timer = wx.Timer(self, wx.ID_ANY)
        self.timer.Start(500)
        self.Bind(wx.EVT_TIMER, self.receive_messages, id=wx.ID_ANY)

        self.Refresh()

    def Refresh(self):
        for name in self.value_list:
            self.client.get(name)

    def on_con(self, client):
        self.SetTitle("signalk client - Connected")
        for name in sorted(self.value_list):
            t = self.value_list[name]['type']
            if t != 'SensorValue':
                client.watch(name)
            else:
                client.get(name)

    def receive_messages(self, event):
        if not self.client:
            try:
                host, port = self.host_port
                self.client = SignalKClient(self.on_con,
                                            host,
                                            port,
                                            autoreconnect=False)
                self.timer.Start(100)
            except socket.error:
                self.timer.Start(1000)
                return

        while True:
            result = False
            try:
                result = self.client.receive()
            except ConnectionLost:
                self.SetTitle("signalk client - Disconnected")
                self.client = False
                return
            except:
                pass
            if not result:
                break

            for name in result:
                if not 'value' in result[name]:
                    print 'no value', result
                    raise 'no value'

                value = round3(result[name]['value'])

                strvalue = str(value)
                if len(strvalue) > 50:
                    strvalue = strvalue[:47] + '...'
                self.values[name].SetLabel(strvalue)

                if name in self.controls:
                    try:
                        if str(type(self.controls[name])
                               ) == "<class 'wx._controls.Choice'>":
                            if not self.controls[name].SetStringSelection(
                                    value):
                                print 'warning, invalid choice value specified'
                        elif str(type(self.controls[name])
                                 ) == "<class 'wx._controls.Slider'>":
                            r = self.sliderrange[name]
                            self.controls[name].SetValue(
                                float(value - r[0]) / (r[1] - r[0]) * 1000)
                        else:
                            self.controls[name].SetValue(value)
                    except:
                        self.controls[name].SetValue(str(value))

                size = self.GetSize()
                self.Fit()
                self.SetSize(size)