Wi-Fi小車記錄3:Windows Phone 8.1 Runtime App編程

  在前兩篇中,路由器已經刷入OpenWrt系統並安裝了Ser2net等相關軟件,如今就能夠寫一個客戶端與路由器進行Socket通訊。一共有三個應用,桌面應用採用WPF編寫,Windows Phone應用採用Windows Phone 8.1 Runtime架構,Win8應用也是Runtime,其實直接把WinPhone代碼複製過去就能夠直接生成一個Win8應用。windows

    本篇記錄主要記錄WinPhone應用編寫過程。數組

  應用功能:利用重力感應控制小車左轉、右轉、前進、後退,點擊視頻能夠查看車載攝像頭視頻畫面。服務器

  先貼圖,基本界面是這樣,大部分都是拖出來的,尚未進行認真佈局。架構

 

 利用Visual Studio 建立一個Windows Phone 8.1空白應用程序(Runtime版本)。而後就能夠把上面一大堆TextBlock和Button控件拖出來。app

左上角一堆TextBlock分別是X-axis(加速度計x值),Y-axis(加速度計y值),Z-axis(加速度計z值),X二、Y2是紅線上面一點的座標。異步

中間那個」山「,左右兩個是ProcessingBar(進度條),下面一條是藍色的線,中間紅色的線以兩條線的交點爲原點,隨着手機左右搖擺而轉動。async

  • 如何進行Socket通訊

    MSDN參考:http://msdn.microsoft.com/library/windows/apps/br226882佈局

       這裏用的是StreamSocket Class。ui

 1 try
 2 {
 3 StatusText.Text = "正在嘗試鏈接。。。";
 4 //新建hostname,用服務器ip地址初始化
 5 HostName serverHost = new HostName("192.168.1.1");
 6 //調用鏈接異步方法,2001爲ser2net程序的端口號
 7 await clientSocket.ConnectAsync(serverHost, "2001");
 8 connected = true;
 9 StatusText.Text = "Connection established" + Environment.NewLine;
10 }
11 catch (Exception exception)
12 {
13 StatusText.Text = "Connect failed with error:" + exception.Message;
14 }
  •  如何發送數據

    MSDN參考http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.storage.streams.datawriter.aspxthis

    主要利用的是DataWriter Class

 1                 uint len = 0;
 2             byte[] bytedata = new byte[10];
 3             //data是要傳送的string,將其轉化爲Byte[]數組進行傳送
 4             bytedata = Encoding.UTF8.GetBytes(data);
 5             try
 6             {
 7                 StatusText.Text = "Trying to send data...";
 8                //新建DataWriter對象,用StreamSocket.OutputStream進行初始化
 9                 using(DataWriter writer = new DataWrite(clientSocket.OutputStream))
10                 {
11                 //獲取要傳送的字節數組的長度
12                 len = writer.MeasureString(data);
13                 //向輸出流寫入數據
14                 writer.WriteBytes(bytedata);
15                 await writer.StoreAsync();
16                 await writer.FlushAsync();
17                 writer.DetachStream();
18 
19 
20                 }
21 
22                 StatusText.Text = "Data " + data + " was sent.";
23             }
24             catch (Exception)
25             {
26                 StatusText.Text = "Send data or receive failed with error: ";
27               
28 
29             }    
  • 如何接收數據

    MSDN參考:http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.storage.streams.datareader

    接收數據不像發送那樣,須要發送的時候直接調用方法便可。接收數據須要單獨用一個線程進行週期性的檢查,不如我這裏就是沒100ms(delay的值)接收一次,若有數據便顯示在文本框中。

 1 //利用線程池對象建立一個週期性工做的計時器。
 2 //調用的方法是ThreadPoolTimer.CreateTimer(TimerElapsedHandler, TimeSpan)
 3 //其中第一個參數是即時結束事件處理委託,這裏用Lambda表達式 處理。
 4 
 5 ThreadPoolTimer timer = ThreadPoolTimer.CreatePeriodicTimer(
 6                     async (source) =>
 7                     {
 8                         if (!connected)
 9                         {
10                             StatusText.Text = "Must be connected to send!";
11                             return;
12                         }
13                         //建立DataReader對象,用輸入流初始化
14                         DataReader reader = new DataReader(clientSocket.InputStream);
15                         //異步方法,載入一個字節
16                         reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
17                         reader.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;
18                         await reader.LoadAsync(1);
19                         while (reader.UnconsumedBufferLength > 0)
20                         {
21                           
22                             s += reader.ReadString(reader.UnconsumedBufferLength);
23                             if (s.Length == 50)
24                             s = "";
25                         }
26                         reader.DetachStream();
27                        //建立要提交到線程池的工做項來更新UI
28                        //RunAsync參考:http://msdn.microsoft.com/zh-cn/library/windows/apps/windows.system.threading.threadpool.runasync.aspx
29 
30 
31                         await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
32                             () =>
33                             {
34                                 ReceiveDataBlock.Text = s;
35                             }
36                             );
37                     }, delay
38 
39                     );

 

  •  如何獲取重力感應信息

    MSDN參考:http://msdn.microsoft.com/zh-cn/library/windows/apps/xaml/hh465272.aspx

    參考文檔能夠直接複製過來就用。

 1 private async void ReadingChanged(object sender, AccelerometerReadingChangedEventArgs e)
 2         {
 3             await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
 4             {
 5                 this.reading = e.Reading;
 6                 //三個文本框中分別顯示出當前加速度計x,y,z的值
 7                 txtXAxis.Text = String.Format("{0,5:0.00}", reading.AccelerationX);
 8                 txtYAxis.Text = String.Format("{0,5:0.00}", reading.AccelerationY);
 9                 txtZAxis.Text = String.Format("{0,5:0.00}", reading.AccelerationZ);
10                 if (!(Math.Abs(this.PreviousY-reading.AccelerationY)<=0.02))
11                 {
12                 //計算紅線端點的座標,顯示在對應的文本框中
13                     Pointer.X2 = (-140 * Math.Sin(Math.PI / 2 * reading.AccelerationY) + 320);
14                     Pointer.Y2 = (-140 * Math.Cos(Math.PI / 2 * reading.AccelerationY) + 280);
15                     X.Text =string.Format("{0,5:0.00}", Pointer.X2);
16                     Y.Text =string.Format("{0,5:0.00}", Pointer.Y2);
17                     int i=(int)Math.Abs(reading.AccelerationY*10);
18                     string s=i.ToString();
19                 //z<0.5 向前走
20                     if(reading.AccelerationZ<=0.5)
21                     {
22                         if (!(Math.Abs(reading.AccelerationY - previous) < 0.05))
23                         {
24                             if (reading.AccelerationY > 0)
25                 //發送控制數據
26                                 SendData("ADL" + s + "A");
27                             else if (reading.AccelerationY < 0)
28                                 SendData("ADR" + s + "A");
29                             sentBack = false;
30                         }
31                     }
32                  //z>0.5 向後退
33                     else if (reading.AccelerationZ > 0.5&&sentBack==false)
34                     {
35                         SendData("ADB0A");
36                         sentBack = true;
37                     }
38                     previous = reading.AccelerationY;
39                 }
40             });
41          
42                    
43         }

  至此,即可以正常像小車發送數據進行重力感應控制了。

相關文章
相關標籤/搜索