65.9K
CodeProject 正在变化。 阅读更多。
Home

将 jQuery Mobile 与 MVC 和 Netduino 结合用于家庭自动化

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (50投票s)

2012年3月12日

CPOL

9分钟阅读

viewsIcon

412645

downloadIcon

4809

本文非常适合任何学习 jQuery Mobile 或使用 MVC3 构建移动应用程序的人。我用手机构建了一个遥控器,可以通过 jQuery Mobile、MVC 和 Netduino 来控制我的游泳池喷水枪、打开我的车库门、给花园浇水以及控制我的燃气壁炉。

引言

你多久会弄丢一次遥控器?我讨厌寻找遥控器,而且家人似乎总是把它藏起来。我决定把我的智能手机变成家里的通用遥控器,这对我来说非常完美,因为我几乎总是能拿到它。我的妻子对她的手机不以为然,所以我不得不为我们的家庭自动化构建外部控制器。到目前为止,我的家庭自动化包括远程控制我的游泳池喷水枪、打开我的车库门、给花园浇水,而且我刚刚增加了对燃气壁炉的控制!请务必查看我的文章“使用 Netduino 和 Kinect 进行家庭自动化”,了解更多信息和代码示例。

我第一次尝试为我的家庭自动化项目构建移动应用程序时,涉及到为 Windows Phone 7 和 Android 构建原生应用程序。这些应用程序达到了目的,但除了后端 Web 服务之外,为不同移动操作系统编写的应用程序之间没有代码重用。问题变得更加复杂,因为每个家庭成员都有自己喜欢的移动设备,运行着不同的移动操作系统。jQuery Mobile 和 HTML5 解决了让遥控器在各种设备上工作的问题。现在我有一个代码库,可以在 iOS、Android、Windows Phone 和大多数相关移动设备上运行。

自毁二维码

二维码和微软标签、Datamatrix 等其他二维条形码让我着迷了很久。几乎任何带摄像头的移动设备都可以读取二维二维码,这些二维码可以引导你访问网站、联系信息、电子邮件地址或地理位置等等。我决定使用二维码将用户引导到我的家庭自动化 jQuery Mobile 网站。我不希望任何找到二维码打印件的人都能控制家庭自动化,所以为了增加乐趣,我添加了一个新的自毁功能,就像老式间谍电影中那样!

扫描此二维码或点击链接观看世界上第一个自毁二维码的视频。

jQuery 和 jQuery Mobile

jQuery 是一个非常流行的 JavaScript 库,用于构建非常丰富的基于 Ajax 的 Web 应用程序。它是一个很棒的库,简化了构建丰富的 Web 2.0 应用程序的开发,并帮助软件开发人员保持代码的简洁。jQuery 单独使用的问题在于它主要是为桌面应用程序编写的,并且没有许多移动应用程序所需的功能,这就是 jQuery Mobile 发挥作用的地方。jQuery Mobile 是一个构建在 jQuery 之上的框架,它解决了 jQuery 在移动设备上的不足。jQuery Mobile 1.0 于 2011 年 11 月发布,代表着移动 Web 领域的一个重要里程碑。

jQuery Mobile 的美妙之处在于它易于开发,并且在大多数相关移动设备上运行良好。界面配置是标记驱动的,你可以在 HTML 中创建基本应用程序,而无需添加自定义 JavaScript。你可以使用 JavaScript 扩展你的移动应用程序,但仅凭普通的 HTML 就能做很多事情,这令人惊讶。我的家庭自动化项目只需要编写 2 个 JavaScript 函数,如果我没有自毁页面的倒计时显示,我甚至可以完全不使用自定义 JavaScript 来完成整个项目。

将 jQuery Mobile 与 MVC3 结合使用

