• C#开发语音机项目


    语音机的基本就是像声讯台那样的能够自动接电话放录音,并且接受用户手机输入的数字然后做相应的处理。最近要做一个用语音机接受用户输入的产品防伪码,查询产品的真假。语音机长的差不多就是这个样子.

    yuyin

    语音机一头接在电话线上,一头通过USB接在电脑上,然后它会告诉程序电话线上的各种状态,程序做相应的处理。这个小项目的业务逻辑并不复杂,关键是要调用这个语音机提供的api,它没有提供.net的api,只有一个windows的dll。我以前没有做过类似的项目,就在这记录下,顺便介绍下.net中调用非托管代码的方法。.

    一般来说,这种设备都会提供一个驱动盘和开发用的dll和一个文档说明。首先要安装好驱动,连接好设备,将dll复制到项目的bin文件夹中。这些dll一般提供的都是C的接口,要在.net中使用非托管的代码,要是用.net interop service.关于 interop service的详细内容打算后文介绍。这里先简单介绍下用法。Consuming Unmanaged DLL Functions 这里有更为详细的介绍。关键的一步是声明dll中的函数和变量,相当于将C的头文件翻译成C#的。C#使用static extern关键字来表示这个方法是外部的dll,同时还是要DllImport属性来标识dll的信息。

    例如,在C的头文件中有如下函数声明:

      #ifndef WIN32
      #define TWCALLFUNC
      #else
      #define TWCALLFUNC    WINAPI
      #endif
      void  TWCALLFUNC TV_SetChannelType (int ch,int type); 

    这个TWCALLFUNC有什么用?我C语言也不精通,也不太清楚,估计起类似于命名空间的作用吧,不管它。那么在C#中的某个类中,可以如下声明:

    [DllImport("tw16vid.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] 
    public static extern void TV_SetChannelType(int ch, int type);
    

    对于C中的常量,struct则基本上只要对应的写成C#的语法形式就可以。写好以后就可以在程序中正常的调用这些方法。其实简单用一下还是挺简单的。下面再简单说下这个语音机的使用。语音机的原理就是当外线有电话打进来的时候,它的一个函数可以返回是否响铃,然后程序中可以调用一个方法接电话,紧接着可以放录音,然后可以接受用户输入的数字。接受数字是靠一个叫DTMF码的方式送过来的,这是电话上常用的,我也不怎么懂,不过API也提供了一个方法接受DTMF码。接受到用户的输入后,你的程序就可以做相应的处理了。这些就是我这个项目用到的,当然语音机硬件还有其他很多功能,好像还支持多方通话什么的,比较复杂,我也没有仔细研究。

    要判断是否有电话打进来,只有采用轮询的方式——古老而实用。

      private void listenChannel()
            {
                for (int i = 0; i < iChannels; i++)
                {
                    CS[i] = TW8Vid.WS_HANGUP;
                }
    
                while (flag)
                {
                    Application.DoEvents();
                    for (int i = 0; i < iChannels; i++)
                    {
                        switch (TW8Vid.TV_ChannelType(i))
                        {
                            case TW8Vid.CT_EXTERNAL:
                                externalChannel(i);
                                break;
                            default: break;
                        }
                    }
                    System.Threading.Thread.Sleep(300);
                }
            }
    
            private void externalChannel(int ch)
            {
                int sig, sigCount = 0, sigLen = 0;
                StringBuilder callingNumber=new StringBuilder();
                switch (CS[ch])
                {
                    case TW8Vid.WS_HANGUP:
                        if (TW8Vid.TV_RingDetect(ch) > 1)
                        {
                            textBoxInfo.Text += "振铃\r\n";
                            char[] phoneBuffer = new char[64];
                            int length = TW8Vid.TV_ReceiveCallingID(ch, phoneBuffer, 64);
                            for (int i = 0; i < length; i++)
                                callingNumber.Append(phoneBuffer[i]);
                            TW8Vid.TV_OffHookCtrl(ch);
                            TW8Vid.TV_FlushDTMF(ch);
                     
                            if (TW8Vid.TV_StartPlayCh(ch, "请输入条码".ToCharArray()) >= 0)
                            {
                                CS[ch] = TW8Vid.WS_PLAYING;
                                textBoxInfo.Text += "播放\r\n";
                            }
                            else
                            {
                                TW8Vid.TV_HangUpCtrl(ch);
                                System.Threading.Thread.Sleep(200);
                                CS[ch] = TW8Vid.WS_HANGUP;
                                textBoxInfo.Text += "播放失败\r\n";
                            }
                        };
                        break;
                    case TW8Vid.WS_PLAYING:
                        sig = TW8Vid.TV_CheckSignal(ch, ref sigCount, ref sigLen);
                        if ((sig == TW8Vid.SIG_BUSY1 || sig == TW8Vid.SIG_BUSY2) && sigCount > 3)
                        {
                            textBoxInfo.Text += "外线挂机";
                            TW8Vid.TV_HangUpCtrl(ch);
                            CS[ch] = TW8Vid.WS_HANGUP;
                        }
                        else
                        {
                            if (TW8Vid.TV_PlayChRest(ch) <= 0)
                            {
                                TW8Vid.TV_StopPlayCh(ch);
                            }
                            int d = TW8Vid.TV_GetDTMFChar(ch);
                            if (d != -1)
                            {
                                if ((char)d == '#')
                                {
                                    textBoxInfo.Text += "用户#确认";
                                    textBoxInfo.Text += msgBuffer[ch].ToString() + "\r\n";
                                    string res = CheckCode(callingNumber.ToString(),msgBuffer[ch].ToString(),DateTime.Now);
                                    if (TW8Vid.TV_StartPlayCh(ch, "你成功输入条码".ToCharArray()) >= 0)
                                    {
                                        CS[ch] = TW8Vid.WS_PLAYING;
                                        textBoxInfo.Text += "播放2\r\n";
                                    }
                                    else
                                    {
                                        TW8Vid.TV_HangUpCtrl(ch);
                                        System.Threading.Thread.Sleep(200);
                                        CS[ch] = TW8Vid.WS_HANGUP;
                                        textBoxInfo.Text += "播放失败\r\n";
                                    }
    
                                }
                                else
                                {
                                    msgBuffer[ch].Append((char)d);
                                }
                            }
                        }; break;
                    case TW8Vid.WS_TIMER:
                        break;
                    default: break;
                }
            }
  • 相关阅读:
    【转】Hive Data Manipulation Language
    【转】Vim显示中文乱码
    【转】Twitter算法面试题详解(Java实现)
    【转】判断单链表中是否存在环及查找环的入口点
    【转】SQL语句面试题
    【转】经典的SQL语句面试题
    【转】Java实现折半查找(二分查找)的递归和非递归算法
    【转】[IT综合面试]牛人整理分享的面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结
    【笔试/面试题】中科创达——9.28(持续更新ing)
    百度2014校园招聘笔试题(成都站,软件研发岗)——2014.09.21
  • 原文地址:https://www.cnblogs.com/yinzixin/p/1917372.html
Copyright © 2020-2023  润新知