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;
            }
        }
posted @ 2011-01-10 10:51  yinzixin  阅读(650)  评论(0编辑  收藏  举报