ASP.NET MVC 3 是一个框架,用于使用成熟的设计模式构建可扩展的、基于标准的 Web 应用程序。MVC 框架也非常适合使用 jQuery Mobile 构建移动 Web 应用程序。特别是 Razor 视图引擎,它对于避免重复编写标记非常有帮助。Razor 部分视图和自定义编写的 @helper 方法帮助你为 HTML 标记创建可重用的模板。它们实现了更好的代码重用,还可以使代码更具可读性。Razor 部分视图允许你定义页面中常见的共享部分,这些部分可以在网站的多个页面中或在网站的同一页面中多次利用。放置在 \app_code 目录中的 Razor @helper 方法可以在项目的所有视图中重用。我编写了简单的 @helper 方法,使向项目中添加 JavaScript 和 CSS 文件的代码更简洁。ASP.NET 运行时编译 \app_code 目录中的任何 Razor 视图,并使其帮助器作为静态方法可用。

@helper Script(string scriptName, UrlHelper url) {
    <script src="@url.Content("~/Scripts/" + scriptName)" type="text/javascript"></script>
}

@helper Css(string cssName, UrlHelper url) {
    <link href="@url.Content("~/Content/" + cssName)" rel="stylesheet" type="text/css" />
}

Razor 布局类似于熟悉的 ASPX 母版页。它们允许您定义网站中要通用的元素,并定义页面中要特定视图呈现的区域。对于 jQuery Mobile 网站,布局需要包含应用程序的 CSS 文件、应用程序的 JavaScript 库,并设置视口,以便应用程序在移动设备上正确显示大小。我的应用程序有 3 个 CSS 文件。jQuery Mobile 有它自己的样式,您必须包含。我使用 ThemeRoller 工具对网站进行了主题化,该工具生成了主题的 CSS。ThemeRoller 工具将在本文后面更详细地讨论。第三个 CSS 文件是 Site.css 文件,用于我需要的任何额外 CSS,而 ThemeRoller 工具没有为我生成。

<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    
    @Content.Css("jquery.mobile-1.0.min.css", Url)
    @Content.Css("themes/LogicalLiving.css", Url)
    @Content.Css("Site.css", Url)
    @Content.Script("jquery-1.7.1.min.js", Url)
    @Content.Script("jquery.unobtrusive-ajax.min.js", Url)
    @Content.Script("jquery.mobile-1.0.min.js", Url)
    @Content.Script("LogicalLiving.js",Url)
 
    <meta name="viewport" content="initial-scale=1, maximum-scale=1">
</head>
<body>
    @RenderBody()
</body>
</html>

所有 jQuery Mobile 网站都需要引用 jQuery JavaScript 文件和 jQuery Mobile JavaScript 文件。我添加了对 jquery.unobtrusive-ajax 的引用,以实现额外的 Ajax 功能,并引用了 LogicalLiving.js JavaScript 文件,以用于我项目的自定义 JavaScript。在 HTML5 中,<meta> 标签用于定义 HTML 文档的元数据。<meta name="viewport"/> 元标签用于控制 HTML 内容在移动浏览器中的显示方式,以便内容针对设备正确调整大小。

数据属性

jQuery Mobile 框架使用 HTML5 “data-” 属性来实现基于标记的初始化和配置。数据属性允许您向单个元素添加简单的元数据,这些元数据由 jQuery Mobile JavaScript 函数解释。

<div data-role="header">Defines a header toolbar for the app</div>


<div data-role="header" data-position="fixed">Defines a header toolbar for the app that holds its position when the user scrolls down</div>


<div data-role="content">Defines a content area for the mobile page</div>


<div data-role="footer">Defines a footer area for the mobile page</div> 

jQuery Mobile 中的页面可以是单页,也可以是页面内的内部链接页面。一个单独的 HTML 文档可以包含多个页面,这些页面一起加载并通过 <div> 标签分隔。jQuery Mobile 使用 Ajax 来显示相应的页面。我在 Index.cshtml 视图中将所有页面加载到移动应用程序的 <div> 中。

