准备
在科大讯飞官网下载Android MSC(SDK)
在下载好的SDK中把libs内的文件复制到工程的libs目录下
右键libs中的jar包,选择add as library
将SDK中的assets复制到main目录下
固件
代码
esp8266(micropython)
from machine import Pin
import dht,time,network
from socket import *
global wendu,shidu
#初始化相关模块
led = Pin(2,Pin.OUT,value=1)#灯
#创建DTH11对象
d = dht.DHT11(Pin(5)) #传感器连接到引脚14
time.sleep(1) #首次+启动停顿1秒让传感器稳定
def WIFI_Connect():
wlan = network.WLAN(network.STA_IF) #STA模式
wlan.active(True) #激活接口
#配置单片机ip 掩码等
start_time=time.time() #记录时间做超时判断
if not wlan.isconnected():
wlan.connect('wifi名字', 'wifi密码') #WIFI账号密码
while not wlan.isconnected():
#超时判断,15秒没连接成功判定为超时
if time.time()-start_time > 50 :
print('WIFI Connected Timeout!')
break
if wlan.isconnected():
#串口打印信息
print('network information:', wlan.ifconfig())
return True
else:
return False
def dht_get():
d.measure() #温湿度采集
wendu = d.temperature()
shidu = d.humidity()
HOST = '' # 主机号为空白表示可以使用任何可用的地址。
PORT = 8998 # 端口号
BUFSIZ = 1024 # 接收数据缓冲大小
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM) # 创建TCP服务器套接字
tcpSerSock.bind(ADDR) # 套接字与地址绑定
tcpSerSock.listen(5) # 监听连接,同时连接请求的最大数目
while True:
print('等待客户端的连接...')
tcpCliSock, addr = tcpSerSock.accept() # 接收客户端连接请求
print('取得连接:', addr)
while True:
data = tcpCliSock.recv(BUFSIZ) # 连续接收指定字节的数据,接收到的是字节数组
if not data: # 如果数据空白,则表示客户端退出,所以退出接收
break
tcpCliSock.send(('温度为%s湿度为%s'%(wendu,shidu)).encode())
#发送消息
print(data.decode().strip())
#接收到的消息
if(data.decode().strip() == 'on'):
led.value(0)
elif(data.decode().strip() == 'off'):
led.value(1)
tcpCliSock.close() # 关闭与客户端的连接
tcpSerSock.close() # 关闭服务器socket
if WIFI_Connect():
dht_get()
Android Studio
MainActivity.java
package com.example.esp8266;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.EditText;
import com.google.gson.Gson;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private Socket socke;
private PrintWriter pw;
private String data;
private String Recognition_txt;
//所需申请的权限
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.INTERNET,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.CHANGE_NETWORK_STATE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA
};
public static class AudioUtils {
private static AudioUtils audioUtils;
private SpeechSynthesizer mySynthesizer;
public AudioUtils(){
}
public static AudioUtils getInstance() {
if (audioUtils == null) {
synchronized (AudioUtils.class) {
if (audioUtils == null) {
audioUtils = new AudioUtils();
}
}
}
return audioUtils;
}
private InitListener myInitListener = new InitListener() { @Override public void onInit(int code) { } };
public void init(Context context) {
mySynthesizer = SpeechSynthesizer.createSynthesizer(context, myInitListener);
mySynthesizer.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");
//发音人xiaoyan
mySynthesizer.setParameter(SpeechConstant.SPEED,"50");
//语速50
mySynthesizer.setParameter(SpeechConstant.PITCH, "50");
//语调50
mySynthesizer.setParameter(SpeechConstant.VOLUME, "100");
//音量100
}
public void speakText(String content){
int code =mySynthesizer.startSpeaking(content,new SynthesizerListener(){
@Override
public void onSpeakBegin() {
}
@Override
public void onBufferProgress(int i, int i1, int i2, String s) {
}
@Override
public void onSpeakPaused() {
}
@Override
public void onSpeakResumed() {
}
@Override
public void onSpeakProgress(int i, int i1, int i2) {
}
@Override
public void onCompleted(SpeechError speechError) {
}
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
});
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
applypermission();
// 将“xxxxxx”替换成您申请的APPID,申请地址:http://www.xfyun.cn
// 请勿在“=”与appid之间添加任何空字符或者转义符
SpeechUtility.createUtility(this, SpeechConstant.APPID +"=xxxxxx");
final Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if(msg.what==1){
}
}
};
new Thread(
new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Socket sk = null;
while(true) {
try {
// 读Sock里面的数据
InputStream s = socke.getInputStream();
byte[] buf = new byte[1024];
int len = 0;
while ((len = s.read(buf)) != -1) {
data = new String(buf, 0, len);
handler.sendEmptyMessage(1);
}
Thread.sleep(1000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
//建立socket连接
Thread connection = new Thread(new Runnable() {
@Override
public void run() {
final EditText editext1 = (EditText) findViewById(R.id.edittext1);
final EditText editext2 = (EditText) findViewById(R.id.edittext2);
try {
socke = new Socket(editext1.getText().toString(),Integer.valueOf(editext2.getText().toString()));
pw = new PrintWriter(socke.getOutputStream(),true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
public void run(View view){
connection.start();
}
//定义判断权限申请的函数,在onCreat中调用就行
public void applypermission(){
if(Build.VERSION.SDK_INT>=23){
boolean needapply=false;
for(int i=0;i<PERMISSIONS_STORAGE.length;i++){
int chechpermission= ContextCompat.checkSelfPermission(getApplicationContext(),
PERMISSIONS_STORAGE[i]);
if(chechpermission!= PackageManager.PERMISSION_GRANTED){
needapply=true;
}
}
if(needapply){
ActivityCompat.requestPermissions(MainActivity.this,PERMISSIONS_STORAGE,1);
}
}
}
public class Recognition{
/**
*@TODO 科大讯飞语音听写
* linowl 2020.09.11
*/
public void initSpeech(final Context context) {
//1.创建RecognizerDialog对象
RecognizerDialog mDialog = new RecognizerDialog(context, null);
//识别器定义
//2.设置accent、language等参数
mDialog.setParameter(SpeechConstant.DOMAIN,"iat");
//应用领域 iat:日常用语 medical:医疗
mDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
//语言 zh_cn:中文 en_us:英文 ja_jp:日语 ko_kr:韩语 ru-ru:俄语 fr_fr:法语 es_es:西班牙语
mDialog.setParameter(SpeechConstant.ACCENT, "mandarin");
//方言 默认mandarin
//3.设置回调接口
mDialog.setListener(new RecognizerDialogListener() {
@Override
public void onResult(RecognizerResult recognizerResult, boolean isLast) {
if (!isLast) {
//解析语音
String result = parseVoice(recognizerResult.getResultString());
voiceif(result);
}
}
@Override
public void onError(SpeechError speechError) {
}
});
//4.显示dialog,接收语音输入
mDialog.show();
}
}
/**
* 解析语音json
*/
public String parseVoice(String resultString) {
Gson gson = new Gson();
Voice voiceBean = gson.fromJson(resultString, Voice.class);
StringBuffer sb = new StringBuffer();
ArrayList<Voice.WSBean> ws = voiceBean.ws;
for (Voice.WSBean wsBean : ws) {
String word = wsBean.cw.get(0).w;
sb.append(word);
}
return sb.toString();
}
/**
* 语音实体类
*/
public class Voice {
public ArrayList<WSBean> ws;
public class WSBean {
public ArrayList<CWBean> cw;
}
public class CWBean {
public String w;
}
}
//调用use类的initSpeech函数
public void Recognition(View view){
new Recognition().initSpeech(this);
}
public void send_msg(String send_txt){
pw.println(send_txt);
}
public void voiceif(String speek_txt){//在服务器读取esp8266的数据
if (speek_txt.equals("当前状态")){//判断语音识别的信息
try {
AudioUtils.getInstance().init(this); //初始化语音对象
AudioUtils.getInstance().speakText(data); //播放语音
}catch (Exception e){
e.printStackTrace();
}
}else if(speek_txt.equals("开灯")){
new Thread(new Runnable() {
@Override
public void run() {
send_msg("on");
}
}).start();
}else if(speek_txt.equals("关灯")){
new Thread(new Runnable() {
@Override
public void run() {
send_msg("off");
}
}).start();
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/edittext1"
android:layout_width="210dp"
android:layout_height="40dp"
android:layout_marginTop="28dp"
android:hint="IP地址"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/edittext2"
android:layout_width="210dp"
android:layout_height="40dp"
android:layout_marginTop="20dp"
android:hint="端口号"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edittext1" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:onClick="run"
android:text="连接"
app:layout_constraintEnd_toEndOf="@+id/edittext2"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="@+id/edittext2"
app:layout_constraintTop_toBottomOf="@+id/edittext2" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="Recognition"
android:text="识别"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />
</androidx.constraintlayout.widget.ConstraintLayout>
在AndroidManifest.xml添加权限
<!--连接网络权限,用于执行云端语音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--获取当前wifi状态 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允许程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--读取联系人权限,上传联系人需要用到此权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--外存储写权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外存储读权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务-->
<!--定位信息是敏感信息,可通过Setting.setLocationEnable(false)关闭定位请求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--如需使用人脸识别,还要添加:摄相头权限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />
build.gradle
注意