enode-host 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- enode_host/__init__.py +1 -0
- enode_host/async_socket.py +165 -0
- enode_host/backup/c-wing3.py +226 -0
- enode_host/backup/c.py +226 -0
- enode_host/backup/esp_mesh.py +136 -0
- enode_host/backup/gui_comps.py +113 -0
- enode_host/backup/gui_wx_bk.py +270 -0
- enode_host/backup/load_file.py +27 -0
- enode_host/backup/mesh.py +0 -0
- enode_host/backup/mesh_bk.py +0 -0
- enode_host/backup/s.py +151 -0
- enode_host/backup/sandbox.py +93 -0
- enode_host/backup/shm.py +262 -0
- enode_host/backup/shmtools.py +70 -0
- enode_host/backup/smarts.py +243 -0
- enode_host/backup/test_wxpython_choice.py +49 -0
- enode_host/backup/view-wing3.py +494 -0
- enode_host/backup/wx_example.py +55 -0
- enode_host/backup/wx_test01.py +43 -0
- enode_host/cli.py +192 -0
- enode_host/config.py +8 -0
- enode_host/constants.py +25 -0
- enode_host/framed_mesh.py +237 -0
- enode_host/gui_framed.py +207 -0
- enode_host/model.py +1415 -0
- enode_host/protocol.py +311 -0
- enode_host/psd_recursive.py +139 -0
- enode_host/queues.py +11 -0
- enode_host/resampling.py +206 -0
- enode_host/shm_sigproc.py +47 -0
- enode_host/storage.py +93 -0
- enode_host/timestamping.py +79 -0
- enode_host/types.py +38 -0
- enode_host/view.py +1233 -0
- enode_host-0.1.0.dist-info/METADATA +81 -0
- enode_host-0.1.0.dist-info/RECORD +39 -0
- enode_host-0.1.0.dist-info/WHEEL +5 -0
- enode_host-0.1.0.dist-info/entry_points.txt +2 -0
- enode_host-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import wx
|
|
2
|
+
|
|
3
|
+
class ChoiceExample(wx.Frame):
|
|
4
|
+
def __init__(self, parent, title):
|
|
5
|
+
super(ChoiceExample, self).__init__(parent, title=title, size=(300, 200))
|
|
6
|
+
|
|
7
|
+
panel = wx.Panel(self)
|
|
8
|
+
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
9
|
+
|
|
10
|
+
# Create a label
|
|
11
|
+
label = wx.StaticText(panel, label="Pick an option:")
|
|
12
|
+
sizer.Add(label, 0, wx.ALL | wx.CENTER, 10)
|
|
13
|
+
|
|
14
|
+
# Create a wx.Choice control with a list of strings
|
|
15
|
+
self.choice = wx.Choice(panel, choices=["Option 1", "Option 2", "Option 3"])
|
|
16
|
+
sizer.Add(self.choice, 0, wx.ALL | wx.CENTER, 5)
|
|
17
|
+
|
|
18
|
+
# Bind the choice selection event
|
|
19
|
+
self.choice.Bind(wx.EVT_CHOICE, self.on_choice)
|
|
20
|
+
|
|
21
|
+
# Create a label to display the selected item
|
|
22
|
+
self.display_label = wx.StaticText(panel, label="")
|
|
23
|
+
sizer.Add(self.display_label, 0, wx.ALL | wx.CENTER, 10)
|
|
24
|
+
|
|
25
|
+
panel.SetSizer(sizer)
|
|
26
|
+
self.Centre()
|
|
27
|
+
self.Show()
|
|
28
|
+
|
|
29
|
+
def on_choice(self, event):
|
|
30
|
+
"""
|
|
31
|
+
Event handler for a selection from the wx.Choice control.
|
|
32
|
+
"""
|
|
33
|
+
# Get the string corresponding to the selected item
|
|
34
|
+
selection = self.choice.GetString(self.choice.GetSelection())
|
|
35
|
+
print(self.choice.GetSelection())
|
|
36
|
+
|
|
37
|
+
# Update the display label
|
|
38
|
+
self.display_label.SetLabel(f"Selected: {selection}")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class MyApp(wx.App):
|
|
42
|
+
def OnInit(self):
|
|
43
|
+
frame = ChoiceExample(None, title="wx.Choice Example")
|
|
44
|
+
frame.Show()
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
app = MyApp(False)
|
|
49
|
+
app.MainLoop()
|
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
#!/usr/local/bin/python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# This is the file to construct GUI elements
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
###########################################################################
|
|
10
|
+
## Python code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
|
11
|
+
## http://www.wxformbuilder.org/
|
|
12
|
+
##
|
|
13
|
+
## PLEASE DO *NOT* EDIT THIS FILE!
|
|
14
|
+
###########################################################################
|
|
15
|
+
|
|
16
|
+
import wx
|
|
17
|
+
import wx.xrc
|
|
18
|
+
import wx.grid
|
|
19
|
+
|
|
20
|
+
import gettext
|
|
21
|
+
_ = gettext.gettext
|
|
22
|
+
|
|
23
|
+
import wx
|
|
24
|
+
import wx.lib.agw.aui as aui
|
|
25
|
+
import wx.lib.mixins.inspection as wit
|
|
26
|
+
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
|
|
27
|
+
from matplotlib.backends.backend_wxagg import \
|
|
28
|
+
NavigationToolbar2WxAgg as NavigationToolbar
|
|
29
|
+
from matplotlib.figure import Figure
|
|
30
|
+
import wx.grid as gridlib
|
|
31
|
+
import queues
|
|
32
|
+
import datetime
|
|
33
|
+
from numpy import empty, where, array, delete, append, ones, nan, floor, shape
|
|
34
|
+
import random
|
|
35
|
+
import logging
|
|
36
|
+
import pandas as pd
|
|
37
|
+
|
|
38
|
+
logger = logging.getLogger(__name__)
|
|
39
|
+
|
|
40
|
+
class Plot(wx.Panel):
|
|
41
|
+
def __init__(self, parent, id=-1, dpi=None, **kwargs):
|
|
42
|
+
super().__init__(parent, id=id, **kwargs)
|
|
43
|
+
self.figure = Figure(dpi=dpi, figsize=(2, 2))
|
|
44
|
+
self.canvas = FigureCanvas(self, -1, self.figure)
|
|
45
|
+
self.toolbar = NavigationToolbar(self.canvas)
|
|
46
|
+
self.toolbar.Realize()
|
|
47
|
+
|
|
48
|
+
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
49
|
+
sizer.Add(self.canvas, 1, wx.EXPAND)
|
|
50
|
+
sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
|
|
51
|
+
self.SetSizer(sizer)
|
|
52
|
+
|
|
53
|
+
class PandasTable(wx.grid.GridTableBase):
|
|
54
|
+
def __init__(self, dataframe):
|
|
55
|
+
wx.grid.GridTableBase.__init__(self)
|
|
56
|
+
self.dataframe = dataframe
|
|
57
|
+
|
|
58
|
+
def GetNumberRows(self):
|
|
59
|
+
return self.dataframe.shape[0]
|
|
60
|
+
|
|
61
|
+
def GetNumberCols(self):
|
|
62
|
+
return self.dataframe.shape[1]
|
|
63
|
+
|
|
64
|
+
def GetValue(self, row, col):
|
|
65
|
+
# Fetch value from pandas DataFrame
|
|
66
|
+
return str(self.dataframe.iat[row, col])
|
|
67
|
+
|
|
68
|
+
def SetValue(self, row, col, value):
|
|
69
|
+
# Set value in pandas DataFrame
|
|
70
|
+
self.dataframe.iat[row, col] = value
|
|
71
|
+
self.GetView().ForceRefresh()
|
|
72
|
+
|
|
73
|
+
def GetColLabelValue(self, col):
|
|
74
|
+
# Get column names from pandas DataFrame
|
|
75
|
+
return str(self.dataframe.columns[col])
|
|
76
|
+
|
|
77
|
+
def GetRowLabelValue(self, row):
|
|
78
|
+
# Optional: Get row indices from pandas DataFrame
|
|
79
|
+
return str(self.dataframe.index[row])
|
|
80
|
+
|
|
81
|
+
def update_table(self):
|
|
82
|
+
# msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_TABLE_RESET)
|
|
83
|
+
msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED)
|
|
84
|
+
self.GetView().ProcessTableMessage(msg)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
###########################################################################
|
|
88
|
+
## Class View
|
|
89
|
+
###########################################################################
|
|
90
|
+
|
|
91
|
+
class View(wx.Frame):
|
|
92
|
+
|
|
93
|
+
def __init__(self, parent):
|
|
94
|
+
|
|
95
|
+
wx.Frame.__init__ ( self, None, id = wx.ID_ANY, title = _(u"Wireless Sensor DAQ"), pos = wx.DefaultPosition, size = wx.Size( 1024,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
|
|
96
|
+
|
|
97
|
+
self.controller = parent
|
|
98
|
+
self.model = self.controller.model
|
|
99
|
+
self.m_table = None
|
|
100
|
+
self.timehistory_lines = {}
|
|
101
|
+
self.psd_lines = {}
|
|
102
|
+
self.PPS_outdate_check = True
|
|
103
|
+
self.channel_selection = [False, True, False]
|
|
104
|
+
self.timespan_length = 30 # seconds
|
|
105
|
+
|
|
106
|
+
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
|
|
107
|
+
|
|
108
|
+
bSizer1 = wx.BoxSizer( wx.VERTICAL )
|
|
109
|
+
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
|
|
110
|
+
|
|
111
|
+
self.m_staticText2 = wx.StaticText( self, wx.ID_ANY, _(u"Sensor Nodes:"), wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
112
|
+
self.m_staticText2.Wrap(-1)
|
|
113
|
+
bSizer2.Add( self.m_staticText2, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
|
|
114
|
+
|
|
115
|
+
self.m_textCtrl2 = wx.TextCtrl( self, wx.ID_ANY, self.controller.model.options['node_nums_txt'], wx.DefaultPosition, wx.DefaultSize, 0)
|
|
116
|
+
bSizer2.Add( self.m_textCtrl2, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
|
|
117
|
+
|
|
118
|
+
# # Fs selection
|
|
119
|
+
# self.m_staticText3 = wx.StaticText( self, wx.ID_ANY, _(u"Fs="), wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
120
|
+
# self.m_staticText3.Wrap(-1)
|
|
121
|
+
# bSizer2.Add( self.m_staticText3, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
|
|
122
|
+
|
|
123
|
+
# m_choice1Choices = [ _(u"62.5"), _(u"125") ]
|
|
124
|
+
# self.m_choice1 = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice1Choices, 0 )
|
|
125
|
+
# self.m_choice1.SetSelection( 0 )
|
|
126
|
+
# bSizer2.Add( self.m_choice1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
|
|
127
|
+
|
|
128
|
+
# self.m_staticText4 = wx.StaticText( self, wx.ID_ANY, _(u"Hz"), wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
129
|
+
# self.m_staticText4.Wrap(-1)
|
|
130
|
+
# bSizer2.Add( self.m_staticText4, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
|
|
131
|
+
|
|
132
|
+
# Operation Mode Choice
|
|
133
|
+
|
|
134
|
+
self.m_staticText4 = wx.StaticText( self, wx.ID_ANY, _(u"Operation Mode :"), wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
135
|
+
self.m_staticText4.Wrap(-1)
|
|
136
|
+
bSizer2.Add( self.m_staticText4, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
|
|
137
|
+
|
|
138
|
+
self.m_choice_OperationMode = wx.Choice(self, choices=["Online DAQ", "Standalone - Data Peeking", "Post-DAQ Data Stream", "Maintenance"])
|
|
139
|
+
bSizer2.Add(self.m_choice_OperationMode, 0, wx.ALL | wx.CENTER, 5)
|
|
140
|
+
self.m_choice_OperationMode.SetStringSelection("Online DAQ")
|
|
141
|
+
|
|
142
|
+
# Start Button
|
|
143
|
+
self.m_button1 = wx.Button( self, wx.ID_ANY, _(u"Start"), wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
144
|
+
bSizer2.Add(self.m_button1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
|
|
145
|
+
|
|
146
|
+
# Stop Button
|
|
147
|
+
self.m_button2 = wx.Button( self, wx.ID_ANY, _(u"Stop"), wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
148
|
+
bSizer2.Add(self.m_button2, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
bSizer1.Add(bSizer2, 0, wx.EXPAND, 5 )
|
|
152
|
+
|
|
153
|
+
bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
|
|
154
|
+
bSizer4 = wx.BoxSizer( wx.VERTICAL )
|
|
155
|
+
|
|
156
|
+
self.m_staticText21 = wx.StaticText( self, wx.ID_ANY, _(u"WiFi Mesh Status"), wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
157
|
+
self.m_staticText21.Wrap(-1)
|
|
158
|
+
|
|
159
|
+
bSizer4.Add( self.m_staticText21, 0, wx.ALL, 5 )
|
|
160
|
+
|
|
161
|
+
self.m_grid2 = wx.grid.Grid( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
162
|
+
self.mesh_status_data_view()
|
|
163
|
+
|
|
164
|
+
# Grid
|
|
165
|
+
self.nrows = len(self.controller.model.node_nums)
|
|
166
|
+
# self.m_grid2.CreateGrid(self.nrows, 6)
|
|
167
|
+
# self.m_grid2.EnableEditing( True )
|
|
168
|
+
# self.m_grid2.EnableGridLines( True )
|
|
169
|
+
# self.m_grid2.EnableDragGridSize( True )
|
|
170
|
+
# self.m_grid2.SetMargins( 0, 0 )
|
|
171
|
+
|
|
172
|
+
# self.m_grid2.SetColSize( 3, 40 )
|
|
173
|
+
# self.m_grid2.SetColSize( 4, 40 )
|
|
174
|
+
# self.m_grid2.SetColSize( 5, 45 )
|
|
175
|
+
# self.m_grid2.EnableDragColMove( False )
|
|
176
|
+
# self.m_grid2.EnableDragColSize( True )
|
|
177
|
+
# self.m_grid2.SetColLabelValue( 0, _(u"Node ID") )
|
|
178
|
+
# self.m_grid2.SetColLabelValue( 1, _(u"Status") )
|
|
179
|
+
# self.m_grid2.SetColLabelValue( 2, _(u"L") )
|
|
180
|
+
# self.m_grid2.SetColLabelValue( 3, _(u"RSSI") )
|
|
181
|
+
# self.m_grid2.SetColLabelValue( 4, _(u"PPS") )
|
|
182
|
+
# self.m_grid2.SetColLabelValue( 5, _(u"Data") )
|
|
183
|
+
# self.m_grid2.SetColLabelSize( wx.grid.GRID_AUTOSIZE )
|
|
184
|
+
# self.m_grid2.SetColLabelAlignment( wx.ALIGN_CENTER, wx.ALIGN_CENTER )
|
|
185
|
+
|
|
186
|
+
# # Rows
|
|
187
|
+
# self.m_grid2.EnableDragRowSize( True )
|
|
188
|
+
self.m_grid2.SetRowLabelSize( wx.grid.GRID_AUTOSIZE )
|
|
189
|
+
# self.m_grid2.SetRowLabelAlignment( wx.ALIGN_CENTER, wx.ALIGN_CENTER )
|
|
190
|
+
|
|
191
|
+
# # Label Appearance
|
|
192
|
+
|
|
193
|
+
# # Cell Defaults
|
|
194
|
+
self.m_grid2.SetDefaultCellAlignment( wx.ALIGN_CENTER, wx.ALIGN_CENTER)
|
|
195
|
+
# self.m_grid2.AutoSizeColumns()
|
|
196
|
+
bSizer4.Add( self.m_grid2, 1, wx.ALL|wx.EXPAND, 5 )
|
|
197
|
+
|
|
198
|
+
bSizer3.Add( bSizer4, 0, wx.EXPAND, 5 )
|
|
199
|
+
|
|
200
|
+
self.m_notebook2 = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
|
|
201
|
+
self.m_panel1 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
|
|
202
|
+
self.m_notebook2.AddPage( self.m_panel1, _(u"Time history plot"), True )
|
|
203
|
+
self.m_panel2 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
|
|
204
|
+
self.m_notebook2.AddPage( self.m_panel2, _(u"PSD plot"), False )
|
|
205
|
+
|
|
206
|
+
bSizer3.Add( self.m_notebook2, 1, wx.ALL|wx.EXPAND, 5 )
|
|
207
|
+
|
|
208
|
+
bSizer1.Add( bSizer3, 1, wx.EXPAND, 5 )
|
|
209
|
+
|
|
210
|
+
self.m_textCtrl21 = wx.TextCtrl( self, wx.ID_ANY, _(u"status reporting panel"), wx.DefaultPosition, wx.Size( -1,100 ), wx.TE_MULTILINE )
|
|
211
|
+
bSizer1.Add( self.m_textCtrl21, 0, wx.ALL|wx.EXPAND, 5 )
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
self.SetSizer( bSizer1 )
|
|
215
|
+
self.Layout()
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# MENU
|
|
219
|
+
self.m_statusBar1 = self.CreateStatusBar(1, wx.STB_SIZEGRIP, wx.ID_ANY)
|
|
220
|
+
self.m_menubar = wx.MenuBar(0)
|
|
221
|
+
self.m_menu_file = wx.Menu()
|
|
222
|
+
self.m_menu_file_open = wx.MenuItem(self.m_menu_file, wx.ID_ANY, _(u"&Open"), wx.EmptyString, wx.ITEM_NORMAL)
|
|
223
|
+
self.m_menu_file_save = wx.MenuItem(self.m_menu_file, wx.ID_ANY, _(u"&Save"), wx.EmptyString, wx.ITEM_NORMAL)
|
|
224
|
+
self.m_menu_file_quit = wx.MenuItem(self.m_menu_file, wx.ID_ANY, _(u"&Quit"), wx.EmptyString, wx.ITEM_NORMAL)
|
|
225
|
+
self.m_menu_file.Append(self.m_menu_file_open)
|
|
226
|
+
self.m_menu_file.Append(self.m_menu_file_save)
|
|
227
|
+
self.m_menu_file.AppendSeparator()
|
|
228
|
+
self.m_menu_file.Append(self.m_menu_file_quit)
|
|
229
|
+
self.m_menubar.Append(self.m_menu_file, _(u"&File"))
|
|
230
|
+
|
|
231
|
+
self.m_menu_data = wx.Menu()
|
|
232
|
+
self.m_menu_data_export = wx.MenuItem(self.m_menu_file, wx.ID_ANY, _(u"&Export"), wx.EmptyString, wx.ITEM_NORMAL)
|
|
233
|
+
self.m_menu_data.Append(self.m_menu_data_export)
|
|
234
|
+
self.m_menubar.Append(self.m_menu_data, _(u"&Data"))
|
|
235
|
+
|
|
236
|
+
self.m_menu_cmd = wx.Menu()
|
|
237
|
+
self.m_menu_cmd_sdclear = wx.MenuItem(self.m_menu_cmd, wx.ID_ANY, _(u"SD &Clear"), wx.EmptyString, wx.ITEM_NORMAL)
|
|
238
|
+
self.m_menu_cmd.Append(self.m_menu_cmd_sdclear)
|
|
239
|
+
self.m_menu_cmd_shutdown = wx.MenuItem(self.m_menu_cmd, wx.ID_ANY, _(u"&Shutdown"), wx.EmptyString, wx.ITEM_NORMAL)
|
|
240
|
+
self.m_menu_cmd.Append(self.m_menu_cmd_shutdown)
|
|
241
|
+
self.m_menubar.Append(self.m_menu_cmd, _(u"&CMD"))
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
self.m_menu_view = wx.Menu()
|
|
245
|
+
self.m_menu_view_clf = wx.MenuItem(self.m_menu_view, wx.ID_ANY, _(u"&Clear Figure"), wx.EmptyString, wx.ITEM_NORMAL)
|
|
246
|
+
self.m_menu_view.Append(self.m_menu_view_clf)
|
|
247
|
+
|
|
248
|
+
self.m_menu_view_chsel = wx.Menu()
|
|
249
|
+
self.m_menu_view_chsel_x = self.m_menu_view_chsel.AppendCheckItem(wx.ID_ANY, "X")
|
|
250
|
+
self.m_menu_view_chsel_y = self.m_menu_view_chsel.AppendCheckItem(wx.ID_ANY, "Y")
|
|
251
|
+
self.m_menu_view_chsel_z = self.m_menu_view_chsel.AppendCheckItem(wx.ID_ANY, "Z")
|
|
252
|
+
self.m_menu_view_chsel_y.Check(True)
|
|
253
|
+
self.m_menu_view.AppendSubMenu(self.m_menu_view_chsel, "Channel Selection")
|
|
254
|
+
self.Bind(wx.EVT_MENU, self.onChannelToggled, self.m_menu_view_chsel_x)
|
|
255
|
+
self.Bind(wx.EVT_MENU, self.onChannelToggled, self.m_menu_view_chsel_y)
|
|
256
|
+
self.Bind(wx.EVT_MENU, self.onChannelToggled, self.m_menu_view_chsel_z)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
self.m_menu_view_timespan = wx.Menu()
|
|
260
|
+
self.m_menu_view_timespan_radio_30s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "30 sec")
|
|
261
|
+
self.m_menu_view_timespan_radio_20s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "20 sec")
|
|
262
|
+
self.m_menu_view_timespan_radio_10s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "10 sec")
|
|
263
|
+
self.m_menu_view_timespan_radio_05s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "5 sec")
|
|
264
|
+
self.m_menu_view_timespan_radio_02s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "2 sec")
|
|
265
|
+
self.m_menu_view_timespan_radio_30s.Check(True)
|
|
266
|
+
self.m_menu_view.AppendSubMenu(self.m_menu_view_timespan, "Timespan Select")
|
|
267
|
+
self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_30s)
|
|
268
|
+
self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_20s)
|
|
269
|
+
self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_10s)
|
|
270
|
+
self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_05s)
|
|
271
|
+
self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_02s)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
self.m_menubar.Append(self.m_menu_view, _(u"&View"))
|
|
275
|
+
|
|
276
|
+
self.m_menu_help = wx.Menu()
|
|
277
|
+
self.m_menu_help_about = wx.MenuItem(self.m_menu_help, wx.ID_ANY, _(u"&Help"), wx.EmptyString, wx.ITEM_NORMAL)
|
|
278
|
+
self.m_menu_help.Append(self.m_menu_help_about)
|
|
279
|
+
self.m_menubar.Append(self.m_menu_help, _(u"&Help"))
|
|
280
|
+
|
|
281
|
+
self.SetMenuBar(self.m_menubar)
|
|
282
|
+
self.Centre( wx.BOTH )
|
|
283
|
+
|
|
284
|
+
# FIGURE PANEL
|
|
285
|
+
|
|
286
|
+
self.m_fig1 = Plot(self.m_panel1)
|
|
287
|
+
self.axes1 = self.m_fig1.figure.add_subplot()
|
|
288
|
+
self.m_fig2 = Plot(self.m_panel2)
|
|
289
|
+
self.axes2 = self.m_fig2.figure.add_subplot()
|
|
290
|
+
self.init_plot()
|
|
291
|
+
|
|
292
|
+
canvas1 = FigureCanvas(self.m_panel1, -1, self.m_fig1.figure)
|
|
293
|
+
sizer1 = wx.BoxSizer(wx.VERTICAL)
|
|
294
|
+
sizer1.Add(canvas1, 1, wx.EXPAND)
|
|
295
|
+
|
|
296
|
+
canvas2 = FigureCanvas(self.m_panel2, -1, self.m_fig2.figure)
|
|
297
|
+
sizer2 = wx.BoxSizer(wx.VERTICAL)
|
|
298
|
+
sizer2.Add(canvas2, 1, wx.EXPAND)
|
|
299
|
+
|
|
300
|
+
# Set the sizer for the panel1
|
|
301
|
+
self.m_panel1.SetSizer(sizer1)
|
|
302
|
+
self.m_panel2.SetSizer(sizer2)
|
|
303
|
+
|
|
304
|
+
# UPDATE TIMER
|
|
305
|
+
|
|
306
|
+
self.timer = wx.Timer(self)
|
|
307
|
+
self.Bind(wx.EVT_TIMER, self.gui_update, self.timer)
|
|
308
|
+
self.timer.Start(1000)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
self.timespan_map = {
|
|
312
|
+
self.m_menu_view_timespan_radio_30s.GetId(): 30,
|
|
313
|
+
self.m_menu_view_timespan_radio_20s.GetId(): 20,
|
|
314
|
+
self.m_menu_view_timespan_radio_10s.GetId(): 10,
|
|
315
|
+
self.m_menu_view_timespan_radio_05s.GetId(): 5,
|
|
316
|
+
self.m_menu_view_timespan_radio_02s.GetId(): 2,
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
def mesh_status_data_view(self):
|
|
320
|
+
|
|
321
|
+
self.m_table = PandasTable(self.controller.model.mesh_status_data)
|
|
322
|
+
self.m_grid2.SetTable(self.m_table, takeOwnership=True)
|
|
323
|
+
# Columns
|
|
324
|
+
self.m_grid2.SetColSize( 0, 70 ) # Node ID
|
|
325
|
+
self.m_grid2.SetColSize( 1, 100 ) # Status
|
|
326
|
+
self.m_grid2.SetColSize( 2, 20 ) # L
|
|
327
|
+
self.m_grid2.SetColSize( 3, 70 ) # Parent
|
|
328
|
+
self.m_grid2.SetColSize( 4, 40 ) # RSSI
|
|
329
|
+
self.m_grid2.SetColSize( 5, 70 ) # Children
|
|
330
|
+
self.m_grid2.SetColSize( 6, 40 ) # PPS
|
|
331
|
+
self.m_grid2.SetColSize( 7, 50 ) # CMD
|
|
332
|
+
self.m_grid2.SetColSize( 8, 0 ) # PPS-time
|
|
333
|
+
self.m_grid2.SetColSize( 9, 0 ) # Parent's MAC
|
|
334
|
+
self.m_grid2.SetColSize(10, 0 ) # Self MAC
|
|
335
|
+
self.m_grid2.SetColSize(11, 0 ) # Conn Report Time
|
|
336
|
+
self.m_grid2.SetColSize(12, 0 ) # inode
|
|
337
|
+
|
|
338
|
+
def __del__( self ):
|
|
339
|
+
pass
|
|
340
|
+
|
|
341
|
+
# Virtual event handlers, override them in your derived class
|
|
342
|
+
def test( self, event ):
|
|
343
|
+
event.Skip()
|
|
344
|
+
|
|
345
|
+
# def init_plot(self, parent, id=-1, dpi=None, **kwargs):
|
|
346
|
+
# wx.Panel.__init__(parent)
|
|
347
|
+
# self.figure = Figure(dpi=dpi, figsize=(2, 2))
|
|
348
|
+
# self.canvas = FigureCanvas(self, -1, self.figure)
|
|
349
|
+
# self.toolbar = NavigationToolbar(self.canvas)
|
|
350
|
+
# self.toolbar.Realize()
|
|
351
|
+
|
|
352
|
+
# sizer = wx.BoxSizer(wx.VERTICAL)
|
|
353
|
+
# sizer.Add(self.canvas, 1, wx.EXPAND)
|
|
354
|
+
# sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
|
|
355
|
+
# self.SetSizer(sizer)
|
|
356
|
+
|
|
357
|
+
# return self.figure
|
|
358
|
+
|
|
359
|
+
def getTimeWindow(self, t1):
|
|
360
|
+
Tspan = self.timespan_length
|
|
361
|
+
r = [datetime.datetime.fromtimestamp(floor(t1.timestamp() / Tspan) * Tspan),
|
|
362
|
+
datetime.datetime.fromtimestamp(floor(t1.timestamp() / Tspan + 1) * Tspan)]
|
|
363
|
+
# logger.info("{}, {}".format(r[0], r[1]))
|
|
364
|
+
return r
|
|
365
|
+
|
|
366
|
+
def init_plot(self):
|
|
367
|
+
|
|
368
|
+
self.axes1.cla()
|
|
369
|
+
for index, row in self.model.mesh_status_data.iterrows():
|
|
370
|
+
for idx, ch in enumerate(['X', 'Y', 'Z']):
|
|
371
|
+
if self.channel_selection[idx]:
|
|
372
|
+
NodeID_CH = row['Node ID'] + ch
|
|
373
|
+
self.timehistory_lines[NodeID_CH] = self.axes1.plot([], [], label=NodeID_CH)[0]
|
|
374
|
+
self.axes1.set_xlabel('Time')
|
|
375
|
+
self.axes1.set_ylabel('Acceleration (g)')
|
|
376
|
+
self.axes1.grid(True)
|
|
377
|
+
self.axes1.set_ylim(-2, 2)
|
|
378
|
+
self.axes1.legend()
|
|
379
|
+
|
|
380
|
+
self.axes2.cla()
|
|
381
|
+
for index, row in self.model.mesh_status_data.iterrows():
|
|
382
|
+
for idx, ch in enumerate(['X', 'Y', 'Z']):
|
|
383
|
+
if self.channel_selection[idx]:
|
|
384
|
+
NodeID_CH = row['Node ID'] + ch
|
|
385
|
+
self.psd_lines[NodeID_CH] = self.axes2.semilogy([], [], label=NodeID_CH)[0]
|
|
386
|
+
|
|
387
|
+
self.axes2.set_xlabel('Frequency (Hz)')
|
|
388
|
+
self.axes2.set_ylabel('ASD (g/sq(Hz))')
|
|
389
|
+
self.axes2.grid(True)
|
|
390
|
+
self.axes2.set_ylim(1e-6, 1e1)
|
|
391
|
+
self.axes2.set_xlim(0, 25)
|
|
392
|
+
self.axes2.legend()
|
|
393
|
+
|
|
394
|
+
def status_table_update(self):
|
|
395
|
+
|
|
396
|
+
t_now = datetime.datetime.now()
|
|
397
|
+
for index, row in self.model.mesh_status_data.iterrows():
|
|
398
|
+
if row['Connection'] == 'disconnected':
|
|
399
|
+
attr = gridlib.GridCellAttr()
|
|
400
|
+
attr.SetBackgroundColour(wx.Colour(255, 0, 0)) # light Red
|
|
401
|
+
self.m_grid2.SetAttr(index, 1, attr)
|
|
402
|
+
else:
|
|
403
|
+
attr = gridlib.GridCellAttr()
|
|
404
|
+
attr.SetBackgroundColour(wx.Colour(255, 255, 255)) # light Red
|
|
405
|
+
self.m_grid2.SetAttr(index, 1, attr)
|
|
406
|
+
|
|
407
|
+
if isinstance(row['PPS-time'], datetime.datetime) and self.PPS_outdate_check:
|
|
408
|
+
dt = t_now - row['PPS-time']
|
|
409
|
+
if dt.seconds > 10:
|
|
410
|
+
attr = gridlib.GridCellAttr()
|
|
411
|
+
attr.SetBackgroundColour(wx.Colour(255, 0, 0)) # light Red
|
|
412
|
+
self.m_grid2.SetAttr(index, 6, attr)
|
|
413
|
+
else:
|
|
414
|
+
attr = gridlib.GridCellAttr()
|
|
415
|
+
attr.SetBackgroundColour(wx.Colour(255, 255, 255)) # light Red
|
|
416
|
+
self.m_grid2.SetAttr(index, 6, attr)
|
|
417
|
+
|
|
418
|
+
if row['Connection'] == 'connected' and not isinstance(row['PPS-time'], datetime.datetime):
|
|
419
|
+
attr = gridlib.GridCellAttr()
|
|
420
|
+
attr.SetBackgroundColour(wx.Colour(255, 0, 0)) # light Red
|
|
421
|
+
self.m_grid2.SetAttr(index, 6, attr)
|
|
422
|
+
|
|
423
|
+
def table_update(self):
|
|
424
|
+
|
|
425
|
+
self.m_grid2.ForceRefresh()
|
|
426
|
+
self.status_table_update()
|
|
427
|
+
|
|
428
|
+
def figure_update(self):
|
|
429
|
+
|
|
430
|
+
for index, row in self.model.mesh_status_data.iterrows():
|
|
431
|
+
nodeID = row['nodeID']
|
|
432
|
+
for idx, ch in enumerate(['X', 'Y', 'Z']):
|
|
433
|
+
NodeID_CH = row['Node ID'] + ch
|
|
434
|
+
if NodeID_CH in self.timehistory_lines.keys() and nodeID in self.model.timehistory_xdata.keys():
|
|
435
|
+
with self.model.plot_mutex[nodeID]:
|
|
436
|
+
if len(self.model.timehistory_xdata[nodeID]) > 1:
|
|
437
|
+
self.timehistory_lines[NodeID_CH].set_xdata(self.model.timehistory_xdata[nodeID])
|
|
438
|
+
self.timehistory_lines[NodeID_CH].set_ydata(self.model.timehistory_ydata[nodeID][:, idx])
|
|
439
|
+
if self.model.timehistory_xlim:
|
|
440
|
+
self.axes1.set_xlim(self.model.timehistory_xlim)
|
|
441
|
+
try:
|
|
442
|
+
# for nodeID in self.timehistory_lines:
|
|
443
|
+
# logger.info('draw(): {} / {} / {}'.format(nodeID, shape(self.timehistory_lines[nodeID].get_xdata()), shape(self.timehistory_lines[nodeID].get_ydata())))
|
|
444
|
+
self.m_fig1.figure.canvas.draw()
|
|
445
|
+
# for nodeID in self.timehistory_lines:
|
|
446
|
+
# logger.info('draw(): {} / {} / {}'.format(nodeID, shape(self.timehistory_lines[nodeID].get_xdata()), shape(self.timehistory_lines[nodeID].get_ydata())))
|
|
447
|
+
except:
|
|
448
|
+
# pass
|
|
449
|
+
raise
|
|
450
|
+
|
|
451
|
+
for index, row in self.model.mesh_status_data.iterrows():
|
|
452
|
+
nodeID = row['nodeID']
|
|
453
|
+
for idx, ch in enumerate(['X', 'Y', 'Z']):
|
|
454
|
+
NodeID_CH = row['Node ID'] + ch
|
|
455
|
+
if NodeID_CH in self.psd_lines.keys() and nodeID in self.model.psd_ydata.keys():
|
|
456
|
+
with self.model.plot_mutex[nodeID]:
|
|
457
|
+
self.psd_lines[NodeID_CH].set_xdata(self.model.psd_xdata)
|
|
458
|
+
self.psd_lines[NodeID_CH].set_ydata(self.model.psd_ydata[nodeID][:, idx])
|
|
459
|
+
|
|
460
|
+
if len(self.model.psd_xdata) > 0:
|
|
461
|
+
self.axes2.set_xlim(0, round(self.model.psd_xdata[-1]))
|
|
462
|
+
try:
|
|
463
|
+
self.m_fig2.figure.canvas.draw()
|
|
464
|
+
except:
|
|
465
|
+
# pass
|
|
466
|
+
raise
|
|
467
|
+
|
|
468
|
+
# self.m_fig2.figure.canvas.draw()
|
|
469
|
+
|
|
470
|
+
def gui_update(self, event):
|
|
471
|
+
|
|
472
|
+
self.table_update()
|
|
473
|
+
self.figure_update()
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def onChannelToggled(self, event):
|
|
477
|
+
|
|
478
|
+
self.channel_selection = [
|
|
479
|
+
self.m_menu_view_chsel_x.IsChecked(),
|
|
480
|
+
self.m_menu_view_chsel_y.IsChecked(),
|
|
481
|
+
self.m_menu_view_chsel_z.IsChecked()
|
|
482
|
+
]
|
|
483
|
+
|
|
484
|
+
self.init_plot()
|
|
485
|
+
|
|
486
|
+
def onTimeSpanChange(self, event):
|
|
487
|
+
|
|
488
|
+
ts = self.timespan_map.get(event.GetId(), None)
|
|
489
|
+
if ts:
|
|
490
|
+
logger.info(f"Timespan selected: {ts} sec")
|
|
491
|
+
self.timespan_length = ts
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import wx
|
|
2
|
+
import wx.lib.agw.aui as aui
|
|
3
|
+
import wx.lib.mixins.inspection as wit
|
|
4
|
+
|
|
5
|
+
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
|
|
6
|
+
from matplotlib.backends.backend_wxagg import \
|
|
7
|
+
NavigationToolbar2WxAgg as NavigationToolbar
|
|
8
|
+
from matplotlib.figure import Figure
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Plot(wx.Panel):
|
|
12
|
+
def __init__(self, parent, id=-1, dpi=None, **kwargs):
|
|
13
|
+
super().__init__(parent, id=id, **kwargs)
|
|
14
|
+
self.figure = Figure(dpi=dpi, figsize=(2, 2))
|
|
15
|
+
self.canvas = FigureCanvas(self, -1, self.figure)
|
|
16
|
+
self.toolbar = NavigationToolbar(self.canvas)
|
|
17
|
+
self.toolbar.Realize()
|
|
18
|
+
|
|
19
|
+
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
20
|
+
sizer.Add(self.canvas, 1, wx.EXPAND)
|
|
21
|
+
sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
|
|
22
|
+
self.SetSizer(sizer)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class PlotNotebook(wx.Panel):
|
|
26
|
+
def __init__(self, parent, id=-1):
|
|
27
|
+
super().__init__(parent, id=id)
|
|
28
|
+
self.nb = aui.AuiNotebook(self)
|
|
29
|
+
sizer = wx.BoxSizer()
|
|
30
|
+
sizer.Add(self.nb, 1, wx.EXPAND)
|
|
31
|
+
self.SetSizer(sizer)
|
|
32
|
+
|
|
33
|
+
def add(self, name="plot"):
|
|
34
|
+
page = Plot(self.nb)
|
|
35
|
+
self.nb.AddPage(page, name)
|
|
36
|
+
return page.figure
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def demo():
|
|
40
|
+
# Alternatively you could use:
|
|
41
|
+
# app = wx.App()
|
|
42
|
+
# InspectableApp is a great debug tool, see:
|
|
43
|
+
# http://wiki.wxpython.org/Widget%20Inspection%20Tool
|
|
44
|
+
app = wit.InspectableApp()
|
|
45
|
+
frame = wx.Frame(None, -1, 'Plotter')
|
|
46
|
+
plotter = PlotNotebook(frame)
|
|
47
|
+
axes1 = plotter.add('figure 1').add_subplot()
|
|
48
|
+
axes1.plot([1, 2, 3], [2, 1, 4])
|
|
49
|
+
axes2 = plotter.add('figure 2').add_subplot()
|
|
50
|
+
axes2.plot([1, 2, 3, 4, 5], [2, 1, 4, 2, 3])
|
|
51
|
+
frame.Show()
|
|
52
|
+
app.MainLoop()
|
|
53
|
+
|
|
54
|
+
if __name__ == "__main__":
|
|
55
|
+
demo()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import wx
|
|
2
|
+
|
|
3
|
+
class MyFrame(wx.Frame):
|
|
4
|
+
def __init__(self):
|
|
5
|
+
super().__init__(None, title="Menu with Tick Marks", size=(300, 200))
|
|
6
|
+
|
|
7
|
+
menuBar = wx.MenuBar()
|
|
8
|
+
modeMenu = wx.Menu()
|
|
9
|
+
|
|
10
|
+
self.mode_auto = modeMenu.AppendRadioItem(wx.ID_ANY, "Auto")
|
|
11
|
+
self.mode_manual = modeMenu.AppendRadioItem(wx.ID_ANY, "Manual")
|
|
12
|
+
self.mode_custom = modeMenu.AppendRadioItem(wx.ID_ANY, "Custom")
|
|
13
|
+
|
|
14
|
+
menuBar.Append(modeMenu, "&Mode")
|
|
15
|
+
self.SetMenuBar(menuBar)
|
|
16
|
+
|
|
17
|
+
# Set default ticked item
|
|
18
|
+
self.mode_auto.Check(True)
|
|
19
|
+
|
|
20
|
+
# Bind events
|
|
21
|
+
self.Bind(wx.EVT_MENU, self.on_select_mode, self.mode_auto)
|
|
22
|
+
self.Bind(wx.EVT_MENU, self.on_select_mode, self.mode_manual)
|
|
23
|
+
self.Bind(wx.EVT_MENU, self.on_select_mode, self.mode_custom)
|
|
24
|
+
|
|
25
|
+
def on_select_mode(self, event):
|
|
26
|
+
selected = "?"
|
|
27
|
+
if self.mode_auto.IsChecked():
|
|
28
|
+
selected = "Auto"
|
|
29
|
+
elif self.mode_manual.IsChecked():
|
|
30
|
+
selected = "Manual"
|
|
31
|
+
elif self.mode_custom.IsChecked():
|
|
32
|
+
selected = "Custom"
|
|
33
|
+
|
|
34
|
+
wx.MessageBox(f"You selected: {selected}")
|
|
35
|
+
|
|
36
|
+
class MyApp(wx.App):
|
|
37
|
+
def OnInit(self):
|
|
38
|
+
frame = MyFrame()
|
|
39
|
+
frame.Show()
|
|
40
|
+
return True
|
|
41
|
+
|
|
42
|
+
app = MyApp(False)
|
|
43
|
+
app.MainLoop()
|