一百元的智能家居——Asp.Net Mvc Api+訊飛語音+Android+Arduino

大半夜的,先說些廢話提提神git

     現在智能家居已經再也不停留在概念階段,高大上的科技公司都已經推出了本身的部分或全套的智能家居解決方案,不過就目前的現狀而言,大多還停留在展廳階段,尚未普遍的推廣起來,有人說最大的問題是標準不統一云云,但在我看來,最大的問題在於兩個方面,一個是價格,一個是操做的簡便性,技術上的問題並非阻礙智能家居推廣的核心因素。程序員

     再來講說最近很火很惹人愛的微軟小娜,Cortana。本人做爲微軟的死忠,做爲一名靠.Net混飯的屌絲程序男,天然是有一部擼妹的,而且在小娜推送當天更新了手機,火燒眉毛地體驗了小娜的功能,小娜會記事、會提醒、會唱歌、會說笑話、會學林志玲等等着實讓我驚歎了一把,並且語氣很是接近天然人的語氣,不是那種生澀的機器語調。做爲平時生活中不使用Android,Iphone的我,那晚想固然的以爲小娜應該就是當今世界上最好的語音助手了吧,懷着這樣的心情,讓小娜給我定了個鬧鐘,次日早早起牀火燒眉毛要向同事得瑟一把了。web

    次日給同事小馬看後,小馬淡然一笑,拿出他的Android手機,默默的打開手機上的一個叫「靈犀」的軟件,遞給我說:「試試這個」。不試不知道,一試,心情還有點小低落,優越感頓無,怎麼說呢,應該說除了在語氣上小娜佔上風外,在識準率,識別速度,各種功能應用上,小娜和「靈犀」已然不是一個檔次,多是小娜剛起步吧,但願之後能夠不斷完善。數據庫

    看了一下「靈犀」官網,恍然大悟,這就是科大訊飛的產品啊,再次把玩靈犀,就只想真心點讚了,當時腦子裏還飄過一個畫面,將來可以對百度形成威脅的,頗有可能就是科大訊飛,科大訊飛將把持移動互聯網的使用入口!哦,那畫面太美,不知李彥宏怎麼想這個問題。編程

    語音識別不只僅會影響到人們使用手機的方式,在智能家居方面也大有可爲,最直接的就是帶來操做上的便捷性,試想,若是你在家時,你慢悠悠的拿出你的手機,慢悠悠的打開你的操做應用,慢悠悠的點擊一個控制按鈕,而後你的電視或者調動窗簾才執行你的命令,這圖的個什麼啊,還不如直接走過去手動暴力解決,而若是你在家的時候,只須要說「小文,換到體育頻道」,或者「小文,打開窗簾」,而後安放在屋子裏的中控盒子二十四小時隨時聽候理解你的命令,出門在外的時候,也只需對着手機說一聲就行,這才叫易用的智能家居啊!api

    今天咱們就採用Arduino開發板+Asp.Net MVC Api+Android版的訊飛語言SDK,實現用語音來控制一個小Led的實驗。服務器

