智慧開關1.0
阿新 • • 發佈:2020-07-25
arduino程式碼:
#include <ESP8266WiFi.h> #include <PubSubClient.h> WiFiClient espClient; PubSubClient client(espClient); const char* wifissid = "HO"; //改成自己家wifi const char* password = "zlf7783616"; //改成自己家wifi const char* mqtt_server = "106.13.150.28"; const char* mqtt_id = "1151226060_ESP"; //改成自己的QQ號+_ESPconst char* Mqtt_sub_topic = "1151226060_ESP"; //改成自己的QQ號+_ESP const char* Mqtt_pub_topic = "1151226060"; // 上報訊息給 手機APP的TOPIC //改成自己的QQ號 void setup() { pinMode(2, OUTPUT); //如果該引腳通過pinMode()設定為輸出模式(OUTPUT),您可以通過digitalWrite()語句將該引腳設定為HIGH(5伏特)或LOW(0伏特/GND)。 Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server,1883); client.setCallback(callback); } void setup_wifi() { Serial.println(); Serial.print("Connecting to "); Serial.println(wifissid); WiFi.begin(wifissid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(char* topic, byte* payload, unsigned int length) { String msg=""; String LED_set = ""; Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { msg+= (char)payload[i]; } Serial.println(msg); if(msg.indexOf("led")) //判斷是否是要設定LED燈 { //取出LED_set資料 並執行 LED_set = msg.substring(msg.indexOf("led\":")+5,msg.indexOf("}")); digitalWrite(2,!LED_set.toInt()); } } void reconnect() { while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect(mqtt_id)) { Serial.println("connected"); //連線成功以後就開始訂閱 client.subscribe(Mqtt_sub_topic,1); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void loop() { if (!client.connected()) { reconnect(); } client.loop(); }
IDEA Android stydio程式碼:
package com.example.intelligent_switch; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.provider.Settings; 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.JSONException; import org.json.JSONObject; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class MainActivity extends AppCompatActivity { private String host = "tcp://106.13.150.28:1883"; private String userName = "android"; private String passWord = "android"; private String mqtt_id = "1151226060"; //定義成自己的QQ號 切記!不然會掉線!!! private String mqtt_sub_topic = "1151226060"; //為了保證你不受到別人的訊息 哈哈 private String mqtt_pub_topic = "1151226060_ESP"; //為了保證你不受到別人的訊息 哈哈 自己QQ好後面加 _ESP private int led_flag =1; private ScheduledExecutorService scheduler; private Button btn_1; //類似於微控制器開發裡面的 引數初始化 private Button image_1; private MqttClient client; private MqttConnectOptions options; private Handler handler; @SuppressLint("HandlerLeak") @Override protected void onCreate(Bundle savedInstanceState) { //這裡是介面開啟後 最先執行的地方 super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 對應介面UI //一般先用來進行介面初始化 控制元件初始化 初始化一些引數和變數。。。。。 //不恰當比方 類似於 微控制器的 main函式 btn_1 = findViewById(R.id.btn_1); // 尋找xml裡面真正的id 與自己定義的id繫結 btn_1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 這裡就是單機之後執行的地方 // 玩微控制器 最常用的就是除錯 printf(“hello”) System.out.println("hello"); //更直觀的方法 用彈窗:toast //在當前activity 顯示內容為“hello”的短時間彈窗 Toast.makeText(MainActivity.this,"hello" ,Toast.LENGTH_SHORT).show(); } }); //到這裡 你已經學會了基本的安卓開發 // 按鈕單機事件你會了 圖片單機呢??? image_1 =findViewById(R.id.image_1); image_1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(led_flag == 0) { publishmessageplus(mqtt_pub_topic,"{\"set_led\":1}"); led_flag =1; }else{ publishmessageplus(mqtt_pub_topic,"{\"set_led\":0}"); led_flag =0; } } }); // 兩個控制元件聯動 按鈕單機 更改 textview 的內容 //**********************************************************// 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()); //Toast.makeText(MainActivity.this,T_val ,Toast.LENGTH_SHORT).show(); 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 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(); msg.what = 3; //收到訊息標誌位 msg.obj = topicName + "---" + message.toString(); handler.sendMessage(msg); // hander 回傳 } }); } catch (Exception e) { e.printStackTrace(); } } private 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; handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); Message msg = new Message(); msg.what = 30; handler.sendMessage(msg); } } }).start(); } private void startReconnect() { scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { if (!client.isConnected()) { Mqtt_connect(); } } }, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS); } private 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(); } } }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" 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_width="match_parent" android:layout_height="160dp"> <TextView android:layout_width="wrap_content" android:text="基於物聯網的智慧開關" android:textSize="35dp" android:textColor="#CCFFFF" android:background="@drawable/background_lvshe" android:layout_height="wrap_content"> </TextView> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="160dp"> </LinearLayout> <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"> <Button android:layout_width="wrap_content" android:text="電源開關" android:textSize="50dp" android:background="@drawable/drawable" android:layout_gravity="center_horizontal" android:id="@+id/image_1" android:layout_height="wrap_content"> </Button> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="230dp"> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <Button android:layout_width="wrap_content" android:text="按下有驚喜" android:id="@+id/btn_1" android:layout_height="wrap_content"> </Button> </LinearLayout> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.intelligent_switch"> <!--允許程式開啟網路套接字--> <uses-permission android:name="android.permission.INTERNET" /> <!--允許程式獲取網路狀態--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="智慧開關" 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>