initialize
diff --git a/.project b/.project
new file mode 100644
index 0000000..fb9ffc1
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>tcutils</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.python.pydev.PyDevBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.python.pydev.pythonNature</nature>
+ </natures>
+</projectDescription>
diff --git a/.pydevproject b/.pydevproject
new file mode 100644
index 0000000..a270ffe
--- /dev/null
+++ b/.pydevproject
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?>
+
+<pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/tcutils/src</path>
+</pydev_pathproperty>
+</pydev_project>
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..9991c1a
--- /dev/null
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,4 @@
+#Mon Sep 26 12:39:46 CST 2011
+eclipse.preferences.version=1
+encoding//src/pybccclt.py=gbk
+encoding/setup.py=utf-8
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..a49c273
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from distutils.core import setup
+import os
+
+def find_all_dist_module():
+ base_dir = 'src'
+ all_files = os.listdir(base_dir)
+ modules=[]
+ for f in all_files:
+ fname = os.path.join(base_dir,f)
+ if os.path.isfile(fname):
+ ext = f.split('.')[-1]
+ #print f.split('.')
+ if ext == 'py':
+ modules.append(f)
+
+ return modules
+
+#print find_all_dist_module()
+
+setup(
+ name = 'tcutils',
+ version = "0.2",
+ description = "Cheng Tang 's python libraries",
+ author = 'Cheng Tang',
+ author_email = 'cashtang@gmail.com',
+ platforms=['All'],
+ packages=['tcutils']
+ )
\ No newline at end of file
diff --git a/src/amassprotocol.py b/src/amassprotocol.py
new file mode 100644
index 0000000..5f56fee
--- /dev/null
+++ b/src/amassprotocol.py
@@ -0,0 +1,389 @@
+#!/usr/bin/python
+# -*- coding: gbk -*-
+
+import sys,codecs,struct
+
+IFT_NULL=0
+IFT_ULONG=1
+IFT_BYTE=2
+IFT_USHORT=3
+IFT_DATETIME=4
+IFT_BUFFER=5
+IFT_STRING=6
+IFT_LONG=7
+
+# (0,0,1,IFT_BYTE,0,"msgtype","ÏûÏ¢Âë"),
+
+FLD_NO_IDX=0
+FLD_LENGTH_IDX=2
+FLD_TYPE_IDX=3
+FLD_FLAG_IDX=4
+FLD_NAME_IDX=5
+FLD_DESC_IDX=6
+
+HDFieldsDef = [
+(1,0,0,IFT_NULL,0,"extend","À©Õ¹Óò·ñ"),
+(2,0,4,IFT_ULONG,0,"terminalsn"," ÖÕ¶ËÐòÁкÅ"),
+(3,0,2,IFT_USHORT,0,"address","CANµØÖ·"),
+(4,0,4,IFT_ULONG,0,"cardnumber","¿¨ºÅ"),
+(5,0,1,IFT_BYTE,0,"indexofew"," Ç®°üË÷Òý"),
+(6,0,2,IFT_USHORT,0,"traceofew"," Ç®°üÁ÷Ë®ºÅ"),
+(7,0,4,IFT_LONG,0,"amount"," ½»Ò×½ð¶î"),
+(8,0,4,IFT_LONG,0,"additionalamount1","¸½¼Ó½ð¶î"),
+(9,0,4,IFT_ULONG,0,"traceofpos","POSÁ÷Ë®ºÅ"),
+(10,0,4,IFT_ULONG,0,"orgtranstrace","Ô½»Ò×Á÷Ë®ºÅ"),
+(11,0,7,IFT_DATETIME,0,"datetime","½»Ò×ÈÕÆÚºÍʱ¼ä"),
+(12,0,1,IFT_BYTE,0,"responsecode","ÏìÓ¦Âë"),
+(13,0,2,IFT_USHORT,0,"terminalid","Öն˺Å"),
+(14,0,2,IFT_USHORT,0,"terminaltype","ÖÕ¶ËÀàÐÍ"),
+(15,0,2,IFT_USHORT,0,"merchantid","ÉÌ»§(Íøµã)ºÅ"),
+(16,0,4,IFT_ULONG,0,"operatorid","²Ù×÷Ô±ºÅ"),
+(17,0,8,IFT_BUFFER,0,"pin","¸öÈËʶ±ðÂëPIN"),
+(18,0,4,IFT_ULONG,0,"veroflist","ºÚÃûµ¥°æ±¾"),
+(19,0,4,IFT_ULONG,0,"managefee","½»Ò×Åú´ÎºÅ(Ôݲ»ÓÃ)"),
+(20,0,360,IFT_BUFFER,2,"additionaldata1","¸½¼ÓÐÅÏ¢1"),
+(21,0,528,IFT_BUFFER,2,"additionaldata2","¸½¼ÓÐÅÏ¢2"),
+(22,0,528,IFT_STRING,2,"additionaldata3","¸½¼ÓÐÅÏ¢3"),
+(23,0,528,IFT_STRING,2,"additionaldata4","¸½¼ÓÐÅÏ¢4"),
+(24,0,2,IFT_USHORT,0,"mac","ÏûÏ¢ÈÏÖ¤Âë")
+]
+
+class HDPack:
+ ''' »ã¶à 8583 ÐÒé°ü '''
+ def __init__(self):
+ self.msg_type = 0
+ self.value={}
+ self.field_idx={}
+ self.field_name={}
+ self.msgtype = 0
+
+ self.load_config()
+
+ def __eq__(self,other):
+ if not isinstance(other,HDPack):
+ return False
+ return self.compare(other)
+ def __ne__(self,other):
+ if not isinstance(other,HDPack):
+ return True
+ return not self.compare(other)
+
+ def compare(self,other):
+ if self.msgtype != other.msgtype:
+ return False
+ for k,v in self.value.items():
+ if not other.value.has_key(k):
+ print "field [%s] not equal" % k
+ return False
+ if v <> other.get(k):
+ print "field [%s] value not equal [%s,%s]" % (k,v,other.get(k))
+ return False
+ return True
+
+ def load_config(self):
+ for field in HDFieldsDef:
+ index,t,len,type,flag,name,desc = field
+ self.field_idx[index] = field
+ self.field_name[name] = field
+ #print self.field_name
+
+ def get_field_def(self,index):
+ field_def = None
+ if isinstance(index,int):
+ if not self.field_idx.has_key(index):
+ raise ValueError("field index %d not exists" % index)
+ field_def = self.field_idx[index]
+ elif isinstance(index,str):
+ if not self.field_name.has_key(index):
+ raise ValueError("field index %s not exists" % index)
+ field_def = self.field_name[index]
+ else:
+ raise ValueError("field index type not support")
+
+ return field_def
+
+ def set(self,index,value):
+ field_def = self.get_field_def(index)
+ t = field_def[FLD_TYPE_IDX]
+ n = field_def[FLD_NAME_IDX]
+ l = field_def[FLD_LENGTH_IDX]
+ f = field_def[FLD_FLAG_IDX]
+ if t == IFT_USHORT or t == IFT_ULONG or t == IFT_NULL or t == IFT_BYTE or t == IFT_LONG:
+ if isinstance(value,int):
+ b = value
+ elif isinstance(value,str):
+ if value.startswith('0x'):
+ b = int(value,16)
+ else:
+ b = int(value)
+ else:
+ raise ValueError("field %s value type not integer" % n)
+ elif t == IFT_DATETIME:
+ if len(value) != 12 and len(value) != 14:
+ raise ValueError("field %s length must be 12 or 14" % n)
+ if len(value) == 14:
+ value = value[2:]
+ b = value + "00"
+ else:
+ if not isinstance(value,str):
+ raise ValueError("field %s value type not string" % n)
+
+ if t == IFT_DATETIME:
+ l *= 2
+ elif value.startswith('0x'):
+ l *= 2
+ l += 2
+
+ if f <> 2 and len(value) <> l:
+ raise ValueError("field %s value data length not equal %d<>%d " % (n,len(value),l))
+ elif len(value) > l:
+ raise ValueError("field %s value data length exceed %d " % (n,l))
+
+ b = value
+
+ self.value[n] = b
+
+ def get(self,index):
+ field_def = self.get_field_def(index)
+ t = field_def[3]
+ n = field_def[5]
+
+ if self.value.has_key(n):
+ return self.value[n]
+ raise ValueError("Field %s not specified" % n)
+
+
+ def encode_bitmap(self,bitmap):
+ buffer = ''
+ offset = 0
+ #print "bit len[%d]" % len(bitmap)
+ while offset < len(bitmap):
+ bit = 0
+ for i in range(8):
+ t = ord(bitmap[offset+i]) - 0x30
+ if t == 0: continue
+ bit |= (1 << (7 - i % 8))
+ buffer += chr(bit&0xFF)
+ offset += 8
+ return buffer
+
+ def pack(self,workkey=None):
+ buffer = ''
+ bitmap = ['0' for i in range(24)]
+ for field in HDFieldsDef:
+ index,x,len,t,flag,name,desc = field
+ if not self.value.has_key(name):
+ continue
+
+ if t == IFT_USHORT or t == IFT_ULONG or t == IFT_NULL or t == IFT_BYTE or t == IFT_LONG:
+ buffer += self.int_2_buffer(self.value[name],t,len)
+ else:
+ buffer += self.string_2_buffer(self.value[name],t,len,flag)
+ bitmap[index-1] = '1'
+ #print bitmap
+
+ bitmap_buffer = self.encode_bitmap(bitmap)
+ full_data = chr(self.msgtype&0xFF) + bitmap_buffer + buffer
+ header = self.data_header(full_data)
+ #print "h[%s]d[%s]" % (codecs.encode(header,'hex'),codecs.encode(full_data,'hex'))
+ return header + full_data
+
+ def data_header(self,buffer):
+ if len(buffer) > 0xFFFF:
+ raise ValueError("Buffer max length exceed %d", len(buffer))
+ header = struct.pack('<H',len(buffer))
+ return header
+
+ def int_2_buffer(self,value,type,length):
+ buffer = ''
+ if type == IFT_BYTE:
+ buffer = chr(value%0x100)
+ elif type == IFT_NULL:
+ return buffer
+ elif type == IFT_USHORT:
+ v = value % 0x10000
+ buffer = struct.pack('<H',v)
+ elif type == IFT_ULONG:
+ buffer = struct.pack('<I',value)
+ elif type == IFT_LONG:
+ buffer = struct.pack('<i',value)
+ else:
+ raise ValueError('Input Error')
+
+ return buffer
+
+ def encode_bcd(self,value):
+ if len(value) % 2 != 0:
+ raise ValueError("value length must div 2")
+ i = 0
+ #print "value [%s]" % value
+ buffer = ''
+ while i < len(value):
+ t1 = (ord(value[i]) - 0x30)& 0xFF
+ t2 = (ord(value[i+1]) - 0x30) & 0xFF
+ #print "t1[%d]t2[%d]" % (t1,t2)
+ t = ((t1<<4) | t2) & 0xFF
+ #print "t1[%d]t2[%d]t[%d]" % (t1,t2,t)
+ buffer += chr(t)
+ i += 2
+ #print "bcd value[%s]" % codecs.encode(buffer,'hex')
+ return buffer
+
+ def decode_bcd(self,value):
+ buffer = ''
+ #print "bcd [%s]" % codecs.encode(value,'hex')
+ for c in value:
+ t = ord(c) & 0xFF
+ t1 = (t >> 4) & 0x0F
+ t2 = t & 0x0F
+ #print "t[%02x]t1[%d]t2[%d]" % (t,t1,t2)
+ buffer += chr(t1 + 0x30) + chr(t2 + 0x30)
+ #print "bcd value[%s]" % buffer
+ return buffer
+
+ def string_2_buffer(self,value,type,length,flag):
+ buffer = ''
+ if type == IFT_STRING or type == IFT_BUFFER:
+ if value.startswith('0x'):
+ buffer = codecs.decode(value[2:],'hex')
+ else:
+ buffer = value
+ elif type == IFT_DATETIME:
+ buffer = ''
+ i = 0
+ while i < len(value):
+ t = int(value[i:i+2])
+ buffer += chr(t & 0xFF)
+ i += 2
+ else:
+ raise ValueError('Input Error')
+
+ if flag == 2:
+ header = struct.pack('<H',len(buffer) % 0x10000)
+ return header + buffer
+ else:
+ #if type == IFT_BUFFER:
+ # if len(buffer) % 2 <> 0 or len(buffer)/2 <> length:
+ # raise ValueError("Value length not matched [%s]" % value)
+ # buffer = codecs.decode(buffer,'hex')
+ if len(buffer) != length:
+ padlen = length - len(buffer)
+ if padlen < 0:
+ raise ValueError("Value length not matched [%s]" % value)
+
+ pad = chr(0) * padlen
+ buffer = pad + buffer
+ return buffer
+
+
+ def decode_bitmap(self,bitmap):
+ if len(bitmap) != 3:
+ raise ValueError("bitmap length error")
+ #print "bitmap[%s]" % codecs.encode(bitmap,'hex')
+ buffer=[]
+ for t in bitmap:
+ v = ord(t) & 0xFF
+ for i in range(8):
+ x = (v & (1 << (7-i)))
+ if x > 0:
+ buffer.append('1')
+ else:
+ buffer.append('0')
+ return buffer
+
+ def unpack(self,data):
+ self.value = {}
+ #print "data[%s]" % codecs.encode(data,'hex')
+ data_len = struct.unpack('<H',data[:2])[0]
+ if len(data) != data_len + 2:
+ print "input[%d] extually[%d]" % (data_len,len(data))
+ return False
+
+ offset = 2
+ self.msgtype = ord(data[offset]) & 0xFF
+ offset += 1
+ bitmap = self.decode_bitmap(data[offset:offset+3])
+ offset += 3
+ #print bitmap
+ for i in range(len(bitmap)):
+ if bitmap[i] == '0': continue
+ findex = i + 1
+ field = self.get_field_def(findex)
+ ftype = field[FLD_TYPE_IDX]
+ flen = field[FLD_LENGTH_IDX]
+ fflag = field[FLD_FLAG_IDX]
+ fname = field[FLD_NAME_IDX]
+ #print "parse field[%s] [%d]off[%d][%s]" % (fname,fflag,offset,codecs.encode(data[offset:offset+2],'hex'))
+ if fflag == 2: # ±ä³¤Êý¾Ý
+ #print "len [%s]" % codecs.encode(data[offset:offset+2],'hex')
+ endpos = self.buffer_2_int(data[offset:offset+2],IFT_USHORT)
+ offset += 2
+ endpos += offset
+ else:
+ endpos = offset + flen
+
+ if ftype == IFT_USHORT or ftype == IFT_ULONG or ftype == IFT_NULL or ftype == IFT_BYTE or ftype == IFT_LONG:
+ value = self.buffer_2_int(data[offset:endpos],ftype)
+ else:
+ #temp = self.buffer_2_string(data[offset:endpos],ftype)
+ #if fflag != 2 and ftype == IFT_STRING:
+ # for i in temp:
+ # print "char [%02x]" % ord(i)
+ # if ord(i) > 0:
+ # value += i
+ #else:
+ # value = temp
+ value = self.buffer_2_string(data[offset:endpos],ftype)
+ if fflag <> 2 and ftype == IFT_BUFFER:
+ value = '0x' + codecs.encode(value,'hex')
+
+ self.set(findex,value)
+ #print "parse field[%s] OK =====" % fname
+ offset = endpos
+ #print self.value
+ return True
+
+ def buffer_2_int(self,data,type):
+ if type == IFT_BYTE:
+ return ord(data)
+ elif type == IFT_USHORT:
+ return struct.unpack('<H',data)[0]
+ elif type == IFT_ULONG:
+ return struct.unpack('<I',data)[0]
+ elif type == IFT_LONG:
+ return struct.unpack('<i',data)[0]
+ elif type == IFT_NULL:
+ return None
+ else:
+ raise ValueError("input data type error")
+
+ def buffer_2_string(self,data,type):
+ if type == IFT_STRING:
+ return data
+ elif type == IFT_BUFFER:
+ return data
+ elif type == IFT_DATETIME:
+ return self.decode_bcd(data)
+ else:
+ raise ValueError("input data type error")
+
+
+ def get_2byte_int(self,data):
+ return struct.unpack(">H",data)[0]
+
+ def get_3byte_int(self,data):
+ temp = data + chr(0)
+ return struct.unpack("<I",temp)[0]
+
+ def get_4byte_int(self,data):
+ return struct.unpack("<I",data)[0]
+
+ def set_2byte_int(self,data):
+ return struct.pack('<H',data)
+
+ def set_3byte_int(self,data):
+ temp = struct.pack('<H',data)
+ return temp[:-1]
+
+ def set_4byte_int(self,data):
+ return struct.pack('<I',data)
\ No newline at end of file
diff --git a/src/pbocfunc.py b/src/pbocfunc.py
new file mode 100644
index 0000000..f21bf37
--- /dev/null
+++ b/src/pbocfunc.py
@@ -0,0 +1,131 @@
+#! /usr/bin/env python
+# vim: tabstop=4
+
+import pyDes, codecs
+
+
+
+def desencrypt(key, data, m=pyDes.ECB):
+ k = pyDes.des(key, pad=None, padmode=pyDes.PAD_NORMAL, mode=m)
+ return k.encrypt(data)
+
+def desdecrypt(key, data, m=pyDes.ECB):
+ k = pyDes.des(key, pad=None, padmode=pyDes.PAD_NORMAL, mode=m)
+ return k.decrypt(data)
+
+def tripledesencrypt(key, data, m=pyDes.ECB):
+ k = pyDes.triple_des(key, pad=None, padmode=pyDes.PAD_NORMAL, mode=m)
+ return k.encrypt(data)
+
+def tripledesdecrypt(key, data, m=pyDes.ECB):
+ k = pyDes.triple_des(key, pad=None, padmode=pyDes.PAD_NORMAL, mode=m)
+ return k.decrypt(data)
+
+
+def desencrypthex(key, data):
+ k = pyDes.des(codecs.decode(key, 'hex'), pad=None, padmode=pyDes.PAD_NORMAL)
+ e = k.encrypt(codecs.decode(data, 'hex'))
+ return codecs.encode(e, 'hex')
+
+def tripledesencrypthex(key, data):
+ k = pyDes.triple_des(codecs.decode(key, 'hex'), pad=None, padmode=pyDes.PAD_NORMAL)
+ e1 = k.encrypt(codecs.decode(data, 'hex'))
+ return codecs.encode(e1, 'hex')
+
+def DataNot(data):
+ r = ''
+ for a in data:
+ r = r + chr((~ord(a)) & 0xFF)
+ return r
+
+def PadCardPhyNo(phyno):
+ r = ''
+ if len(phyno) < 8:
+ pad = "\x80\x00\x00\x00\x00\x00\x00\x00"
+ l = 8 - len(phyno)
+ r = phyno + pad[:l]
+ elif len(phyno) == 8:
+ r = phyno
+ else:
+ r = phyno[:8]
+ return r
+
+def PadCardPhyNoHex(phyno):
+ return codecs.encode(PadCardPhyNo(codecs.decode(phyno, 'hex')), 'hex')
+
+def PbocDeliveryKey(factor, key):
+ cipherdatanot = ''
+ cipherdata = PadCardPhyNo(factor)
+
+ print "factor is [%s]" % codecs.encode(cipherdata, 'hex')
+
+ if len(key) == 8: # singledes delivery
+ k1 = desencrypt(key, cipherdata)
+ return k1
+ elif len(key) == 16:
+ cipherdatanot = DataNot(cipherdata)
+
+ k1 = tripledesencrypt(key, cipherdata)
+ k2 = tripledesencrypt(key, cipherdatanot)
+
+ return k1 + k2
+ else:
+ raise ValueError('key length error')
+
+def PbocDeliveryKeyHex(factor, key):
+ f = codecs.decode(factor, 'hex')
+ k = codecs.decode(key, 'hex')
+ k1 = PbocDeliveryKey(f, k)
+ return codecs.encode(k1, 'hex')
+
+
+def CalcMac3DES(data, initdata, key):
+ datalen = len(data)
+ k = pyDes.des(key[:8], pad=None, padmode=pyDes.PAD_NORMAL)
+
+ for i in range(datalen / 8):
+ m = ""
+ for j in range(len(initdata)):
+ m = m + chr(ord(initdata[j]) ^ ord(data[i * 8 + j]))
+
+ initdata = m
+ x = k.encrypt(initdata)
+ initdata = x
+
+
+ k1 = pyDes.des(key[8:], pad=None, padmode=pyDes.PAD_NORMAL)
+ n = k1.decrypt(initdata)
+ initdata = k.encrypt(n)
+ return initdata
+
+def CalcMac3DESHex(data, initdata, key):
+ d = codecs.decode(data, 'hex')
+ id = codecs.decode(initdata, 'hex')
+ k = codecs.decode(key, 'hex')
+ k1 = CalcMac3DES(d, id, k)
+ return codecs.encode(k1, 'hex')
+
+def CalcMacDES(data, initdata, key):
+ datalen = len(data)
+ k = pyDes.des(key, pad=None, padmode=pyDes.PAD_NORMAL)
+
+ for i in range(datalen / 8):
+ m = ""
+ for j in range(len(initdata)):
+ m = m + chr(ord(initdata[j]) ^ ord(data[i * 8 + j]))
+
+ initdata = m
+ x = k.encrypt(initdata)
+ initdata = x
+
+ return initdata
+
+def CalcMacDESHex(data, initdata, key):
+ d = codecs.decode(data, 'hex')
+ id = codecs.decode(initdata, 'hex')
+ k = codecs.decode(key, 'hex')
+ k1 = CalcMacDES(d, id, k)
+ return codecs.encode(k1, 'hex')
+
+
+
diff --git a/src/performance.py b/src/performance.py
new file mode 100644
index 0000000..ce3cf93
--- /dev/null
+++ b/src/performance.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env
+
+import datetime, threading, thread
+
+class CheckPerf:
+ writelock = threading.Lock()
+ def __init__(self):
+ self.begintime = datetime.datetime.now()
+ self.endtime = None
+ self.mintime = 0.0
+ self.maxtime = 0.0
+ self.successcount = 0
+ self.failedcount = 0
+ self.totaltime = 0.0
+ self.reportmsg = ''
+ self.prechktime = None
+
+ def startchk(self):
+ self.begintime = datetime.datetime.now()
+ self.endtime = None
+ self.mintime = 99999999.0
+ self.maxtime = 0.0
+ self.checkcount = 0
+ self.totaltime = 0.0
+ self.reportmsg = ''
+ self.prechktime = self.begintime
+
+ def setchkpoint(self, success=True):
+ self.endtime = datetime.datetime.now()
+ delta = self.endtime - self.prechktime
+ t = delta.seconds + delta.microseconds / 1000000.0
+ if t < self.mintime: self.mintime = t
+ if t > self.maxtime: self.maxtime = t
+ if success:
+ self.successcount += 1
+ else:
+ self.failedcount += 1
+ self.totaltime += t
+ self.prechktime = self.endtime
+
+ def _output_file(self, out_file):
+ handler = open(out_file, 'a+b')
+ handler.write("thrd[%d]" % thread.get_ident())
+ handler.write(' - ' + self.reportmsg + '\n')
+ handler.close()
+
+ def _reportToFile(self, out_file):
+ CheckPerf.writelock.acquire()
+ try:
+ self._output_file(out_file)
+ print "generate report file " , out_file
+ except Exception, ex:
+ print "generator report file ", out_file , " Error ", ex
+ CheckPerf.writelock.release()
+
+ def report_msg(self):
+ totalcheckcount = self.successcount + self.failedcount
+ if totalcheckcount > 2:
+ avg = (self.totaltime - self.mintime - self.maxtime) / (totalcheckcount - 2)
+ elif totalcheckcount == 0:
+ rpt = "No check point has been set"
+ return rpt
+ else:
+ avg = self.totaltime / totalcheckcount
+ rpt = 'execute[%d]count cost(s) [%.4f]max[%.4f]min[%.4f]avg[%.4f] success[%d] failed[%d]' \
+ % (totalcheckcount, self.totaltime, self.maxtime, self.mintime, avg, \
+ self.successcount, self.failedcount)
+ return rpt
+
+ def report(self, out_file=None):
+ self.reportmsg = self.report_msg()
+ if out_file:
+ self._reportToFile(out_file)
+ return self.reportmsg
+
diff --git a/src/pybccclt.py b/src/pybccclt.py
new file mode 100644
index 0000000..ce10630
--- /dev/null
+++ b/src/pybccclt.py
@@ -0,0 +1,353 @@
+#!/usr/bin/python
+# -*- coding: gbk -*-
+
+from ctypes import *
+
+bccclt_dll = None
+xpack_path = 'cpack.dat'
+
+cpack_fields = [
+"scust_no",
+"scust_no2",
+"sholder_ac_no",
+"sholder_ac_no2",
+"sholder_type",
+"sholder_type2",
+"sname",
+"sname2",
+"sall_name",
+"smarket_code",
+"smarket_code2",
+"sdate0",
+"sdate1",
+"sdate2",
+"sdate3",
+"stime0",
+"stime1",
+"stime2",
+"stime3",
+"lvol0",
+"lvol1",
+"lvol2",
+"lvol3",
+"lvol4",
+"lvol5",
+"lvol6",
+"lvol7",
+"lvol8",
+"lvol9",
+"lvol10",
+"lvol11",
+"lvol12",
+"damt0",
+"damt1",
+"damt2",
+"damt3",
+"damt4",
+"damt5",
+"damt6",
+"damt7",
+"damt8",
+"damt9",
+"damt10",
+"damt11",
+"damt12",
+"damt13",
+"damt14",
+"damt15",
+"damt16",
+"damt17",
+"damt18",
+"damt19",
+"damt20",
+"damt21",
+"damt22",
+"damt23",
+"damt24",
+"damt25",
+"damt26",
+"damt27",
+"damt28",
+"damt29",
+"damt30",
+"damt31",
+"damt32",
+"damt33",
+"sstock_code",
+"sstock_code2",
+"scust_type",
+"scust_type2",
+"sstat_type",
+"sstat_type2",
+"sroom_no",
+"sroom_no2",
+"sopen_emp",
+"sclose_emp",
+"schange_emp",
+"scheck_emp",
+"semp",
+"snation_code",
+"lcert_code",
+"stx_pwd",
+"stx_pwd2",
+"swithdraw_pwd",
+"swithdraw_pwd2",
+"semp_pwd",
+"semp_pwd2",
+"sbank_pwd",
+"sbank_pwd2",
+"scust_auth",
+"scust_auth2",
+"scust_limit",
+"scust_limit2",
+"lsafe_level",
+"lsafe_level2",
+"spost_code",
+"spost_code2",
+"sphone",
+"sphone2",
+"sphone3",
+"spager",
+"semail",
+"semail2",
+"snote",
+"snote2",
+"scert_no",
+"scert_no2",
+"scert_addr",
+"sstatus0",
+"sstatus1",
+"sstatus2",
+"sstatus3",
+"sstatus4",
+"lwithdraw_flag",
+"saddr",
+"saddr2",
+"sserial0",
+"sserial1",
+"sserial2",
+"sserial3",
+"sserial4",
+"scurrency_type",
+"scurrency_type2",
+"sbranch_code0",
+"sbranch_code1",
+"sbranch_code2",
+"usset0",
+"usset1",
+"usset2",
+"usset3",
+"usset4",
+"usset5",
+"usset6",
+"sstation0",
+"sstation1",
+"sbank_acc",
+"sbank_acc2",
+"lbank_acc_type",
+"lbank_acc_type2",
+"smain_flag",
+"smain_flag2",
+"sbank_code",
+"sbank_code2",
+"semp_no",
+"semp_no2",
+"drate0",
+"drate1",
+"lserial0",
+"lserial1",
+"sbankname",
+"sbankname2",
+"scard0",
+"scard1",
+"sorder0",
+"sorder1",
+"sorder2",
+"scusttypes",
+"ssectypes",
+"vsmess",
+"vsvarstr0",
+"vsvarstr1",
+"vsvarstr2"
+]
+
+def load_bccclt():
+ global bccclt_dll
+ bccclt_dll = cdll.LoadLibrary('bccclt.dll')
+
+
+load_bccclt()
+
+class pyBccclt:
+ drtp_no = -1
+
+ def setup(ip,port,xpack='cpack.dat',debug=0):
+ ''' ³õʼ»¯ '''
+ global xpack_path
+ xpack_path = xpack
+ bccclt_dll.SetDebugSwitch( debug )
+ r = bccclt_dll.BCCCLTInit(1)
+ if not r:
+ raise RuntimeError("³õʼ»¯Á¬½Óʧ°Ü")
+ no = bccclt_dll.AddDrtpNode(ip,port)
+ pyBccclt.drtp_no = no
+ if pyBccclt.drtp_no < 0:
+ raise RuntimeError('³õʼ»¯Í¨Ñ¶Æ½Ì¨Á¬½Óʧ°Ü')
+
+
+
+ setup = staticmethod(setup)
+
+ def __init__(self,mainfunc):
+ self.handle = bccclt_dll.NewXpackHandle( xpack_path )
+ self.mainfunc = mainfunc
+ self.reset()
+
+ def get_errormsg(self):
+ return self.error_msg.value
+
+ def reset(self):
+ self.request_row = 0
+ self.error_code = c_int(0)
+ self.error_msg = create_string_buffer('\000' * 1024)
+ self.return_code = c_int(0)
+ self.record_count = 0
+ self.record = None
+ self.timeout = 5000
+ self.response_row = 0
+ bccclt_dll.ResetPackHandle(self.handle)
+
+ def close(self):
+ if self.handle <> None:
+ bccclt_dll.DeleteXpackHandle( self.handle )
+ self.handle = None
+
+ def callsvr(self,func,request,timeout = 1000):
+ self.reset()
+ self.timeout = timeout
+ for k,v in request.iteritems():
+ if k not in cpack_fields:
+ raise ValueError("×Ö¶Î %s ²»´æÔÚ" % k)
+
+ if isinstance(v,int):
+ bccclt_dll.SetIntFieldByName(self.handle,self.request_row,k,v)
+ elif isinstance(v,float):
+ bccclt_dll.SetDoubleFieldByName(self.handle,self.request_row,k,v)
+ elif isinstance(v,str):
+ bccclt_dll.SetStringFieldByName(self.handle,self.request_row,k,v)
+ else:
+ raise ValueError("×Ö¶Î %s Êý¾ÝÀàÐÍ´íÎó" % k)
+
+ bccclt_dll.SetRequestType(self.handle,func)
+ #print "CallRequest %d:%d" % (self.mainfunc,func)
+ if not bccclt_dll.CallRequest(self.handle,pyBccclt.drtp_no,0,self.mainfunc,timeout,byref(self.error_code),self.error_msg):
+ #print "CallRequest error "
+ return False
+
+ self.get_return_error()
+
+ cnt = c_int(0)
+ bccclt_dll.GetRecordCount(self.handle,byref(cnt))
+ self.record_count = cnt.value
+ return True
+
+ def get_retcode(self):
+ return self.return_code.value
+
+ def get_return_error(self):
+ r = bccclt_dll.GetRetCode(self.handle,byref(self.return_code))
+ if not r:
+ raise RuntimeError('È¡·µ»ØÂë´íÎó')
+ if self.get_retcode() <> 0:
+ bccclt_dll.GetStringFieldByName(self.handle,0,"vsmess",self.error_msg)
+ return self.return_code.value
+
+ def has_more_record(self):
+ #print "resp:%d, record: %d" % (self.response_row , self.record_count)
+ if self.response_row < self.record_count:
+ return True
+ elif not bccclt_dll.HaveNextPack( self.handle ):
+ return False
+ elif not bccclt_dll.CallNext(self.handle,self.timeout,byref(self.error_code),self.error_msg):
+ raise RuntimeError('»ñÈ¡ºóÐøÊý¾Ý°üÒì³£')
+ else:
+ self.response_row = 0
+ self.record_count = 0
+ self.get_return_error()
+ if self.get_retcode() <> 0:
+ raise RuntimeError('È¡ºóÐøÊý¾Ý·µ»Ø´íÎó£¬ret=%d' % self.get_retcode())
+ cnt = c_int(0)
+ bccclt_dll.GetRecordCount(self.handle,byref(cnt))
+ self.record_count = cnt.value
+ if self.response_row < self.record_count:
+ return True
+ return False
+
+ def convert_ascii(self,data):
+ i = 0
+ datalen = len(data)
+ result = ''
+ while i < datalen:
+ t = data[i:i+2]
+ t1 = int(t,16) & 0xFF
+ if (t1 < ord('0') or t1 > ord('9')) and (t1 < ord('A') or t1 > ord('F')):
+ raise ValueError("Value is non-hexdicimal %s:%d" % (chr(t1),t1))
+ result += chr(t1)
+ i += 2
+ return result
+
+ def next_record(self,fields):
+ if self.response_row >= self.record_count:
+ raise ValueError('ÎÞ¿ÉÓüǼ')
+
+ self.record = {}
+ for f in fields:
+ #print "»ñÈ¡×Ö¶Î ",f
+ if f not in cpack_fields:
+ raise ValueError("×Ö¶Î %s ²»´æÔÚ" % f)
+
+ ctype_field = create_string_buffer(f)
+ if f[0] == 'l':
+ v = c_int(0)
+ r = bccclt_dll.GetIntFieldByName(self.handle,self.response_row,ctype_field,byref(v))
+ if not r:
+ raise ValueError("×Ö¶Î %s δ·µ»Ø" % f)
+ self.record[f] = v.value
+ elif f[0] == 's':
+ v = create_string_buffer('\000' * 512)
+ r = bccclt_dll.GetStringFieldByName(self.handle,self.response_row,ctype_field,v,511)
+ if not r:
+ raise ValueError("×Ö¶Î %s δ·µ»Ø" % f)
+ #print "%s: %s" % (f,v.value)
+ self.record[f] = v.value
+ elif f[0] == 'd':
+ v = c_double(0.0)
+ r = bccclt_dll.GetDoubleFieldByName(self.handle,self.response_row,ctype_field,byref(v))
+ if not r:
+ raise ValueError("×Ö¶Î %s δ·µ»Ø" % f)
+ self.record[f] = v.value
+ elif f[0] == 'u':
+ v = create_string_buffer('\000' * 1024)
+ r = bccclt_dll.GetStringFieldByName(self.handle,self.response_row,ctype_field,v,1023)
+ if not r:
+ raise ValueError("×Ö¶Î %s δ·µ»Ø" % f)
+
+ data = v.value
+ data = data[2:]
+ data = self.convert_ascii(data)
+ self.record[f] = data
+ else:
+ raise ValueError('×Ö¶ÎÀàÐÍ´íÎó %s' % f)
+ self.response_row += 1
+ #print "fetch one record , " ,self.record
+ return self.record
+
+ def fetch_record(self,fields):
+ while self.has_more_record():
+ ret = self.next_record(fields)
+ yield ret
+
+
+
+
+
\ No newline at end of file
diff --git a/src/tcutils_module/__init__.py b/src/tcutils_module/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tcutils_module/__init__.py
diff --git a/src/tcutils_module/testmodule.py b/src/tcutils_module/testmodule.py
new file mode 100644
index 0000000..3dfec02
--- /dev/null
+++ b/src/tcutils_module/testmodule.py
@@ -0,0 +1,5 @@
+'''
+Created on 2011-9-26
+
+@author: cheng.tang
+'''