智能家居

Posted Jack-Chan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能家居相关的知识,希望对你有一定的参考价值。

课程简介

智能家居是在互联网的影响之下物联化体现。智能家居通过物联网技术将家中的各种设备连接到一起,提供各种控制或者定时控制的功能和手段。与普通家居相比,智能家居不仅具有传统的家庭居住功能,同时还兼备建筑、网络通信、信息家电、设备自动化功能,提供全方位的信息交互功能。

在本课程中一共有两个案例,第一个是智能摄像头,我将演示如何通过自己编写android应用控制网络摄像头,实现远程监控功能。第二个是蓝牙继电器,通过手机的蓝牙跟智能设备进行通信进而控制开关,实现电器设备的“智能化”。

智能家居发展情况

智能家居起源

智能家居的概念起源很早,但是直到1984年美国联合科技公司(United Technologies Building System)将建筑设备信息化、整合化概念应用于美国康涅狄格州(Connecticut)哈特佛市(Hartford)的CityPlaceBuilding时,才出现了首栋的“智能型建筑”,从此揭开了全世界争相建造智能家居派的序幕。智能家居从开始到现在主要经历了四个阶段。

1、家庭自动化

通过一个中央微处理机接受相关电子产品(检测环境变化)的信息,再发送给其他产品。

2、家庭网络

家庭网络是在家庭范围内将家电(安全系统、照明系统)和广域网相连接的一种新技术。

3、网络家电

利用数字技术、网络技术及智能控制技术设计改进的新型家电产品,比如网络空调。

4、信息家电

能够通过网络系统交互信息的家电产品。

国内发展现状

智能家居在我国还是一个新生产业,处于一个导入期与成长期的临界点,我国政府在2013年8月14日发表了关于促进信息消费扩大内需的若干意见,大力发展宽带业务,也为智能家居打下了坚实的基础,加之智能家居市场消费观念还未形成,市场的消费潜力必然是巨大的,产业前景光明。

1、萌芽期/智能小区期(1994年-1999年)

概念熟悉、产品认知的阶段,还没有出现专业的智能家居生产厂商。

2、开创期(2000年-2005年)

成立了五十多家智能家居研发生产企业,没有进入国内市场。

3、徘徊期(2006-2010年)

过分夸大智能家居的功能,行业用户、媒体开始质疑智能家居的实际效果 ,国内企业转型,国外企业进入(罗格朗、霍尼韦尔)。

4、融合演变期(2011-2020年)

进入2014年以来,各大厂商已开始密集布局智能家居,经过一年多产业磨合,2015年合作企业已普遍进入到出成果时刻,智能家居新品已经层出不穷的出现了。

智能家电

智能灯泡
智能摄像头
智能空调

蓝牙灯泡

什么是蓝牙灯泡

智能家居的一部分,将蓝牙模块和灯泡相结合,通过手机和蓝牙模块进行通讯,控制电灯中的电压板,从而控制灯泡的打开、关闭、点动等操作。

应用场景

住家、卧室、客厅、厨房、浴厕,办公室、会议室、地下 室、汗蒸房、美容院、医院、疗养院等等地方。

优缺点

优点:方便、快捷、能耗低、寿命长、扩展性好
缺点:受距离限制(5-10米),不稳定

基本组成

灯泡

智能家居

蓝牙模块

智能家居

手机,目标:通过手机控制灯泡的打开、关闭、点动操作

基本流程

智能家居

//获取本地蓝牙适配器
BluetoothAdapter mBluetoothAdapter =  BluetoothAdapter.getDefaultAdapter();

//打开手机蓝牙
mBluetoothAdapter .enable();     
//关闭手机蓝牙
mBluetoothAdapter.disable();

//扫描蓝牙设备
mBluetoothAdapter.startDiscovery();
//取消扫描蓝牙设备,减少资源的消耗
mBluetoothAdapter.cancelDiscovery();

startDiscovery()和cancelDiscovery()必须在工程中注册一个蓝牙广播接受者

//添加蓝牙广播接受者

IntentFilter filter = new IntentFilter();
// 开始扫描的广播
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);    
// 扫描完成的广播
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);   
// 发现一个可用的设备的广播
filter.addAction(BluetoothDevice.ACTION_FOUND);
mBluetoothReceiver = new BluetoothReceiver();
//注册监听
registerReceiver(mBluetoothReceiver, filter);