關於Arduino   網絡

     個人硬件準備app

     

     左邊是Arduino主板,右邊是網絡拓展板,下邊的是什麼?哈哈,實驗室小孟同窗親手給我焊接的小小Led燈,用來模仿開關性質的設備,這麼小,看着都是淚水啊。組合後就是這麼個樣子了dom

   

   以上總造價不超過100元。

    Ardunio是一個開源的開發板,聽說國外都是小朋友和藝術家均可以玩的開發板,簡單易學,功能完善,目前也是很是火爆。事實也確實如此,看了幾個示例工程後,有必定開發基礎的人一看就知道怎麼玩了。大部分web開發者基本上能夠直接上手Arduino的網絡部分的開發,看一遍示例保證你明白怎麼個搞法,不信?那上個截圖吧,這是Ardunio提供的IDE,內置了不少經常使用的開發場景示例,基本上在示例的基礎上簡單修改就能夠完成一些簡單的任務。

 若是你是一個web開發者,好吧,看到菜單你也應該聯想到你熟悉的網站開發模式了吧,是的,Arduino爲你提供了客戶端模式,服務端模式,還有些不經常使用的其餘模式,讓咱們來看看Ardunio的WebClientRepeatping,這是一個客戶端輪詢服務端的方式,簡單粗暴,通訊穩定,容易理解和上手,下面是Ardunio提供的該模式示例代碼

  1 /*
  2   Repeating Web client
  3 
  4  This sketch connects to a a web server and makes a request
  5  using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
  6  the Adafruit Ethernet shield, either one will work, as long as it's got
  7  a Wiznet Ethernet module on board.
  8 
  9  This example uses DNS, by assigning the Ethernet client with a MAC address,
 10  IP address, and DNS address.
 11 
 12  Circuit:
 13  * Ethernet shield attached to pins 10, 11, 12, 13
 14 
 15  created 19 Apr 2012
 16  by Tom Igoe
 17  modified 21 Jan 2014
 18  by Federico Vanzati
 19 
 20  http://arduino.cc/en/Tutorial/WebClientRepeating
 21  This code is in the public domain.
 22 
 23  */
 24 
 25 #include <SPI.h>
 26 #include <Ethernet.h>
 27 
 28 // assign a MAC address for the ethernet controller.
 29 // fill in your address here:
 30 byte mac[] = {
 31   0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
 32 };
 33 // fill in an available IP address on your network here,
 34 // for manual configuration:
 35 IPAddress ip(192, 168, 1, 177);
 36 
 37 // fill in your Domain Name Server address here:
 38 IPAddress myDns(1, 1, 1, 1);
 39 
 40 // initialize the library instance:
 41 EthernetClient client;
 42 
 43 char server[] = "www.arduino.cc";
 44 //IPAddress server(64,131,82,241);
 45 
 46 unsigned long lastConnectionTime = 0;             // last time you connected to the server, in milliseconds
 47 const unsigned long postingInterval = 10L * 1000L; // delay between updates, in milliseconds
 48 // the "L" is needed to use long type numbers
 49 
 50 void setup() {
 51   // start serial port:
 52   Serial.begin(9600);
 53   while (!Serial) {
 54     ; // wait for serial port to connect. Needed for Leonardo only
 55   }
 56 
 57   // give the ethernet module time to boot up:
 58   delay(1000);
 59   // start the Ethernet connection using a fixed IP address and DNS server:
 60   Ethernet.begin(mac, ip, myDns);
 61   // print the Ethernet board/shield's IP address:
 62   Serial.print("My IP address: ");
 63   Serial.println(Ethernet.localIP());
 64 }
 65 
 66 void loop() {
 67   // if there's incoming data from the net connection.
 68   // send it out the serial port.  This is for debugging
 69   // purposes only:
 70   if (client.available()) {
 71     char c = client.read();
 72     Serial.write(c);
 73   }
 74 
 75   // if ten seconds have passed since your last connection,
 76   // then connect again and send data:
 77   if (millis() - lastConnectionTime > postingInterval) {
 78     httpRequest();
 79   }
 80 
 81 }
 82 
 83 // this method makes a HTTP connection to the server:
 84 void httpRequest() {
 85   // close any connection before send a new request.
 86   // This will free the socket on the WiFi shield
 87   client.stop();
 88 
 89   // if there's a successful connection:
 90   if (client.connect(server, 80)) {
 91     Serial.println("connecting...");
 92     // send the HTTP PUT request:
 93     client.println("GET /latest.txt HTTP/1.1");
 94     client.println("Host: www.arduino.cc");
 95     client.println("User-Agent: arduino-ethernet");
 96     client.println("Connection: close");
 97     client.println();
 98 
 99     // note the time that the connection was made:
100     lastConnectionTime = millis();
101   }
102   else {
103     // if you couldn't make a connection:
104     Serial.println("connection failed");
105   }
106 }
View Code

