我的小工具,用C和python实现远程读卡器,远程读写消费卡片

简介: 我的小工具,用C和python实现远程读卡器,远程读写消费卡片

这个远程读卡器就是一普通usb口或串口的读卡器,只不过配合一个电脑软件作为tcp服务器。这样,程序员可以在公司电脑上运行程序连到服务器上。服务器端操作控制现场的读卡器。

晚上睡不着,想着白天工作上的事,让现场同事配合抓包,读取一下卡上数据,但现场同事连串口助手都没听说过,指望不上了。想到可以做一个远程读卡器。


对调试现场读卡之类的程序太有用了。想抓包现场卡上数据,很easy了。封装一些读卡接口。甚至可以实现远程仿真调试程序读卡消费逻辑 。或者实现一完全软件模拟的pos机。


这想法可行吧,我抽空打算实现一个。至少对我的工作很有帮助吧。目前已实现了部分电脑程序模拟车载pos机通信。可以模拟pos机与采集前置服务通信,下载票价,传消费记录。后续加进去读卡功能。跟采集前置服务调通信我一般电脑上先调通,再移植到车载机上,效率提高不少。省得找机器,找流量卡,开外网端口映射,接仿真器。现场再也不用担心车载机记录全采出来咋入库了。用这个模拟程序直接解析模拟车载机通信就传上去。


说做就做。由于我是终端组的,不像平台他们有现成的读卡器。于是想到用车载POS机的读卡模块配合串口做一个。作为读卡器用。服务器端考虑用python,有很多模块可以用,实现起来快。


一、功能简介:


本工具实现一个在电脑上运行的模拟车载机终端。只是功能上的模拟,并不是与车载机完全一样。用现场的B502机器作为模拟终端的读卡模块,在公司远程读、写、消费现场的M1卡,CPU卡,并按照车载机中的记录格式存储记录到电脑上,然后通过与采集前置通信把记录传给采集前置服务。全采的车载机记录也可以拿过来用,通过此工具传给采集前置。


实现了供本地电脑调用的读卡库,通信库和记录存储库,所有库的接口均与嵌入式终端程序中的文件库,卡库,通信库接口一致。此工具只是利用卡库,通信库和文件库的一个例子。若需要在某个具体项目中读写卡,抓包,测卡,消费,上传记录等,需根据提供的接口单独做自己的应用。


二、实现原理:


1.移植嵌入式程序中的文件库到电脑上,实现参数保存和记录存储模块。


2.用电脑上的socket通信封装嵌入式终端上的通信接口。


3.修改B502机器程序,把B502机器做成一个读卡器。


4.做一个TCP服务程序,开启服务端口,运行在远程的电脑上,服务程序通过电脑串口控制B502读卡器并提供读写卡服务接口,供客户端调用。


5.客户端根据提供的接口做应用,实现远程读写卡,消费,记录存储,上传。


 


三、操作说明


现场操作:


1.升级B502车载机程序,把B502机器当作读卡器使用,串口连接到电脑上。


2.在电脑上安装并运行读写卡服务程序,为客户端提供读写卡服务。


3.开启外网端口映射,没有固定IP也不是问题。只要现场的电脑能连外网,就可以把现场电脑的端口映射到外网,可以使用免费的端口映射工具。


4.提供现场映射过的公网IP地址和端口给开发人员。


5.把待读取的卡片放到机器上。


缺点:


现场必须有B502机器,且有串口线。B502机器还需要接12V的电源,体积大也不方便携带。所以用 B502机器做读卡器,有局限性,不通用。不过公司现有E711读卡器,该读卡器只需软件改造一下,升级下程序,就可以配合后台运行的TcpServer读写卡服务实现远程读卡器。消费速度上受网络原因有影响,不过远程读卡器只作为调试测试的手段,不是专门用来消费卡片的。实测消费完M1卡大概需要6秒钟。


客户端接口:


文件库libmyfile.a


通信库libmycom.a


读卡库libmycard.a


算法库libmycalc.a


客户端接口:


文件库libmyfile.a


通信库libmycom.a


读卡库libmycard.a


算法库libmycalc.a


接口和车载机程序的保持一致,参见头文件。


读卡库libmycard.a


CPU卡操作接口:


ICC_APDU_Exchange(……)


M1卡操作接口:


ICC_MiOne_LoadKey(…… );                        


