• 山寨版 WP8.1 Cortana 启动 PC


    8.1 dev preview 发布以来 Cortana 很受关注

    前一段看到有视频演示用 Cortana 来启动 PC

    看视频也是启动第三方应用实现的,简单来弄其实就是个语音启动应用 + 网络唤醒么…

    也动手山寨一个简单的出来

     

    首先先介绍下啥是网络唤醒:

    详细去参考维基百科:http://zh.wikipedia.org/wiki/Wake-on-LAN

    基本要求就是网卡支持(现代的PC一般是支持的,不过有的需要设置下,开启这个功能)

    然后利用UDP往计算机网段广播地址发送一个包含要唤醒计算机的 mac 地址的 Magic Packet,来唤醒计算机。

    魔法封包(Magic Packet)是一个广播性的帧(frame),透过埠7或埠9进行发送,且可以用无连接(Connectionless protocol)的通讯协定(如UDPIPX)来传递,不过一般而言多是用UDP,原因是Novell公司Netware网络操作系统的IPX协定已经愈来愈少机会被使用。

    在魔法封包内,每次都会先有连续6个"FF"(十六进制,换算成二进制即:11111111)的资料,即:FF FF FF FF FF FF,在连续6个"FF"后则开始带出MAC位址资讯,有时还会带出4字节或6字节的密码,一旦经由网络卡侦测、解读、研判(广播)魔法封包的内容,内容中的MAC位址、密码若与电脑自身的位址、密码吻合,就会启动唤醒、开机的程序。

     

    基本原理介绍完了,下面我们动手实现下吧

    首先是计算机设置,我找了一台老机器,貌似板子是G31还是G43来着,先进BIOS里设置下支持远程唤醒

    MediaLib_Camera Roll_WP_20140519_001

     

    这个板子是设置允许 wake up by PCIE Card 就行了,不同板子设置不一样,自己看看设置吧

    MediaLib_Camera Roll_WP_20140519_002

     

     

    设置好了之后,我们的 PC 应该就支持网络唤醒了,先要验证下是否好用,找个程序试试,之前那篇维基百科里介绍了很多工具

    这里我用的是Magic Packet Utility (http://1drv.ms/1gYESk2),远程唤醒下试试效果

    image

    image

     

    验证没问题后我们开始编写程序,首先新建一个wp工程(其实WP从7.1起就支持UDP,不过为了显得高大上我们建立一个8.1的工程吧,当然为了方便改成其他版本的,我们还是继续用silverlight)

    image

     

    选择版本为8.1

    image

     

    简单画个UI,要远程唤醒我们需要知道两个信息,1是目标计算机的 MAC 地址,2就是目标计算机所处网段的广播地址(啥是广播地址继续参见百科:http://zh.wikipedia.org/wiki/IPv4 中的广播地址  ,基本上说就是把IP 地址最后一位改成 255…)

    image

            <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
                <StackPanel HorizontalAlignment="Left" Height="607" VerticalAlignment="Top" Width="432" Margin="12,0,0,0">
                    <TextBlock TextWrapping="Wrap" Text="MAC地址:"/>
                    <TextBox x:Name="mac" Height="72" TextWrapping="Wrap" Text="FFFFFFFFFFFF" FontFamily="Portable User Interface"/>
                    <TextBlock TextWrapping="Wrap" Text="广播地址:"/>
                    <TextBox x:Name="bip" Height="72" TextWrapping="Wrap" Text="192.168.1.255" FontFamily="Portable User Interface"/>
                    <Button Content="启  动" Margin="0,50,0,0" Click="Button_Click"/>
                </StackPanel>
            </Grid>

     

    我们前面已经看百科的介绍了解的 Magic Packet 的组成(102个字节组成,最前面六个字节为0xFF,其他字节为目的主机的MAC地址(6个字节为一组,共16组))

    下面我们需要自己构建 Magic Packet:

                    byte[] sendBytes = new byte[102];
                    for (int i = 0; i < 6; i++)
                    {
                        sendBytes[i] = 0xFF;
                    }
                    for (int i = 0; i < 16; i++)
                    {
                        for (int j = 0; j < 6; j++)
                        {
                            sendBytes[(i + 1) * 6 + j] = byte.Parse(macAddress.Substring(j * 2, 2), System.Globalization.NumberStyles.HexNumber);
                        }
                    }

     

    然后发送UDP包的代码就很简单了,主要摘自MSDN:http://msdn.microsoft.com/zh-cn/library/hh202864(v=vs.92).aspx

            public string Send(string BroadcastIP, string macAddress)
            {
                string response = "Operation Timeout";
     
                // We are re-using the _socket object that was initialized in the Connect method
                if (_socket != null)
                {
                    // Create SocketAsyncEventArgs context object
                    SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
     
                    // Set properties on context object
                    socketEventArg.RemoteEndPoint = new DnsEndPoint(BroadcastIP, 7);
     
                    // Inline event handler for the Completed event.
                    // Note: This event handler was implemented inline in order to make this method self-contained.
                    socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
                    {
                        response = e.SocketError.ToString();
     
                        // Unblock the UI thread
                        _clientDone.Set();
                    });
     
     
                    byte[] sendBytes = new byte[102];
                    for (int i = 0; i < 6; i++)
                    {
                        sendBytes[i] = 0xFF;
                    }
                    for (int i = 0; i < 16; i++)
                    {
                        for (int j = 0; j < 6; j++)
                        {
                            sendBytes[(i + 1) * 6 + j] = byte.Parse(macAddress.Substring(j * 2, 2), System.Globalization.NumberStyles.HexNumber);
                        }
                    }
     
     
     
                    // Add the data to be sent into the buffer
                    byte[] payload = sendBytes;
                    socketEventArg.SetBuffer(payload, 0, payload.Length);
     
                    // Sets the state of the event to nonsignaled, causing threads to block
                    _clientDone.Reset();
     
                    // Make an asynchronous Send request over the socket
                    _socket.SendToAsync(socketEventArg);
     
                    // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
                    // If no response comes back within this time then proceed
                    _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
                }
                else
                {
                    response = "Socket is not initialized";
                }
     
                return response;
            }

     

    程序的唤醒部分基本就完成了,下面我们要添加应用支持语音启动,首先在清单文件中设置程序支持语音:

    image

     

    然后我们在工程中添加一个“语音命令定义”,名称为:SupportedVoiceCommands.xml

    image

     

    修改下内容,我们只是为了语音启动,所以后面的内容就不用了

    <?xml version="1.0" encoding="utf-8"?>
     
    <VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
      <CommandSet xml:lang="en-us">
        <CommandPrefix>start</CommandPrefix>
        <Example> open start </Example>
     
        ......    
     
      </CommandSet>
    </VoiceCommands>

     

     

    然后修改 App.xaml.cs ,加入对该语音指令文件的注册,函数命名为 InitializeVoiceCommands

            async private static void InitializeVoiceCommands()
            {
                var filename = "SupportedVoiceCommands.xml";
                try
                {
                    var location = Windows.ApplicationModel.Package.Current.InstalledLocation.Path;
                    var fileUriString = String.Format("file://{0}/{1}", location, filename);
                    await Windows.Phone.Speech.VoiceCommands.VoiceCommandService.InstallCommandSetsFromFileAsync(new Uri(fileUriString));    
                }
                catch (Exception ex)
                {
                   System.Diagnostics.Debug.WriteLine(ex.Message);
                }
            }

    然后修改 App.xaml.cs 里的构造函数,加入InitializeVoiceCommands()

            public App()
            {
                // 未捕获的异常的全局处理程序。
                UnhandledException += Application_UnhandledException;
     
                // 标准 XAML 初始化
                InitializeComponent();
     
                // 特定于电话的初始化
                InitializePhoneApplication();
     
                // 语言显示初始化
                InitializeLanguage();
     
                //语音初始化
    InitializeVoiceCommands();
     
                // 调试时显示图形分析信息。
                if (Debugger.IsAttached)

     

    完成收工,运行下试试效果。

     

    MediaLib_Screenshots_wp_ss_20140519_0003 MediaLib_Screenshots_wp_ss_20140519_0004 MediaLib_Screenshots_wp_ss_20140519_0005

     

     

    最后源码:

     

     

    参考:

  • 相关阅读:
    [leetcode] Valid Sudoku
    [leetcode] Count and Say
    [leetcode] Decode Ways
    [leetcode] Sqrt(x)
    [leetcode] Best Time to Buy and Sell Stock II
    7-27 兔子繁衍问题
    7-26 最大公约数和最小公倍数
    7-25 求奇数和
    7-24 猜数字游戏
    7-23 分段计算居民水费
  • 原文地址:https://www.cnblogs.com/sun8134/p/3737061.html
Copyright © 2020-2023  润新知