zoukankan      html  css  js  c++  java
  • 树莓派在身份证件核验领域应用

    树莓派在身份证件核验领域应用

    作者:Mr.Kim.Wu 

    邮箱:mrkimwu@gmail.com

    发布:2013-10-08

    关键字:RaspberryPi,Raspi,RPI,树莓派,身份证阅读器,二代证,身份证,居民身份证,RFID,NFC,Debian,linux,创客

    一、简介

    1.1 第二代居民身份证

    第二代居民身份证是一种既具有视读,又具有机读两种功能的法定有效证件。证件内记录了公民的身份信息,是不可以替代而且不能非法复制、仿制的证件,具有唯一性。自2004年换发第二代居民身份证工作正式开展以来,全国二代证的换发量已接近12亿张,基本上人手一张。

    第二代居民身份证是由多层聚酯材料复合而成的单页卡式证件,采用非接触式IC卡技术制作,具备视读和机读两种功能。证件尺寸设计长85.6毫米,宽54毫米,厚1.0毫米。证件正面有姓名、性别、民族、出生日期、常住户口所在地住址、公民身份号码和本人相片7个登记项目,印有彩色花纹。证件背面有签发机关和有效期限2个登记项目,印有国徽图案、证件名称、写意长城图案和彩色花纹。

    第二代居民身份证有六大变化:融入RFID技术、防伪性能提高、办证时间缩短、存储信息增多、有效期重新确定、发放范围扩大等。

    1.2 身份证阅读器

    居民身份证阅读器接口技术规范符合GA 467-2004国家标准,新制定的标准里增加了指纹内容。

    二代身份证读卡器是一种能判断身份证是否伪造的设备,像验钞机一样,能对身份证真伪进行有效识别,二代证内含有RFID芯片,通过二代身份证读卡器,身份证芯片内所存储信息,包括姓名,地址,照片等信息将一一显示,二代证芯片采用智能卡技术,其芯片无法复制,高度防伪,配合二代身份证读卡器,假身份证将无处藏身。可读取、查询第二代居民身份证全部信息,可验证第二代居民身份证真伪。

    具有以下特点:

    ● 通用性强:支持WIN98/2000/XP/NT/WINCE/LINUX等多种操作系统。

    ● 开放性好:提供SDK供系统集成商进行二次开发。

    ● 功能强大:可外接标准键盘、鼠标、显示器,提供RS-232C、USB计算机接口。

    ● 扩展灵活:可加装指纹采集器,现场比对持证人的指纹,进行“人证同一性”认定。也可以外接数码采集设备,采集个人相片、文字等信息,作信息采集设备使用。

    ● 操作简便:开机即进入阅读界面,阅读软件自动找卡和阅读。

    1.3 树莓派 Raspberry Pi

    树莓派(英语:RaspberryPi),是一款基于Linux系统的只有一张信用卡大小的单板机计算机。它由英国的树莓派基金会所开发,目的是以低价硬件及自由软件刺激在学校的基本的电脑科学教育。

    相关介绍请参考维基:

    http://zh.wikipedia.org/wiki/%E6%A0%91%E8%8E%93%E6%B4%BE


    树莓派板载2个USB接口,以及丰富的外设端口,方便与各类外设通讯。

    本文实现了树莓派与身份证阅读器的连接,阅读显示身份证芯片内容。

    二、准备工作

    2.1设备清单:

    l       树莓派+ SD卡Class 4/ Class 10 8G

    l       USB转RS232串口线:ProlificUSB-to-Serial Bridg Y-105 (PL2303HX)

    l       RS232接口身份证阅读器

    l       TP-Link无线网络路由器

    2.2软件

    l       字符终端:SecureCRT软件

    l       文件传输: FileZilla软件 SFTP(SSH2)传输协议

    l       远程桌面:

    u     Windows:VNC Viewer或UltraVNC-Viewer

    u     Android:AndroidVNC

    三、实现步骤

    3.1连接方式

    本文使用树莓派板载USB口,通过USB转换线转成UART RS232串口与身份证9针RS232串口相连: USB<->RS232

    USB 驱动:免驱动安装

    在树莓派USB口插上阅读器之后查看USB<-> RS232设备:

    ls -l /dev/ttyUSB0

    如果直接使用树莓派板载GPIOTTL串口ttyAMA0可参考下面2个网址:

    http://www.savagehomeautomation.com/projects/raspberry-pi-rs232-serial-interface-options-revisit.html

    http://www.irrational.net/2012/04/19/using-the-raspberry-pis-serial-port/

    注意:树莓派板载TTL串口不可直接与身份证阅读器串口相连,电平不匹配容易损坏树莓派板载TTL串口。

    3.2开发工具链

    开发语言:

    G++开发底层通讯库。

    界面开发语言:本文使用GTK+(GIMP Toolkit)作开发界面

    界面设计工具:Glade

    其他可选语言:Python、Java、QT、LazarusPascal

    3.3软件开发

    本文采用调用串口设备/dev/ttyUSB0的方法。

    另外一种是直接调用身份证阅读器的USB IO管道 Pipe驱动设备,

    这种方法需要开发专用USB驱动,需熟悉USB协议,比较麻烦。

    首先保证串口转换线能用。

    短接RS232串口的2,3脚。

    编写串口测试程序一:

    参考:https://sites.google.com/site/semilleroadt/raspberry-pi-tutorials/gpio

    去这个网站下载并安装最新的Pyserial库 

    http://sourceforge.net/projects/pyserial/files/pyserial/

    //Python测试程序 testserial.py 

    import serial

    ser =serial.Serial("/dev/ttyUSB0",115200,timeout=1)

    ser.write("UARTthe Font")

    read =ser.read(13)

    print read

    ser.close()

    运行Python testserial.py 

    可以在终端看到输出一串字符UARTthe Font,如果不短接2,3脚将会在超时1秒后程序自动退出,直接换行输出空白。

    串口测试方法二:

    http://raspberrypi.stackexchange.com/questions/4801/usart-resending-problem-via-console
        在SSH字符终端输入

    sudo stty 115200-F /dev/ttyUSB0 -echo -onlcr

    cat /dev/ttyUSB0

    在VNC远程桌面终端输入

    echo hello>> /dev/ttyUSB0

     

    授权许可:

    身份证阅读器通讯库代码ABCVUtility.cpp、ABCVlib.cpp采用开源GPL授权许可协议,照片图像解码需采用公安专用授权许可协议。详请联系作者。

    阅读器串口通讯协议(具体请参考标准GA 467-2004):

    树莓派与身份阅读器采用命令/应答方式进行数据交换。

    数据通讯帧格式:

    命令数据输入帧格式

    帧头

    长度H

    长度L

    命令码

    命令参数

    数据内容

    校验和

    应答数据输出帧格式

    帧头

    长度H

    长度L

    SW1

    状态

    SW2

    状态SW3

    数据内容

    校验和

    身份证芯片存储编码格式:

    文字:256字节Unicode 编码,可转换成GBK码。

    照片:1024字节图像压缩编码。

    开始敲代码:


    ///////////////////////////////////////////////

    //ABCVlib.cpp代码

    #include<stdio.h>

    #include<fcntl.h>

    #include<time.h>

    #include<stdlib.h>

    #include<string.h>

    #include<unistd.h> 

    #include"ABCVlib.h"

    #include"ABCVUtility.h"

    /*帧头*/

    #define Preamble00xDD

    #define Preamble10xDD

    #define Preamble20xDD

    #define Preamble30xDD

    #define Preamble40xDD

    /*返回错误代码*/

    #define         RD_OK             0     //操作成功

    #define   OPENPORT_ERR      -1    //打开端口失败

    #define   TIMEOUT_ERR       -2    //超时

    #define         RD_CARD_ERR      -3    //无卡或读卡失败

    #define   CHECKSUM_ERR      -4    //校验和错

    #define   FILE_ERR          -5    //读卡结果文件打开出错

    /*机器命令码*/

    const unsignedchar CMD_SAM_READALLMSG[2]={0x00, 0x00};

    /*机器响应命令*/

    #define SW1      inBuffer[7]

    #define SW2      inBuffer[8]

    #define SW3      inBuffer[9]

    #define SAMSTATE     inBuffer[9]

    #defineRD_SAM_OK    0x90          //操作成功

    struct defMsg{

      unsigned char name[30];

      unsigned char sex[2];

      unsigned char nation[4];

      unsigned char bY[8],bM[4],bD[4];

      unsigned char address[70];

      unsigned char id[36];

      unsigned char depart[30];

      unsigned char tsY[8],tsM[4],tsD[4];

      unsigned char tpY[8],tpM[4],tpD[4];

    };

    #define MSG((struct defMsg *)&inBufferTMP[0])

    unsigned charinBuffer[2500],inBufferTMP[2500], outBuffer[50];

    unsigned longnBytesWrite=0;

    int CheckSum=0;

    char TMP[512];

    charchNation[100];

    /*******************************************************************************

    函数名:     *  abcv_SetPreamble      添加数据帧头

    输入参数:   *   无

    输出参数:   *   无

    *******************************************************************************/

    voidabcv_SetPreamble()

    {

        outBuffer[0]=Preamble0; 

        outBuffer[1]=Preamble1;  outBuffer[2]=Preamble2;

        outBuffer[3]=Preamble3;  outBuffer[4]=Preamble4;  CheckSum=0;

        nBytesWrite=0x05;   

    }

    /*******************************************************************************

    函数名:     *  abcv_CheckControlCode           加入待发数据

    输入参数:   *  unsigned char value        加入的数据

    输出参数:   *   无

    *******************************************************************************/

    voidabcv_CheckControlCode(unsigned char value)

    {

        CheckSum ^= value;

        outBuffer[nBytesWrite]=value;   

        nBytesWrite++; 

    }

    int abcv_ReadMsg(intterm, int port, int timeout, unsigned char *pucCHMsg, int *piCHMsgLen, unsignedchar *pucPHMsg, int *piPHMsgLen)

    {

       int Rtn=0;   int i=0;   int nBytes=0;

       FILE *f;

       //unsigned char TMP[512];

       //unsigned char chNation[100];

      

           if(abcv_openPort(term,port)== -1) return (OPENPORT_ERR);

          

       memset(outBuffer,'',50);

       //memset(inBuffer,'',2500);  

       abcv_SetPreamble();

       abcv_CheckControlCode(0x00); 

       abcv_CheckControlCode(0x03); 

       abcv_CheckControlCode(CMD_SAM_READALLMSG[0]); 

       abcv_CheckControlCode(CMD_SAM_READALLMSG[1]); 

       abcv_CheckControlCode(CheckSum);

      

       abcv_write_n(term, outBuffer, nBytesWrite);

       //接收帧头  

           Rtn= abcv_read_n(term, inBuffer, 7, timeout);        

           if(Rtn<7)

           {

              abcv_closePort(term);

               return(TIMEOUT_ERR);      //接收超时  

       }         

       if(inBuffer[0]!=Preamble0 ||inBuffer[1]!=Preamble1 ||

              inBuffer[2]!=Preamble2|| inBuffer[3]!=Preamble3 ||

              inBuffer[4]!=Preamble4)

            {

              abcv_closePort(term);

              return(TIMEOUT_ERR);      //接收超时  

       } 

           nBytes=inBuffer[5]*256+inBuffer[6];//计算数据长度

             

       //接收指定长度的数据

       Rtn = abcv_read_n(term, &inBuffer[7],nBytes, timeout);           

           abcv_closePort(term);   

          

           if(Rtn<nBytes)

           {

              abcv_closePort(term);

              return(TIMEOUT_ERR);      //接收超时  

       } 

       CheckSum=0;

       for (i=5;i<nBytes+6;i++)

            CheckSum^=inBuffer[i];

           if(CheckSum!=inBuffer[nBytes+6])

           {

              abcv_closePort(term);

              return(CHECKSUM_ERR);      //校验和错  

       } 

       //返回状态码 

          if(SW1==0x00 && SW2==0x00 && SW3==RD_SAM_OK)

          {         

              *piCHMsgLen=256;    

              *piPHMsgLen=1024;          

              memcpy(pucCHMsg,&inBuffer[14],256);

              memcpy(pucPHMsg,&inBuffer[270],1024);

              memcpy(inBufferTMP,&inBuffer[14],256);

              return (RD_OK);            

          }

          else 

       {         

              return(RD_CARD_ERR);

           }

            return (RD_CARD_ERR);     

            

    }

    intabcv_ReadIDCard(int term, int port, int timeout,

              unsigned char *pucCHMsg, int*piCHMsgLen, unsigned char *pucPHMsg, int *piPHMsgLen)

             

    {

       int RTN;

       FILE *f;

       char *wzfile="./wz.txt";

       char *wltfile="./xp.wlt";

      char*bmpfile="./xp.bmp";     

     

           unsignedchar CHMsg[512],PHMsg[1024];

           unsignedint CHMsgLen,PHMsgLen;

           RTN=abcv_ReadMsg(term,port, timeout, CHMsg,&CHMsgLen,PHMsg,&PHMsgLen);   

           if(RTN!=RD_OK) return(RTN);

         

          *piCHMsgLen=256;    

          *piPHMsgLen=1024;

          memcpy(pucCHMsg,CHMsg,256);

          memcpy(pucPHMsg,PHMsg,1024);      

       

          

           f=fopen(wzfile,"wb");

           if(f==NULL) return(FILE_ERR);           

       if (fwrite(CHMsg,CHMsgLen,1,f)!=1){

           fclose(f);

           return(FILE_ERR);

           }           

           fclose(f);

          

               

           f=fopen(wltfile,"wb");

       if (f==NULL) return(FILE_ERR); 

       if (fwrite(PHMsg,PHMsgLen,1,f)!=1){   

           fclose(f);

           return(FILE_ERR);

       }

       fclose(f);         

      

       //

        return(RD_OK);   

    }

    intabcv_getName(char * szName)

    {

      memset(TMP,'',512);

      abcv_strUnicode2GB(MSG->name,TMP,30);  

      sprintf( szName,"%s",TMP);       //       姓名:  

      return (0);

    }

    intabcv_getSex(char * szSex)

    {

      memset(TMP,'',512);       

      abcv_strUnicode2GB(MSG->sex,TMP,2);

                                  

      if ( memcmp(TMP,"1",1)==0 )

       sprintf( szSex,"男");     //       性别:

      else

       sprintf( szSex,"女");

          

      return (0);

    }

    //… …

    /////////////////////////////////

    以上cpp 的Makefile:

    #

    # libABCVLib.soMakefile

    #

    ARM_PREFIX=arm-linux-gnueabihf-

    CC   = $(ARM_PREFIX)g++

    LD      := ld

    CFLAGS  := -fpermissive

    LDFLAGS := -shared-fpic

    SOURCE  := $(wildcard *.cpp)

    OBJS    := $(patsubst %.cpp,%.o,$(SOURCE))

    TARGET_LIB := libABCVLib.so

    all:$(OBJS)

           echo $(OBJS)

           $(LD) $(LDFLAGS) -o $(TARGET_LIB) $(OBJS)

    %.o:%.cpp

           @echo Compiling $< ...

           $(CC) -c $(CFLAGS)  $< -o $*.o

            

    .PHONY: clean

    clean:

           rm *.so *.o –rf

     

    so编译环境设置:

    生成的共享库libABCVLib.so在非标准路经,ld.so 怎么找到它呢?

    目前,Linux 通用的做法是将非标准路经加入 /etc/ld.so.conf,然后运行 ldconfig 生成 /etc/ld.so.cache。ld.so加载共享库的时候,会从ld.so.cache 查找。

    或者在/etc/ld.so.conf.d/目录下新建一个共享库名字对应的conf文件:libABCVLib.conf,文件内容为你的工作目录,本文为/home/pi/kim/gtk30

     

    图形界面: 采用GTK+图形工具包调用libABCVLib.so 动态库显示身份证文字和照片。

    图形界面开发参考网址:http://hertaville.com/2012/09/28/development-environment-raspberry-pi-cross-compiler/http://hertaville.com/2013/07/19/cross-compiling-gtk-applications-for-the-raspberry-pi/

    //gtktest.c

    #include<gtk/gtk.h>

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

    #include<time.h>

    #include<termio.h>

    #include<unistd.h>

    #include<errno.h>

    #include<iconv.h>

    #include<locale.h>

    #include<ABCVlib.h> 

    #defineTERM_TYPE       1                //终端类型 默认1

    #defineTERM_PORT       1               //阅读机具所接的串口号

                                            //1:主机串口一

    #defineTIMEOUT         4               //读卡超时4秒返回

    #define BUFLEN 255 

      GtkWidget *window;

      GtkWidget *frame; 

      GtkWidget *label;

      GtkWidget *plus;

      GtkWidget *minus;

     

      GtkWidget *fixed1;

      GtkWidget *entrName;

      GtkWidget *entrSex;

      GtkWidget *label1;

      GtkWidget *entrNation;

      GtkWidget *entrBirthday;

      GtkWidget *entrAddr;

      GtkWidget *entrID;

      GtkWidget *entrDep;

      GtkWidget *entrValid;

      GtkWidget *label7;

      GtkWidget *label9;

      GtkWidget *hseparator1;

      GtkWidget *label2;

      GtkWidget *bt_close;

      GtkWidget *button1;

      GtkWidget *label3;

      GtkWidget *label6;

      GtkWidget *label5;

      GtkWidget *label4;

      GtkWidget *image;

     

    //代码转换:从一种编码转为另一种编码

    int code_convert(char*from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)

    {

       iconv_t cd;

       int rc;

       char **pin = &inbuf;

       char **pout = &outbuf;

       cd = iconv_open(to_charset,from_charset);

       if (cd==0) return -1;

       memset(outbuf,0,outlen);

       if (iconv(cd,pin,&inlen,pout,&outlen)==-1)return -1;

       iconv_close(cd);

       return 0;

    }

    //UNICODE码utf-8转为GB码

    int u2g(char *inbuf,int inlen,char *outbuf,intoutlen)

    {

       returncode_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);

    }

    //GB码转为UNICODE码utf-8

    int g2u(char*inbuf,size_t inlen,char *outbuf,size_t outlen)

    {

       returncode_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);

    }

    voidon_bt_close_clicked(GtkButton *button,gpointer user_data)

    {

       gtk_main_quit();

    }

    voidon_bt_ok_clicked (GtkButton *button,gpointer user_data)

    {

     

      inti,Len,nRet,zpLen;   

       unsigned char Buff[500];

       char outbuf[BUFLEN];

       unsigned char zpBuff[1024];

       char TMP[512];

       char *wltfile="./xp.wlt";

      char*bmpfile="./xp.bmp";     

      FILE*f;                           

                                       

     //调用libABCVLib.so 动态库阅读身份证,自动生成文字和照片文件                                 

      nRet =abcv_ReadIDCard (TERM_TYPE, TERM_PORT,TIMEOUT, Buff, &Len, zpBuff, &zpLen); //libABCVLib.so 

      if (nRet==0)

       {

             //显示姓名

               memset(TMP,'',512);   

              memset(outbuf,'',BUFLEN);       

              abcv_getName(TMP);         

              if ((i=g2u(TMP,strlen(TMP),outbuf,BUFLEN))==0 )

              {                

                     gtk_entry_set_text(GTK_ENTRY(entrName),outbuf); 

              }                                 

             

              //显示性别

              memset(TMP,'',512);                    

              abcv_getSex(TMP);

                    

              if ((i=g2u(TMP,strlen(TMP),outbuf,BUFLEN))==0 )    

              {                             

                  gtk_entry_set_text(GTK_ENTRY(entrSex), outbuf);

              }

              //显示民族

              memset(TMP,'',512);          

              abcv_getchNation(TMP);     

              if ((i=g2u(TMP,strlen(TMP),outbuf,BUFLEN))==0 )    

              {                             

                  gtk_entry_set_text(GTK_ENTRY(entrNation), outbuf);

              }

             

              //显示出生日期      

              memset(TMP,'',512);                     

              abcv_getBirth(TMP);        

              if ((i=g2u(TMP,strlen(TMP),outbuf,BUFLEN))==0 )    

              {                             

                  gtk_entry_set_text(GTK_ENTRY(entrBirthday), outbuf);

              }

             

              //显示户籍地址

              memset(TMP,'',512);             

              abcv_getAddr(TMP);             

              if ((i=g2u(TMP,strlen(TMP),outbuf,BUFLEN))==0 )    

              {                             

                  gtk_entry_set_text(GTK_ENTRY(entrAddr), outbuf);

              }

             //显示身份证号码

              memset(TMP,'',512);             

              abcv_getIdCode(TMP);    

              if ((i=g2u(TMP,strlen(TMP),outbuf,BUFLEN))==0 )    

              {                             

                  gtk_entry_set_text(GTK_ENTRY(entrID), outbuf);

              }

              //显示签发机关

              memset(TMP,'',512);                 

              abcv_getIssue(TMP);            

              if ((i=g2u(TMP,strlen(TMP),outbuf,BUFLEN))==0 )    

              {                             

                  gtk_entry_set_text(GTK_ENTRY(entrDep), outbuf);

              }

              //显示证件有效期

              memset(TMP,'',512);             

              abcv_getValidity(TMP);                   

              if ((i=g2u(TMP,strlen(TMP),outbuf,BUFLEN))==0 )    

              {                             

                  gtk_entry_set_text(GTK_ENTRY(entrValid), outbuf);

              }

                 

              //显示身份证照片

              image =gtk_image_new_from_file(bmpfile);

              gtk_widget_set_size_request(image,102, 126);

              gtk_widget_show (image);     

              gtk_fixed_put (GTK_FIXED (fixed1),image, 438, 160);

                               

       }

       else {

           g_warning ("Error Code: %d", nRet);   

       }

    }

      

    int main(int argc,char** argv) {  

      gtk_init(&argc, &argv);

      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

      gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);

      gtk_window_set_default_size (GTK_WINDOW(window), 580, 400);

      gtk_window_set_title(GTK_WINDOW(window),"Raspi IDCard2 Reader"); 

      fixed1 = gtk_fixed_new ();

      gtk_widget_show (fixed1);

      gtk_container_add (GTK_CONTAINER (window),fixed1);

      gtk_widget_set_size_request (fixed1, 286,123);

     

      entrName = gtk_entry_new ();

      gtk_widget_show (entrName);

      gtk_fixed_put (GTK_FIXED (fixed1), entrName,96, 16);

      gtk_widget_set_size_request (entrName, 158,25);

      entrSex = gtk_entry_new ();

      gtk_widget_show (entrSex);

      gtk_fixed_put (GTK_FIXED (fixed1), entrSex,96, 72);

      gtk_widget_set_size_request (entrSex, 84,25);

      label1 = gtk_label_new("345247223  345220215");

      gtk_widget_show (label1);

      gtk_fixed_put (GTK_FIXED (fixed1), label1, 8,23);

      gtk_widget_set_size_request (label1, 82, 17);

      entrNation = gtk_entry_new ();

      gtk_widget_show (entrNation);

      gtk_fixed_put (GTK_FIXED (fixed1),entrNation, 344, 72);

      gtk_widget_set_size_request (entrNation, 84,25);

      entrBirthday = gtk_entry_new ();

      gtk_widget_show (entrBirthday);

      gtk_fixed_put (GTK_FIXED (fixed1),entrBirthday, 96, 112);

      gtk_widget_set_size_request (entrBirthday,160, 25);

      entrAddr = gtk_entry_new ();

      gtk_widget_show (entrAddr);

      gtk_fixed_put (GTK_FIXED (fixed1), entrAddr,96, 160);

      gtk_widget_set_size_request (entrAddr, 331,25);

      entrID = gtk_entry_new ();

      gtk_widget_show (entrID);

      gtk_fixed_put (GTK_FIXED (fixed1), entrID,96, 200);

      gtk_widget_set_size_request (entrID, 331,25);

      entrDep = gtk_entry_new ();

      gtk_widget_show (entrDep);

      gtk_fixed_put (GTK_FIXED (fixed1), entrDep,96, 240);

      gtk_widget_set_size_request (entrDep, 331,25);

      entrValid = gtk_entry_new ();

      gtk_widget_show (entrValid);

      gtk_fixed_put (GTK_FIXED (fixed1), entrValid,96, 280);

      gtk_widget_set_size_request (entrValid, 331,25);

      label7 = gtk_label_new("345217221350257201346234272345205263");

      gtk_widget_show (label7);

      gtk_fixed_put (GTK_FIXED (fixed1), label7,16, 240);

      gtk_widget_set_size_request (label7, 68, 25);

      label9 = gtk_label_new("346234211346225210346234237351231220");

      gtk_widget_show (label9);

      gtk_fixed_put (GTK_FIXED (fixed1), label9,16, 280);

      gtk_widget_set_size_request (label9, 68, 17);

      hseparator1 = gtk_hseparator_new ();

      gtk_widget_show (hseparator1);

      gtk_fixed_put (GTK_FIXED (fixed1),hseparator1, 24, 312);

      gtk_widget_set_size_request (hseparator1,426, 16);

      label2 = gtk_label_new("346200247  345210253");

      gtk_widget_show (label2);

      gtk_fixed_put (GTK_FIXED (fixed1), label2,16, 80);

      gtk_widget_set_size_request (label2, 64, 17);

      bt_close = gtk_button_new_with_mnemonic("351200200345207272");

      gtk_widget_show (bt_close);

      gtk_fixed_put (GTK_FIXED (fixed1), bt_close,296, 336);

      gtk_widget_set_size_request (bt_close, 53,27);

      button1 = gtk_button_new_with_mnemonic("350257273345215241");

      gtk_widget_show (button1);

      gtk_fixed_put (GTK_FIXED (fixed1), button1,152, 336);

      gtk_widget_set_size_request (button1, 53, 27);

      label3 = gtk_label_new("346260221  346227217");

      gtk_widget_show (label3);

      gtk_fixed_put (GTK_FIXED (fixed1), label3,280, 80);

      gtk_widget_set_size_request (label3, 64, 17);

      label6 = gtk_label_new("350272253344273275350257201345217267");

      gtk_widget_show (label6);

      gtk_fixed_put (GTK_FIXED (fixed1), label6,16, 208);

      gtk_widget_set_size_request (label6, 69, 17);

      label5 = gtk_label_new("345234260  345235200");

      gtk_widget_show (label5);

      gtk_fixed_put (GTK_FIXED (fixed1), label5,16, 168);

      gtk_widget_set_size_request (label5, 64, 17);

      label4 = gtk_label_new("347224237  346227245");

      gtk_widget_show (label4);

      gtk_fixed_put (GTK_FIXED (fixed1), label4,16, 120);

      gtk_widget_set_size_request (label4, 64,17); 

      

     

     

      g_signal_connect ((gpointer) bt_close,"clicked",

                        G_CALLBACK(on_bt_close_clicked),

                        NULL);

                       

      g_signal_connect ((gpointer) button1,"clicked",

                        G_CALLBACK(on_bt_ok_clicked),

                        NULL);

     

      gtk_widget_show_all(window);  

      gtk_main();

      return 0;

    }

    直接在树莓派上编译gtktest.c:

    GTK+ Makefile文件:

    ARM_PREFIX=arm-linux-gnueabihf-

    CC   = $(ARM_PREFIX)gcc

    SRC += gtktest.c

    TARGET = gtktest

    LIBRARY += gtk-3

    LIBRARY += gdk-3

    LIBRARY += atk-1.0

    LIBRARY += gio-2.0

    LIBRARY +=pangocairo-1.0

    LIBRARY +=gdk_pixbuf-2.0

    LIBRARY +=cairo-gobject

    LIBRARY +=pango-1.0

    LIBRARY += cairo

    LIBRARY +=gobject-2.0

    LIBRARY +=glib-2.0

    LIBRARY += stdc++

    LIBRARY+= ABCVLib

    LIBRARY += dl

    LIBRARYDIR +=/lib/arm-linux-gnueabihf

    LIBRARYDIR +=/usr/lib/arm-linux-gnueabihf

    LIBRARYDIR += /lib

    LIBRARYDIR +=/usr/lib

    #请改成你自己的工作目录

    LIBRARYDIR+= /home/pi/kim/gtk30

    XLINK_LIBDIR +=/lib/arm-linux-gnueabihf

    XLINK_LIBDIR +=/usr/lib/arm-linux-gnueabihf

    INCLUDEDIR +=/usr/include/gtk-3.0

    INCLUDEDIR +=/usr/include/pango-1.0

    INCLUDEDIR +=/usr/include/gio-unix-2.0/

    INCLUDEDIR +=/usr/include/atk-1.0

    INCLUDEDIR +=/usr/include/cairo

    INCLUDEDIR +=/usr/include/gdk-pixbuf-2.0

    INCLUDEDIR +=/usr/include/freetype2

    INCLUDEDIR +=/usr/include/glib-2.0

    INCLUDEDIR +=/usr/lib/arm-linux-gnueabihf/glib-2.0/include

    INCLUDEDIR +=/usr/include/pixman-1

    INCLUDEDIR +=/usr/include/libpng12

    #请改成你自己的工作目录

    INCLUDEDIR+= /home/pi/kim/gtk30

    OPT = -O0

    DEBUG = -g

    WARN= -Wall  -Wextra -pedantic

    PTHREAD= -pthread

    INCDIR  = $(patsubst %,-I%,$(INCLUDEDIR))

    LIBDIR  = $(patsubst %,-L%,$(LIBRARYDIR))

    LIB    = $(patsubst %, -l%,$(LIBRARY))

    XLINKDIR =$(patsubst %,-Xlinker -rpath-link=%,$(XLINK_LIBDIR))

    all:

       $(CC) $(OPT) $(DEBUG) $(WARN) $(LIBDIR)$(PTHREAD) $(INCDIR) $(XLINKDIR) $(LIB) $(SRC) -o $(TARGET)

    clean:

       rm -rf $(TARGET)

    3.4 身份证阅读运行效果(在电脑VNC显示读卡界面)

    依次输入:

       $make

       $./gtktest


    当然也可直接在安卓手机VNC界面下打开阅读界面并显示读卡结果:

     

    附:用Lazarus Pascal设计树莓派下图形界面:

     


    还可在Windows环境下交叉设计编译,正如其所说的一次编译到处运行:


    在Windows下执行Lazarus设计的程序:


    四、扩展应用

    与手机结合、触摸屏、摄像头、指纹头、打印机、蓝牙、NFC…

    五、市场前景

    该设备应用领域:自助设备、手持设备、物联网、安防门禁…

    适用范围:

    ●公安:身份证申领、户口登记迁移、人口管理等。 旅馆:住宿登记等。

    ●民政:求学、就业、参军、婚姻登记等。

    ●民航:机票购买、登机等。

    ●银行:开户、信用卡交易、大额取款等。

    ●邮局:领取邮件汇款等。

    ●电信:电话手机开户、各种通信业务等。

    ●证券:股票、期货交易等。

    ●企事业单位:招工、来访登记

  • 相关阅读:
    缅怀我的第一台平板——Surface RT
    【万里征程——Windows App开发】DatePicker&Timepicker
    【万里征程——Windows App开发】用浮出控件做预览效果
    【万里征程——Windows App开发】应用栏
    【万里征程——Windows App开发】画笔和图像
    【万里征程——Windows App开发】绘制图形
    稻香
    【万里征程——Windows App开发】动画1
    【SICP练习】152 练习4.8
    【SICP练习】151 练习4.7
  • 原文地址:https://www.cnblogs.com/james1207/p/3366067.html
Copyright © 2011-2022 走看看