代码的主体是照着B站的视频搞得,这篇文章主要说一下学到的一些点
【物联网项目实战入门(esp8266+阿里云+APP)【重制】】 https://www.bilibili.com/video/BV1vM4y1s7rN/?share_source=copy_web&vd_source=5d4e5f4221bfa55d1399968d0b180d8f
实时同步LED状态
这部分主要是要明白传输的数据格式,读取指定的数据并添加对应的判断和功能
arduino部分
void loop() {
// 轮询MQTT客户端
mqttClient.poll();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// 保存上次发送消息的时间
previousMillis = currentMillis;
String payload;
int value = digitalRead(4);
DynamicJsonDocument json_msg(512);
DynamicJsonDocument json_data(512);
json_data["temp"] = value;
json_msg["params"] = json_data;
json_msg["version"] = "1.0.0";
serializeJson(json_msg,payload);
Serial.print("Sending message to topic: ");
Serial.println(outTopic);
Serial.println(payload);
//Serial.println(value);
// 发送消息,可以使用Print接口设置消息内容
// 在这种情况下,我们提前知道大小,因此可以流式传输消息负载
bool retained = false;
int qos = 1;
bool dup = false;
mqttClient.beginMessage(outTopic, payload.length(), retained, qos, dup);
mqttClient.print(payload);
mqttClient.endMessage();
Serial.println();
count++;
}
}
值得注意的点是digitalRead()函数的运用,最开始的时候我是直接将json_data["temp"] = digitalRead();导致读出来的数据一直是null。后来还是用的(不会这个软件debug,所以用的Serial.println(value);来输出读出来的值)
Android部分
/ 初始化 Handler 对象,用于处理消息回传
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 收到消息回传
// 获取消息内容并进行解析
String message = msg.obj.toString();
Log.d("nicecode", "handleMessage: " + message);
try {
// 解析收到的 JSON 消息
JSONObject jsonObjectALL = new JSONObject(message);
JSONObject items = jsonObjectALL.getJSONObject("items");//问题items
JSONObject obj_temp = items.getJSONObject("temp");
//取值
ledState = obj_temp.getInt("value");
Log.d("nicecode", "temp: "+ ledState);
if (ledState == 0) {
// LED 关,更改 ImageView 的背景为相应的图像
imageView.setBackgroundColor(Color.WHITE);
if(Judgment == 1) {
Toast.makeText(MainActivity.this, "开启成功", Toast.LENGTH_SHORT).show();
Judgment = 0;
}
} else if (ledState == 1) {
// LED 关,更改 ImageView 的背景为相应的图像
imageView.setBackgroundColor(Color.BLACK);
if(Judgment == 1) {
Toast.makeText(MainActivity.this, "关闭成功", Toast.LENGTH_SHORT).show();
Judgment = 0;
}
} else {
Toast.makeText(MainActivity.this, "失败,请重试", Toast.LENGTH_SHORT).show();
}
System.out.println(ledState);
} catch (JSONException e) {
e.printStackTrace();
// 异常处理
break;
}
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(sub_topic, 1);
} catch (MqttException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
};
}
通过解析读取JSON数据中led的标识符temp的值来同步LED和当前页面显示状况
开灯状态
关灯状态
判断是否发生状态的改变
主要是要分清楚功能的先后顺序(我就是栽坑里了)其实就是需求分析的时候出现了问题,画个流程图就没这问题应该(狗头)
这个部分主要先实现LED的状态实时同步,然后再判断是否发生状态的改变
之前一直在考虑怎么实现怎么将“改变状态”这个判断
尝试过监听器里面加限制条件,通过延长进程的执行时间来改变数据收到之后是发生改变的,后来发现要执行两次才能达到效果,之后又加了其他的限制条件(一直是在外面添加,没想过加载里面),也在Handler对象和监听器两个部分来回测试过好几次,都没有达到效果(就这样一直陷入死循环)
public void onClick(View v) {
// 点击“关”按钮时,发布关的消息
publish_message("{\"params\":{\"temp\":1},\"version\":\"1.0.0\"}");
Judgment = 1;
// try {
// sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// if (ledState == 1) {
// imageView.setBackgroundColor(Color.BLACK);
// Toast.makeText(MainActivity.this, "关闭", Toast.LENGTH_SHORT).show();
// }else{
// Toast.makeText(MainActivity.this, "失败,请重试", Toast.LENGTH_SHORT).show();
// }
}
后来的改进是发现实时同步状态是要最先实现的功能,在功能里面通过标识符来判断是否发生状态改变(点击事件),在Handler 对象中实现
if (ledState == 0) {
// LED 关,更改 ImageView 的背景为相应的图像
imageView.setBackgroundColor(Color.WHITE);
if(Judgment == 1) {//是否点击按钮
Toast.makeText(MainActivity.this, "开启成功", Toast.LENGTH_SHORT).show();
Judgment = 0;//标识符返回初始状态
}
} else if (ledState == 1) {
// LED 关,更改 ImageView 的背景为相应的图像
imageView.setBackgroundColor(Color.BLACK);
if(Judgment == 1) {
Toast.makeText(MainActivity.this, "关闭成功", Toast.LENGTH_SHORT).show();
Judgment = 0;
}
} else {
Toast.makeText(MainActivity.this, "失败,请重试", Toast.LENGTH_SHORT).show();
}