蓝牙广播接受者

class BluetoothReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
                //获取蓝牙设备
        }
}

连接设备

public void connectServer(final BluetoothDevice device) {
    new Thread(new Runnable(){
        @Override
        public void run() {
        try {
                    System.out.println(randomUUID.toString());
                    BluetoothSocket clientSocket = device.
            createRfcommSocketToServiceRecord(
        UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"));
                    clientSocket.connect();
                    out = clientSocket.getOutputStream();
                    System.out.println("连接成功");
                    Looper.prepare();
                   Toast.makeText(BluetoothDemoActivity.this, "连接成功", 0).show();
                   Looper.loop();
        } catch (IOException e) {
                   e.printStackTrace();
        }
        }}).start();
    }

注意:蓝牙2.1版本不用使用匹配的UUID也可以,但不保证准确性,蓝牙4.0版本需要使用匹配的UUID,为了兼容性都使用匹配的UUID
UUID: 00001101-0000-1000-8000-00805f9b34fb
匹配密码:1518(高版本为了低功耗不用密码验证)

Looper :是用来封装消息循环和消息队列的一个类,用于在android线程中进行消息处理
Looper.prepare() :在一个线程中运行一个消息循环,通过perpare开启消息循环
Looper.loop() :循环处理消息,直到循环结束为止

打开灯泡

private void openLight() {
        if(out == null) return;
        try {
            // 向服务端写数据
            byte[] b = new byte[5];
            b[0] = (byte) 0x01;
            b[1] = (byte) 0x99;
            b[2] = (byte) 0x10;
            b[3] = (byte) 0x10;
            b[4] = (byte) 0x99;
            out.write(b);
            out.flush();
        } catch (IOException e) {
            Toast.makeText(this, "打开失败", 0).show();
            e.printStackTrace();
        }
    }

注销广播接受者

@Override
protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBluetoothReceiver);
}

智能摄像头

准备工作

网络摄像头,我这里采用的是 品牌: EasyN/易视眼 型号: TM007 ,产品图片如下。
智能家居

对应SDK

智能家居

我们开发的软件是基于第三方智能网平台的,因此需要使用到第三方的SDK。

工作原理

首先当我们将网络摄像头买回来的时候,需要给其设置wifi账号和密码,以让我们的硬件能够连接到物联网云平台。在我们这个案例中使用到的物联网云平台是台湾TUTK公司http://www.tutk.com/推出的IOTC(Internet of Things Cloud 物联网云)平台。摄像头使用的是深圳市普顺达科技有限公司 http://www.easyn.cn/的硬件设备。

这两家公司的网页首页截图如下:

智能家居

智能家居

当我们的摄像头通上电并设置好网络后会自动连接到IOTC服务器。然后处于等待状态,等待接收来自App端发送的指令。App通过硬件设备的UID、用户名、密码登陆到IOTC服务器,然后发送指令。IOTC获取到App的指令后在转发给设备,然后设备将返回结果(可能是状态数据也可能是摄像机画面)在返回给IOTC,IOTC再将这些结果数据传给App。这样整个就实现了手机和摄像头的互联互动。在这整个过程中IOTC平台是核心部分,也可以看出智能家居其实拼的就是服务平台。

智能家居

代码实现

我们要做的案例效果图如下,总共有两个界面,第一个界面是登录界面,在文本框中输入名称、UID、密码,其中名称是我们自己给自己的摄像头设备起的名称,可以随意写。UID在设备上有,我们直接抄过来,是设备的唯一标识,不可以修改。密码是设备出厂时给了默认的,我们后期可以修改的。为了防止被黑客给黑掉,其实我们只要UID不外漏即可。

智能家居

编写布局文件 布局文件共两个,第一个登录界面的布局太简单了,就不给出来了。值给出第二个布局文件。