ICC_MiOne_CheckKey(…… )


ICC_MiOne_BlkRead(……)


ICC_MiOne_BlkWrite(……)


ICC_MiOne_Value(……)


……


若是CPU卡,客户端可直接用TCP调试工具发指令调试卡片。


例如:


选择卡片3F00目录,直接在TCP助手上文本发送:00A40000023F00


若是选择现场PSAM卡的3F00目录,直接在TCP助手上文本发送:P00A40000023F00,前面多加了一个字母P


若是M1卡,指令有点儿复杂,客户端最好写个小程序,调用接口读写卡。


一天时间,初步实现了。原理就是TCP的socket通信转串口通信。源码如下;


#coding=utf-8
#author:yangyongzhen
#QQ:534117529
import sys,threading,time;
import serial;
import binascii,encodings;
import re;
import os;
from socket import *
from struct import *;
from myutil import *;
#''代表服务器为localhost
#在一个非保留端口号上进行监听
class ComThread:
    def __init__(self, Port=0):
        self.l_serial = None;
        self.alive = False;
        self.waitEnd = None;
        self.port = Port;
        #TCP部分
        self.myHost = ''
        self.myPort = 5050
        self.sockobj = socket(AF_INET, SOCK_STREAM)
        self.connection = None
        #数据
        self.snddata = ''
        self.rcvdata = ''
    def waiting(self):
        if not self.waitEnd is None:
            self.waitEnd.wait();
    def SetStopEvent(self):
        if not self.waitEnd is None:
            self.waitEnd.set();
        self.alive = False;
        self.stop();
    def start(self):
        self.l_serial = serial.Serial();
        self.l_serial.port = self.port;
        self.l_serial.baudrate = 115200;
        self.l_serial.timeout = 2;  #秒
        self.l_serial.open();
        if self.l_serial.isOpen():
            self.waitEnd = threading.Event();
            self.alive = True;
            self.thread_read = None;
            self.thread_read = threading.Thread(target=self.FirstReader);
            self.thread_read.setDaemon(1);
            self.thread_read.start();
            self.thread_write = None;
            self.thread_write = threading.Thread(target=self.FirstWriter);
            self.thread_write.setDaemon(1);
            self.thread_write.start();
            #TCP部分
            self.thread_TcpServer = None;
            self.thread_TcpServer = threading.Thread(target=self.TcpServer);
            self.thread_TcpServer.setDaemon(1);
            self.thread_TcpServer.start();
            self.thread_TcpSend = None;
            self.thread_TcpSend = threading.Thread(target=self.TcpSend);
            self.thread_TcpSend.setDaemon(1);
            self.thread_TcpSend.start();
            return True;
        else:
            return False;
    def FirstReader(self):
        while self.alive:
            # 接收间隔
            time.sleep(0.1);
            try:
                data = '';
                n = self.l_serial.inWaiting();
                if n:
                    data = self.l_serial.read(n);
                    #for l in xrange(len(data)):
                        #print '%02X' % ord(data[l]),
                    # 发送数据
                    print 'serial recv:'
                    print data;
                    self.snddata = data
                    #print_hex(data);
                # 判断结束
            except Exception, ex:
                print str(ex);
        self.waitEnd.set();
        self.alive = False;
    def FirstWriter(self):
        while self.alive:
            # 接收间隔
            time.sleep(0.1);
            try:
                #snddata = raw_input('\nenter data send:\n')
                if self.rcvdata!='':
                    self.l_serial.write(self.rcvdata); 
                    print 'serial send:'
                    print self.rcvdata;
                    self.rcvdata = '';
                #print_hex(snddata);
            except Exception, ex:
                print str(ex);
        self.waitEnd.set();
        self.alive = False;
    def TcpServer(self):
      self.sockobj.bind((self.myHost, self.myPort))
        self.sockobj.listen(1)
        print '\nTcpServer listen at 5050 oK!\n'
        while True:
            # 接收间隔
            time.sleep(0.5);
            self.connection, address = self.sockobj.accept()
            print 'Server connected by', address
            self.snddata = ''
            self.rcvdata = ''
            while True:
            #读取客户端套接字的下一行
            data = self.connection.recv(1024)
            #如果没有数量的话,那么跳出循环
            if not data: break
            #发送一个回复至客户端
            self.rcvdata = data
            #connection.send('Echo=>' + data)
            self.connection.close()
        self.waitEnd.set();
        self.alive = False;
    def TcpSend(self):
        while True:
            # 接收间隔
            time.sleep(0.5);
            while True:
              time.sleep(0.5);
              try:
                if not self.connection is None:
                  if self.snddata != '':
                    self.connection.send(self.snddata)
                    self.snddata = ''
              except Exception, ex:
            pass        
    def stop(self):
        self.alive = False;
        self.thread_read.join();
        if self.l_serial.isOpen():
            self.l_serial.close();
