(一)基於阿里雲的MQTT遠程控制(Android 鏈接MQTT服務器,ESP8266鏈接MQTT服務器實現遠程通訊控制----簡單的鏈接通訊)

若是不瞭解MQTT的能夠看這篇文章  http://www.cnblogs.com/yangfengwu/p/7764667.htmlhtml

http://www.cnblogs.com/yangfengwu/p/8026014.htmlandroid

若是看不懂也不要緊,跟着作就能夠了,作完之後您會發現原來MQTT這麼好用,也如此簡單.安全

對了我要儘可能把程序寫的爛一些,界面作的爛一些,由於既然是學習用的應該越直觀越好.......說一下,本身的服務器由於公開了穩定性上確定很差,服務器

數據衝突也是可能的,這是第一篇,下面幾篇慢慢的來,咱一塊慢慢完善哈session

實現的功能--手機和WIFI模塊都鏈接MQTT服務器,手機用按鈕實現遠程控制一個繼電器,而後WIFI模塊採集的DHT11的溫溼度,遠程發給手機tcp

不過本身這批貼片的板子要等到後天纔到..........................ide

  

 

 

 

先看一下Android 程序怎麼寫,首先就是下載個MQTT的jar包函數

連接:https://pan.baidu.com/s/1bpjRzyB 密碼:90vv學習

新建一個Android 工程就不說了吧...............測試

將下載的jar包放在一個地方

 

 

我放在了個人Android的源碼的根目錄

如今在Android 工程導入下載的那個jar包

 

 

 

 

 

 

 

 

 

如今把可能用到的一些權限加上 

 

 <!--     獲取手機信息權限 -->  
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ></uses-permission>"
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission>  
    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"></uses-permission>

 

如今呢先寫個程序獲取手機的IMEI號,由於鏈接的時候每個客戶端的ClientID要求不能同樣,咱就用IMEI號表明ClientID

其實就這兩句

TelephonyManager mTm = (TelephonyManager)this.getSystemService(TELEPHONY_SERVICE);  
TelephonyIMEI = mTm.getDeviceId();

 

如今配置咱的MQTT

 

public class MainActivity extends Activity {
    
    String TelephonyIMEI="";
    