activity_camera.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <com.tutk.IOTC.Monitor
        android:id="@+id/monitor"
        android:layout_width="400dp"
        android:layout_height="320dp" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/tv_state"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="连接状态:" />
    </LinearLayout>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:gravity="bottom" >
        <View
            android:id="@+id/center"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:layout_centerInParent="true"
            android:layout_margin="20dp"
            android:background="#ff0000" />
        <ImageButton
            android:id="@+id/ib_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@id/center"
            android:background="@drawable/left"
            android:contentDescription="@null" />
        <ImageButton
            android:id="@+id/ib_right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@id/center"
            android:background="@drawable/right"
            android:contentDescription="@null" />
        <ImageButton
            android:id="@+id/ib_bottom"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/center"
            android:layout_centerHorizontal="true"
            android:background="@drawable/bottom"
            android:contentDescription="@null" />
        <ImageButton
            android:id="@+id/ib_top"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@id/center"
            android:layout_centerHorizontal="true"
            android:background="@drawable/top"
            android:contentDescription="@null" />
    </RelativeLayout>
</LinearLayout>

添加类库 如下图所示,考虑到类库的保密性在该文档中就不再给出下载地址。

智能家居

核心代码 总共有两个Activity,分别是MainActivity和CameraPlayActivity

MainActivity代码如下:

package com.example.smartcamera;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.google.testapp.R;

public class MainActivity extends ActionBarActivity {
    public static final String NAME = "name";
    public static final String PSW = "psw";
    public static final String UID = "uid";
    private EditText et_name;
    private EditText et_pwd;
    private EditText et_uid;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    /**
     * 初始化子控件
     */
    private void initView() {

        et_name = (EditText) findViewById(R.id.et_devname);
        et_pwd = (EditText) findViewById(R.id.et_psw);
        et_uid = (EditText) findViewById(R.id.et_uid);
    }
    /**
     * 点击Button 开始链接
     *
     * @param view
     */
    public void connect(View view) {
        String name = et_name.getText().toString();
        String pwd = et_pwd.getText().toString();
        String uid = et_uid.getText().toString();
        if (TextUtils.isEmpty(name) || TextUtils.isEmpty(pwd) ||
                TextUtils.isEmpty(uid)) {
            Toast.makeText(this, "数据不能为空。", Toast.LENGTH_SHORT).show();
            return;
        }
        Intent intent = new Intent(this, CameraPlayActivity.class);
        intent.putExtra(NAME, name);
        intent.putExtra(PSW, pwd);
        intent.putExtra(UID, uid);
        //跳转到播放页面
        startActivity(intent);
    }
}

CameraPlayActivity代码如下:

package com.example.smartcamera;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;

import com.google.testapp.R;
import com.tutk.IOTC.AVIOCTRLDEFs;
import com.tutk.IOTC.AVIOCTRLDEFs.SMsgAVIoctrlPtzCmd;
import com.tutk.IOTC.Camera;
import com.tutk.IOTC.IRegisterIOTCListener;
import com.tutk.IOTC.Monitor;