@{ ViewBag.Title = "Logical Living"; }
 
<div data-role="page" id="home" data-theme="a">
    @Html.Partial("_Menu")
</div>
 
<div data-role="page" id="pool" data-theme="a">
    @Html.Partial("_Pool")
</div>
 
<div data-role="page" id="garden" data-theme="a">
    @Html.Partial("_Garden")
</div>
 
<div data-role="page" id="fireplace" data-theme="a">
    @Html.Partial("_Fireplace")
</div>
 
<div data-role="page" id="garage" data-theme="a">
    @Html.Partial("_Garage")
</div>
 
<div data-role="page" id="about" data-theme="a">
    @Html.Partial("_About")
</div>
 
<div data-role="page" id="contact" data-theme="a">
    @Html.Partial("_Contact")
</div>
 
<div data-role="page" id="destruct" data-theme="a">
    @Html.Partial("_Destruct");
</div>

我将每个页面组织为部分视图,以便将代码分解成更易于管理的片段。下面是 _About.cshtml 部分视图的示例

@Html.Partial("_Header", new Netduino.LogicalLiving.Models.HeaderModel { HeaderText = "About" ,ShowBackButton=true})
<div data-role="content"> 
    <div class="center-text">
        <p><b>Logical Living</b></p>
        <div>Version 1.0</div>
        <p>This app rocks!</p> 
        <div>Written by:</div>
        <div><a href="#contact">Dan Thyer</a></div>   
    </div>
</div>
@Html.Partial("_Footer")

每个页面都包含 _Header.cshtml 和 _Footer.cshtml 的部分视图。这让我能够一次编写页眉和页脚,并在所有内部页面中重复使用它们。请注意超链接:<a href="#contact">Dan Thyer</a> jQuery Mobile 知道显示 "#contact" 页面意味着显示具有 data-role="page" 和 id 为 "contact" 的 <div> 标签内的 HTML。

<div data-role="page" id="contact" data-theme="a"> 

与硬件对话

我的 jQuery Mobile 应用大部分代码都在设备本地运行。我编写了一个 MVC 控制器方法,在服务器上运行,与 Netduino 通信,名为 SendMessageToNetduino。该方法通过移动设备的 Ajax 调用。

public ContentResult SendMessageToNetduino(string message, string status)
{
    bool sendToNetduino = bool.Parse(WebConfigurationManager.AppSettings["SendToNetduino"]);
    if (sendToNetduino)
    {
        CommunicateWithNetduino.GetInstance().SendMessage(message);
    }

    return Content(status);
}
该方法是一个简单的传递,它接收来自移动设备通过互联网通过 Ajax 发送的消息,然后通过防火墙后面的本地网络将消息转发到 Netduino .net 微控制器。Netduino Plus 是一个运行 .Net Micro Framework 中 C# 的微控制器。Netduino Plus 内置以太网适配器用于网络通信。有关如何与微控制器通信的更多信息和代码示例,请阅读我的文章“使用 Netduino 和 Kinect 进行家庭自动化”

上图显示了 jQuery Mobile 应用程序和 Netduino 微控制器之间的通信。请注意,同一个 jQuery Mobile 应用程序在具有不同移动操作系统的多个设备上运行。

我编写了一个 MVC Razor @helper 方法来封装与 Netduino 通信所需的逻辑。

@helper NetduinoButton(string buttonText, string netduinoMessage, string statusMessage, string dataIcon, AjaxHelper ajax) {
    @ajax.ActionLink(buttonText, "SendMessageToNetduino", "Home",
        new {
            message = netduinoMessage,
            status = statusMessage
        },
        new AjaxOptions {
            UpdateTargetId = "serverMessage",
            InsertionMode = InsertionMode.Replace,
            HttpMethod = "Get"
        },
        new { 
            data_role = "button", 
            rel = "external", 
            data_icon = dataIcon,
            data_theme ="a"
        })
} 

