关于ESP8266-NodeMCU和onenet通信传输学习总结(三)
一、前篇概述
很久没更新了,原因在于物流快递太慢和重温Android开发知识去了,想着脱离onenet平台 写自己的app使用,这里要先感谢下各位大佬的开发经验和教学分享。前面两节,我用esp8266nodemcu实现了onenet平台的连接和数据点上传下发指令,然后还接入了byj-48电机的操作,实现了一些基础通信控制。
整体构建:
时隔多日,到今天终于实现了Android app的开发使用和天猫精灵的语音接入控制,其中有很多槽点和想法,文末再提,下面开始正文:
二、基于之前的设计开发Android app
app我采用android studio 进行开发,这里要感谢一下b站博主阿正的教学分享!这里用多线程分别处理界面显示和数据处理,大致过程如下:
Android数据处理:
1、xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<LinearLayout
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="250dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="match_parent">
<ImageView
android:layout_width="80dp"
android:id="@+id/image_temperture"
android:layout_gravity="left"
android:src="@drawable/temperture"
android:layout_height="wrap_content">
</ImageView>
<TextView
android:id="@+id/text_temperture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="60sp"
android:text="暂无数据">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="match_parent">
<ImageView
android:layout_width="80dp"
android:id="@+id/image_5"
android:layout_gravity="left"
android:src="@drawable/bright"
android:layout_height="wrap_content">
</ImageView>
<TextView
android:id="@+id/text_bright"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="60sp"
android:text="暂无数据">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="match_parent">
<ImageView
android:layout_width="80dp"
android:id="@+id/image_7"
android:layout_gravity="left"
android:src="@drawable/door_lock"
android:layout_height="wrap_content">
</ImageView>
<TextView
android:id="@+id/text_doorLock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="60sp"
android:text="暂无数据">
</TextView>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_marginTop="5dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="80dp"
android:id="@+id/light_control"
android:layout_gravity="center_horizontal"
android:src="@drawable/open"
android:layout_height="80dp">
</ImageView>
<TextView
android:layout_width="wrap_content"
android:text="灯"
android:textSize="20sp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="80dp"
android:src="@drawable/lock"
android:layout_gravity="center_horizontal"
android:id="@+id/door_control"
android:layout_height="80dp">
</ImageView>
<TextView
android:layout_width="wrap_content"
android:text="门禁"
android:textSize="20sp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="80dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/air_control"
android:id="@+id/air_control"
android:layout_height="80dp">
</ImageView>
<TextView
android:layout_width="wrap_content"
android:text="空调"
android:textSize="20sp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_marginTop="20dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="80dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/curtain"
android:id="@+id/curtain_control"
android:layout_height="80dp">
</ImageView>
<TextView
android:layout_width="wrap_content"
android:text="窗帘"
android:textSize="20sp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="80dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/tv"
android:id="@+id/tv_control"
android:layout_height="80dp">
</ImageView>
<TextView
android:layout_width="wrap_content"
android:text="电视"
android:textSize="20sp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="80dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/water_heater"
android:id="@+id/water_control"
android:layout_height="80dp">
</ImageView>
<TextView
android:layout_width="wrap_content"
android:text="热水器"
android:textSize="20sp" android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
显示效果:
2、AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.admin.mqtt">
<!--允许程序打开网络套接字-->
<uses-permission android:name="android.permission.INTERNET" />
<!--允许程序获取网络状态-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/home"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
3、MainActivity.java
package com.example.admin.mqtt;
import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
protected String host = "tcp://183.230.40.39:6002";
protected String userName = "396066";
protected String passWord = "tx6WM==zmW21Z2pt4susBRlHMuY=";
protected String mqtt_id = "671460025"; //
protected String mqtt_sub_topic = "getMessage"; //
protected String mqtt_pub_topic = "sendMessage"; //
protected int led_flag =1;
protected int door_flag =1;
protected ScheduledExecutorService scheduler;
private ImageView light_control;
private ImageView door_control;
private ImageView air_control;
private ImageView curtain_control;
private ImageView tv_control;
private ImageView water_control;
private TextView text_temperature;
private TextView text_light;
private TextView text_door_lock;
protected MqttClient client;
protected MqttConnectOptions options;
protected Handler handler;
@SuppressLint("HandlerLeak")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
curtain_control =findViewById(R.id.curtain_control);
curtain_control.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(door_flag == 0)
{
publishmessageplus(mqtt_pub_topic,"{\"doorLock\":\"open\",\"led\":\"\"}");
Toast.makeText(MainActivity.this,"开门" ,Toast.LENGTH_SHORT).show();
door_flag =1;
}else{
publishmessageplus(mqtt_pub_topic,"{\"doorLock\":\"close\",\"led\":\"\"}");
Toast.makeText(MainActivity.this,"关门" ,Toast.LENGTH_SHORT).show();
door_flag =0;
}
}
});
light_control=findViewById(R.id.light_control);
light_control.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(led_flag == 0)
{
publishmessageplus(mqtt_pub_topic,"{\"led\":\"open\",\"doorLock\":\"\"}");
Toast.makeText(MainActivity.this,"开灯" ,Toast.LENGTH_SHORT).show();
led_flag =1;
}else{
publishmessageplus(mqtt_pub_topic,"{\"led\":\"close\",\"doorLock\":\"\"}");
Toast.makeText(MainActivity.this,"关灯" ,Toast.LENGTH_SHORT).show();
led_flag =0;
}
}
});
// 两个控件联动 按钮单机 更改 textview 的内容
text_temperature =findViewById(R.id.text_temperture);
text_door_lock=findViewById(R.id.text_doorLock);
text_light=findViewById(R.id.text_bright);
//**********************************************************//
Mqtt_init();
startReconnect();
handler = new Handler() {
@SuppressLint("SetTextI18n")
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1: //开机校验更新回传
break;
case 2: // 反馈回传
break;
case 3: //MQTT 主页消息处理 收到消息回传 UTF8Buffer msg=new UTF8Buffer(object.toString());
//处理message 传过来的 obj字段(里面包了数据)
/*
String T_val = msg.obj.toString().substring(msg.obj.toString().indexOf("temperature\":")+13,msg.obj.toString().indexOf("}"));
String text_val = T_val+"℃";
//在主进程 handler 里面更新UI 既保证了稳定性 又不影响网络传输
text_temperature.setText(text_val);
//Toast.makeText(MainActivity.this,T_val ,Toast.LENGTH_SHORT).show();
*/
try{
Log.v("1",msg.obj.toString());
JSONObject jsonObject=new JSONObject(msg.obj.toString());
GetMessage getMessage=new GetMessage();
getMessage.setTemperture(jsonObject.getString("temperature"));
getMessage.setLight(jsonObject.getString("bright"));
getMessage.setDoor_lock(jsonObject.getString("doorLock"));
Log.v("3",getMessage.getDoor_lock());
if(getMessage.getTemperture()!=null){
String text_val = getMessage.getTemperture()+"℃";
text_temperature.setText(text_val);
}
if(getMessage.getDoor_lock()!=null){
String text_val = getMessage.getDoor_lock();
text_door_lock.setText(text_val);
}
if(getMessage.getLight()!=null){
String text_val = getMessage.getLight();
text_light.setText(text_val);
}
getMessage.setTemperture(null);
getMessage.setLight(null);
getMessage.setDoor_lock(null);
}catch (Exception e){e.printStackTrace();}
break;
case 30: //连接失败
Toast.makeText(MainActivity.this,"连接失败" ,Toast.LENGTH_SHORT).show();
break;
case 31: //连接成功
Toast.makeText(MainActivity.this,"连接成功" ,Toast.LENGTH_SHORT).show();
try {
client.subscribe(mqtt_sub_topic,1);
} catch (MqttException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
};
}
private void parseEasyJson(String json){
try{
JSONArray jsonArray = new JSONArray(json);
for(int i = 0;i < jsonArray.length();i++){
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
GetMessage getMessage=new GetMessage();
getMessage.setTemperture(jsonObject.getString("temperature"));
getMessage.setLight(jsonObject.getString("bright"));
getMessage.setDoor_lock(jsonObject.getString("doorLock"));
}
}catch (Exception e){e.printStackTrace();}
}
protected void Mqtt_init()
{
try {
//host为主机名,test为clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
client = new MqttClient(host, mqtt_id,
new MemoryPersistence());
//MQTT的连接设置
options = new MqttConnectOptions();
//设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
options.setCleanSession(false);
//设置连接的用户名
options.setUserName(userName);
//设置连接的密码
options.setPassword(passWord.toCharArray());
// 设置超时时间 单位为秒
options.setConnectionTimeout(10);
// 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
options.setKeepAliveInterval(20);
//设置回调
client.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
//连接丢失后,一般在这里面进行重连
System.out.println("connectionLost----------");
startReconnect();
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
//publish后会执行到这里
System.out.println("deliveryComplete---------"
+ token.isComplete());
}
@Override
public void messageArrived(String topicName, MqttMessage message)
throws Exception {
//subscribe后得到的消息会执行到这里面
System.out.println("messageArrived----------");
Message msg = new Message();
//封装message包
msg.what = 3; //收到消息标志位
msg.obj =message.toString();
//发送messge到handler
handler.sendMessage(msg); // hander 回传
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
protected void Mqtt_connect() {
new Thread(new Runnable() {
@Override
public void run() {
try {
if(!(client.isConnected()) ) //如果还未连接
{
client.connect(options);
Message msg = new Message();
msg.what = 31;
// 没有用到obj字段
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
Message msg = new Message();
msg.what = 30;
// 没有用到obj字段
handler.sendMessage(msg);
}
}
}).start();
}
protected void startReconnect() {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
if (!client.isConnected()) {
Mqtt_connect();
}
}
}, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);
}
protected void publishmessageplus(String topic,String message2)
{
if (client == null || !client.isConnected()) {
return;
}
MqttMessage message = new MqttMessage();
message.setPayload(message2.getBytes());
try {
client.publish(topic,message);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
三、esp8266客户端
这里由于准备不用onenet的功能了,因此只是把他当成一个服务器中转使用,代码建立在前两篇成果之上。
#define BLINKER_WIFI
#define BLINKER_ALIGENIE_OUTLET
#define BLINKER_PRINT Serial
#include <Blinker.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "AccelStepper.h"
#include <Ticker.h>
#define PRODUCT_ID "396066" //产品名
#define API_KEY "tx6WM==zmW21Z2pt4susBRlHMuY="//产品密钥
#define DEVICE_ID "666259032"//设备名
#define TOPIC "sendMessage"//订阅主题
char auth[] = "0c39eb647f6d";
char ssid[] = "CMCC-Q4QF";
char pswd[] = "jcv53rvq";
WiFiClient wifiClient;
Ticker ticker;
Ticker ticker2;
int count = 0; //ticker1控制 数据上传下发的间隔时间(s)
int count2 = 0; //ticker2控制 电机转动的时间(s)
AccelStepper stepper1(4, D0, D2, D1, D3);//电机引脚
String door = "close"; //默认检测门关闭
PubSubClient mqttClient(wifiClient);
const char* mqttServer = "183.230.40.39";//onenet地址
const uint16_t mqttPort = 6002;//mqtt接口端口
String doorLock = "close"; //默认门锁指令关闭
char msgJson[75];//存json下发信息数据
char msg_buf[200];//存json上传数据及标识位
// 新建组件对象
BlinkerButton Button1("btn-door");
bool oState = false;
void aligeniePowerState(const String & state)
{
BLINKER_LOG("need set power state: ", state);
if (state == BLINKER_CMD_ON) {
digitalWrite(LED_BUILTIN, LOW);
BlinkerAliGenie.powerState("on");
BlinkerAliGenie.print();
oState = true;
}
else if (state == BLINKER_CMD_OFF) {
digitalWrite(LED_BUILTIN, HIGH);
BlinkerAliGenie.powerState("off");
BlinkerAliGenie.print();
oState = false;
}
}
void aligenieQuery(int32_t queryCode)
{
BLINKER_LOG("AliGenie Query codes: ", queryCode);
switch (queryCode)
{
case BLINKER_CMD_QUERY_ALL_NUMBER :
BLINKER_LOG("AliGenie Query All");
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.print();
break;
case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
BLINKER_LOG("AliGenie Query Power State");
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.print();
break;
default :
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.print();
break;
}
}
// 按下按键即会执行该函数
void button1_callback(const String & state) {
BLINKER_LOG("get button state: ", state);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
}
void setup() {
// 初始化串口
Serial.begin(9600);
stepper1.setMaxSpeed(500); // 设置电机最大速度为500
stepper1.setSpeed(0); // 初始化电机速度为300
#if defined(BLINKER_PRINT)
BLINKER_DEBUG.stream(BLINKER_PRINT);
#endif
pinMode(A0, INPUT);
pinMode(D6, INPUT);
pinMode(D8, INPUT);
// 初始化有LED的IO
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
WiFi.mode(WIFI_STA);
mqttClient.setServer(mqttServer, mqttPort);
// 设置MQTT订阅回调函数
mqttClient.setCallback(receiveCallback);
connectMQTTServer();
ticker.attach(1, addCount);
// 初始化blinker
Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead);
Button1.attach(button1_callback);
BlinkerAliGenie.attachPowerState(aligeniePowerState);
BlinkerAliGenie.attachQuery(aligenieQuery);
}
void loop() {
Blinker.run();
if (mqttClient.connected()) { // 如果开发板成功连接服务器
// 每隔2秒钟发布一次信息
// 保持心跳 若电机正在运转,暂时不发信息(由于mcu没有多线程,不能同时运转电机和上传下发数据)
if (count >= 2)
{
if (count2 == 0)
{
pubMsgAndroid();
//pubMQTTmsg();
mqttClient.loop();
count = 0;
}
}
} else { // 如果开发板未能成功连接服务器
connectMQTTServer(); // 则尝试连接服务器
}
//电机控制
if (doorLock == "close" && door == "open")
{
stepper1.setSpeed(-500);
ticker2.attach(1, controlDoor);
Serial.println("door closed");
door = "close";
}
else if (doorLock == "open" && door == "close")
{ stepper1.setSpeed(500);
ticker2.attach(1, controlDoor);
door = "open";
Serial.println("door opened");
}
stepper1.runSpeed();
}
//ticker2控制 电机运转时间
void controlDoor() {
count2++;
Serial.print("ticker调用");
if (count2 >= 6) {
stepper1.setSpeed(0);
count2 = 0;
ticker2.detach(); // 使用detach来停止ticker对象定时调用函数
Serial.print("ticker.detach()");
}
}
//连接mqtt服务器
void connectMQTTServer() {
String clientId = DEVICE_ID;
String productId = PRODUCT_ID;
String apiKey = API_KEY;
// 连接MQTT服务器
if (mqttClient.connect(clientId.c_str(), productId.c_str(), apiKey.c_str())) {
Serial.println("MQTT Server Connected.");
Serial.println("Server Address: ");
Serial.println(mqttServer);
Serial.println("ClientId:");
Serial.println(clientId);
subscribeTopic(); // 订阅指定主题
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(3000);
}
}
// 订阅指定主题
void subscribeTopic() {
// 这么做是为确保不同设备使用同一个MQTT服务器测试消息订阅时,所订阅的主题名称不同
String topicString = TOPIC;
char subTopic[topicString.length() + 1];
strcpy(subTopic, topicString.c_str());
// 通过串口监视器输出是否成功订阅主题以及订阅的主题名称
if (mqttClient.subscribe(subTopic)) {
Serial.println("Subscrib Topic:");
Serial.println(subTopic);
} else {
Serial.print("Subscribe Fail...");
}
}
//获取下发指令topic 指定主题 payload 下发信息,以字节存储 length 下发信息长度
void receiveCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message Received [");
Serial.print(topic);
Serial.print("] ");
String receivePassage;
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
receivePassage += (char)payload[i];
}
Serial.println("----" + receivePassage + "----");
Serial.print("Message Length(Bytes) ");
Serial.println(length);
///
StaticJsonDocument<96> doc;
deserializeJson(doc, receivePassage);
const char* doorLock = doc["doorLock"]; // "close"
const char* led = doc["led"]; // "close"
receivePassage = "";
if (doc["doorLock"].as<String>() == "open")
{
doorLock = "open";
} else if (doc["doorLock"].as<String>() == "close") {
doorLock = "close";
Serial.println("door closed");
}
if (doc["led"].as<String>() == "open")
{
digitalWrite(BUILTIN_LED, LOW); // 则点亮LED。
Serial.println("LED ON");
} else if (doc["led"].as<String>() == "close") {
digitalWrite(BUILTIN_LED, HIGH); // 否则熄灭LED。
Serial.println("LED OFF");
}
/*
const char* json = (char *)payload;
DynamicJsonDocument doc(64);
deserializeJson(doc, json);
const char* led = doc["led"]; // 灯控
const char* door = doc["door"]; // 门控
///
if(doc["door"].as<String>()=="open")
{
doorLock='1';
Serial.println("door open");
}
else if(doc["door"].as<String>()=="close")
{
doorLock='2';
Serial.println("door off");
}
if(doc["led"].as<String>()=="open")
{
digitalWrite(BUILTIN_LED, LOW); // 则点亮LED。
Serial.println("LED ON");
}
else if(doc["led"].as<String>()=="close")
{
digitalWrite(BUILTIN_LED, HIGH); // 否则熄灭LED。
Serial.println("LED OFF");
}*/
/* //onenet测试下发数据
if ((char)payload[0] == 'L') { // 如果收到的信息以“1”为开始
if((char)payload[1] == '0')
{
digitalWrite(BUILTIN_LED, LOW); // 则点亮LED。
Serial.println("LED ON");
}
else if((char)payload[1] == '1')
{
digitalWrite(BUILTIN_LED, HIGH); // 否则熄灭LED。
Serial.println("LED OFF");
}
}else if((char)payload[0] == 'D') { // 如果收到的信息以“1”为开始
if((char)payload[1] == '1')
doorLock="open";
else if((char)payload[1] == '2')
doorLock="close";
}
//
*/
}
/*
void doorControl(char doorLock)
{
//开门
if(doorLock=='1')
{
digitalWrite(D5, HIGH);
}
//关门
else if(doorLock=='2')
{
digitalWrite(D5, LOW);
}
doorLock='0';
}
*/
//对指定主题上传信息
void pubMsgAndroid() {
String topicString = "getMessage";
char publishTopic[topicString.length() + 1];
strcpy(publishTopic, topicString.c_str());
//json数据转换为数组
DynamicJsonDocument doc(64);
doc["temperature"] = analogRead(A0);
doc["doorLock"] = digitalRead(D8);
doc["bright"] = digitalRead(D5);
serializeJson(doc, Serial);
String jsonCode;
serializeJson(doc, jsonCode);
Serial.print("json Code: "); Serial.println(jsonCode);
String messageString = jsonCode;
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
int json_len = strlen(publishMsg);
mqttClient.publish(publishTopic, publishMsg, json_len);
}
/*void pubMQTTmsg(){
//onenet数据点上传系统主题
String topicString = "$dp";
char publishTopic[topicString.length() + 1];
strcpy(publishTopic, topicString.c_str());
//json数据转换为数组
DynamicJsonDocument doc(64);
bool pinState = !digitalRead(BUILTIN_LED);
bool doorState = !digitalRead(D6);
doc["led"] = pinState;
doc["door"] = doorState;
serializeJson(doc, Serial);
// 建立发布信息。温度
String jsonCode;
serializeJson(doc, jsonCode);
Serial.print("json Code: ");Serial.println(jsonCode);
String messageString = jsonCode;
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
int json_len=strlen(publishMsg);
memset(msg_buf,0,200);
msg_buf[0]=char(0x03);
msg_buf[1]=char(json_len>>8);
msg_buf[2]=char(json_len &0xff);
memcpy(msg_buf+3,publishMsg,json_len);
// 实现ESP8266向主题发布信息
if(mqttClient.publish(publishTopic, (uint8_t*)msg_buf,3+json_len)){
Serial.println("Publish Topic:");Serial.println(publishTopic);
String msg_bufTotal;
for(int i=0;i<sizeof(msg_buf)/sizeof(msg_buf[0]);i++)
{
msg_bufTotal+=msg_buf[i];
}
Serial.println("Publish message:");Serial.println(msg_bufTotal);
} else {
Serial.println("Message Publish Failed.");
}
}*/
void addCount() {
count++;
}
这里android手机端 发布主题 sendMessage专门用来发送手机端指令,订阅主题getMessage用来接收esp8266客户端数据并通过handler异步处理,将数据显示在界面上。esp8266客户端订阅与发布相反。
在此基础上,使用了blinker接入天猫精灵的示例,并加以改进,融入到了该程序中,实现了天猫精灵的语音控制。
四、成果展示
天猫精灵与esp8266开发板通信