RD腦說:我們就先設計ESP8266 AP
Station mode與Android手機對連
這樣就可以百分百連接到AP了!
具體設計流程如下
1、先讓ESP8266初始就進入AP mode
2、使用Android送Socket到ESP8266設定帳號密碼
3、ESP8266關閉AP mode,進入Station mode 
4、接收BLE掃瞄的值
5、將掃進來的值用MQTT的Publish往Server上丟
6、Subscribe
Server 回傳的值
寫法如下
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <SoftwareSerial.h>
WiFiServer server(5000); //Initialize the
server on Port 5000
int
flag1=1,flag2=0,flag3=0,flag4=0,flag5=0; //待會往下看就知道為什麼要有5個flag,這是當作開關使用
const char* Topic =
"hello/world";//MQTT要設定Topic,先隨便設定
const char* mqtt_server =
"192.168.1.19";//local端的IP
const char *array[5], *BLE_UID[5]; //array是拿來放Android丟來的資料,BLE_UID是拿來放BLE丟上來的資料
  
int i = 0;
WiFiClient espClient;
PubSubClient client(espClient);
//下面是寫MQTT收到的回傳資料
void callback(char* topic, byte* payload,
unsigned int length) {
 
Serial.print("Message arrived [");
 
Serial.print(topic);
 
Serial.print("] ");
  for
(int i = 0; i < length; i++) {
   
Serial.print((char)payload[i]);
  }
 
Serial.println();
}
void reconnect() {//這裡是寫,當變成Station mode時,去連接MQTT的Server
  //
Loop until we're reconnected
 
while (!client.connected()) {
   
Serial.print("Attempting MQTT connection...");
   
// Create a random client ID
   
String clientId = "ESP8266Client-";
   
clientId += String(random(0xffff), HEX);
   
// Attempt to connect
   
if (client.connect(clientId.c_str())) {
     
Serial.println("connected");
     
// Once connected, publish an announcement...
     
client.publish(Topic, "hello world");
     
// ... and resubscribe
     
client.subscribe(Topic);
    }
else {
      Serial.print("failed, rc=");
     
Serial.print(client.state());
     
Serial.println(" try again in 5 seconds");
     
// Wait 5 seconds before retrying
     
delay(5000);
    }
  }
}
void setup() {
 
delay(1000);
 
Serial.begin(115200);
     
Serial.println();
 
Serial.print("Configuring access point...");
WiFi.mode(WIFI_AP); //讓ESP8266變成AP mode 
WiFi.softAP("Simple Care",
""); // 一開始ESP8266變成AP的名稱
 
IPAddress myIP = WiFi.softAPIP();
 
Serial.println();
 
Serial.print("AP IP address: ");
 
Serial.println(myIP);
server.begin(); // Start the HTTP Server
}
void loop() { //這裡共有5個flag
  if
(flag1==1){
   
// Check if a client has connected
 
WiFiClient client = server.available();
  if
(!client) {
   
return;
  }
  // 如果連上了,就show個new client連進來了
 
Serial.println("new client");
 
while(!client.available()){
   
delay(1);
  }
  //
Read the first line of the request
 
String req = client.readString();
 
char charBuf[50];//for string to char
  int
req_len = req.length() + 1;
 
req.toCharArray(charBuf, req_len); 
 
Serial.println(charBuf);
 
client.flush();
//以下是把Android送來的socket用strok切割放入array的陣列裡
char *p = strtok (charBuf, "\\");
   
while (p != NULL)
    {
       
array[i++] = p;
       
p = strtok (NULL, "\\");
    }
      
WiFi.disconnect();  
 
WiFi.softAPdisconnect(true);
   
WiFi.mode(WIFI_OFF);
   
flag1=0;
   
flag2=1;
}
if (flag2==1)
{
Serial.println();
   
Serial.println(array[0]);//印出android第一個值,拿來Debug用
   
Serial.println();
   
Serial.println(array[1]); //印出android第二個值,拿來Debug用
 
WiFi.mode(WIFI_STA);//讓ESP8266變成Station mode
 
delay(1000);
 
WiFi.begin(array[0], array[1]);//設定連接上家中的AP的帳號密碼
 
Serial.println("Wifi station mode");
   
while (WiFi.status() != WL_CONNECTED) {
   
delay(500);
   
Serial.print(".");
  }
  randomSeed(micros());
 
Serial.println("");
 
Serial.println("WiFi connected");
 
Serial.println("IP address: ");
 
Serial.println(WiFi.localIP());
 
client.setServer(mqtt_server, 1883);
 
client.setCallback(callback);
 
delay(500);
 
Serial.println("\\G\\O\\]");//連上AP傳個\G\O\給MCU把BLE叫起來開始Scan
flag2=0;
flag3=1;
  }
  if
(flag3==1)
  {
   
String s = "";
   
char a[30];
   
int i=0;
   
while (Serial.available()) {//把uart RX的值讀進來
       
char c = Serial.read();
       
if(c!='\n'){
           
s += c;
           
a[i]=c;
           
i++;
       
}
       
delay(5); //沒有延遲的話 UART 串口速度會跟不上Arduino的速度,會導致資料不完整
    }
   
if(s!=""){
       
i=0;
 
char *p = strtok (a, "\\");//分割讀進來的值
   
while (p != NULL)
    {
       
BLE_UID[i++] = p;
       
p = strtok (NULL, "\\");
    }
   
flag3=0;
   
flag4=1;
    }
    }
if (flag4==1)
{
 
Topic = "hello/add_data";//這裡的Topic是add_data
   
if (!client.connected()) {
   
reconnect();
  }
 
client.loop();
   
char str[30];
   
strcat (str,"\\");
   
strcat (str,array[2]);
   
strcat (str,"\\");
   
strcat (str,array[3]);
   
strcat (str,"\\");
   
strcat (str,array[4]);
   
client.publish(Topic, str);//把add_data送上Cloud,add_data指的是初始,使用者給這個主機叫什麼名字,例如主機名叫room,代表這東西放在房間,以及gps位置,原本還想上傳WIFI MAC,但浪費資源就不做
   
flag4=0;
   
flag5=1;
  }
 if
(flag5==1)
{
Topic = "hello/update_BLE_data";//這裡是代表Topic要上傳BLE Scan的資料
  if
(!client.connected()) {
   
reconnect();
  }
 
client.loop();
  if
(Serial.available() > 0) {
String incomingByte = Serial.readString();
Serial.println(incomingByte);
 
char charBuf[50];//for string to char
  int
req_len = incomingByte.length() + 1; //for string to char
 
incomingByte.toCharArray(charBuf, req_len);//for string to char
   
Serial.print("Publish message: ");
   
Serial.println(charBuf);
   
client.publish(Topic, charBuf);//把BLE Scan的資料傳到Server
  }
}
}
PM腦說:如此ESP8266+MQTT就完成了,但要怎麼讓它動?
RD腦回應:別急! 還要搭配Android和MQTT Server才會動!
接下來我們先做Android的部份,就可以百分百連到AP
這樣就不怕北美的使用者配不上網就退貨啦!
本體:讀者也許會發現Topic叫hello/xxx,這裡我們暫時把主機叫作hello
將來要改為BLE的唯一碼,也就是UID,這樣每個燈座都有唯一碼
MQTT就不會認錯人,把小明叫成小黃
註:如果不會寫APP,也可以改用Sokit這個軟體測試
註:如果不會寫APP,也可以改用Sokit這個軟體測試
 
 
 
 
 
請問版主 當wifi密碼打錯,連不到只能一直在while迴圈裡,這時手機已經斷開AP裝置連線了,有辦法錯誤時不斷,手機可以再發訊息給裝置嗎?
回覆刪除