public class CameraPlayActivity extends Activity implements OnClickListener,
        IRegisterIOTCListener {
    private Monitor     monitor;
    private ImageButton ib_left;
    private ImageButton ib_right;
    private ImageButton ib_top;
    private ImageButton ib_bottom;
    private TextView    tv_state;
    private String      mName;
    private String      mPsw;
    private String      mUID;
    private Camera      mCamera;
    Handler handler = new Handler() {
        @Override
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                // 针对不同的连接状态做不同的处理
                case Camera.CONNECTION_STATE_CONNECT_FAILED:
                    tv_state.setText("连接失败");
                    break;
                // 如果是已经连接成功
                case Camera.CONNECTION_STATE_CONNECTED:
                    tv_state.setText("已连接");
                    // 调用play()方法,完成Camera 和Monitor 的绑定,最终将画面显示出来
                    play();
                    break;
                case Camera.CONNECTION_STATE_CONNECTING:
                    tv_state.setText("连接中...");
                    break;
                case Camera.CONNECTION_STATE_DISCONNECTED:
                    tv_state.setText("未连接");
                    break;
                case Camera.CONNECTION_STATE_TIMEOUT:
                    tv_state.setText("连接超时");
                    break;
                case Camera.CONNECTION_STATE_UNKNOWN_DEVICE:
                    tv_state.setText("未知设备");
                    break;
                case Camera.CONNECTION_STATE_UNSUPPORTED:
                    tv_state.setText("不支持的设备");
                    break;
                case Camera.CONNECTION_STATE_WRONG_PASSWORD:


                    tv_state.setText("密码不正确");
                    break;
                case Camera.CONNECTION_STATE_NONE:
                    tv_state.setText("未知错误");
                    break;
                default:
                    tv_state.setText("未知" + msg.what);
                    break;
            }
        }

        ;
    };

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        // 初始化控件
        initView();
        // 初始化数据
        initData();
        // 开始连接网络
        connectNet();
    }

    /**
     * 显示画面的核心方法
     */
    protected void play() {
        /**
         * 如果条件满足则<br>
         * 1 将界面monitor 和Camera 进行绑定<br>
         * 2 开始播放Camera 画面
         *
         */
        if (mCamera != null && mCamera.isChannelConnected(Camera.DEFAULT_AV_CHANNEL)) {
            monitor.attachCamera(mCamera, Camera.DEFAULT_AV_CHANNEL);
            mCamera.startShow(Camera.DEFAULT_AV_CHANNEL, true);
        }
    }

    private void connectNet() {
        // 初始化摄像头内部加载c 语言库
        Camera.init();
        // 新创建一个Camera 实例不是Android 中的Camera 而是com.tutk.IOTC.Camera.Camera
        mCamera = new Camera();
        /**
         * 给Camera 注册IOTC 监听<br>
         * IOTC Internet of Things Cloud 物联网云平台<br>
         * 该平台是台湾TUTK 公司推出,有偿使用,因此SDK 不开源
         */
        mCamera.registerIOTCListener(this);
        /**
         * 连接到IOTC 云平台<br>
         * 连接传入的是UID <br>
         * 每个硬件设备出厂时都有唯一的UID编号,并且出厂时已经将该编号注册到IOTC平台服务器<br>
         * 硬件在连接服务器的时候需要带着自己的身边标识(就是UID)
         */
        mCamera.connect(mUID);
        /**
         * 仅仅让硬件连接网络还是不够了,作为终端用户我们想看到云平台上的摄像头画面那么还需要用户
         * 通过用户名和密码登陆进行身份验证<br>
         *
         * @parameter Camera.DEFAULT_AV_CHANNEL
         * 我们可以把一个摄像头硬件理解为一个电视机,那么电视机可以有多个频道,这里我
         * 们使用默认频道即可
         * @parameter mName 用户名<br>
         * @parameter mPsw 密码<br>
         *
         * 当开始连接的时候,由于之前注册了Camera 监听,因此接收到的数据会以回调的形
         * 式传到形参中
         * ,因此这个时候我们就去IRegisterIOTCListener 的回调方法中等数据就行了
         */
        mCamera.start(Camera.DEFAULT_AV_CHANNEL, mName, mPsw);
    }

    /**
     * 从上一个Activity 中获取用户数据
     */
    private void initData() {
        Intent intent = getIntent();
        mName = intent.getStringExtra(MainActivity.NAME);
        mPsw = intent.getStringExtra(MainActivity.PSW);
        mUID = intent.getStringExtra(MainActivity.UID);
    }

    /**
     * 当前类已经实现了OnClickListener 接口因此绑定点击事件只需要传递this 即可
     */
    private void initView() {
        monitor = (Monitor) findViewById(R.id.monitor);
        ib_left = (ImageButton) findViewById(R.id.ib_left);
        ib_right = (ImageButton) findViewById(R.id.ib_right);
        ib_top = (ImageButton) findViewById(R.id.ib_top);
        ib_bottom = (ImageButton) findViewById(R.id.ib_bottom);

        tv_state = (TextView) findViewById(R.id.tv_state);
        // 初始化点击事件
        ib_bottom.setOnClickListener(this);
        ib_left.setOnClickListener(this);
        ib_right.setOnClickListener(this);
        ib_top.setOnClickListener(this);
    }

    /**
     * 上下左右点击事件的绑定
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.ib_left:
                /**
                 * 发送左移动画面指令<br>
                 * PTZ :在安防监控应用中是Pan/Tilt/Zoom 的简写,代表云台全方位(左右/上下)移
                 * 动及镜头变倍、变焦控制。<br>
                 * 因为上下左右都需要发送指令,因此我抽取出一个方法
                 */
                sendPTZ(AVIOCTRLDEFs.AVIOCTRL_PTZ_LEFT);
                break;
            case R.id.ib_right:
                sendPTZ(AVIOCTRLDEFs.AVIOCTRL_PTZ_RIGHT);
                break;
            case R.id.ib_bottom:
                sendPTZ(AVIOCTRLDEFs.AVIOCTRL_PTZ_DOWN);
                break;
            case R.id.ib_top:
                sendPTZ(AVIOCTRLDEFs.AVIOCTRL_PTZ_UP);
                break;
        }
    }

    ;

    /**
     * 发送移动指令
     */
    private void sendPTZ(int type) {
        /**
         * 给摄像头发送指令
         *
         * @parameter Camera.DEFAULT_AV_CHANNEL 默认频道
         * AVIOCTRLDEFs.IOTYPE_USER_IPCAM_PTZ_COMMAND 指令类型
         * SMsgAVIoctrlPtzCmd.parseContent((byte) type, (byte) 0,
         * (byte) 0, (byte) 0, (byte) 0, (byte)
         * Camera.DEFAULT_AV_CHANNEL)

         * 指令数据,第三个参数是字节数组我们直接使用SMsgAVIoctrlPtzCmd 类的
         * parseContent 方法生成即可
         *
         */
        mCamera.sendIOCtrl(Camera.DEFAULT_AV_CHANNEL,
                AVIOCTRLDEFs.IOTYPE_USER_IPCAM_PTZ_COMMAND, SMsgAVIoctrlPtzCmd.parseContent((byte
                        ) type, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) Camera
                        .DEFAULT_AV_CHANNEL));
    }

    // 销毁时退出摄像头
    @Override
    protected void onDestroy() {
        super.onDestroy();
        quit();
    }

    /**
     * 当接收到服务器的数据时回调该函数
     *
     * @param resultCode 返回状态码
     */
    @Override
    public void receiveChannelInfo(Camera arg0, int channel, int resultCode) {
        Message msg = Message.obtain();
        msg.what = resultCode;
        handler.sendMessage(msg);
    }

    @Override
    public void receiveFrameData(Camera arg0, int arg1, Bitmap arg2) {
    }

    @Override
    public void receiveFrameInfo(Camera arg0, int arg1, long arg2, int arg3, int arg4,
                                 int arg5, int arg6) {

    }

    @Override
    public void receiveIOCtrlData(Camera arg0, int arg1, int arg2, byte[] arg3) {
    }

    @Override
    public void receiveSessionInfo(Camera arg0, int arg1) {
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();


        quit();
    }

    /**
     * 断开连接
     */
    private void quit() {
        if (monitor != null) {
            // 1.解除绑定
            monitor.deattachCamera();
            // 2.停止显示
            mCamera.stopShow(Camera.DEFAULT_AV_CHANNEL);
            // 3.断开连接
            // 3.1 取消渠道号
            mCamera.stop(Camera.DEFAULT_AV_CHANNEL);
            // 3.2 断开连接
            mCamera.disconnect();
            // 4.注销监听
            mCamera.unregisterIOTCListener(this);
        }
    }
}