#测试用部分
if __name__ == '__main__':
    print 'CardTest TcpServer  - Simple Test Card Tool 1.00\n' 
    print 'Copyright (c) Newcapec 2015-2016.\n'
    com =raw_input('please enter com port(1-9):')
    rt = ComThread(int(com)-1);
    try:
        if rt.start():
            rt.waiting();
            rt.stop();
        else:
            pass;            
    except Exception,se:
        print str(se);
    if rt.alive:
        rt.stop();
    os.system("pause")
    print '';
    print 'End OK .';
    del rt;


实现的效果图:



用C语言封装一下读写卡接口,可以做个客户端测试了:



 

相关文章
|
21天前
|
数据可视化 编译器 Python
Manim:数学可视化的强大工具 | python小知识
Manim(Manim Community Edition)是由3Blue1Brown的Grant Sanderson开发的数学动画引擎,专为数学和科学可视化设计。它结合了Python的灵活性与LaTeX的精确性,支持多领域的内容展示,能生成清晰、精确的数学动画,广泛应用于教育视频制作。安装简单,入门容易,适合教育工作者和编程爱好者使用。
96 7
|
1月前
|
JavaScript 前端开发 开发者
探索 DrissionPage: 强大的Python网页自动化工具
DrissionPage 是一个基于 Python 的网页自动化工具,结合了浏览器自动化的便利性和 requests 库的高效率。它提供三种页面对象:ChromiumPage、WebPage 和 SessionPage,分别适用于不同的使用场景,帮助开发者高效完成网页自动化任务。
151 4
|
1月前
|
开发者 Python
探索Python中的列表推导式:简洁而强大的工具
【10月更文挑战第41天】 在编程的世界中,效率与简洁是永恒的追求。本文将深入探讨Python编程语言中一个独特且强大的特性——列表推导式(List Comprehension)。我们将通过实际代码示例,展示如何利用这一工具简化代码、提升性能,并解决常见编程问题。无论你是初学者还是资深开发者,掌握列表推导式都将使你的Python之旅更加顺畅。
|
2月前
|
数据采集 数据可视化 数据挖掘
R语言与Python:比较两种数据分析工具
R语言和Python是目前最流行的两种数据分析工具。本文将对这两种工具进行比较,包括它们的历史、特点、应用场景、社区支持、学习资源、性能等方面,以帮助读者更好地了解和选择适合自己的数据分析工具。
59 2
|
2月前
|
C语言 开发者 Python
探索Python中的列表推导式:简洁而强大的工具
【10月更文挑战第21天】在Python的世界里,代码的优雅与效率同样重要。列表推导式(List Comprehensions)作为一种强大而简洁的工具,允许开发者通过一行代码完成对列表的复杂操作。本文将深入探讨列表推导式的使用方法、性能考量以及它如何提升代码的可读性和效率。
|
2月前
|
Python
python读写操作excel日志
主要是读写操作,创建表格
69 2
|
2月前
|
自然语言处理 算法 数据挖掘
探讨如何利用Python中的NLP工具,从被动收集到主动分析文本数据的过程
【10月更文挑战第11天】本文介绍了自然语言处理(NLP)在文本分析中的应用,从被动收集到主动分析的过程。通过Python代码示例,详细展示了文本预处理、特征提取、情感分析和主题建模等关键技术,帮助读者理解如何有效利用NLP工具进行文本数据分析。
60 2
|
2月前
|
测试技术 Python
Python MagicMock: Mock 变量的强大工具
Python MagicMock: Mock 变量的强大工具
59 4
|
2月前
|
存储 Python
python数据类型、debug工具(一)
python数据类型、debug工具(一)
|
2月前
|
网络协议 IDE iOS开发
Python编程---简单的聊天工具
Python编程---简单的聊天工具
48 2