請從頭至尾看一變,我保證若是你有編程基礎看一遍也就知道的差很少該怎麼玩了。無非就是定時輪詢,請求服務器,對返回的字符串進行處理。下面的代碼就是我在上面代碼的基礎上作的修改,實現了定時從服務器獲取命令,若是是1則打開Led,若是是2則關閉Led。

  1 /*
  2   Repeating Web client
  3 
  4  This sketch connects to a a web server and makes a request
  5  using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
  6  the Adafruit Ethernet shield, either one will work, as long as it's got
  7  a Wiznet Ethernet module on board.
  8 
  9  This example uses DNS, by assigning the Ethernet client with a MAC address,
 10  IP address, and DNS address.
 11 
 12  Circuit:
 13  * Ethernet shield attached to pins 10, 11, 12, 13
 14 
 15  created 19 Apr 2012
 16  by Tom Igoe
 17  modified 21 Jan 2014
 18  by Federico Vanzati
 19 
 20  http://arduino.cc/en/Tutorial/WebClientRepeating
 21  This code is in the public domain.
 22 
 23  */
 24 
 25 #include <SPI.h>
 26 #include <Ethernet.h>
 27 const int ledPin =  2; 
 28 // assign a MAC address for the ethernet controller.
 29 // fill in your address here:
 30 byte mac[] = {
 31   0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF
 32 };
 33 // fill in an available IP address on your network here,
 34 // for manual configuration:
 35 IPAddress ip(192, 168, 1, 177);
 36 
 37 EthernetClient client;
 38 
 39 IPAddress server(你的服務器地址);
 40 
 41 unsigned long lastConnectionTime = 0;             // last time you connected to the server, in milliseconds
 42 const unsigned long postingInterval = 2L * 1000L; // delay between updates, in milliseconds
 43 // the "L" is needed to use long type numbers
 44 
 45 void setup() {
 46   // start serial port:
 47   Serial.begin(9600);
 48   while (!Serial) {
 49     ; // wait for serial port to connect. Needed for Leonardo only
 50   }
 51   // give the ethernet module time to boot up:
 52   delay(1000);
 53   pinMode(ledPin, OUTPUT);
 54   // start the Ethernet connection using a fixed IP address and DNS server:
 55   Ethernet.begin(mac);
 56   // print the Ethernet board/shield's IP address:
 57   Serial.print("My IP address: ");
 58   Serial.println(Ethernet.localIP());
 59   
 60 }
 61 int iscoming=0;
 62 
 63 void loop() {
 64   // if there's incoming data from the net connection.
 65   // send it out the serial port.  This is for debugging
 66   // purposes only:
 67   if (client.available()) {
 68     char c = client.read();
 69     if(iscoming==1){
 70       handle(c);
 71       iscoming=0;
 72     }
 73     if(c=='@'){
 74      iscoming=1;
 75     }
 76     Serial.write(c);
 77   }
 78 
 79   // if ten seconds have passed since your last connection,
 80   // then connect again and send data:
 81   if (millis() - lastConnectionTime > postingInterval) {
 82     httpRequest();
 83   }
 84 
 85 }
 86 
 87 void handle(char value){
 88  if(value=='1'){
 89     Serial.print("dakai");
 90   digitalWrite(ledPin, LOW);
 91  }
 92  if(value=='2'){
 93     Serial.print("guanbi");
 94   digitalWrite(ledPin, HIGH);
 95  }
 96 }
 97 // this method makes a HTTP connection to the server:
 98 void httpRequest() {
 99   // close any connection before send a new request.
100   // This will free the socket on the WiFi shield
101   client.stop();
102   // if there's a successful connection:
103   delay(1000);
104   if (client.connect(server, 8009)) {
105     Serial.println("connecting...");
106     // send the HTTP PUT request:
107     //api/getcmd是請求的網站資源
108     client.println("GET /api/getcmd HTTP/1.1");
109     client.println("Host: www.arduino.cc");
110     client.println("User-Agent: arduino-ethernet");
111     client.println("Connection: close");
112     client.println();
113     // note the time that the connection was made:
114     lastConnectionTime = millis();
115   }
116   else {
117     // if you couldn't make a connection:
118     Serial.println("connection failed");
119    
120   }
121 }
View Code

Android客戶端