添加访问网络权限 因为我们的App是访问网络的,当然得记得添加权限

<uses-permission android:name="android.permission.INTERNET"/>

智能继电器

智能继电器目前多用于控制家庭电器的断电与通电。智能继电器跟普通继电器的不同之处就是上面内置了蓝牙芯片,该蓝牙芯片允许手机蓝牙进行连接,然后接收手机蓝牙发送的指令,根据不同的指令打开或者关闭开关,从而间接实现控制家用电器的功能。

准备工作

1、智能继电器

从网上购买了蓝牙继电器。产品详情链接(可能有做广告嫌疑):https://detail.tmall.com/item.htm?id=44157073788&spm=a1z09.2.9.133.cmtDUE&_u=2am3rd62f16

2、灯泡组 电池 电线 螺丝刀工具等

该继电器是针对220v居民用电设计的,但是我们是实验的用途因此用3v的电池即可,灯泡就是用发光二极管即可,这样保证了绝对的安全。

3、发光二极管详情:https://detail.tmall.com/item.htm?id=17637399755&spm=a1z09.2.9.100.cmtDUE&_u=2am3rd662b0

4、不需要开发SDK,只需要知道继电器蓝牙的指令集即可,在购买的界面商家提供了所有的指令集

工作原理

手机搜索到继电器的蓝牙,然后通过蓝牙的配对密码连接上继电器,继电器就是开关,只不过这里用的是继电器上有多个开关组,手机通过蓝牙给继电器发送指令,继电器把指令解析成相应的开或者关的动作,这样就实现了手机控制电器的操作。我自己做成以后的真实图如下。中间方形的是蓝牙继电器,右侧是发光二极管,二极管使用干电池供电。手机通过软件控制灯泡的开和关。

