t push -u origin master

This commit is contained in:
Tyrel Souza 2016-03-14 11:31:56 -04:00
commit 1b565ebb07
60 changed files with 2762 additions and 0 deletions

BIN
.hg/00changelog.i Normal file

Binary file not shown.

1
.hg/branch Normal file
View File

@ -0,0 +1 @@
default

2
.hg/cache/branch2-served vendored Normal file
View File

@ -0,0 +1,2 @@
f955b00a6181dc5bdf0112fcaef09591a748fadd 25
f955b00a6181dc5bdf0112fcaef09591a748fadd o default

1
.hg/cache/rbc-names-v1 vendored Normal file
View File

@ -0,0 +1 @@
default

BIN
.hg/cache/rbc-revs-v1 vendored Normal file

Binary file not shown.

BIN
.hg/dirstate Normal file

Binary file not shown.

14
.hg/hgrc Normal file
View File

@ -0,0 +1,14 @@
# example repository config (see "hg help config" for more info)
[paths]
default = ssh://hg@bitbucket.org/tyrelsouza/torchtester
# path aliases to other clones of this repo in URLs or filesystem paths
# (see "hg help config.paths" for more info)
#
# default-push = ssh://jdoe@example.net/hg/jdoes-fork
# my-fork = ssh://jdoe@example.net/hg/jdoes-fork
# my-clone = /home/jdoe/jdoes-clone
[ui]
# name and email (local to this repository, optional), e.g.
# username = Jane Doe <jdoe@example.com>

4
.hg/requires Normal file
View File

@ -0,0 +1,4 @@
dotencode
fncache
revlogv1
store

BIN
.hg/store/00changelog.i Normal file

Binary file not shown.

BIN
.hg/store/00manifest.i Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

24
.hg/store/fncache Normal file
View File

@ -0,0 +1,24 @@
data/TorchTester/TorchDB.i
data/TorchTester/logic.py.i
data/TorchTester/logic.pyc.i
data/TorchTester/TorchTester.pyproj.i
data/TorchTester/test.pyc.i
data/Program Files/TorchTester/red.png.i
data/README.txt.txt.i
data/TorchTester/frmMain.py.i
data/TorchTester/port_select.pyc.i
data/TorchTester/wxImages.py.i
data/TorchTester/TorchTester.ico.i
data/TorchTester/initialization.py.i
data/.hgignore.i
data/Program Files/TorchTester/green.png.i
data/TorchTester/TorchTester.pyw.i
data/TorchTester/Program.py.i
data/README.txt.i
data/TorchTester.suo.i
data/TorchTester/scanports.pyc.i
data/TorchTester.sln.i
data/TorchTester.fbp.i
data/TorchTester/port_select.py.i
data/TorchTester/scanports.py.i
data/Program Files/TorchTester/blank.png.i

0
.hg/store/phaseroots Normal file
View File

BIN
.hg/store/undo Normal file

Binary file not shown.

BIN
.hg/store/undo.backupfiles Normal file

Binary file not shown.

View File

0
.hg/undo.bookmarks Normal file
View File

1
.hg/undo.branch Normal file
View File

@ -0,0 +1 @@
default

3
.hg/undo.desc Normal file
View File

@ -0,0 +1,3 @@
0
pull
ssh://hg@bitbucket.org/tyrelsouza/torchtester

0
.hg/undo.dirstate Normal file
View File

3
.hgignore Normal file
View File

@ -0,0 +1,3 @@
syntax:glob
*.pyc
TorchDB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

19
README.txt Normal file
View File

