Initial Commit - Fault Monitoring
This commit is contained in:
commit
64580f8f8a
13 changed files with 1045 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/venv/
|
||||
*.bak
|
||||
/__pycache__/
|
||||
2
.idea/.gitignore
generated
vendored
Normal file
2
.idea/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Default ignored files
|
||||
/workspace.xml
|
||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
4
.idea/misc.xml
generated
Normal file
4
.idea/misc.xml
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (modbus-test)" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
10
.idea/modbus-test.iml
generated
Normal file
10
.idea/modbus-test.iml
generated
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modbus-test.iml" filepath="$PROJECT_DIR$/.idea/modbus-test.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/vcs.xml
generated
Normal file
7
.idea/vcs.xml
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
160
FaultMonitor.py
Normal file
160
FaultMonitor.py
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# generated by wxGlade 0.9.5 on Fri Feb 7 20:10:41 2020
|
||||
#
|
||||
|
||||
import wx
|
||||
import wx.grid
|
||||
|
||||
import gettext
|
||||
gettext.install(None)
|
||||
|
||||
from pubsub import pub
|
||||
|
||||
print('pubsub API version', pub.VERSION_API)
|
||||
|
||||
from pubsub.utils.notification import useNotifyByWriteFile
|
||||
import sys
|
||||
|
||||
useNotifyByWriteFile(sys.stdout)
|
||||
|
||||
import pprint
|
||||
|
||||
from stabiliti import StabilitiController as SC
|
||||
from faults import faultInfo
|
||||
from FaultView import FaultFrame
|
||||
|
||||
class Controller:
|
||||
def __init__(self, view):
|
||||
self.sc = None
|
||||
self.view = view
|
||||
self.timer = wx.Timer()
|
||||
self.timer.Bind(wx.EVT_TIMER, self.OnTimer)
|
||||
|
||||
pub.subscribe(self.getFaultInfo, 'fault_selected')
|
||||
pub.subscribe(self.startTimer, 'monitoring_started')
|
||||
pub.subscribe(self.stopTimer, 'monitoring_stopped')
|
||||
pub.subscribe(self.applyNetworkConfigs, 'apply_network_configs')
|
||||
pub.subscribe(self.resetNetworkConfigs, 'reset_network_configs')
|
||||
|
||||
def startTimer(self):
|
||||
self.timer.Start(2000)
|
||||
|
||||
def stopTimer(self):
|
||||
self.timer.Stop()
|
||||
|
||||
def applyNetworkConfigs(self, ncDict):
|
||||
if self.sc:
|
||||
self.sc.checkClose()
|
||||
self.sc = SC(**ncDict)
|
||||
|
||||
def resetNetworkConfigs(self):
|
||||
if self.sc:
|
||||
self.sc.checkClose()
|
||||
self.sc = None
|
||||
|
||||
def getFaultInfo(self, pos):
|
||||
y, x = pos
|
||||
fid = x + y*8
|
||||
if 0 <= fid <= 63:
|
||||
try:
|
||||
info_text = faultInfo[fid]
|
||||
except IndexError:
|
||||
info_text = "Fault Number: {} (Reserved)".format(fid)
|
||||
self.view.text_fault_doc.SetValue(info_text)
|
||||
|
||||
status_text = "Not Connected"
|
||||
if self.sc:
|
||||
fDict = self.sc.readFaultDetail(fid)
|
||||
status_text = pprint.pformat(fDict)
|
||||
self.view.text_fault_status.SetValue(status_text)
|
||||
|
||||
def OnTimer(self, event):
|
||||
factivity = self.sc.readFaultActivity()
|
||||
foccurence = self.sc.readFaultOccurence()
|
||||
self.view.SetFaultGrid(factivity, foccurence)
|
||||
event.Skip()
|
||||
|
||||
class MyFrame(FaultFrame):
|
||||
def __init__(self, *args, **kwds):
|
||||
FaultFrame.__init__(self, *args, **kwds)
|
||||
|
||||
def OnFaultSelect(self, event): # wxGlade: MyFrame.<event_handler>
|
||||
pub.sendMessage("fault_selected", pos=(event.GetRow(), event.GetCol()))
|
||||
event.Skip()
|
||||
|
||||
def SetFaultGrid(self, fActivity, fOccurence):
|
||||
if len(fActivity) == len(fOccurence) == 64:
|
||||
for i in range(8):
|
||||
for j in range(8):
|
||||
if fActivity[i*8+j] == '1':
|
||||
self.fault_grid.SetCellBackgroundColour(i, j, wx.LIGHT_GREY)
|
||||
if fOccurence[i*8+j] == '1':
|
||||
self.fault_grid.SetCellValue(i, j, "O")
|
||||
|
||||
def ToggleMonitoring(self, event): # wxGlade: MyFrame.<event_handler>
|
||||
btnLabel = self.button_1.GetLabel()
|
||||
if self.button_1.Value:
|
||||
pub.sendMessage("monitoring_started")
|
||||
self.button_1.SetLabel("Stop")
|
||||
else:
|
||||
pub.sendMessage("monitoring_stopped")
|
||||
self.button_1.SetLabel("Start")
|
||||
|
||||
if event:
|
||||
event.Skip()
|
||||
|
||||
def OnApply(self, event):
|
||||
|
||||
if self.button_1.Enabled:
|
||||
return
|
||||
|
||||
self.input_uid.Disable()
|
||||
self.input_port.Disable()
|
||||
self.input_ip.Disable()
|
||||
self.input_refresh.Disable()
|
||||
|
||||
ncDict = {
|
||||
"ipaddr": self.input_ip.GetValue(),
|
||||
"port": int(self.input_port.GetValue()),
|
||||
"uid": int(self.input_uid.GetValue()),
|
||||
}
|
||||
|
||||
pub.sendMessage("apply_network_configs", ncDict=ncDict)
|
||||
|
||||
self.button_1.Enable()
|
||||
|
||||
def OnReset(self, event):
|
||||
|
||||
if not self.button_1.Enabled:
|
||||
return
|
||||
|
||||
pub.sendMessage("reset_network_configs")
|
||||
self.button_1.SetValue(False)
|
||||
self.ToggleMonitoring(None)
|
||||
|
||||
self.button_1.Disable()
|
||||
|
||||
self.input_uid.Enable()
|
||||
self.input_port.Enable()
|
||||
self.input_ip.Enable()
|
||||
self.input_refresh.Enable()
|
||||
|
||||
|
||||
# end of class MyFrame
|
||||
|
||||
class MyApp(wx.App):
|
||||
def OnInit(self):
|
||||
self.frame = MyFrame(None, wx.ID_ANY, "")
|
||||
self.c = Controller(self.frame)
|
||||
self.SetTopWindow(self.frame)
|
||||
self.frame.Show()
|
||||
return True
|
||||
|
||||
# end of class MyApp
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = MyApp(0)
|
||||
app.MainLoop()
|
||||
app.c.sc.checkClose()
|
||||
122
FaultView.py
Normal file
122
FaultView.py
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# generated by wxGlade 0.9.5 on Mon Feb 10 19:42:48 2020
|
||||
#
|
||||
|
||||
import wx
|
||||
import wx.grid
|
||||
|
||||
# begin wxGlade: dependencies
|
||||
import gettext
|
||||
# end wxGlade
|
||||
|
||||
# begin wxGlade: extracode
|
||||
# end wxGlade
|
||||
|
||||
|
||||
class FaultFrame(wx.Frame):
|
||||
def __init__(self, *args, **kwds):
|
||||
# begin wxGlade: FaultFrame.__init__
|
||||
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
|
||||
wx.Frame.__init__(self, *args, **kwds)
|
||||
self.SetSize((632, 556))
|
||||
self.input_ip = wx.TextCtrl(self, wx.ID_ANY, _("192.168.1.21"))
|
||||
self.input_port = wx.TextCtrl(self, wx.ID_ANY, _("502"))
|
||||
self.input_uid = wx.TextCtrl(self, wx.ID_ANY, _("240"))
|
||||
self.input_refresh = wx.TextCtrl(self, wx.ID_ANY, _("2000"))
|
||||
self.reset_button = wx.Button(self, wx.ID_ANY, _("Reset"))
|
||||
self.apply_button = wx.Button(self, wx.ID_ANY, _("Apply"))
|
||||
self.fault_grid = wx.grid.Grid(self, wx.ID_ANY, size=(1, 1))
|
||||
self.button_1 = wx.ToggleButton(self, wx.ID_ANY, _("Start"))
|
||||
self.text_fault_doc = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
|
||||
self.text_fault_status = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
|
||||
self.Bind(wx.EVT_BUTTON, self.OnReset, self.reset_button)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnApply, self.apply_button)
|
||||
self.Bind(wx.grid.EVT_GRID_CMD_CELL_LEFT_CLICK, self.OnFaultSelect, self.fault_grid)
|
||||
self.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleMonitoring, self.button_1)
|
||||
# end wxGlade
|
||||
|
||||
def __set_properties(self):
|
||||
# begin wxGlade: FaultFrame.__set_properties
|
||||
self.SetTitle(_("frame"))
|
||||
self.fault_grid.CreateGrid(8, 8)
|
||||
self.fault_grid.SetRowLabelSize(30)
|
||||
self.fault_grid.SetColLabelSize(30)
|
||||
self.fault_grid.EnableEditing(0)
|
||||
self.fault_grid.EnableDragColSize(0)
|
||||
self.fault_grid.EnableDragRowSize(0)
|
||||
self.fault_grid.EnableDragGridSize(0)
|
||||
self.fault_grid.SetColSize(0, 30)
|
||||
self.fault_grid.SetColSize(1, 30)
|
||||
self.fault_grid.SetColSize(2, 30)
|
||||
self.fault_grid.SetColSize(3, 30)
|
||||
self.fault_grid.SetColSize(4, 30)
|
||||
self.fault_grid.SetColSize(5, 30)
|
||||
self.fault_grid.SetColSize(6, 30)
|
||||
self.fault_grid.SetColSize(7, 30)
|
||||
self.fault_grid.SetRowSize(0, 30)
|
||||
self.fault_grid.SetRowSize(1, 30)
|
||||
self.fault_grid.SetRowSize(2, 30)
|
||||
self.fault_grid.SetRowSize(3, 30)
|
||||
self.fault_grid.SetRowSize(4, 30)
|
||||
self.fault_grid.SetRowSize(5, 30)
|
||||
self.fault_grid.SetRowSize(6, 30)
|
||||
self.fault_grid.SetRowSize(7, 30)
|
||||
self.fault_grid.SetMinSize((270, 270))
|
||||
self.button_1.Enable(False)
|
||||
self.text_fault_doc.SetMinSize((-1, 120))
|
||||
self.text_fault_status.SetMinSize((-1, 120))
|
||||
# end wxGlade
|
||||
|
||||
def __do_layout(self):
|
||||
# begin wxGlade: FaultFrame.__do_layout
|
||||
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_3 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_4 = wx.GridSizer(5, 2, 0, 0)
|
||||
label_1 = wx.StaticText(self, wx.ID_ANY, _("IP Address"))
|
||||
sizer_4.Add(label_1, 0, 0, 0)
|
||||
sizer_4.Add(self.input_ip, 0, 0, 0)
|
||||
label_2 = wx.StaticText(self, wx.ID_ANY, _("Port"))
|
||||
sizer_4.Add(label_2, 0, 0, 0)
|
||||
sizer_4.Add(self.input_port, 0, 0, 0)
|
||||
label_3 = wx.StaticText(self, wx.ID_ANY, _("Unit ID"))
|
||||
sizer_4.Add(label_3, 0, 0, 0)
|
||||
sizer_4.Add(self.input_uid, 0, 0, 0)
|
||||
label_4 = wx.StaticText(self, wx.ID_ANY, _("Refresh Period (ms)"))
|
||||
sizer_4.Add(label_4, 0, 0, 0)
|
||||
sizer_4.Add(self.input_refresh, 0, 0, 0)
|
||||
sizer_4.Add(self.reset_button, 0, 0, 0)
|
||||
sizer_4.Add(self.apply_button, 0, 0, 0)
|
||||
sizer_1.Add(sizer_4, 1, wx.EXPAND, 0)
|
||||
sizer_2.Add(self.fault_grid, 0, wx.ALIGN_CENTER, 0)
|
||||
sizer_2.Add(self.button_1, 0, wx.ALIGN_CENTER, 0)
|
||||
sizer_3.Add(sizer_2, 1, wx.ALIGN_CENTER, 0)
|
||||
sizer_3.Add(self.text_fault_doc, 0, wx.EXPAND, 0)
|
||||
sizer_3.Add(self.text_fault_status, 0, wx.EXPAND, 0)
|
||||
sizer_1.Add(sizer_3, 1, wx.EXPAND, 0)
|
||||
self.SetSizer(sizer_1)
|
||||
self.Layout()
|
||||
# end wxGlade
|
||||
|
||||
def OnReset(self, event): # wxGlade: FaultFrame.<event_handler>
|
||||
print("Event handler 'OnReset' not implemented!")
|
||||
event.Skip()
|
||||
|
||||
def OnApply(self, event): # wxGlade: FaultFrame.<event_handler>
|
||||
print("Event handler 'OnApply' not implemented!")
|
||||
event.Skip()
|
||||
|
||||
def OnFaultSelect(self, event): # wxGlade: FaultFrame.<event_handler>
|
||||
print("Event handler 'OnFaultSelect' not implemented!")
|
||||
event.Skip()
|
||||
|
||||
def ToggleMonitoring(self, event): # wxGlade: FaultFrame.<event_handler>
|
||||
print("Event handler 'ToggleMonitoring' not implemented!")
|
||||
event.Skip()
|
||||
|
||||
# end of class FaultFrame
|
||||
184
faultView.wxg
Normal file
184
faultView.wxg
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- generated by wxGlade 0.9.5 on Mon Feb 10 19:42:46 2020 -->
|
||||
|
||||
<application encoding="UTF-8" for_version="3.0" header_extension=".h" indent_amount="4" indent_symbol="space" is_template="0" language="python" mark_blocks="0" option="0" overwrite="1" path="FaultView.py" source_extension=".cpp" top_window="frame" use_gettext="1" use_new_namespace="1">
|
||||
<object class="FaultFrame" name="frame" base="EditFrame">
|
||||
<size>632, 556</size>
|
||||
<title>frame</title>
|
||||
<style>wxDEFAULT_FRAME_STYLE</style>
|
||||
<object class="wxBoxSizer" name="sizer_1" base="EditBoxSizer">
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<option>1</option>
|
||||
<border>0</border>
|
||||
<flag>wxEXPAND</flag>
|
||||
<object class="wxGridSizer" name="sizer_4" base="EditGridSizer">
|
||||
<rows>5</rows>
|
||||
<cols>2</cols>
|
||||
<vgap>0</vgap>
|
||||
<hgap>0</hgap>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxStaticText" name="label_1" base="EditStaticText">
|
||||
<label>IP Address</label>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxTextCtrl" name="input_ip" base="EditTextCtrl">
|
||||
<value>192.168.1.21</value>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxStaticText" name="label_2" base="EditStaticText">
|
||||
<label>Port</label>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxTextCtrl" name="input_port" base="EditTextCtrl">
|
||||
<value>502</value>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxStaticText" name="label_3" base="EditStaticText">
|
||||
<label>Unit ID</label>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxTextCtrl" name="input_uid" base="EditTextCtrl">
|
||||
<value>240</value>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxStaticText" name="label_4" base="EditStaticText">
|
||||
<label>Refresh Period (ms)</label>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxTextCtrl" name="input_refresh" base="EditTextCtrl">
|
||||
<value>2000</value>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxButton" name="reset_button" base="EditButton">
|
||||
<events>
|
||||
<handler event="EVT_BUTTON">OnReset</handler>
|
||||
</events>
|
||||
<label>Reset</label>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<object class="wxButton" name="apply_button" base="EditButton">
|
||||
<events>
|
||||
<handler event="EVT_BUTTON">OnApply</handler>
|
||||
</events>
|
||||
<label>Apply</label>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>1</option>
|
||||
<border>0</border>
|
||||
<flag>wxEXPAND</flag>
|
||||
<object class="wxBoxSizer" name="sizer_3" base="EditBoxSizer">
|
||||
<orient>wxVERTICAL</orient>
|
||||
<object class="sizeritem">
|
||||
<option>1</option>
|
||||
<border>0</border>
|
||||
<flag>wxALIGN_CENTER</flag>
|
||||
<object class="wxBoxSizer" name="sizer_2" base="EditBoxSizer">
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<flag>wxALIGN_CENTER</flag>
|
||||
<object class="wxGrid" name="fault_grid" base="EditGrid">
|
||||
<events>
|
||||
<handler event="EVT_GRID_CMD_CELL_LEFT_CLICK">OnFaultSelect</handler>
|
||||
</events>
|
||||
<size>270, 270</size>
|
||||
<create_grid>1</create_grid>
|
||||
<columns>
|
||||
<column size="30">A</column>
|
||||
<column size="30">B</column>
|
||||
<column size="30">C</column>
|
||||
<column size="30">D</column>
|
||||
<column size="30">E</column>
|
||||
<column size="30">F</column>
|
||||
<column size="30">G</column>
|
||||
<column size="30">H</column>
|
||||
</columns>
|
||||
<rows>
|
||||
<row size="30">0</row>
|
||||
<row size="30">1</row>
|
||||
<row size="30">2</row>
|
||||
<row size="30">3</row>
|
||||
<row size="30">4</row>
|
||||
<row size="30">5</row>
|
||||
<row size="30">6</row>
|
||||
<row size="30">7</row>
|
||||
</rows>
|
||||
<enable_editing>0</enable_editing>
|
||||
<enable_grid_lines>1</enable_grid_lines>
|
||||
<enable_col_resize>0</enable_col_resize>
|
||||
<enable_row_resize>0</enable_row_resize>
|
||||
<enable_grid_resize>0</enable_grid_resize>
|
||||
<selection_mode>wxGrid.wxGridSelectCells</selection_mode>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<flag>wxALIGN_CENTER</flag>
|
||||
<object class="wxToggleButton" name="button_1" base="EditToggleButton">
|
||||
<events>
|
||||
<handler event="EVT_TOGGLEBUTTON">ToggleMonitoring</handler>
|
||||
</events>
|
||||
<disabled>1</disabled>
|
||||
<label>Start</label>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<flag>wxEXPAND</flag>
|
||||
<object class="wxTextCtrl" name="text_fault_doc" base="EditTextCtrl">
|
||||
<size>-1, 120</size>
|
||||
<style>wxTE_MULTILINE|wxTE_READONLY</style>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<option>0</option>
|
||||
<border>0</border>
|
||||
<flag>wxEXPAND</flag>
|
||||
<object class="wxTextCtrl" name="text_fault_status" base="EditTextCtrl">
|
||||
<size>-1, 120</size>
|
||||
<style>wxTE_MULTILINE|wxTE_READONLY</style>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</application>
|
||||
372
faults.py
Normal file
372
faults.py
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
faultInfo = [
|
||||
'''\
|
||||
Fault Number: 0
|
||||
Description: GFDI fault (grounded DC)
|
||||
Selector Values:
|
||||
0x01 = GFDI fault detected
|
||||
0x10 = Loss of communication
|
||||
Severity: 0x110 = Lockdown
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 1
|
||||
Description: IMI fault (floating DC)
|
||||
Selector Values: NA
|
||||
Severity: 0x110 = Lockdown
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 2
|
||||
Description: Power module heatsink temperature fault
|
||||
Selector Values:
|
||||
0x00 = Over temperature
|
||||
0x01 = Under temperature
|
||||
Severity: 0x100 Abort 1
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 3
|
||||
Description: Control board temperature fault
|
||||
Selector Values:
|
||||
0x00 = Over temperature
|
||||
0x01 = Under temperature
|
||||
Severity: 0x100 Abort 1
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 4
|
||||
Description: 24V auxiliary supply under voltage
|
||||
Selector Values: NA
|
||||
Severity: 0x100 Abort 1
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 5
|
||||
Description: Fan fault
|
||||
Selector Values:
|
||||
0x00 = Fan not spinning
|
||||
0x01 = Bad tach reading
|
||||
Severity: 0x110 = Lockdown
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 6
|
||||
Description: DC differential over voltage
|
||||
Selector Values:
|
||||
0x00 = Port 2
|
||||
0x01 = Port 3
|
||||
Severity: 0x100 Abort 1
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 7
|
||||
Description: DC differential under voltage
|
||||
Selector Values:
|
||||
0x00 = Port 2
|
||||
0x01 = Port 3
|
||||
Severity: 0x100 Abort 1
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 8
|
||||
Description: Link over voltage
|
||||
Selector Values: NA
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 9
|
||||
Description: Link starving
|
||||
Selector Values: NA
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 10
|
||||
Description: Link over current
|
||||
Selector Values: NA
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 11
|
||||
Description: IGBT VCES over voltage 1
|
||||
Selector Values:
|
||||
0x00 = Link positive to phase A
|
||||
0x01 = Link positive to phase B
|
||||
0x10 = Link positive to phase C
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 12
|
||||
Description: IGBT VCES over voltage 2
|
||||
Selector Values:
|
||||
0x00 = Link negative to phase A
|
||||
0x01 = Link negative to phase B
|
||||
0x10 = Link negative to phase C
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 13
|
||||
Description: IGBT VCES over voltage 3
|
||||
Selector Values:
|
||||
0x00 = Link positive to DC port 2
|
||||
0x01 = Link positive to DC port 3
|
||||
0x10 = Link positive to DC common
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 14
|
||||
Description: IGBT VCES over voltage 4
|
||||
Selector Values:
|
||||
0x00 = Link positive to DC port 2
|
||||
0x01 = Link positive to DC port 3
|
||||
0x10 = Link positive to DC common
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 15
|
||||
Description: AC A-B hard switch
|
||||
Selector Values: 0x00, 0x01, 0x10, 0x11
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 16
|
||||
Description: AC B-C hard switch
|
||||
Selector Values: 0x00, 0x01, 0x10, 0x11
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 17
|
||||
Description: AC C-A hard switch
|
||||
Selector Values: 0x00, 0x01, 0x10, 0x11
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 18
|
||||
Description: DC2 input hard switch
|
||||
Selector Values: 0x00, 0x01, 0x10, 0x11
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 19
|
||||
Description: DC2 output hard switch
|
||||
Selector Values: 0x00, 0x01, 0x10, 0x11
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 20
|
||||
Description: DC3 input hard switch
|
||||
Selector Values: 0x00, 0x01, 0x10, 0x11
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 21
|
||||
Description: DC3 output hard switch
|
||||
Selector Values: 0x00, 0x01, 0x10, 0x11
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 22
|
||||
Description: Link state timer check
|
||||
Selector Values: NA
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 23
|
||||
Description: Bad link start
|
||||
Selector Values: 0x00, 0x01, 0x10, 0x11
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 24
|
||||
Description: Invalid method/settings
|
||||
Selector Values:
|
||||
0x00 = Invalid port1 method/setting
|
||||
0x01 = Invalid port2 method/setting
|
||||
0x10 = Invalid port3 method/setting
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 25
|
||||
Description: Island detected
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 26
|
||||
Description: AC under voltage level 1 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 27
|
||||
Description: AC under voltage level 2 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 28
|
||||
Description: AC under voltage level 3 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 29
|
||||
Description: AC under voltage level 4 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 30
|
||||
Description: AC over voltage level 1 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 31
|
||||
Description: AC over voltage level 2 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 32
|
||||
Description: AC over voltage level 3 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 33
|
||||
Description: AC over voltage level 4 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 34
|
||||
Description: AC under frequency level 1 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 35
|
||||
Description: AC under frequency level 2 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 36
|
||||
Description: AC under frequency level 3 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 37
|
||||
Description: AC under frequency level 4 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 38
|
||||
Description: AC over frequency level 1 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 39
|
||||
Description: AC over frequency level 2 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 40
|
||||
Description: AC over frequency level 3 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 41
|
||||
Description: AC over frequency level 4 trip
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 42
|
||||
Description: Watchdog timeout
|
||||
Selector Values: 0x00, 0x01
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 43
|
||||
Description: Emergency stop active
|
||||
Selector Values: NA
|
||||
Severity: 0x011 = Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 44
|
||||
Description: Sensing fault
|
||||
Selector Values: NA
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 45
|
||||
Description: Arc fault
|
||||
Selector Values: NA
|
||||
Severity: 0x011 Abort 0
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 46
|
||||
Description: Comms processor initiated shutdown
|
||||
Selector Values: NA
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 47
|
||||
Description: Surge detect
|
||||
Selector Values:
|
||||
0x00 = Phase A
|
||||
0x01 = Phase B
|
||||
0x10 = Phase C
|
||||
Severity: 0x100 Abort 1
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 48
|
||||
Description: AC switch breakdown voltage exceeded
|
||||
Selector Values:
|
||||
0x00 = Phase A to phase B
|
||||
0x01 = Phase B to phase C
|
||||
0x10 = Phase C to phase A
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 49
|
||||
Description: DC switch breakdown voltage exceeded
|
||||
Selector Values:
|
||||
0x00 = DC2
|
||||
0x01 = DC3
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 50
|
||||
Description: Precharge timeout
|
||||
Selector Values: NA
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 51
|
||||
Description: AC to link primary high voltage
|
||||
Selector Values:
|
||||
0x000 = Positive to ground
|
||||
0x001 = Negative to ground
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 52
|
||||
Description: AC line to line instantaneous over voltage
|
||||
Selector Values:
|
||||
0x000 = Phase A to phase B
|
||||
0x001 = Phase B to phase C
|
||||
0x010 = Phase C to phase A
|
||||
Severity: 0x100 Abort 1
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 53
|
||||
Description: License fault
|
||||
Selector Values: NA
|
||||
Severity: 0x101 Abort 2
|
||||
''',
|
||||
'''\
|
||||
Fault Number: 54
|
||||
Description: Grid_Ack timeout
|
||||
Selector Values: NA
|
||||
Severity: 0x100 Abort 1
|
||||
'''
|
||||
]
|
||||
122
stabiliti.py
Normal file
122
stabiliti.py
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
import easymodbus.modbusClient
|
||||
from datetime import datetime as dt
|
||||
from functools import reduce
|
||||
|
||||
class StabilitiController(object):
|
||||
''''''
|
||||
def __init__(self, ipaddr, port=502, uid=240):
|
||||
self.client = easymodbus.modbusClient.ModbusClient(ipaddr, port)
|
||||
self.client.unitidentifier = uid
|
||||
|
||||
def checkConnect(self):
|
||||
if not self.client.is_connected():
|
||||
self.client.connect()
|
||||
|
||||
def checkClose(self):
|
||||
if self.client.is_connected():
|
||||
self.client.close()
|
||||
|
||||
def reg2str(self, r):
|
||||
ms = (r & 0xff00) >> 8
|
||||
ls = (r & 0xff)
|
||||
return chr(ms) + chr(ls)
|
||||
|
||||
def getNetworkConfigs(self, config=None):
|
||||
self.checkConnect()
|
||||
configDict = {}
|
||||
from functools import reduce
|
||||
if config:
|
||||
pass
|
||||
else:
|
||||
holdingRegisters = self.client.read_holdingregisters(2030,8)
|
||||
configDict["ipaddr"] = (reduce (lambda a, b: str(a)+str(b), map(self.reg2str, holdingRegisters)))
|
||||
holdingRegisters = self.client.read_holdingregisters(2038,8)
|
||||
configDict["netmask"] = (reduce (lambda a, b: str(a)+str(b), map(self.reg2str, holdingRegisters)))
|
||||
|
||||
return configDict
|
||||
|
||||
def reg2utc(self, timel, timeu):
|
||||
return dt.utcfromtimestamp((timeu << 16) + timel)
|
||||
|
||||
def reg2bits(self, reg):
|
||||
return bin(reg)[2:].zfill(16)
|
||||
|
||||
def readFaultDetail(self, findex):
|
||||
if not (0<=findex<=63):
|
||||
return None
|
||||
|
||||
self.checkConnect()
|
||||
|
||||
self.client.write_single_register(0, findex)
|
||||
regs = self.client.read_holdingregisters(1, 9)
|
||||
flimit, fval, fcount, ftimel, ftimeu = regs[:5]
|
||||
fselector, fstatus = regs[-2:]
|
||||
fselector = bin(fselector)[2:].zfill(16)[-3:]
|
||||
print(bin(fstatus)[2:].zfill(16))
|
||||
fseverity = bin(fstatus)[2:].zfill(16)[-3:]
|
||||
'''
|
||||
b0-b2: The severity of the fault.
|
||||
0x000 = Info: increments the fault counter only.
|
||||
0x001 = Alert: increments the fault counter only.
|
||||
0x010 = Alarm: fault is logged.
|
||||
0x011 = Abort 0: fault is logged and unit is stopped. Reconnect timer 0 is used for restart.
|
||||
0x100 = Abort 1: fault is logged and unit is stopped. Reconnect timer 1 is used for restart.
|
||||
0x101 = Abort 2: fault is logged and unit is stopped. Reconnect timer 2 is used for restart.
|
||||
0x110 = Lockdown: fault is logged, unit stops processing power and requires a reset.
|
||||
0x111 = Reserved
|
||||
'''
|
||||
fstatus = bin(fstatus)[2:].zfill(16)[-5:-3]
|
||||
'''
|
||||
b3-b4: The status of the fault.
|
||||
0x01 = No fault
|
||||
0x10 = Active
|
||||
0x11 = Occurred
|
||||
'''
|
||||
print(flimit, fval, fcount,
|
||||
self.reg2utc(ftimel, ftimeu),
|
||||
fselector,
|
||||
fstatus,
|
||||
fseverity
|
||||
)
|
||||
|
||||
return {
|
||||
"Number": findex,
|
||||
"Limit": flimit,
|
||||
"Value": fval,
|
||||
"Occurence": fcount,
|
||||
"TimeStamp": self.reg2utc(ftimel, ftimeu),
|
||||
"Selector": fselector,
|
||||
"Severity": fseverity,
|
||||
"Status": fstatus,
|
||||
}
|
||||
|
||||
def readFaultArray(self, start):
|
||||
|
||||
import operator as op
|
||||
self.checkConnect()
|
||||
|
||||
faults = self.client.read_holdingregisters(start,4)
|
||||
faultStrings = map(lambda x: bin(x)[2:].zfill(16)[::-1], faults)
|
||||
return reduce(op.add, faultStrings)
|
||||
|
||||
def readFaultActivity(self):
|
||||
return self.readFaultArray(16)
|
||||
|
||||
def readFaultOccurence(self):
|
||||
return self.readFaultArray(24)
|
||||
|
||||
def printAllFaults(self, faults):
|
||||
fmt = " {} || {} | {} | {} | {} | {} | {} | {} | {} "
|
||||
sep = " ================================== "
|
||||
print (fmt.format(" ", *list(range(8))))
|
||||
print (sep)
|
||||
for i in range(8):
|
||||
idx = i * 8
|
||||
print (fmt.format(i, *faults[idx:idx+8]))
|
||||
|
||||
def reconnectTimer(self):
|
||||
pass
|
||||
|
||||
def getSystemStatus(self):
|
||||
pass
|
||||
|
||||
45
test1.py
Normal file
45
test1.py
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import easymodbus.modbusClient
|
||||
|
||||
ipaddr, port = ('192.168.1.21', 502)
|
||||
uid = 240
|
||||
|
||||
modbusclient = easymodbus.modbusClient.ModbusClient(ipaddr, port)
|
||||
# modbusclient.timeout = 5000
|
||||
modbusclient.unitidentifier = uid
|
||||
modbusclient.connect()
|
||||
|
||||
modbusclient.is_connected()
|
||||
|
||||
# holdingRegisters = easymodbus.modbusClient.convert_registers_to_float(modbusclient.read_holdingregisters(2038,8))
|
||||
# print (holdingRegisters)
|
||||
|
||||
def reg2str (r):
|
||||
ms = (r & 0xff00) >> 8
|
||||
ls = (r & 0xff)
|
||||
return chr(ms) + chr(ls)
|
||||
|
||||
from functools import reduce
|
||||
|
||||
holdingRegisters = modbusclient.read_holdingregisters(296,1)
|
||||
print(hex(holdingRegisters[0]))
|
||||
|
||||
holdingRegisters = modbusclient.read_holdingregisters(297,1)
|
||||
print(holdingRegisters)
|
||||
|
||||
modbusclient.close()
|
||||
|
||||
from stabiliti import StabilitiController as SC
|
||||
|
||||
sc = SC(ipaddr)
|
||||
|
||||
sc.getNetworkConfigs()
|
||||
|
||||
sc.printAllFaults(sc.readFaultActivity())
|
||||
|
||||
sc.printAllFaults(sc.readFaultOccurence())
|
||||
|
||||
print (
|
||||
list(filter (lambda x: x[1] == '1', enumerate(sc.readFaultActivity())))
|
||||
)
|
||||
|
||||
sc.checkClose()
|
||||
Loading…
Add table
Reference in a new issue