智能家居

代码实现

软件总共有2个界面,运行效果图如下所示。
第一个界面用于查找周围的蓝牙设备。将找到的蓝牙用ListView显示出来,然后点击智能继电器对应的蓝牙设备,进入第二个界面,在第二个界面完成对智能继电器的多种操作。

智能家居

activity_main.xml对应第一个界面:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
        <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:onClick="checkBluetooth"
            android:text="监测蓝牙设备" />
        <Button
            android:id="@+id/btn_scan"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:onClick="scanBluetooth"
            android:text="扫描蓝牙" />
    </LinearLayout>
    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >
    </ListView>
</LinearLayout>

activity_control.xml对应第二个界面

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn_kaiguan1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="开关1"/>

        <Button
            android:id="@+id/btn_kaiguan2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="开关2"/>

        <Button
            android:id="@+id/btn_kaiguan3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="开关3"/>

        <Button
            android:id="@+id/btn_kaiguan4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="开关4"/>

        <Button
            android:id="@+id/btn_kaiguan5"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="开关5"/>

        <Button
            android:id="@+id/btn_kaiguanAll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="全部"/>

        <Button
            android:id="@+id/btn_kaiguan5_diandong"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="开关5 点动1s"/>

        <Button
            android:id="@+id/btn_kaiguan5_husuo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="开关5 互锁"/>

        <Button
            android:id="@+id/btn_kaiguan5_zisuo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="开关5 自锁"/>
    </LinearLayout>
</ScrollView>

MainActivity.java是入口Activity

package com.example.bluetoothtest;

import android.support.v7.app.ActionBarActivity;

package com.example.bluetoothtest;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

import com.google.testapp.R;

import java.util.ArrayList;

public class MainActivity extends ActionBarActivity {
    private static final String BTN_SCANING       = "正在扫描蓝牙设备...";
    private static final String BTN_SCAN          = "扫描蓝牙设备";
    private static final int    REQUEST_ENABLE_BT = 1;
    private BluetoothAdapter mBluetoothAdapter;
    private ArrayList<String> mArrayAdapter = new ArrayList<>();
    private Button btn_scan;
    private ArrayList<BluetoothDevice> devices = new ArrayList<>();
    private ListView             mListView;
    private ArrayAdapter<String> mAdapter;
    // Create a BroadcastReceiver for ACTION_FOUND
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device =
                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // Add the name and address to an array adapter to show in a ListView
                mArrayAdapter.add(device.getName() + "\\n" + device.getAddress());
                devices.add(device);
                mAdapter.notifyDataSetChanged();
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        mListView = (ListView) findViewById(R.id.lv);
        mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
                mArrayAdapter);
        mListView.setAdapter(mAdapter);
        mListView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position,
                                    long id) {
                Intent intent = new Intent(MainActivity.this,
                        ControlActivity.class);
                intent.putExtra("device", devices.get(position));
                mBluetoothAdapter.cancelDiscovery();
                btn_scan.setText(BTN_SCAN);
                startActivity(intent);
            }
        });
        btn_scan = (Button) findViewById(R.id.btn_scan);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    }

    /**
     * 监测蓝牙是否开启,如果没有开,请求打开
     *
     * @param view
     */
    public void checkBluetooth(View view) {

        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "对不起,您的设备不支持蓝牙。", 0).show();
            return;
        }
        //监测蓝牙是否可用
        boolean enabled = mBluetoothAdapter.isEnabled();
        if (!enabled) {
            Intent enableBtIntent = new
                    Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            return;
        }
        //查询已经配对的蓝牙
        queryingPairedDevices();
    }

    private void queryingPairedDevices() {
        mArrayAdapter.clear();
        devices = new ArrayList(mBluetoothAdapter.getBonde

以上是关于智能家居的主要内容,如果未能解决你的问题,请参考以下文章

html 智能菜单简单片段

AI智能剪辑,仅需2秒一键提取精彩片段

SQL Prompt7.2下载及破解教程

快速剪辑-助力度咔智能剪辑提效实践

C++ - 指针和“智能指针”

SnippetsLab for Mac 1.9 中文共享版 – 强大的代码收藏管理工具