C#を使ってニューマンUSBを開発して秘書のクライアントの小さい結び目に電話します
前にC#でCRMの着信弾スクリーンを開発した後、一部のお客様は新しい要求がありました.彼らは着信弾スクリーンを実現するだけでなく、呼び出した電話を録音してCRMサーバーにアップロードし、後で記録を追跡するのに便利であることを望んでいます.そこで、小さな秘書クライアントの開発が行われた.
着信秘書クライアントの開発はニューマンUSBに基づいてクライアントを電気的に通信する(詳細は参考:
http://renzhen.iteye.com/blog/580746)をベースに開発されたのですが、ニューマンUSBで通信するハードウェアには録音機能がないため、ハードウェアにニューマンのもう一つのハードウェア製品着信小秘書が使用されています.同じメーカーの製品ですが、それらのAPIは完全に互換性がなく、さらに煩わしいことに、着信小秘書APIには着信のコールバックインタフェースがなく、コールバックトリガプログラムを通過できません.C#のDemoもなく、多くの機能はそんなに詳しくないドキュメントとDelphiのDemoで模索するしかなく、いくつかの挫折と困惑を経て、ついにこのクライアントプログラムを完成しました.
まず、開発はハードウェアのAPIとコミュニケーションをとり、依然としてC#のP/Invokeで完成し、以下は着信秘書のP/Invokeコードである.
そしてデバイス状態検出については、APIがなくて直接着信コールバックをサポートしているため、自分で手動でデバイス状態を検出して判断するしかないが、この部分を実現するには一般的に2つの方法があり、Timerを使用するかThreadを使用するか、DelphiのDemoでTimerを使用しているが、Timerが実現する弊害は非同期の考え方を使用する必要があり、私の考え方に合わない.柔軟性も十分ではなく、C#はスレッドを作成するのに便利で、スレッドは同期で考えるのでThreadモードを使いました.
そして、特定のタイミングで、電話番号、弾屏(着信なら)、電話終了後にファイルや情報をCRMサーバに録音してアップロードします.ここで、着信番号は簡単に取得できますが、放送番号の取得は面倒です.C#では次のコードを使用できます.
次はC#の大きなファイルをアップロードしましょう.ネット上にはいろいろな例がありますが、以下のblogのコードを参考に開発しました.
http://www.cnblogs.com/bccu/archive/2009/01/05/1363771.html、しかしアップロードに成功することができなくて、そこで私はコードを読んで、彼が情報の中のrを空の文字で取って代わったことを発見して、サーバーが識別することができなくて、そこで私は彼のコードを変更して、問題を解決して、コードは以下の通りです:
CRM着信秘書クライアントが完了しました.もちろん、この機能に合わせて、サーバー側CRMシステムもいくつかの修正をしなければなりませんが、この文章の主な内容ではありません.サーバー側の修正に関する小節は、次回にしましょう.
着信秘書クライアントの開発はニューマンUSBに基づいてクライアントを電気的に通信する(詳細は参考:
http://renzhen.iteye.com/blog/580746)をベースに開発されたのですが、ニューマンUSBで通信するハードウェアには録音機能がないため、ハードウェアにニューマンのもう一つのハードウェア製品着信小秘書が使用されています.同じメーカーの製品ですが、それらのAPIは完全に互換性がなく、さらに煩わしいことに、着信小秘書APIには着信のコールバックインタフェースがなく、コールバックトリガプログラムを通過できません.C#のDemoもなく、多くの機能はそんなに詳しくないドキュメントとDelphiのDemoで模索するしかなく、いくつかの挫折と困惑を経て、ついにこのクライアントプログラムを完成しました.
まず、開発はハードウェアのAPIとコミュニケーションをとり、依然としてC#のP/Invokeで完成し、以下は着信秘書のP/Invokeコードである.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace WindowsApplication1
{
class LDT1
{
[DllImport("usbms.dll", EntryPoint = "LoadDRV")]
public static extern int LoadDRV();
[DllImport("usbms.dll", EntryPoint = "EnableCard")]
public static extern int EnableCard();
[DllImport("usbms.dll", EntryPoint = "StopSigCheck")]
public static extern int StopSigCheck(int Handle);
[DllImport("usbms.dll", EntryPoint = "ReSetUsb")]
public static extern int ReSetUsb(int Handle);
[DllImport("usbms.dll", EntryPoint = "HangUp")]
public static extern int HangUp(int Handle);
[DllImport("usbms.dll", EntryPoint = "InitDtmfBuf")]
public static extern int InitDtmfBuf(int Handle);
[DllImport("usbms.dll", EntryPoint = "SetDialPara")]
public static extern int SetDialPara(UInt16 RingBack1, UInt16 RingBack0, UInt16 BusyLen, UInt16 RingTimes, UInt16 SendNoSignalLen);
[DllImport("usbms.dll", EntryPoint = "DisableCard")]
public static extern int DisableCard();
[DllImport("usbms.dll", EntryPoint = "FreeDRV")]
public static extern int FreeDRV();
[DllImport("usbms.dll", EntryPoint = "GetDtmfCode")]
public static extern int GetDtmfCode(UInt16 Line);
[DllImport("usbms.dll", EntryPoint = "IsRing")]
public static extern bool IsRing(UInt16 Line);
[DllImport("usbms.dll", EntryPoint = "GetCallerIDStr")]
public static extern UInt16 GetCallerIDStr(UInt16 Line, StringBuilder IDStr);
[DllImport("usbms.dll", EntryPoint = "IsOffHook")]
public static extern bool IsOffHook(UInt16 Line);
[DllImport("usbms.dll", EntryPoint = "StartRecordFile")]
public static extern bool StartRecordFile(UInt16 Line, string FileName, UInt32 dwRecordLen);
[DllImport("usbms.dll", EntryPoint = "CheckRecordEnd")]
public static extern bool CheckRecordEnd(UInt16 Line);
[DllImport("usbms.dll", EntryPoint = "StopRecordFile")]
public static extern bool StopRecordFile(UInt16 Line);
[DllImport("usbms.dll", EntryPoint = "PCMtoWave")]
public static extern int PCMtoWave(string SourceFileName, string TargetFileName);
[DllImport("usbms.dll", EntryPoint = "ReadCheckResult")]
public static extern int ReadCheckResult(int line, int mode);
[DllImport("usbms.dll", EntryPoint = "StartSigCheck")]
public static extern void StartSigCheck(int line);
[DllImport("usbms.dll", EntryPoint = "ReadUsbState")]
public static extern bool ReadUsbState(int line);
[DllImport("usbms.dll", EntryPoint = "GetRingNum")]
public static extern int GetRingNum(int line);
[DllImport("usbms.dll", EntryPoint = "InitRingNum")]
public static extern void InitRingNum(int line);
[DllImport("usbms.dll", EntryPoint = "ReadSerialNo")]
public static extern int ReadSerialNo(int line,StringBuilder serialNo);
}
}
そしてデバイス状態検出については、APIがなくて直接着信コールバックをサポートしているため、自分で手動でデバイス状態を検出して判断するしかないが、この部分を実現するには一般的に2つの方法があり、Timerを使用するかThreadを使用するか、DelphiのDemoでTimerを使用しているが、Timerが実現する弊害は非同期の考え方を使用する必要があり、私の考え方に合わない.柔軟性も十分ではなく、C#はスレッドを作成するのに便利で、スレッドは同期で考えるのでThreadモードを使いました.
そして、特定のタイミングで、電話番号、弾屏(着信なら)、電話終了後にファイルや情報をCRMサーバに録音してアップロードします.ここで、着信番号は簡単に取得できますが、放送番号の取得は面倒です.C#では次のコードを使用できます.
while (LDT1.IsOffHook((ushort)this.line))
{
int temp = LDT1.GetDtmfCode((ushort)this.line);
if (temp > 0)
{
phonenum = phonenum + this.convertInt(temp);
}
Thread.Sleep(300);
}
private string convertInt(int code)
{
string ret="";
switch (code)
{
case 10:
ret = "0";
break;
case 11:
ret = "*";
break;
case 12:
ret = "#";
break;
case 13:
ret = "A";
break;
case 14:
ret = "B";
break;
case 15:
ret = "C";
break;
case 16:
ret = "D";
break;
default:
ret = code.ToString();
break;
}
return ret;
}
次はC#の大きなファイルをアップロードしましょう.ネット上にはいろいろな例がありますが、以下のblogのコードを参考に開発しました.
http://www.cnblogs.com/bccu/archive/2009/01/05/1363771.html、しかしアップロードに成功することができなくて、そこで私はコードを読んで、彼が情報の中のrを空の文字で取って代わったことを発見して、サーバーが識別することができなくて、そこで私は彼のコードを変更して、問題を解決して、コードは以下の通りです:
public static string UploadFileEx(string uploadfile, string url,
string fileFormName, string contenttype, NameValueCollection querystring,
CookieContainer cookies)
{
if ((fileFormName == null) ||
(fileFormName.Length == 0))
{
fileFormName = "file";
}
if ((contenttype == null) ||
(contenttype.Length == 0))
{
contenttype = "application/octet-stream";
}
string postdata;
postdata = "?";
if (querystring != null)
{
foreach (string key in querystring.Keys)
{
postdata += key + "=" + querystring.Get(key) + "&";
}
}
Uri uri = new Uri(url + postdata);
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(uri);
//webrequest.CookieContainer = cookies;
webrequest.ContentType = "multipart/form-data; boundary=" + boundary;
webrequest.Method = "POST";
string huanhang = "\r
";
byte[] huanhangbyte = Encoding.UTF8.GetBytes(huanhang);
// Build up the post message header
StringBuilder sb = new StringBuilder();
sb.Append("--");
sb.Append(boundary);
sb.Append("\r
");
sb.Append("Content-Disposition: form-data; name=\"");
sb.Append(fileFormName);
sb.Append("\"; filename=\"");
sb.Append(Path.GetFileName(uploadfile));
sb.Append("\"");
sb.Append("\r
");
sb.Append("Content-Type: ");
sb.Append(contenttype);
sb.Append("\r
");
sb.Append("\r
");
string postHeader = sb.ToString();
byte[] postHeaderBytes = Encoding.UTF8.GetBytes(postHeader);
// Build the trailing boundary string as a byte array
// ensuring the boundary appears on a line by itself
byte[] boundaryBytes =
Encoding.ASCII.GetBytes("--" + boundary + "");
FileStream fileStream = new FileStream(uploadfile,
FileMode.Open, FileAccess.Read);
long length = postHeaderBytes.Length + fileStream.Length +
boundaryBytes.Length + huanhangbyte.Length;
webrequest.ContentLength = length;
Stream requestStream = webrequest.GetRequestStream();
// Write out our post header
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
// Write out the file contents
byte[] buffer = new Byte[checked((uint)Math.Min(4096,
(int)fileStream.Length))];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
requestStream.Write(buffer, 0, bytesRead);
requestStream.Write(huanhangbyte, 0, huanhangbyte.Length);
// Write out the trailing boundary
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
fileStream.Dispose();
requestStream.Dispose();
WebResponse responce = webrequest.GetResponse();
Stream s = responce.GetResponseStream();
StreamReader sr = new StreamReader(s);
string retval=sr.ReadToEnd();
sr.Dispose();
if (File.Exists(uploadfile))
{
try
{
File.Delete(uploadfile);
}catch(Exception e)
{
}
}
return retval;
}
CRM着信秘書クライアントが完了しました.もちろん、この機能に合わせて、サーバー側CRMシステムもいくつかの修正をしなければなりませんが、この文章の主な内容ではありません.サーバー側の修正に関する小節は、次回にしましょう.