    private MqttClient client;//client
    private MqttConnectOptions options;//配置
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        TelephonyManager mTm = (TelephonyManager)this.getSystemService(TELEPHONY_SERVICE);  
        TelephonyIMEI = mTm.getDeviceId();
        //Toast.makeText(getApplicationContext(), TelephonyIMEI, 500).show();
        MyMqttInit();
    }
    
    /*  初始化配置Mqtt  */
    private void MyMqttInit()
    {
        
        try
        {
            //(1)主機地址(2)客戶端ID,通常以客戶端惟一標識符(不可以和其它客戶端重名)(3)最後一個參數是指數據保存在內存(具體保存什麼數據,之後再說,其實如今我也不是很肯定)
            client = new MqttClient("tcp://47.93.19.134:1883",TelephonyIMEI,new MemoryPersistence());
        } catch (MqttException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        options = new MqttConnectOptions();//MQTT的鏈接設置
        
        options.setCleanSession(true);//設置是否清空session,這裏若是設置爲false表示服務器會保留客戶端的鏈接記錄,這裏設置爲true表示每次鏈接到服務器都以新的身份鏈接
        
        options.setUserName("username");//設置鏈接的用戶名(本身的服務器沒有設置用戶名)
        
        options.setPassword("password".toCharArray());//設置鏈接的密碼(本身的服務器沒有設置密碼)
        
        options.setConnectionTimeout(10);// 設置鏈接超時時間 單位爲秒
        
        options.setKeepAliveInterval(20);// 設置會話心跳時間 單位爲秒 服務器會每隔1.5*20秒的時間向客戶端發送個消息判斷客戶端是否在線,但這個方法並無重連的機制
        
        client.setCallback(new MqttCallback() {
            @Override//獲取的消息會執行這裏--arg0是主題,arg1是消息
            public void messageArrived(String arg0, MqttMessage arg1) throws Exception {
                // TODO Auto-generated method stub
                
            }
            
            @Override//訂閱主題後會執行到這裏
            public void deliveryComplete(IMqttDeliveryToken arg0) {
                // TODO Auto-generated method stub
                
            }
            
            @Override//鏈接丟失後,會執行這裏
            public void connectionLost(Throwable arg0) {
                // TODO Auto-generated method stub
                
            }
        });
    }

 

 如今鏈接咱的服務器,鏈接成功後打印一下鏈接成功,鏈接是阻塞的,因此放在一個任務裏面執行鏈接

 

public class MainActivity extends Activity {
    
    String TelephonyIMEI="";
    
    private MqttClient client;//client
    private MqttConnectOptions options;//配置
    MqttConnectThread mqttConnectThread = new MqttConnectThread();//鏈接服務器任務
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        TelephonyManager mTm = (TelephonyManager)this.getSystemService(TELEPHONY_SERVICE);  
        TelephonyIMEI = mTm.getDeviceId();
        //Toast.makeText(getApplicationContext(), TelephonyIMEI, 500).show();
        MyMqttInit();//初始化配置MQTT客戶端
        mqttConnectThread.start();//執行鏈接服務器任務
    }
    
    /*  初始化配置Mqtt  */
    private void MyMqttInit()
    {
        .........
    }
    
    
    /*鏈接服務器任務*/
    class MqttConnectThread extends Thread
    {
        public void run()
        {
            try 
            {
                client.connect(options);//鏈接服務器,鏈接不上會阻塞在這
                runOnUiThread(new Runnable() {//
                    public void run() {
                        Toast.makeText(getApplicationContext(), "鏈接成功", 500).show();
                    }
                });
            } 
            catch (MqttSecurityException e) 
            {
                //安全問題鏈接失敗
            } 
            catch (MqttException e) 
            {
                //鏈接失敗緣由
            }
        }
    }

 

 如今下載到手機試一試

 

 如今呢測試一下通訊,測試接收消息,用調試助手發信息,而後手機端接收,而後顯示出來

 調試助手連接

連接:https://pan.baidu.com/s/1qYxEeLI 密碼:exfj

 

 如今先設置一下APP的訂閱的主題,和接收到消息以後就顯示出來

 

 

public class MainActivity extends Activity {
    
    String TelephonyIMEI="";
    
    private MqttClient client;//client
    private MqttConnectOptions options;//配置
    MqttConnectThread mqttConnectThread = new MqttConnectThread();//鏈接服務器任務
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        TelephonyManager mTm = (TelephonyManager)this.getSystemService(TELEPHONY_SERVICE);  
        TelephonyIMEI = mTm.getDeviceId();
        //Toast.makeText(getApplicationContext(), TelephonyIMEI, 500).show();
        MyMqttInit();//初始化配置MQTT客戶端
        mqttConnectThread.start();//執行鏈接服務器任務
    }
    
    /*  初始化配置Mqtt  */
    private void MyMqttInit()
    {
        
        try
        {
            //(1)主機地址(2)客戶端ID,通常以客戶端惟一標識符(不可以和其它客戶端重名)(3)最後一個參數是指數據保存在內存(具體保存什麼數據,之後再說,其實如今我也不是很肯定)
            client = new MqttClient("tcp://47.93.19.134:1883",TelephonyIMEI,new MemoryPersistence());
        } catch (MqttException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        options = new MqttConnectOptions();//MQTT的鏈接設置
        
        options.setCleanSession(true);//設置是否清空session,這裏若是設置爲false表示服務器會保留客戶端的鏈接記錄,這裏設置爲true表示每次鏈接到服務器都以新的身份鏈接
        
        options.setUserName("username");//設置鏈接的用戶名(本身的服務器沒有設置用戶名)
        
        options.setPassword("password".toCharArray());//設置鏈接的密碼(本身的服務器沒有設置密碼)
        
        options.setConnectionTimeout(10);// 設置鏈接超時時間 單位爲秒
        
        options.setKeepAliveInterval(20);// 設置會話心跳時間 單位爲秒 服務器會每隔1.5*20秒的時間向客戶端發送個消息判斷客戶端是否在線,但這個方法並無重連的機制
        
        client.setCallback(new MqttCallback() {
            @Override//獲取消息會執行這裏--arg0是主題,arg1是消息
            public void messageArrived(String arg0, MqttMessage arg1) throws Exception {
                // TODO Auto-generated method stub
                final String topic = arg0;//主題
                final String msgString = arg1.toString();//消息
                
                runOnUiThread(new Runnable() {//
                    public void run() {
                        Toast.makeText(getApplicationContext(),"主題:"+topic+"消息:"+msgString, 500).show();
                    }
                });
            }
            
            @Override//訂閱主題後會執行到這裏
            public void deliveryComplete(IMqttDeliveryToken arg0) {
                // TODO Auto-generated method stub
                
            }
            
            @Override//鏈接丟失後,會執行這裏
            public void connectionLost(Throwable arg0) {
                // TODO Auto-generated method stub
                
            }
        });
    }
    
    
    /*鏈接服務器任務*/
    class MqttConnectThread extends Thread
    {
        public void run()
        {
            try 
            {
                client.connect(options);//鏈接服務器,鏈接不上會阻塞在這
                
                client.subscribe("test",0);//設置(訂閱)接收的主題,主題的級別是0
                
                runOnUiThread(new Runnable() {//
                    public void run() {
                        Toast.makeText(getApplicationContext(), "鏈接成功", 500).show();
                    }
                });
            } 
            catch (MqttSecurityException e) 
            {
                //安全問題鏈接失敗
            } 
            catch (MqttException e) 
            {
                //鏈接失敗緣由
            }
        }
    }

下載到手機 

 

 如今配置一下軟件,對了有些參數如今不明白不要緊,後面會介紹一下相關的知識,

軟件的主題名稱要和APP中訂閱的主題同樣 都是 test

如今鏈接

 

 

 如今點擊發布消息

 

 

 看手機端

 

 說明已經能通訊了

 如今說一下關於主題哈,關於/

 如今把手機端的訂閱的主題改成"/#"

 

 而後下載到手機

 

你會發現手機也能接收消息

 

手機都能接收到消息

# 是一個匹配主題中任意層次數的通配符。好比說,若是你訂閱了test/device/#,你就能夠接收到如下這些主題的消息。

test/device
test/device/後面隨即是什麼
我們的設備能夠用"/"來進行分類,我們的APP呢能夠指定接收哪一類的產品的數據"XXXX/#"....是否是很方便


對了若是如今接收兩個已知主題的設備
假如說是

第一種方式

  

 

 

第二種方式

 

結果和上面同樣

 

 如今呢在界面加一個按鈕,按下發送消息"1",鬆開發送消息"0"

而後設置發佈的主題是"/test/button"

 

 

 

 

public class MainActivity extends Activity {
    
    String TelephonyIMEI="";
    
    private MqttClient client;//client
    private MqttConnectOptions options;//配置
    MqttConnectThread mqttConnectThread = new MqttConnectThread();//鏈接服務器任務
    
    Button button;//發送消息按鈕
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        button = (Button) findViewById(R.id.button1);//獲取發送消息按鈕
        button.setOnTouchListener(buttonTouch);//設置按鈕的觸摸事件
        
        TelephonyManager mTm = (TelephonyManager)this.getSystemService(TELEPHONY_SERVICE);  
        TelephonyIMEI = mTm.getDeviceId();
        //Toast.makeText(getApplicationContext(), TelephonyIMEI, 500).show();
        MyMqttInit();//初始化配置MQTT客戶端
        mqttConnectThread.start();//執行鏈接服務器任務
    }
    
    /*按鈕觸摸事件*/
    private OnTouchListener buttonTouch = new OnTouchListener() {
        
        @Override
        public boolean onTouch(View v, MotionEvent event) 
        {
            MqttMessage msgMessage = null;//Mqtt消息變量
            if (event.getAction() == MotionEvent.ACTION_DOWN) //按下
            {
                msgMessage = new MqttMessage("1".getBytes());
            }
            else if (event.getAction() == MotionEvent.ACTION_UP) //鬆開
            {
                msgMessage = new MqttMessage("0".getBytes());
            }
            
            try 
            {
                client.publish("/test/button",msgMessage);//發送主題爲"/test/button"的消息
            } catch (MqttPersistenceException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (MqttException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            catch (Exception e) {
                //其他的狀態msgMessage = null;因此加了這個catch (Exception e)
            }
            
            
            return false;
        }
    };

 

 如今下載到手機,

調試助手訂閱一下主題 "/test/button"

 

 動做一下按鈕

 

 

 

 如今把發過來的數據用文本框顯示,不讓他提示了

 

     接收顯示的換一下

 

 

runOnUiThread(new Runnable() {//由於操做的是主界面的控件因此用刷新UI的線程,最好用handle哈,我這裏怎麼簡單怎麼寫
                    public void run() {
                        //Toast.makeText(getApplicationContext(),"主題:"+topic+"消息:"+msgString, 500).show();
                        textView.setText("主題:"+topic+"\n消息:"+msgString);
                    }
                });

 

 如今試一下

 

 

 

好了,如今咱開始控制咱的WIFI模塊了....用咱的手機控制WIFI板子上的繼電器,WIFI模塊呢採集溫溼度,而後顯示在手機的文本框中

本身更傾向於用lua開發,因此要刷入lua的固件哈

關於刷固件能夠參考

http://www.cnblogs.com/yangfengwu/p/7514336.html

本身已經下載好的固件

連接:https://pan.baidu.com/s/1o8pAISy 密碼:9zns

 

若是親們本身下載的話別忘了,把mqtt和dht選擇上哈

 

 

程序--init.lua

wifi.setmode(wifi.STATION)

RelayPin = 2;--RelayPin
gpio.mode(RelayPin,gpio.OUTPUT)--RelayPin
gpio.write(RelayPin,0)--RelayPin

LedPin = 4;--LedPin
gpio.mode(LedPin,gpio.OUTPUT)--LedPin
gpio.write(LedPin,0)--LedPin

DHT11pin = 5--DHT11 GPIO

Temperature = "0";--Storage temperature
Humidity = "0";--Store humidity


apcfg={}
apcfg.ssid="qqqqq"
apcfg.pwd="11223344"
wifi.sta.config(apcfg)
--wifi.sta.connect()
wifi.sta.autoconnect(1)


clientid = wifi.sta.getmac()
mqttClient=nil
mqttConnectedFlage = 0;

Mymqtt = mqtt.Client(clientid, 120,"user", "password");


--[[The connection serve]]
tmr.alarm(0, 1000, 1, function()
    Mymqtt:connect("47.93.19.134", 1883, 0,ConnectSuccess,ConnectFailed)
end)


--[[The connection Success]]
function ConnectSuccess(client)
     client:subscribe("/test/button", 0, subscribeSuccess)
                                         
     print("connected")
     mqttClient = client;
     tmr.stop(0);
     mqttConnectedFlage = 1;
end

--[[The connection fails]]
function mqttConnectFailed(client,reason)
   mqttConnectedFlage = 0;
   print("failed reason: " .. reason)
   tmr.start(0);
end


--[[The subscribe Success]]
function subscribeSuccess(client)
    print("subscribe success") 
end

--[[The Receive Msg]]
Mymqtt:on("message", function(client, topic, data) 
    if  string.find(data,"1") ~= nil then
        gpio.write(RelayPin,1)
    end

    if  string.find(data,"0") ~= nil then
        gpio.write(RelayPin,0)
    end
   
end)


--[[The Send Msg]]
tmr.alarm(1, 1000, 1, function()

    if mqttClient ~= nil and mqttConnectedFlage == 1 then
        mqttClient:publish("/test/yang","Temperature="..Temperature..";".."Humidity="..Humidity, 0, 0, 
          function(client) 
            gpio.write(4,1-gpio.read(4))
          end)
    end      
end)

--[[The gather humiture data]]
tmr.alarm(5, 2000, 1, function()--Every other 1S
    local status, temp, humi, temp_dec, humi_dec = dht.read11(DHT11pin)--Gathering temperature and humidity                 
    if status == dht.OK or status == dht.ERROR_CHECKSUM then
        Temperature = temp;
        Humidity = humi;
        --print("DHT Temperature:"..temp..";".."Humidity:"..humi)
    end
end)


printip = 0
wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, function(T)
    printip = 0
end)


wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function(T)
   if printip == 0 then
      ip,netmask,gateway = wifi.sta.getip()
      print(gateway)
   end
   printip = 1
end)

 

如今說一下個個部分的功能,對了關於語法問題和其他的問題就請你們參考個人,其實上面的代碼就是參考的官方給的API函數,

我但願親們最重要的是有自學的能力,而不是須要別人灌輸東西的機器.

 

 

 

 

 

 好了親們能夠本身去測試了

源碼和資料連接

連接:https://pan.baidu.com/s/1xLv1VB2yiqQJeTb1vDB6kQ 密碼:5jzd

wifi的就是上面的,直接複製粘貼過去就好啦

相關文章
相關標籤/搜索