關於科大訊飛的介紹,本身去官網看吧,深耕語音領域二十年,不是通常企業能夠超越的,很好很強大。申請成爲開發者,建立應用,開通服務,下載SDK(我下的是帶UI的SDK),參考SDK的代碼就能夠開始本身的開發了。話很少說,直接上核心代碼

 

 1 /**
 2      * 聽寫UI監聽器
 3      */
 4     private RecognizerDialogListener recognizerDialogListener=new RecognizerDialogListener(){
 5         public void onResult(RecognizerResult results, boolean isLast) {
 6             String text = JsonParser.parseIatResult(results.getResultString());
 7             mResultText.append(text);
 8             mResultText.setSelection(mResultText.length());
 9             sendmeg(text);
10         }
11 
12     private void sendmeg(String msg){
13          AsyncHttpClient client = new AsyncHttpClient();
14          try {
15                 String url = "http://服務器地址/api/values/"+msg;
16                 client.get(url, new AsyncHttpResponseHandler() {
17                     @Override
18                     public void onSuccess(int statusCode, Header[] headers,
19                             byte[] responseBody) {
20                         super.onSuccess(statusCode, headers, responseBody);
21                         Toast.makeText(CmdActivity.this,
22                                 "請求成功" + new String(responseBody), Toast.LENGTH_SHORT).show();
23                     }
24 
25                     @Override
26                     public void onFailure(int statusCode, Header[] headers,
27                             byte[] responseBody, Throwable error) {
28                         // TODO Auto-generated method stub
29                         super.onFailure(statusCode, headers, responseBody, error);
30                     }
31                 });
32             } catch (Exception e) {
33             }
34 
35     }    /**
View Code

 

Asp.Net Mvc Api

服務端的代碼相對就簡單了,我這裏建立了兩個控制器,一個負責接收手機端的命令,存入數據庫,一個負責返回Arduino的網絡請求,將命令代碼返回。雖然以爲不必,仍是上一下代碼吧

接收手機端傳過來的命令

 1 // GET api/values/5
 2         public string Get(string id)
 3         {
 4             ardunioEntities a = new ardunioEntities();
 5             string tempid = "123456789";
 6             cmd c = a.cmd.Where<cmd>(n => n.ardunioid ==tempid).SingleOrDefault();
 7             if (c == null)
 8             {
 9                 c = new cmd();
10                 c.ardunioid = tempid;
11                 c.command = "0";
12                 c.status = "未讀";
13                 a.cmd.Add(c);
14             }
15             if (id.Contains("打開")) 
16             {
17                 {
18                     c.command = "1";
19                     c.status = "未讀";
20                     
21                 }
22             }
23             if (id.Contains("關閉"))
24             {
25                 {
26                     c.command = "2";
27                     c.status = "未讀";
28                 }
29             }
30             a.SaveChanges();
31             return "接收成功!";
32             
33         }
View Code

返回命令給Arduino的請求

 1  public string Get()
 2         {
 3            
 4             ardunioEntities a = new ardunioEntities();
 5             string tempid = "123456789";
 6             cmd c = a.cmd.Where<cmd>(n => n.ardunioid == tempid & n.status == "未讀").SingleOrDefault();
 7             if (c == null)
 8             {
 9                 return "@0";
10             }
11             c.status = "已讀";
12             a.Entry(c).State = EntityState.Modified;
13             a.SaveChanges();
14             return "@"+c.command;
15         }
View Code

效果實現與總結

    對着手機說「打開燈泡」,而後燈就亮了!話說程序員看到這一幕,興奮之情溢於言表啊。(請忽略旁邊的美桃,女朋友因爲對我崇拜的五體投地給我洗的,嘻嘻)。

    這篇文章只是一個小實驗而已,後續還能夠作不少有趣的玩法,好比在這個程序的基礎上開發語音控制電動窗簾的的工做(目前正在玩耍...),好比直接弄一個Android開發板或者使用語音模塊作一箇中控,二十四小時伺服,回到家直接說話「小文,換臺到體育頻道」等等等等,現有的智能家居產品均可以把語音技術集成過來,相信會大大增長智能家居的易用性。

    本月科大訊飛即將召開智能家庭產品發佈會,咱們實驗室也申請了票,期待看到高大上的東東開開眼。。。。一場革命或許已經來臨。

    看完了就默默點個贊吧:)

相關文章
相關標籤/搜索