1、先來段視頻看看效果
2、基本原理
(1)幾個控制器通過wifi連接到AP上,組成局域網。
(2)控制器基於arduion,使用了串口轉wifi模塊,它在控制器上建立了一個TCP服務器。控制端通過調用TCP服務來達到控制的目的。
下面分別介紹各個控制器。
3、電燈控制器
(1)硬件構成
arduino模塊+wifi模塊+繼電器模塊。
繼電器模塊的AC端接到零線開關上。
(2)Arduino代碼

void setup() { Serial.begin(115200); pinMode(2,OUTPUT); digitalWrite(2, HIGH); // switch off } void loop() { // delay(500); if (Serial.available() > 0) { char val; val = Serial.read(); // read serial data if(val == '1') { digitalWrite(2, LOW); // switch on } else if(val == '0') { digitalWrite(2, HIGH); // switch off } Serial.print(val); //將收到是數據再通過串口發送出去 //delay(1000); } }
(3)PC端代碼

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Diagnostics; using System.Timers; using System.Net; namespace WiseHouse.SI { public class LightController { // *********************************************** 全局字段 ****************************************************** TcpClient tcp = new TcpClient(); NetworkStream stream; System.Timers.Timer tmrConnecting = new System.Timers.Timer(); // 連線的周期。 若斷線,在10秒后嘗試建立連接 // *********************************************** 事件 ****************************************************** // *********************************************** 屬性 ****************************************************** /// <summary> /// IP地址 /// </summary> public string IP { get { return _IP; } set { } } string _IP; /// <summary> /// 是否在線 /// </summary> public bool IsOnline { get { return _IsOnline; } set { } } bool _IsOnline = false; /// <summary> /// 信號強度 /// </summary> public int SignalStrength { get { return GetSignalStrength(); } set { } } // int _SignalStrength; // *********************************************** 構造函數 ****************************************************** /// <summary> /// 以IP地址為參數實例化一個對象 /// </summary> /// <param name="ip"></param> public LightController( string ip ) { _IP = ip; // 計時器1 tmrConnecting.Elapsed += new ElapsedEventHandler( tmrConnecting_Elapsed ); tmrConnecting.Interval = 10000; // 每10秒種嘗試連接一次 tmrConnecting.Enabled = true; // 首次連接 Open(); } // *********************************************** 公共方法 ****************************************************** // 打開燈1 public void TurnOnLight1() { try { if( tcp.Connected == true ) { // 發送 byte[] command = Encoding.ASCII.GetBytes( "1" ); stream.Write( command, 0, command.Length ); // 寫入 System.Threading.Thread.Sleep( 100 ); // // 接收 int bufferSize = 30; // 13個,00.00;00.00 // 接收字節數組 byte[] buffer = new byte[ bufferSize ]; int bytesRead = stream.Read( buffer, 0, bufferSize ); //將值放入buffer string data = Encoding.ASCII.GetString( buffer ); // 將字節轉換成字符串 // Console.WriteLine( data ); } else { } } catch { Trace.WriteLine( _IP.PadRight( 20 ) + "發送指令失敗" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } /// <summary> /// 關閉燈1 /// </summary> public void TurnOffLight1() { try { if( tcp.Connected == true ) { // 發送 byte[] command = Encoding.ASCII.GetBytes( "0" ); stream.Write( command, 0, command.Length ); // 寫入 System.Threading.Thread.Sleep( 100 ); // // 接收 int bufferSize = 30; // 13個,00.00;00.00 // 接收字節數組 byte[] buffer = new byte[ bufferSize ]; int bytesRead = stream.Read( buffer, 0, bufferSize ); //將值放入buffer string data = Encoding.ASCII.GetString( buffer ); // 將字節轉換成字符串 // Console.WriteLine( data ); } else { } } catch { Trace.WriteLine( _IP.PadRight( 20 ) + "發送指令失敗" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } /// <summary> /// 釋放資源 /// </summary> public void Close() { stream.Close(); tcp.Close(); } // *********************************************** 私有方法 ****************************************************** /// <summary> /// 定時進行連接。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void tmrConnecting_Elapsed( object sender, ElapsedEventArgs e ) { Open(); } /// <summary> /// 打開連接。 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> void Open() { try { if( tcp.Connected == false ) //若連線失敗,則嘗試進行連接 { // 若是連接斷了,則先關閉當前的TCP client實例。然后再開啟另一個TCP client實例 tcp.Close(); tcp = new TcpClientWithTimeout( _IP, 8000, 2000 ).Connect(); tcp.ReceiveTimeout = 1000; tcp.SendTimeout = 1000; // timeout stream = tcp.GetStream(); _IsOnline = true; Console.WriteLine( _IP.PadRight( 20 ) + "燈連接成功!" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } catch { _IsOnline = false; Trace.WriteLine( _IP.PadRight( 20 ) + "燈連接失敗!" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } /// <summary> /// 獲得信號強度 /// </summary> /// <returns></returns> int GetSignalStrength() { try { // 從頁面中下載html文本 WebClient client = new WebClient(); client.Credentials = new NetworkCredential( "admin", "admin" ); // 認證 string str1 = client.DownloadString( "http://" + _IP + "/station/link_status.asp" ); //? // 初次截取文本。 int j1 = str1.IndexOf( "Link Quality" ) + 22; string str2 = str1.Substring( j1, 70 ); // 類似於:<td>Good 95%</td>\n <td rowspan=\"4\">< // 再次截取文本。在str2的基礎上截取 int j2 = str2.LastIndexOf( ";" ); //信號值前的文本 int j3 = str2.IndexOf( "%</td>" ); //信號值前的文本 string str3 = str2.Substring( j2 + 1, j3 - j2 - 1 ); // 截取信號值。 return int.Parse( str3 ); } catch { return 0; // 若讀取失敗,則返回 0 } } } }
4、空調控制器
(1)硬件構成
arduino模塊+wifi模塊+紅外LED燈管。
我的空調是格力的,要控制空調首先需要捕獲紅外信號的原始碼。關於如何捕獲原始碼,請參考本人的另一篇文章:http://www.cnblogs.com/dehai/p/3730156.html
(2)Arduino代碼

#include <IRremote.h> IRsend irsend; unsigned int open26[300] = {9040,4438,665,1643,701,508,697,508,698,1606,702,1606,696,1610,638,1670,638,571,697,508,696,1608,663,545,698,1606,700,509,698,508,700,506,698,507,701,505,696,509,698,507,696,509,665,541,699,1606,699,509,698,507,698,506,696,510,697,509,695,509,698,1606,664,545,697,1606,664,544,699,507,697,1608,667,542,697,19939,666,1643,699,508,698,508,698,507,698,1606,666,542,696,509,698,508,698,508,699,507,699,507,698,507,698,508,699,1606,699,509,699,507,698,507,700,506,697,508,698,508,696,509,697,508,698,507,698,507,699,507,697,509,700,506,698,507,699,506,696,509,697,508,696,510,698,39948,9041,4437,669,1640,664,543,696,509,698,1606,668,1639,666,1642,699,1607,701,507,698,508,698,1606,663,545,662,1642,701,507,697,509,699,507,699,507,697,507,697,508,696,510,698,508,696,510,699,1605,699,509,697,508,699,507,699,507,699,507,699,507,697,1608,665,1642,701,1605,701,507,700,506,698,1605,664,544,698,19938,700,507,698,507,697,509,698,508,697,508,699,507,698,507,697,509,697,509,698,507,697,508,698,508,699,506,699,507,696,510,695,510,698,507,697,508,696,509,697,508,699,1605,665,543,699,1605,667,543,699,506,698,507,699,507,698,507,698,507,696,1609,699,508,698,508,698}; unsigned int close27[279] = {9004,4499,699,1609,697,511,695,511,695,510,693,1611,697,1612,696,510,695,510,695,1610,696,1609,696,512,695,1609,696,512,695,511,695,511,694,512,694,511,695,510,694,512,694,512,694,511,695,1611,696,512,693,512,694,512,694,511,694,511,694,512,694,1611,696,512,694,1610,696,512,694,511,694,1609,698,510,694,19942,698,511,694,512,694,511,694,511,694,511,694,511,695,510,695,511,694,511,696,510,692,513,694,511,694,511,694,1611,696,511,693,512,694,511,693,512,694,512,695,511,694,512,694,511,694,511,695,511,694,511,694,512,695,511,694,511,693,512,694,511,695,511,695,1609,698,39952,9037,4443,698,1609,697,511,695,511,694,510,695,1610,696,1609,697,512,693,512,694,1610,698,1610,695,511,694,1611,696,512,695,511,694,512,694,512,692,512,694,511,695,511,694,512,695,511,695,1608,697,512,694,511,693,512,692,512,693,538,694,512,694,1610,697,1610,697,1612,697,511,694,511,694,1611,697,512,695,19941,698,511,694,511,693,512,693,512,695,511,693,512,696,510,694,511,695,511,695,510,695,511,693,512,694,511,695,511,694,511,694,511,694,512,693,512,694,511,693,512,694,1610,697,511,695,1610,695,513,694,511,693,512,694,511,693,512,693,1611,698,1610,697,511,695,1610,696}; void setup() { Serial.begin(115200); } void loop() { // irsend.sendRaw2(open26, 279, 38); //delay(2000); if (Serial.available() > 0) { char val; val = Serial.read(); // read serial data if(val == '1') { irsend.sendRaw2(open26, 279, 38); } else if(val == '0') { irsend.sendRaw2(close27, 279, 38); } Serial.print(val); //將收到是數據再通過串口發送出去 //delay(1000); } }
(3)PC端代碼

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Diagnostics; using System.Timers; using System.Net; namespace WiseHouse.SI { public class AirConditioner { // *********************************************** 全局字段 ****************************************************** TcpClient tcp = new TcpClient(); NetworkStream stream; System.Timers.Timer tmrConnecting = new System.Timers.Timer(); // 連線的周期。 若斷線,在10秒后嘗試建立連接 // *********************************************** 事件 ****************************************************** // *********************************************** 屬性 ****************************************************** /// <summary> /// IP地址 /// </summary> public string IP { get { return _IP; } set { } } string _IP; /// <summary> /// 是否在線 /// </summary> public bool IsOnline { get { return _IsOnline; } set { } } bool _IsOnline = false; /// <summary> /// 信號強度 /// </summary> public int SignalStrength { get { return GetSignalStrength(); } set { } } // int _SignalStrength; // *********************************************** 構造函數 ****************************************************** /// <summary> /// 以IP地址為參數實例化一個對象 /// </summary> /// <param name="ip"></param> public AirConditioner( string ip ) { _IP = ip; // 計時器1 tmrConnecting.Elapsed += new ElapsedEventHandler( tmrConnecting_Elapsed ); tmrConnecting.Interval = 10000; // 每10秒種嘗試連接一次 tmrConnecting.Enabled = true; // 首次連接 Open(); } // *********************************************** 公共方法 ****************************************************** // 打開空調 public void TurnOn() { try { if( tcp.Connected == true ) { // 發送 byte[] command = Encoding.ASCII.GetBytes( "1" ); stream.Write( command, 0, command.Length ); // 寫入 System.Threading.Thread.Sleep( 100 ); // // 接收 int bufferSize = 30; // 13個,00.00;00.00 // 接收字節數組 byte[] buffer = new byte[ bufferSize ]; int bytesRead = stream.Read( buffer, 0, bufferSize ); //將值放入buffer string data = Encoding.ASCII.GetString( buffer ); // 將字節轉換成字符串 // Console.WriteLine( data ); } else { } } catch { Trace.WriteLine( _IP.PadRight( 20 ) + "發送指令失敗" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } /// <summary> /// 關閉空調 /// </summary> public void TurnOff() { try { if( tcp.Connected == true ) { // 發送 byte[] command = Encoding.ASCII.GetBytes( "0" ); stream.Write( command, 0, command.Length ); // 寫入 System.Threading.Thread.Sleep( 100 ); // // 接收 int bufferSize = 30; // 13個,00.00;00.00 // 接收字節數組 byte[] buffer = new byte[ bufferSize ]; int bytesRead = stream.Read( buffer, 0, bufferSize ); //將值放入buffer string data = Encoding.ASCII.GetString( buffer ); // 將字節轉換成字符串 // Console.WriteLine( data ); } else { } } catch { Trace.WriteLine( _IP.PadRight( 20 ) + "發送指令失敗" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } /// <summary> /// 釋放資源 /// </summary> public void Close() { stream.Close(); tcp.Close(); } // *********************************************** 私有方法 ****************************************************** /// <summary> /// 定時進行連接。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void tmrConnecting_Elapsed( object sender, ElapsedEventArgs e ) { Open(); } /// <summary> /// 打開連接。 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> void Open() { try { if( tcp.Connected == false ) //若連線失敗,則嘗試進行連接 { // 若是連接斷了,則先關閉當前的TCP client實例。然后再開啟另一個TCP client實例 tcp.Close(); tcp = new TcpClientWithTimeout( _IP, 8000, 2000 ).Connect(); tcp.ReceiveTimeout = 1000; tcp.SendTimeout = 1000; // timeout stream = tcp.GetStream(); _IsOnline = true; Console.WriteLine( _IP.PadRight( 20 ) + "空調連接成功!" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } catch { _IsOnline = false; Trace.WriteLine( _IP.PadRight( 20 ) + "空調連接失敗!" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } /// <summary> /// 獲得信號強度 /// </summary> /// <returns></returns> int GetSignalStrength() { try { // 從頁面中下載html文本 WebClient client = new WebClient(); client.Credentials = new NetworkCredential( "admin", "admin" ); // 認證 string str1 = client.DownloadString( "http://" + _IP + "/station/link_status.asp" ); //? // 初次截取文本。 int j1 = str1.IndexOf( "Link Quality" ) + 22; string str2 = str1.Substring( j1, 70 ); // 類似於:<td>Good 95%</td>\n <td rowspan=\"4\">< // 再次截取文本。在str2的基礎上截取 int j2 = str2.LastIndexOf( ";" ); //信號值前的文本 int j3 = str2.IndexOf( "%</td>" ); //信號值前的文本 string str3 = str2.Substring( j2 + 1, j3 - j2 - 1 ); // 截取信號值。 return int.Parse( str3 ); } catch { return 0; // 若讀取失敗,則返回 0 } } } }
5、房門控制器
(1)硬件構成
arduino模塊+wifi模塊+場效管模塊+自制的穩壓模塊。
我的鎖是電控鎖,它里面有一個線圈,當線圈通電后,它中間的鋼芯被磁化,吸位鎖的卡扣,門就開了。由於線圈在通電時的瞬間電流較大,為避免它對電路的其它部分造成干擾(可能會造成控制器死機),加上一個自制的穩壓模塊。穩壓模塊由一些電感和電容組成。
(2)Arduino代碼

void setup() { Serial.begin(115200); pinMode(2,OUTPUT); digitalWrite(2, LOW); // switch off } void loop() { // delay(500); if (Serial.available() > 0) { char val; val = Serial.read(); // read serial data if(val == '1') { // digitalWrite(2, LOW); // switch on // delay(1000); digitalWrite(2, HIGH); // switch off } else if(val == '0') { digitalWrite(2, LOW); // switch off } Serial.print(val); //將收到是數據再通過串口發送出去 //delay(1000); } }
(3)PC端代碼

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Diagnostics; using System.Timers; using System.Net; namespace WiseHouse.SI { public class DoorController { // *********************************************** 全局字段 ****************************************************** TcpClient tcp = new TcpClient(); NetworkStream stream; System.Timers.Timer tmrConnecting = new System.Timers.Timer(); // 連線的周期。 若斷線,在10秒后嘗試建立連接 // *********************************************** 事件 ****************************************************** // *********************************************** 屬性 ****************************************************** /// <summary> /// IP地址 /// </summary> public string IP { get { return _IP; } set { } } string _IP; /// <summary> /// 是否在線 /// </summary> public bool IsOnline { get { return _IsOnline; } set { } } bool _IsOnline = false; /// <summary> /// 信號強度 /// </summary> public int SignalStrength { get { return GetSignalStrength(); } set { } } // int _SignalStrength; // *********************************************** 構造函數 ****************************************************** /// <summary> /// 以IP地址為參數實例化一個對象 /// </summary> /// <param name="ip"></param> public DoorController( string ip ) { _IP = ip; // 計時器1 tmrConnecting.Elapsed += new ElapsedEventHandler( tmrConnecting_Elapsed ); tmrConnecting.Interval = 10000; // 每10秒種嘗試連接一次 tmrConnecting.Enabled = true; // 首次連接 Open(); } // *********************************************** 公共方法 ****************************************************** // 打1號門 public void OpenDoor1() { try { if( tcp.Connected == true ) { // 發送 byte[] command = Encoding.ASCII.GetBytes( "1" ); stream.Write( command, 0, command.Length ); // 寫入 // System.Threading.Thread.Sleep( 100 ); // // 接收 // int bufferSize = 30; // 13個,00.00;00.00 // 接收字節數組 // byte[] buffer = new byte[ bufferSize ]; // int bytesRead = stream.Read( buffer, 0, bufferSize ); //將值放入buffer // string data = Encoding.ASCII.GetString( buffer ); // 將字節轉換成字符串 // Console.WriteLine( data ); } else { } } catch { Trace.WriteLine( _IP.PadRight( 20 ) + "發送指令失敗" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } ///// <summary> ///// 釋放資源 ///// </summary> //public void Close() //{ // //stream.Close(); // // tcp.Close(); //} // *********************************************** 私有方法 ****************************************************** /// <summary> /// 定時進行連接。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void tmrConnecting_Elapsed( object sender, ElapsedEventArgs e ) { Open(); } /// <summary> /// 打開連接。 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> void Open() { try { if( tcp.Connected == false ) //若連線失敗,則嘗試進行連接 { // 若是連接斷了,則先關閉當前的TCP client實例。然后再開啟另一個TCP client實例 tcp.Close(); tcp = new TcpClientWithTimeout( _IP, 8000, 2000 ).Connect(); tcp.ReceiveTimeout = 1000; tcp.SendTimeout = 1000; // timeout stream = tcp.GetStream(); _IsOnline = true; Console.WriteLine( _IP.PadRight( 20 ) + "門連接成功!" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } catch { _IsOnline = false; Trace.WriteLine( _IP.PadRight( 20 ) + "門連接失敗!" + DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss" ) ); } } /// <summary> /// 獲得信號強度 /// </summary> /// <returns></returns> int GetSignalStrength() { try { // 從頁面中下載html文本 WebClient client = new WebClient(); client.Credentials = new NetworkCredential( "admin", "admin" ); // 認證 string str1 = client.DownloadString( "http://" + _IP + "/station/link_status.asp" ); //? // 初次截取文本。 int j1 = str1.IndexOf( "Link Quality" ) + 22; string str2 = str1.Substring( j1, 70 ); // 類似於:<td>Good 95%</td>\n <td rowspan=\"4\">< // 再次截取文本。在str2的基礎上截取 int j2 = str2.LastIndexOf( ";" ); //信號值前的文本 int j3 = str2.IndexOf( "%</td>" ); //信號值前的文本 string str3 = str2.Substring( j2 + 1, j3 - j2 - 1 ); // 截取信號值。 return int.Parse( str3 ); } catch { return 0; // 若讀取失敗,則返回 0 } } } }
6、控制端
使用了微軟的語音識別和合成庫,命名空間是System.Speech.Recognition和 System.Speech.Synthesis。
核心代碼:

public partial class Frm控制台 : Form { // ********************************************* 全局變量 ********************************************************************** SpeechRecognitionEngine _recognizer = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("zh-CN")); // 語音識別引擎 SpeechSynthesizer speech = new SpeechSynthesizer(); // 語音合成器。默認使用女聲Lily。 AirConditioner airConditioner; // 空調控制器 LightController lightController; // 電燈控制器 DoorController doorController; // 門禁控制器 bool IsStandingBy = false; // 是否進入待命模式 System.Threading.Timer tmrCurrent; // 當前的 System.Threading.Timer tmrPrevious; // 之前的 public Frm控制台() { InitializeComponent(); } private void Frm控制台_Load(object sender, EventArgs e) { // 控制器初始化 airConditioner = new AirConditioner("172.16.1.12"); lightController = new LightController("172.16.1.13"); doorController = new DoorController("172.16.1.14"); // 添加語法 GrammarBuilder gb1 = new GrammarBuilder(new Choices("小黑", "取消")); GrammarBuilder gb2 = new GrammarBuilder(new Choices("打開電燈", "關閉電燈")); GrammarBuilder gb3 = new GrammarBuilder(new Choices("打開空調", "關閉空調", "18度")); GrammarBuilder gb4 = new GrammarBuilder(new Choices("打開房門")); // 加載語法 _recognizer.LoadGrammar(new Grammar(gb1)); _recognizer.LoadGrammar(new Grammar(gb2)); _recognizer.LoadGrammar(new Grammar(gb3)); _recognizer.LoadGrammar(new Grammar(gb4)); // 綁定事件 _recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(_recognizer_SpeechRecognized); _recognizer.SpeechRecognitionRejected += new EventHandler<SpeechRecognitionRejectedEventArgs>(_recognizer_SpeechRecognitionRejected); _recognizer.SetInputToDefaultAudioDevice(); // 設置語音輸入設備 _recognizer.RecognizeAsync(RecognizeMode.Multiple); // 開啟異步語音識別 } /// <summary> /// 語音識別后的處理函數 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void _recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { // 關閉識別,防止speech說出來的話被誤識別 _recognizer.RecognizeAsyncStop(); Thread.Sleep(30); if (e.Result.Confidence > 0.95) { Console.WriteLine(e.Result.Text); if (e.Result.Text == "計算機" || e.Result.Text == "小黑") { speech.Speak("在"); // 進入待命模式 IsStandingBy = true; Console.WriteLine("進入待命模式"); // 重新計時,10秒命令超時。 tmrPrevious = tmrCurrent; tmrCurrent = new System.Threading.Timer(new TimerCallback(TimerCall), this, 10000, 0); // 當前的,新的 if (tmrPrevious != null) // 取消前一個tmr. { tmrPrevious.Dispose(); } } // 待命模式下的處理 if (IsStandingBy == true && e.Result.Text != "小黑") { if (e.Result.Text == "打開電燈") { lightController.TurnOnLight1(); speech.Speak("燈成功打開"); } else if (e.Result.Text == "關閉電燈") { lightController.TurnOffLight1(); speech.Speak("燈成功關閉"); } else if (e.Result.Text == "打開空調") { airConditioner.TurnOn(); speech.Speak("空調成功打開"); } else if (e.Result.Text == "關閉空調") { airConditioner.TurnOff(); speech.Speak("空調成功關閉"); } else if (e.Result.Text == "18度") { speech.Speak("操作成功"); } else if (e.Result.Text == "打開房門") { doorController.OpenDoor1(); speech.Speak("門成功打開"); } else if (e.Result.Text == "取消") { speech.Speak("指令取消"); } IsStandingBy = false; // 退出待命模式 tmrCurrent.Dispose(); } } _recognizer.RecognizeAsync(RecognizeMode.Multiple); // 開啟識別 } void _recognizer_SpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e) { _recognizer.RecognizeAsyncStop(); Thread.Sleep(30); speech.Speak("請再說一遍"); _recognizer.RecognizeAsync(RecognizeMode.Multiple); // 開啟識別 } void TimerCall(object sender) { IsStandingBy = false; Console.WriteLine("退出待命模式"); MediaHelper.Beep(); //蜂鳴聲 } }