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裝置連線了,有辦法錯誤時不斷,手機可以再發訊息給裝置嗎?
回覆刪除