@ -0,0 +1,19 @@
For this project we need to install:
Python2.7 [http://python.org/ftp/python/2.7.2/python-2.7.2.msi]
wxPython [http://downloads.sourceforge.net/wxpython/wxPython2.8-win32-unicode-2.8.12.1-py27.exe]
pyserial [http://sourceforge.net/projects/pyserial/files/pyserial/2.5/pyserial-2.5.win32.exe/download]
TODO: [Priority]
[8] Calculate Pass/fails
[6] Separate the panels with a border.
[6] Store the tests in the database.
[6] read thresholds settings from a file.
[2] Wrap everything up to a .exe file
[1] Create Installer
Getting there!

1571
TorchTester.fbp Normal file

File diff suppressed because it is too large Load Diff

18
TorchTester.sln Normal file
View File

@ -0,0 +1,18 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "TorchTester", "TorchTester\TorchTester.pyproj", "{A172B229-11F0-4265-9205-FA5A8EC52471}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A172B229-11F0-4265-9205-FA5A8EC52471}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A172B229-11F0-4265-9205-FA5A8EC52471}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

BIN
TorchTester.suo Normal file

Binary file not shown.

140
TorchTester/Program.py Normal file
View File

@ -0,0 +1,140 @@
"""
Author: Tyrel Souza
<tyrel@tyrelsouza.com>
TO DO:
Watch for "Stop Button Pressed"
if test is pass, show colors red and green
If index of combo box is changed,
change all visible combo boxes.
Box for Name
Map Button
(have defaults saved)
pop up page to enter in Progra Number, Test Number, Set target sccm
Sync button on bottom
ex: write " asdfjasdf jsadf js #2\r\n"
write " asdfsadjf askjdf kasf 3.0"
deferreds
"""
import wx
import sqlite3 as sqlite
import logic
import serial
import scanports
import os
import io
import ConfigParser
import pdb
import sys
from threading import *
from frmMain import frmMain
EXITMETHOD = ["Unknown","Completed","Stop Button","Severe Leak"]
global DEBUG
DEBUG = True
APPNAME = "TorchTester"
class settings():
COMPORT = "COM3" # This is the default comport.
BAUDRATE = 115200
BYTESIZE = serial.EIGHTBITS
PARITY = serial.PARITY_NONE
STOPBITS = serial.STOPBITS_ONE
DIR = os.path.join(os.environ['APPDATA'], APPNAME)
CONFIG_FILE = os.path.join(os.environ['APPDATA'], APPNAME) + '\\config.ini'
DB_FILE = os.path.join(os.environ['APPDATA'], APPNAME) + '\\Torch.sqlite'
ICON_FILE = os.path.join(os.environ['APPDATA'], APPNAME) + "\HyperTherm.ico"
def __init__(self):
if not os.path.exists(self.DIR):
os.makedirs(self.DIR)
with open(self.CONFIG_FILE,'w') as f:
inifile = """[LEAK]
LEAKA = 2.0
LEAKB = 2.0
LEAKC = 2.0
LEAKD = 2.0
[FLOW]
FLOWA = 28000
FLOWB = 28000
FLOWC = 28000
FLOWD = 78000"""
f.write(inifile)
f.close
def get_limits(self,runno=None,settings=None):
try:
parser = ConfigParser.ConfigParser()
parser.read(settings.CONFIG_FILE)
limits = []
limits.append([None,parser.get('LEAK','LEAKA')])
limits.append([None,parser.get('LEAK','LEAKB')])
limits.append([None,parser.get('LEAK','LEAKC')])
limits.append([None,parser.get('LEAK','LEAKD')])
limits.append([None,parser.get('FLOW','FLOWA')])
limits.append([None,parser.get('FLOW','FLOWB')])
limits.append([None,parser.get('FLOW','FLOWC')])
limits.append([None,parser.get('FLOW','FLOWD')])
except:
limits = []
limits.append(['LEAKA','2.0'])
limits.append(['LEAKB','2.0'])
limits.append(['LEAKC','2.0'])
limits.append(['LEAKD','2.0'])
limits.append(['FLOWA','28000'])
limits.append(['FLOWB','28000'])
limits.append(['FLOWC','28000'])
limits.append(['FLOWD','78000'])
limit = limits[runno][1]
return limit
def main(settings):
app = wx.App()
frame = frmMain(None,settings)
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()
def check_db(s):
"""
This function will select the LAST set comport in the database.
If there is no last set comport, it will prompt you for your comports,
then it will accept the comport and save it to the database.
"""
conn = sqlite.connect(s.DB_FILE,detect_types=sqlite.PARSE_DECLTYPES)
c = conn.cursor()
try:
c.execute('SELECT CASE WHEN tbl_name = "torch_record" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "torch_record" AND type = "table"')
table_exists = c.fetchone()
if not table_exists:
c.execute("CREATE TABLE torch_record (id INTEGER PRIMARY KEY AUTOINCREMENT, port_number TEXT, program_number TEXT, test_date DATE, test_time TEXT, measurement REAL,result TEXT)");
c.execute('SELECT CASE WHEN tbl_name = "torch_record" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "torch_record" AND type = "table"')
table_exists = c.fetchone()
except sqlite.OperationalError, e:
print e
c.close()
return s
def run_test(settings):
ser = logic.connect_serial_and_open(settings)
try:
# listen to what's happeneing on the serial port.
EM,out = logic.read_serial(ser)
except Exception, ex:
ser.close()
try:
ser.close()
except:
pass
return EM,out
if __name__ == "__main__":
settings = settings()
settings = check_db(settings)
main(settings)

BIN
TorchTester/TorchTester.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{a172b229-11f0-4265-9205-fa5a8ec52471}</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>Program.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<AssemblyName>TorchTester</AssemblyName>
<Name>TorchTester</Name>
<RootNamespace>TorchTester</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="logic.py" />
<Compile Include="frmMain.py" />
<Compile Include="initialization.py" />
<Compile Include="wxImages.py" />
<Compile Include="scanports.py" />
<Compile Include="Program.py" />
</ItemGroup>
</Project>

127
TorchTester/TorchTester.pyw Normal file
View File

@ -0,0 +1,127 @@
"""
Author: Tyrel Souza
<tyrel@tyrelsouza.com>
TO DO:
Watch for "Stop Button Pressed"
if test is pass, show colors red and green
If index of combo box is changed,
change all visible combo boxes.
Box for Name
Map Button
(have defaults saved)
pop up page to enter in Progra Number, Test Number, Set target sccm
Sync button on bottom
ex: write " asdfjasdf jsadf js #2\r\n"
write " asdfsadjf askjdf kasf 3.0"
deferreds
"""
import wx
import sqlite3 as sqlite
import logic
import serial
import scanports
import os
import io
import ConfigParser
import pdb
import sys
from threading import *
from frmMain import frmMain
EXITMETHOD = ["Unknown","Completed","Stop Button","Severe Leak"]
global DEBUG
DEBUG = True
APPNAME = "TorchTester"
class settings():
COMPORT = "COM1" # This is the default comport.
BAUDRATE = 115200
BYTESIZE = serial.EIGHTBITS
PARITY = serial.PARITY_NONE
STOPBITS = serial.STOPBITS_ONE
DIR = os.path.join(os.environ['APPDATA'], APPNAME)
CONFIG_FILE = os.path.join(os.environ['APPDATA'], APPNAME) + '\\config.ini'
DB_FILE = os.path.join(os.environ['APPDATA'], APPNAME) + '\\Torch.sqlite'
ICON_FILE = os.path.join(os.environ['APPDATA'], APPNAME) + "\HyperTherm.ico"
def __init__(self):
if not os.path.exists(self.DIR):
os.makedirs(self.DIR)
def get_limits(self,runno=None,settings=None):
try:
parser = ConfigParser.ConfigParser()
parser.read(settings.CONFIG_FILE)
limits = []
limits.append([None,parser.get('LEAK','LEAKA')])
limits.append([None,parser.get('LEAK','LEAKB')])
limits.append([None,parser.get('LEAK','LEAKC')])
limits.append([None,parser.get('LEAK','LEAKD')])
limits.append([None,parser.get('FLOW','FLOWA')])
limits.append([None,parser.get('FLOW','FLOWB')])
limits.append([None,parser.get('FLOW','FLOWC')])
limits.append([None,parser.get('FLOW','FLOWD')])
except:
limits = []
limits.append(['LEAKA','2.0'])
limits.append(['LEAKB','2.0'])
limits.append(['LEAKC','2.0'])
limits.append(['LEAKD','2.0'])
limits.append(['FLOWA','28000'])
limits.append(['FLOWB','28000'])
limits.append(['FLOWC','28000'])
limits.append(['FLOWD','78000'])
limit = limits[runno][1]
return limit
def main(settings):
app = wx.App()
frame = frmMain(None,settings)
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()
def check_db(s):
"""
This function will select the LAST set comport in the database.
If there is no last set comport, it will prompt you for your comports,
then it will accept the comport and save it to the database.
"""
conn = sqlite.connect(s.DB_FILE,detect_types=sqlite.PARSE_DECLTYPES)
c = conn.cursor()
try:
c.execute('SELECT CASE WHEN tbl_name = "torch_record" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "torch_record" AND type = "table"')
table_exists = c.fetchone()
if not table_exists:
c.execute("CREATE TABLE torch_record (id INTEGER PRIMARY KEY AUTOINCREMENT, port_number TEXT, program_number TEXT, test_date DATE, test_time TEXT, measurement REAL,result TEXT)");
c.execute('SELECT CASE WHEN tbl_name = "torch_record" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "torch_record" AND type = "table"')
table_exists = c.fetchone()
except sqlite.OperationalError, e:
print e
c.close()
return s
def run_test(settings):
ser = logic.connect_serial_and_open(settings)
try:
# listen to what's happeneing on the serial port.
EM,out = logic.read_serial(ser)
except Exception, ex:
ser.close()
try:
ser.close()
except:
pass
return EM,out
if __name__ == "__main__":
settings = settings()
settings = check_db(settings)
main(settings)

251
TorchTester/frmMain.py Normal file
View File

@ -0,0 +1,251 @@
# -*- coding: utf-8 -*-
###########################################################################
## Python code generated with wxFormBuilder (version Sep 8 2010)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE!
###########################################################################
import wx
import logic
import thread
import time
import datetime
import subprocess
from wx.lib.wordwrap import wordwrap
###########################################################################
## Class frmMain
###########################################################################
class frmMain ( wx.Frame ):
def __init__( self, parent,settings):
self.settings = settings
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Torch Tester",
pos = wx.DefaultPosition, size = wx.Size( 925,631 ), style = wx.SYSTEM_MENU | wx.CLOSE_BOX | wx.CAPTION | wx.MINIMIZE_BOX )
favicon = wx.Icon(settings.ICON_FILE,
wx.BITMAP_TYPE_ICO)
self.SetIcon(favicon)
self.Bind(wx.EVT_CLOSE, self.onClose)
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
formSizer = wx.BoxSizer( wx.VERTICAL )
mainSizer = wx.BoxSizer( wx.VERTICAL )
self.m_panel2 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
mainSizer.Add( self.m_panel2, 1, wx.EXPAND, 5 )
formSizer.Add( mainSizer, 0, wx.EXPAND, 5 )
self.m_panel1 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
gSizer3 = wx.GridSizer( 2, 4, 0, 0 )
LeakSizerLeft = wx.BoxSizer( wx.VERTICAL )
leakTitleSizer = wx.BoxSizer( wx.VERTICAL )
self.leakTitle = wx.StaticText( self.m_panel1, wx.ID_ANY, u"Leak", wx.DefaultPosition, wx.DefaultSize, 0 )
self.leakTitle.Wrap( -1 )
self.leakTitle.SetFont( wx.Font( 22, 74, 90, 90, True, "Tahoma" ) )
leakTitleSizer.Add( self.leakTitle, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
LeakSizerLeft.Add( leakTitleSizer, 0, wx.EXPAND, 5 )
leakSizer1 = wx.BoxSizer( wx.HORIZONTAL )
self.leak1 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0 )
self.leak1.Wrap( -1 )
self.leak1.SetFont( wx.Font( 12, 74, 90, 90, False, "Tahoma" ) )
self.imgLeak1 = wx.StaticBitmap( self.m_panel1, wx.ID_ANY|wx.ALIGN_RIGHT, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
leakSizer1.Add( self.imgLeak1, 1, wx.ALL, 5)
leakSizer1.Add( self.leak1, 0, wx.ALL, 5 )
LeakSizerLeft.Add( leakSizer1, 1, wx.EXPAND, 5 )
leakSizer2 = wx.BoxSizer( wx.HORIZONTAL )
self.leak2 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0 )
self.leak2.Wrap( -1 )
self.leak2.SetFont( wx.Font( 12, 74, 90, 90, False, "Tahoma" ) )
self.imgLeak2 = wx.StaticBitmap( self.m_panel1, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
leakSizer2.Add( self.imgLeak2, 1, wx.ALL, 5 )
leakSizer2.Add( self.leak2, 0, wx.ALL, 5 )
LeakSizerLeft.Add( leakSizer2, 1, wx.EXPAND, 5 )
leakSizer3 = wx.BoxSizer( wx.HORIZONTAL )
self.leak3 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0 )
self.leak3.Wrap( -1 )
self.leak3.SetFont( wx.Font( 12, 74, 90, 90, False, "Tahoma" ) )
self.imgLeak3 = wx.StaticBitmap( self.m_panel1, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
leakSizer3.Add( self.imgLeak3, 1, wx.ALL, 5 )
leakSizer3.Add( self.leak3, 0, wx.ALL, 5 )
LeakSizerLeft.Add( leakSizer3, 1, wx.EXPAND, 5 )
leakSizer4 = wx.BoxSizer( wx.HORIZONTAL )
self.leak4 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0 )
self.leak4.Wrap( -1 )
self.leak4.SetFont( wx.Font( 12, 74, 90, 90, False, "Tahoma" ) )
self.imgLeak4 = wx.StaticBitmap( self.m_panel1, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
leakSizer4.Add( self.imgLeak4, 1, wx.ALL, 5 )
leakSizer4.Add( self.leak4, 0, wx.ALL, 5 )
LeakSizerLeft.Add( leakSizer4, 1, wx.EXPAND, 5 )
LeakSizerLeft.AddSpacer( ( 0, 150), 1, wx.EXPAND, 5 )
gSizer3.Add( LeakSizerLeft, 0, wx.EXPAND|wx.RIGHT, 5 )
gSizer3.AddSpacer( ( 18, 0), 1, wx.EXPAND, 5 )
FlowSizerRight = wx.BoxSizer( wx.VERTICAL )
flowTitleSizer = wx.BoxSizer( wx.VERTICAL )
self.flowTitle = wx.StaticText( self.m_panel1, wx.ID_ANY, u"Flow", wx.DefaultPosition, wx.DefaultSize, 0 )
self.flowTitle.Wrap( -1 )
self.flowTitle.SetFont( wx.Font( 22, 74, 90, 90, True, "Tahoma" ) )
flowTitleSizer.Add( self.flowTitle, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
FlowSizerRight.Add( flowTitleSizer, 0, wx.EXPAND, 5 )
flowSizer1 = wx.BoxSizer( wx.HORIZONTAL )
self.flow1 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0 )
self.flow1.Wrap( -1 )
self.flow1.SetFont( wx.Font( 12, 74, 90, 90, False, "Tahoma" ) )
self.imgFlow1 = wx.StaticBitmap( self.m_panel1, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
flowSizer1.Add( self.imgFlow1, 1, wx.ALL, 5 )
flowSizer1.Add( self.flow1, 0, wx.ALL, 5 )
FlowSizerRight.Add( flowSizer1, 1, wx.EXPAND, 5 )
flowSizer2 = wx.BoxSizer( wx.HORIZONTAL )
self.flow2 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0 )
self.flow2.Wrap( -1 )
self.flow2.SetFont( wx.Font( 12, 74, 90, 90, False, "Tahoma" ) )
self.imgFlow2 = wx.StaticBitmap( self.m_panel1, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
flowSizer2.Add( self.imgFlow2, 1, wx.ALL, 5 )
flowSizer2.Add( self.flow2, 0, wx.ALL, 5 )
FlowSizerRight.Add( flowSizer2, 1, wx.EXPAND, 5 )
flowSizer3 = wx.BoxSizer( wx.HORIZONTAL )
self.flow3 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0 )
self.flow3.Wrap( -1 )
self.flow3.SetFont( wx.Font( 12, 74, 90, 90, False, "Tahoma" ) )
self.imgFlow3 = wx.StaticBitmap( self.m_panel1, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
flowSizer3.Add( self.imgFlow3, 1, wx.ALL, 5 )
flowSizer3.Add( self.flow3, 0, wx.ALL, 5 )
FlowSizerRight.Add( flowSizer3, 1, wx.EXPAND, 5 )
flowSizer4 = wx.BoxSizer( wx.HORIZONTAL )
self.flow4 = wx.StaticText( self.m_panel1, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0 )
self.flow4.Wrap( -1 )
self.flow4.SetFont( wx.Font( 12, 74, 90, 90, False, "Tahoma" ) )
self.imgFlow4 = wx.StaticBitmap( self.m_panel1, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
flowSizer4.Add( self.imgFlow4, 1, wx.ALL, 5 )
flowSizer4.Add( self.flow4, 0, wx.ALL, 5 )
FlowSizerRight.Add( flowSizer4, 1, wx.EXPAND, 5 )
FlowSizerRight.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 )
gSizer3.Add( FlowSizerRight, 0, wx.EXPAND|wx.LEFT, 5 )
self.m_panel1.SetSizer( gSizer3 )
self.m_panel1.Layout()
gSizer3.Fit( self.m_panel1 )
formSizer.Add( self.m_panel1, 1, wx.EXPAND, 5 )
formSizer.AddSpacer( ( 1024 , 0), 0, wx.EXPAND, 5 )
self.SetSizer( formSizer )
self.Layout()
self.mnuMainBar = wx.MenuBar( 0 )
self.mnuOptions = wx.Menu()
self.m_sqlite = wx.MenuItem( self.mnuOptions, wx.ID_ANY, u"SQLite Browser", wx.EmptyString, wx.ITEM_NORMAL )
self.Bind(wx.EVT_MENU, self.sqlite_browser, self.m_sqlite)
self.mnuOptions.AppendItem( self.m_sqlite )
self.about = wx.MenuItem( self.mnuOptions, wx.ID_ANY, u"&About", wx.EmptyString, wx.ITEM_NORMAL )
self.Bind(wx.EVT_MENU, self.about_button, self.about)
self.mnuOptions.AppendItem( self.about )
self.m_exit = wx.MenuItem( self.mnuOptions, wx.ID_ANY, u"E&xit", wx.EmptyString, wx.ITEM_NORMAL )
self.Bind(wx.EVT_MENU, self.onClose, self.m_exit)
self.mnuOptions.AppendItem( self.m_exit )
self.mnuMainBar.Append( self.mnuOptions, u"&Options" )
self.SetMenuBar( self.mnuMainBar )
#self.m_statusBar1 = self.CreateStatusBar( 1, wx.ST_SIZEGRIP, wx.ID_ANY )
self.Centre( wx.BOTH )
thread.start_new_thread(WorkerThread,(self,settings,))
def __del__( self ):
self.destroy()
pass
def onClose(self,event):
self.Destroy()
def about_button(self, evt):
# First we create and fill the info object
info = wx.AboutDialogInfo()
info.Name = "TorchTester"
info.Version = "1.0.0.1"
info.Copyright = "(C) 2011 Benchtop Devices LLC"
info.Description = wordwrap("""
This program monitors the CTS Blackbelt.
In the left column are leak tests, and on the right are flow tests.
The tests are compared with default values found in config.ini (an example of which is provided for you in the %APPDATA%/TorchTester/ directory)
In the config.ini file, the leak value is the highest value to pass, and the flow is the lowest value to pass.
To view the database, select SQLite Browser from the Options menu.
""",
# change the wx.ClientDC to use self.panel instead of self
350, wx.ClientDC(self))
info.WebSite = ("http://www.benchtopdevices.com", "Benchtop Devices")
info.Developers = [ "Tyrel Souza",
"Anthony Souza"]
# Then we call wx.AboutBox giving it that info object
wx.AboutBox(info)
def sqlite_browser(self,event):
p1=subprocess.Popen(self.settings.DIR + '\\SQLiteBrowser\\SQLiteBrowser.exe "'+self.settings.DB_FILE+'"')
def WorkerThread(self,settings):
while True:
logic.run_test(self,settings)

View File

@ -0,0 +1,39 @@
import wx
import os
APPNAME = "TorchTester"
def clear(wxObj):
wx.CallAfter(wxObj.flow1.SetLabel, '')
wx.CallAfter(wxObj.flow2.SetLabel, '')
wx.CallAfter(wxObj.flow3.SetLabel, '')
wx.CallAfter(wxObj.flow4.SetLabel, '')
wx.CallAfter(wxObj.leak1.SetLabel, '')
wx.CallAfter(wxObj.leak2.SetLabel, '')
wx.CallAfter(wxObj.leak3.SetLabel, '')
wx.CallAfter(wxObj.leak4.SetLabel, '')
wx.CallAfter(wxObj.imgFlow1.SetBitmap, (wx.Bitmap(os.path.join(os.environ['APPDATA'], APPNAME) +'\\blank.png')))
wx.CallAfter(wxObj.imgFlow1.SetSize, (72,72))
wx.CallAfter(wxObj.imgFlow2.SetBitmap, (wx.Bitmap(os.path.join(os.environ['APPDATA'], APPNAME) +'\\blank.png')))
wx.CallAfter(wxObj.imgFlow2.SetSize, (72,72))
wx.CallAfter(wxObj.imgFlow3.SetBitmap, (wx.Bitmap(os.path.join(os.environ['APPDATA'], APPNAME) +'\\blank.png')))
wx.CallAfter(wxObj.imgFlow3.SetSize, (72,72))
wx.CallAfter(wxObj.imgFlow4.SetBitmap, (wx.Bitmap(os.path.join(os.environ['APPDATA'], APPNAME) +'\\blank.png')))
wx.CallAfter(wxObj.imgFlow4.SetSize, (72,72))
wx.CallAfter(wxObj.imgLeak1.SetBitmap, (wx.Bitmap(os.path.join(os.environ['APPDATA'], APPNAME) +'\\blank.png')))
wx.CallAfter(wxObj.imgLeak1.SetSize, (72,72))
wx.CallAfter(wxObj.imgLeak2.SetBitmap, (wx.Bitmap(os.path.join(os.environ['APPDATA'], APPNAME) +'\\blank.png')))
wx.CallAfter(wxObj.imgLeak2.SetSize, (72,72))
wx.CallAfter(wxObj.imgLeak3.SetBitmap, (wx.Bitmap(os.path.join(os.environ['APPDATA'], APPNAME) +'\\blank.png')))
wx.CallAfter(wxObj.imgLeak3.SetSize, (72,72))
wx.CallAfter(wxObj.imgLeak4.SetBitmap, (wx.Bitmap(os.path.join(os.environ['APPDATA'], APPNAME) +'\\blank.png')))
wx.CallAfter(wxObj.imgLeak4.SetSize, (72,72))

248
TorchTester/logic.py Normal file
View File

@ -0,0 +1,248 @@
import wx
import time
import datetime
import serial
import platform
import sqlite3
import initialization as ini
from decimal import Decimal
import locale
#EXITMETHOD = ["Unknown","Completed","Stop Button","Severe Leak"]
leak_template = """Test %s:
Actual Leak: %s sccm
Target Leak: %s
Delta: %s"""
flow_template = """Test %s:
Actual Flow: %s sccm
Target Flow: %s
Delta: %s"""
def connect_serial_and_open(s):
"""
This function will determine if thecomputer is running Windows
or Linux, and set the Serial port appropriately.
Then it will setup the serial port as 8-n-1 and 115200 baud.
This function then checks if the serial port is not open,
if it is not, it opens it and returns the serial port object.
"""
ser = serial.Serial()
# Set up 15200 8-N-1
ser.port = s.COMPORT
ser.baudrate = s.BAUDRATE
ser.bytesize = s.BYTESIZE
ser.parity = s.PARITY
ser.stopbits = s.STOPBITS
if not ser.isOpen():
ser.open()
return ser
#71E1011 T Start Streaming
def run_test(wxObj,settings):
ser = connect_serial_and_open(settings)
test = 0
for run,exit in read_serial(ser,wxObj):
test += 1
if exit == 1 or exit == 0:
if isinstance(run,dict):
runno = int(run['run_number'])
_runs=('A','B','C','D')
if runno < 4:
for k,v in enumerate(_runs):
if k == runno:
tol,delta = passes(run,settings,wxObj,runno)
delta = "%.2f" % delta
lbl = leak_template % (v, str(round(float(run['sccm']),2)),tol,delta)
wx.CallAfter(wxObj.leak1.SetLabel, lbl)
else:
for k,v in enumerate(_runs):
if k+4 == runno:
sccm = float(run['sccm'])
tol,delta = passes(run,settings,wxObj,runno)
sccm = intWithCommas(sccm)
tol = intWithCommas(tol)
delta= intWithCommas(delta)
lbl = flow_template % (v, sccm,tol,delta)
wx.CallAfter(wxObj.flow1.SetLabel, lbl)
else:
msg = None
if exit == 2 and run == 'SB':
msg = 'STOP BUTTON PRESSED'
elif exit == 3 and run == 'SL':
msg = 'SEVERE LEAK'
elif exit == 4 and run == 'MISC':
msg = 'BELOW PRESSURE'
if msg:
if test < 5:
if test ==1:
ini.clear(wxObj)
wx.CallAfter( getattr(wxObj, 'lead%s' % test).SetLabel, msg)
else:
wx.CallAfter( getattr(wxObj, 'flow%s' % test - 4).SetLabel, msg)
return None
def read_serial(ser=None,wxObj=None):
STOP = False
ExitMethod = 0
if ser and ser.isOpen() and wxObj:
buffer = ''
run_number = -1
while not STOP:
sent = False
buffer = buffer + ser.read(1)
last_list = buffer.partition('\r\n')
if last_list[1]:
last_received = last_list[0]
output = parse_line(last_received)
if output == "SB":
STOP = True
ExitMethod = 2
elif output == "SL":
STOP = True
ExitMethod = 3
elif output == "MISC":
STOP = True
ExitMethod = 4
elif output:
if run_number < 0:
ini.clear(wxObj)
run_number +=1
output['run_number'] = run_number
if run_number == 8:
STOP = True
ExitMethod = 1
yield output,ExitMethod
continue
# P12 is a dummy test to release pressure between 7 and 8, so we must ignore that.
if not output['program_number'] == "P12":
sent = True
yield output,ExitMethod
if output and not sent:
try:
yield output,ExitMethod
except GeneratorExit:
pass
buffer = last_list[2]
def parse_line(line_to_parse,last_program_number=None ):
# strip all whitespace from end of line
#if there remains anything, continue on.
if line_to_parse:
# actually store result as a list of strings, split by \t
try:
if "TTY Pressure Decay-L" in line_to_parse:
return "MISC"
result = line_to_parse.rstrip().split('\t')
# check if the list is equal to 3, and that "R" is the 2nd item
if len(result) == 3 and "R" in result[1]:
# If R is the second item, split Result by spaces.
l = result[2].split(' ')
# Remove all blank items in the list
l = [item for item in l if item]
# There will be a summary as the last item, if this is so,
# Skip the item and return None
if l[4] == "SB":
return "SB"
if l[4] == "SL":
return "SL"
if l[5] == "LNK":
return None
# Prepare a dictionary with the keys and values
# we yanked from the test
out_result = {}
out_result['port_number'] = l[0]
out_result['program_number'] = l[1]
out_result['run_datetime'] = datetime.datetime.strptime(
"%s %s" % (l[2], l[3]), "%H:%M:%S.%f %m/%d/%y")
out_result['evaluation'] = l[6]
out_result['sccm'] = l[8]
if out_result:
return out_result
except:
pass
def passes(run,settings,wxObj,runno):
GREEN = wx.Bitmap(settings.DIR + '\\green.png')
RED = wx.Bitmap(settings.DIR + '\\red.png')
for i in range(0,9):
if i > 9:
raise AttributeError('Not sure what this all means, but I dont think we can continute')
if i < 4:
tol,delta,pass_or_fail=withinTolerance(run,settings,run['run_number'])
color = GREEN if pass_or_fail else RED
wx.CallAfter(getattr(wxObj, 'imgLeak%s' % i +1).SetBitmap, (color))
else:
tol,delta,pass_or_fail=withinTolerance(run,settings,run['run_number'])
color = GREEN if pass_or_fail else RED
wx.CallAfter( getattr(wxObj,'imgFlow%s'% i -4).SetBitmap, (color))
return tol,delta
def withinTolerance(run,settings,runno):
tol = Decimal(settings.get_limits(runno,settings))
sccm = Decimal(run['sccm'])
passes = False
if runno < 4:
delta = sccm - tol
if sccm < tol:
passes = True
else:
delta = tol - sccm
if sccm > tol:
passes = True
delta = abs(delta)
rundate = run['run_datetime'].date()
runtime = str(run['run_datetime'].time())
if passes:
passes_ar = "A"
else:
passes_ar = "R"
results = [run['port_number'],
run['program_number'],
rundate,
runtime,
run['sccm'],
passes_ar]
conn = sqlite3.connect(settings.DB_FILE,detect_types=sqlite3.PARSE_DECLTYPES)
c = conn.cursor()
c.execute("INSERT INTO torch_record (port_number,program_number,test_date,test_time,measurement,result) VALUES(?,?,?,?,?,?)",results)
conn.commit()
c.close()
return tol,delta,passes
def intWithCommas(x):
x = int(x)
if type(x) not in [type(0), type(0L)]:
raise TypeError("Parameter must be an integer.")
if x < 0:
return '-' + intWithCommas(-x)
result = ''
while x >= 1000:
x, r = divmod(x, 1000)
result = ",%03d%s" % (r, result)
return "%d%s" % (x, result)

43
TorchTester/scanports.py Normal file
View File

@ -0,0 +1,43 @@
#! /usr/bin/env python
"""\
Scan for serial ports.
Part of pySerial (http://pyserial.sf.net)
(C) 2002-2003 <cliechti@gmx.net>
The scan function of this module tries to open each port number
from 0 to 255 and it builds a list of those ports where this was
successful.
"""
import serial
import glob
import sys
def win_scan():
"""scan for available ports. return a list of tuples (num, name)"""
available = []
for i in range(256):
try:
s = serial.Serial(i)
available.append( (i, s.portstr))
s.close() # explicit close 'cause of delayed GC in java
except serial.SerialException:
pass
return available
def get():
ports = []
if sys.platform.startswith('win'):
for n,s in win_scan():
ports.append(s)
else:
for name in lin_scan():
ports.append(name)
return ports
def lin_scan():
"""scan for available ports. return a list of device names."""
return glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*')

221
TorchTester/wxImages.py Normal file
View File

@ -0,0 +1,221 @@
#----------------------------------------------------------------------
# This file was generated by img2py.py
#
from wx.lib.embeddedimage import PyEmbeddedImage
red = PyEmbeddedImage(
"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"
"/wNREk1547u9MgAAAABJRU5ErkJggg==")
getredData = red.GetData
getredImage = red.GetImage
getredBitmap = red.GetBitmap
getredIcon = red.GetIcon
green = PyEmbeddedImage(
"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")
getgreenData = green.GetData
getgreenImage = green.GetImage
getgreenBitmap = green.GetBitmap
getgreenIcon = green.GetIcon