使用我的 NetduinoButton @helper 方法,只需在视图中添加一行简单的代码即可添加一个控制设备的按钮。以下代码添加了一个按钮来打开车库门。

@Content.NetduinoButton("Garage", "C", "Garage Door.", "", Ajax) 

以下是用于控制喷水枪的 _Pool.cshtml 视图。请注意逻辑是如何巧妙地封装到 @Content.NetduinoButton 方法调用中,以防止代码重复。

@Html.Partial("_Header", new Netduino.LogicalLiving.Models.HeaderModel { HeaderText = "Pool" ,ShowBackButton=true})
<div data-role="content"> 
    <div data-role="controlgroup">
        @Content.NetduinoButton("Trace Shallow End","1","Trace shallow end.","", Ajax)
        @Content.NetduinoButton("Trace Pool", "2", "Trace pool.", "", Ajax)
        @Content.NetduinoButton("Get People Wet", "3", "Get people wet!", "", Ajax)
    </div>
    <br />
    
    <div style="margin-left:max;margin-right:max;">
    @Content.NetduinoButton("Up", "U 5", "Move up.", "arrow-u", Ajax)
    
    <div data-role="controlgroup" data-type="horizontal" style="text-align:center">
        @Content.NetduinoButton("Left", "L 5", "Move left.", "arrow-l", Ajax)
        @Content.NetduinoButton("Home", "H", "Move home.", "home", Ajax)
        @Content.NetduinoButton("Right", "R 5", "Move right.", "arrow-r", Ajax)
    </div>

    @Content.NetduinoButton("Down", "D 5", "Move down.", "arrow-d", Ajax)
    </div>

    <br />
    <div data-role="controlgroup" data-type="horizontal">
        @Content.NetduinoButton("On", "O", "Turned water on.", "", Ajax)
        @Content.NetduinoButton("Off", "F", "Turned water off.", "", Ajax)
    </div>
</div>
@Html.Partial("_Footer") 

下面的屏幕截图显示了应用程序中页面的几个示例。泳池和壁炉页面主体中的所有按钮都是 NetduinoButton 的示例。

主题

jQuery Mobile 围绕面向对象的 CSS 框架设计,该框架将主题应用于您的移动应用程序。主题利用 CSS3 属性添加美观的圆角、框和文本阴影以及渐变。它尽可能利用 CSS3 属性,以减少对图像的需求,因为图像的下载服务器请求量更大。

主题滚轮

jQuery Mobile 提供了一个很酷的 Web 工具来帮助开发人员为他们的移动网站创建漂亮的主题。这个工具叫做 ThemeRoller,http://jquerymobile.com/themeroller/index.php,它可以被程序员、图形设计师甚至新手用来为移动网站创建好看的主题。

上图显示了 ThemeRoller 的两个色板,标记为 A 和 B。每个色板都可以应用自己的样式。一个 jQuery Mobile 应用程序最多可以有 26 个色板 (A-Z)。可以通过将元素的 data-theme 属性设置为其色板字母来为页面上的 HTML 元素设置主题:data-theme="a" 或 data-theme="b"。从上面主题中显示的色板来看,可以通过设置 data-theme="a" 将按钮样式设置为橙色,或者通过设置 data-theme="b" 将其设置为白色。

结论

借助 jQuery Mobile 和 HTML5,您可以构建适用于大多数相关移动操作系统和设备的移动网站和应用程序。MVC 框架与 jQuery Mobile 配合良好,可帮助您避免编写重复代码。Razor 视图引擎可实现更好的代码重用,并有助于提高代码的可读性。jQuery Mobile 允许您为移动网站/应用程序设置主题,使其看起来像原生应用程序一样精美。

Microsoft MSDN Channel9 Coding4Fun 特别报道了我的项目:借助 jQuery Mobile MVC 和 Netduino 进行家庭自动化
© . All rights reserved.