毕业设计,基于语音控制的智能家居控制系统

基于语音控制的智能家居控制系统(安卓,蓝牙,语音控制,单片机)

上位机是安卓机,下位机是51,上位机(语音识别出指令如开关灯)与下位机(接蓝牙模块BLE:CC2451)通过蓝牙通信进行控制。
初步设想是语音识别部分用科大讯飞的sdk,然后再找个开源的蓝牙通信Demo来进行二次开发,无奈本人小白,无安卓开发经验,java零基础,虽然论坛上有很多现成的蓝牙控制单片机的例子,但是好像没有语音识别这一部分的,做得很难受。

以下贴出我的进展图、App闪退错误代码,以及半成品Demo(只实现了语音识别部分),希望有大牛指导一下。

开发环境:Android Studio 2.1.3
Gradle版本:com.android.tools.build:gradle:2.1.3
SDK版本:android-sdk_r24.4.1-windows
JDK版本:jdk1.8.0_201
Compile Sdk Version:API 25
Build Tools Version:28.0.3
半成品Demo:(https://download.csdn.net/download/qq_40093925/10975515)

**

AndroidManifest.xml

**




    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
     
    
    
    
    


    
        
            
                

                
            
        
        
    


MainActivitiy.java

package com.example.luoyn.speechdemo;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Environment;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Handler;

import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.UUID;



public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    //显示听写结果
    private TextView textView;

    //语音听写对象
    private SpeechRecognizer speechRecognizer;

    //语音听写UI
    private RecognizerDialog recognizerDialog;

    //是否显示听写UI
    private boolean isShowDialog = true;

    //缓存
    private SharedPreferences sharedPreferences;

    //用hashmap存储听写结果
    private HashMap hashMap = new LinkedHashMap();

    //引擎类型(云端或本地)
    private String mEngineType = null;

    //函数返回值
    private int ret = 0;

    private Toast toast;


    //插入部分--------------------------------------------------------------------------------------
    public static final int REQUEST_BT_ENABLE_CODE = 200;
    public static final String BT_UUID = "00001101-0000-1000-8000-00805F9B34FB";//YahBoom_uuid

    private BluetoothAdapter mBluetoothAdapter;//蓝牙适配器
    private BlueToothStateReceiver mReceiver;//广播接收器
    private ConnectThread mConnectThread; //客户端线程
    private AcceptThread mAcceptThread; //服务端线程

    private RecyclerView mRecyclerView;
    private RvAdapter mRvAdapter;

    private RecyclerView mMessageView;
    private static MsgAdapter mMessageAdapter;

    private EditText inputEt;

    private static Handler mHandler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {
            mMessageAdapter.addMessage((String) msg.obj);
        }
    };
    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient client;
    //----------------------------------------------------------------------------------------------

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initDate();
        //插入部分--------------------------------------------------------------------------------------
        initUI();
        registerRec();
        //------------------------------------------------------------------------------------------
        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
    }

    private void initDate() {
        //初始化sdk 将自己申请的appid放到下面
        //此句代码应该放在application中的,这里为了方便就直接放代码中了
        SpeechUtility.createUtility(this, "appid=5c6abcfc");
        speechRecognizer = SpeechRecognizer.createRecognizer(this, initListener);
        recognizerDialog = new RecognizerDialog(this, initListener);
        sharedPreferences = getSharedPreferences(this.getPackageName(), Context.MODE_PRIVATE);
        toast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
        //这里我直接将引擎类型设置为云端,因为本地需要下载讯飞语记,这里为了方便直接使用云端
        //有需要的朋友可以加个单选框 让用户选择云端或本地
        mEngineType = SpeechConstant.TYPE_CLOUD;
    }

    private void initView() {
        textView = (TextView) findViewById(R.id.tv);
    }

    //插入部分--------------------------------------------------------------------------------------
    private void initUI() {
        findViewById(R.id.open).setOnClickListener(this);
        findViewById(R.id.close).setOnClickListener(this);
        findViewById(R.id.start).setOnClickListener(this);
        findViewById(R.id.stop).setOnClickListener(this);
        findViewById(R.id.send).setOnClickListener(this);

        inputEt = (EditText) findViewById(R.id.input);

        mRecyclerView = (RecyclerView) findViewById(R.id.devices);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRvAdapter = new RvAdapter(this);
        mRecyclerView.setAdapter(mRvAdapter);
        mRvAdapter.setOnItemClickListener(new RvAdapter.OnItemClickListener() {
            @Override
            public void onClick(BluetoothDevice device) {
                mConnectThread = new ConnectThread(device);
                mConnectThread.start();
            }
        });

        mMessageView = (RecyclerView) findViewById(R.id.msglist);
        mMessageView.setLayoutManager(new LinearLayoutManager(this));
        mMessageAdapter = new MsgAdapter(this);
        mMessageView.setAdapter(mMessageAdapter);
    }

    private void openBT() {
        if (mBluetoothAdapter == null) {
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        }
        //1.设备不支持蓝牙,结束应用
        if (mBluetoothAdapter == null) {
            finish();
            return;
        }
        //2.判断蓝牙是否打开
        if (!mBluetoothAdapter.enable()) {
            //没打开请求打开
            Intent btEnable = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(btEnable, REQUEST_BT_ENABLE_CODE);
        }
    }

    private void registerRec() {
        //3.注册蓝牙广播
        mReceiver = new BlueToothStateReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_FOUND);//搜多到蓝牙
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索结束
        registerReceiver(mReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
        }
        super.onDestroy();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_BT_ENABLE_CODE) {
            if (resultCode == RESULT_OK) {
                //用户允许打开蓝牙
                mMessageAdapter.addMessage("用户同意打开蓝牙");
            } else if (resultCode == RESULT_CANCELED) {
                //用户取消打开蓝牙
                mMessageAdapter.addMessage("用户拒绝打开蓝牙");
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.open:
                openBT();
                mMessageAdapter.addMessage("打开蓝牙");
                if (mAcceptThread == null && mBluetoothAdapter != null) {
                    mAcceptThread = new AcceptThread();
                    mAcceptThread.start();
                    mMessageAdapter.addMessage("启动服务线程");
                }
                break;
            case R.id.close:
                mBluetoothAdapter.disable();
                break;
            case R.id.start:
                if (mBluetoothAdapter != null) {
                    mRvAdapter.clearDevices();//开始搜索前清空上一次的列表
                    mBluetoothAdapter.startDiscovery();
                    mMessageAdapter.addMessage("开始搜索蓝牙");
                } else {
                    openBT();
                    if (mBluetoothAdapter != null) {
                        mRvAdapter.clearDevices();//开始搜索前清空上一次的列表
                        mBluetoothAdapter.startDiscovery();
                        mMessageAdapter.addMessage("开始搜索蓝牙");
                    }
                }
                break;
            case R.id.stop:
                if (mBluetoothAdapter != null && mBluetoothAdapter.isDiscovering()) {
                    mBluetoothAdapter.cancelDiscovery();
                }
                break;
            case R.id.send:
                String msg = inputEt.getText().toString();
                if (TextUtils.isEmpty(msg)) {
                    Toast.makeText(this, "消息为空", Toast.LENGTH_SHORT).show();
                    return;
                }
                if (mConnectThread != null) {//证明我主动去链接别人了
                    mConnectThread.write(msg);
                } else if (mAcceptThread != null) {
                    mAcceptThread.write(msg);
                }
                mMessageAdapter.addMessage("发送消息:" + msg);
                break;
        }
    }

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

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client.connect();
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://host/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://com.example.luoyn.speechdemo/http/host/path")
        );
        AppIndex.AppIndexApi.start(client, viewAction);
    }

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

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://host/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://com.example.luoyn.speechdemo/http/host/path")
        );
        AppIndex.AppIndexApi.end(client, viewAction);
        client.disconnect();
    }

    class BlueToothStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(MainActivity.this, "触发广播", Toast.LENGTH_SHORT).show();
            String action = intent.getAction();
            switch (action) {
                case BluetoothDevice.ACTION_FOUND:
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    Toast.makeText(MainActivity.this, "找到设备" + device.getName(), Toast.LENGTH_SHORT).show();
                    if (mRvAdapter != null) {
                        mRvAdapter.addDevice(device);
                    }
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    mMessageAdapter.addMessage("搜索结束");
                    break;
            }
        }
    }


    class ConnectThread extends Thread {
        private BluetoothDevice mDevice;
        private BluetoothSocket mSocket;
        private InputStream btIs;
        private OutputStream btOs;
        private boolean canRecv;
        private PrintWriter writer;

        public ConnectThread(BluetoothDevice device) {
            mDevice = device;
            canRecv = true;
        }

        @Override
        public void run() {
            if (mDevice != null) {
                try {
                    //获取套接字
                    BluetoothSocket temp = mDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString(BT_UUID));
                    //mDevice.createRfcommSocketToServiceRecord(UUID.fromString(BT_UUID));//sdk 2.3以下使用
                    mSocket = temp;
                    //发起连接请求
                    if (mSocket != null) {
                        mSocket.connect();
                    }
                    sendHandlerMsg("连接 " + mDevice.getName() + "成功!");
                    //获取输入输出流
                    btIs = mSocket.getInputStream();
                    btOs = mSocket.getOutputStream();

                    //通讯-接收消息
                    BufferedReader reader = new BufferedReader(new InputStreamReader(btIs, "UTF-8"));
                    String content = null;
                    while (canRecv) {
                        content = reader.readLine();
                        sendHandlerMsg("收到消息:" + content);
                    }


                } catch (IOException e) {
                    e.printStackTrace();
                    sendHandlerMsg("错误:" + e.getMessage());
                } finally {
                    try {
                        if (mSocket != null) {
                            mSocket.close();
                        }
                        //btIs.close();//两个输出流都依赖socket,关闭socket即可
                        //btOs.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        sendHandlerMsg("错误:" + e.getMessage());
                    }
                }
            }
        }

        private void sendHandlerMsg(String content) {
            Message msg = mHandler.obtainMessage();
            msg.what = 1001;
            msg.obj = content;
            mHandler.sendMessage(msg);
        }

        public void write(String msg) {
            if (btOs != null) {
                try {
                    if (writer == null) {
                        writer = new PrintWriter(new OutputStreamWriter(btOs, "UTF-8"), true);
                    }
                    writer.println(msg);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    writer.close();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }
    }

    class AcceptThread extends Thread {
        private BluetoothServerSocket mServerSocket;
        private BluetoothSocket mSocket;
        private InputStream btIs;
        private OutputStream btOs;
        private PrintWriter writer;
        private boolean canAccept;
        private boolean canRecv;

        public AcceptThread() {
            canAccept = true;
            canRecv = true;
        }

        @Override
        public void run() {
            try {
                //获取套接字
                BluetoothServerSocket temp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("TEST", UUID.fromString(BT_UUID));
                mServerSocket = temp;
                //监听连接请求 -- 作为测试,只允许连接一个设备
                if (mServerSocket != null) {
                    // while (canAccept) {
                    mSocket = mServerSocket.accept();
                    sendHandlerMsg("有客户端连接");
                    // }
                }
                //获取输入输出流
                btIs = mSocket.getInputStream();
                btOs = mSocket.getOutputStream();
                //通讯-接收消息
                BufferedReader reader = new BufferedReader(new InputStreamReader(btIs, "UTF-8"));
                String content = null;
                while (canRecv) {
                    content = reader.readLine();
                    sendHandlerMsg("收到消息:" + content);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (mSocket != null) {
                        mSocket.close();
                    }
                    // btIs.close();//两个输出流都依赖socket,关闭socket即可
                    // btOs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }

        private void sendHandlerMsg(String content) {
            Message msg = mHandler.obtainMessage();
            msg.what = 1001;
            msg.obj = content;
            mHandler.sendMessage(msg);
        }

        public void write(String msg) {
            if (btOs != null) {
                try {
                    if (writer == null) {
                        writer = new PrintWriter(new OutputStreamWriter(btOs, "UTF-8"), true);
                    }
                    writer.println(msg);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    writer.close();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }
    }

    //----------------------------------------------------------------------------------------------


    //开始听写
    public void start(View view) {
        textView.setText("");
        hashMap.clear();
        setParams();

        if (isShowDialog) {
            recognizerDialog.setListener(dialogListener);
            recognizerDialog.show();
        } else {
            ret = speechRecognizer.startListening(recognizerListener);
            if (ret != ErrorCode.SUCCESS) {
                Log.e("tag", "听写失败,错误码" + ret);
            }
        }

    }

    //结束听写
    public void stop(View view) {
        Toast.makeText(this, "停止听写", Toast.LENGTH_SHORT).show();
        if (isShowDialog) {
            recognizerDialog.dismiss();
        } else {
            speechRecognizer.stopListening();
        }
    }

    //初始化监听器
    private InitListener initListener = new InitListener() {
        @Override
        public void onInit(int i) {
            if (i != ErrorCode.SUCCESS) {
                Log.e("tag", "初始化失败,错误码" + i);
            }
        }
    };

    //无UI监听器
    private RecognizerListener recognizerListener = new RecognizerListener() {
        @Override
        public void onVolumeChanged(final int i, byte[] bytes) {
            Log.e("tag", "返回数据大小" + bytes.length);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    toast.setText("当前音量" + i);
                }
            });
        }

        @Override
        public void onBeginOfSpeech() {
            Log.e("tag", "开始说话");
        }

        @Override
        public void onEndOfSpeech() {
            Log.e("tag", "结束说话");
        }

        @Override
        public void onResult(RecognizerResult recognizerResult, boolean b) {
            if (recognizerResult != null) {
                Log.e("tag", "听写结果:" + recognizerResult.getResultString());
                printResult(recognizerResult);

            }

        }

        @Override
        public void onError(SpeechError speechError) {
            Log.e("tag", "错误信息" + speechError.getPlainDescription(true));

        }

        @Override
        public void onEvent(int i, int i1, int i2, Bundle bundle) {
            // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            // 若使用本地能力,会话id为null
            //  if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //      String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //      Log.d(TAG, "session id =" + sid);
            //  }
        }
    };

    //有UI监听器
    private RecognizerDialogListener dialogListener = new RecognizerDialogListener() {
        @Override
        public void onResult(RecognizerResult recognizerResult, boolean b) {
            if (recognizerResult != null) {
                Log.e("tag", "听写结果:" + recognizerResult.getResultString());
                printResult(recognizerResult);

            }
        }

        @Override
        public void onError(SpeechError speechError) {
            Log.e("tag", speechError.getPlainDescription(true));

        }
    };

    //输出结果,将返回的json字段解析并在textVie中显示
    private void printResult(RecognizerResult results) {
        String text = JsonParser.parseIatResult(results.getResultString());

        String sn = null;
        // 读取json结果中的sn字段
        try {
            JSONObject resultJson = new JSONObject(results.getResultString());
            sn = resultJson.optString("sn");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        hashMap.put(sn, text);

        StringBuffer resultBuffer = new StringBuffer();
        for (String key : hashMap.keySet()) {
            resultBuffer.append(hashMap.get(key));
        }

        textView.setText(resultBuffer.toString());
    }

    private void setParams() {
        //清空参数
        speechRecognizer.setParameter(SpeechConstant.PARAMS, null);
        //设置引擎
        speechRecognizer.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        //设置返回数据类型
        speechRecognizer.setParameter(SpeechConstant.RESULT_TYPE, "json");
        //设置中文 普通话
        speechRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        speechRecognizer.setParameter(SpeechConstant.ACCENT, "mandarin");

        // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
        speechRecognizer.setParameter(SpeechConstant.VAD_BOS,
                sharedPreferences.getString("iat_vadbos_preference", "4000"));

        // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
        speechRecognizer.setParameter(SpeechConstant.VAD_EOS,
                sharedPreferences.getString("iat_vadeos_preference", "1000"));

        // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        speechRecognizer.setParameter(SpeechConstant.ASR_PTT,
                sharedPreferences.getString("iat_punc_preference", "0"));

        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
        speechRecognizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        speechRecognizer.setParameter(SpeechConstant.ASR_AUDIO_PATH,
                Environment.getExternalStorageDirectory() + "/msc/iat.wav");

    }
}


activity_main.xml




    

    

        

毕业设计,基于语音控制的智能家居控制系统_第1张图片
毕业设计,基于语音控制的智能家居控制系统_第2张图片
毕业设计,基于语音控制的智能家居控制系统_第3张图片

App闪退错误日志logcat

毕业设计,基于语音控制的智能家居控制系统_第4张图片

毕业设计,基于语音控制的智能家居控制系统_第5张图片

你可能感兴趣的:(学习)