123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- /*
- ESP8266/ESP32 publish the RSSI as the WiFi signal strength to ThingSpeak channel.
- This example is for explaining how to use the AutoConnect library.
- In order to execute this example, the ThingSpeak account is needed. Sing up
- for New User Account and create a New Channel via My Channels.
- For details, please refer to the project page.
- https://hieromon.github.io/AutoConnect/howtoembed.html#used-with-mqtt-as-a-client-application
- This example is based on the environment as of March 20, 2018.
- Copyright (c) 2020 Hieromon Ikasamo.
- This software is released under the MIT License.
- https://opensource.org/licenses/MIT
- */
- #if defined(ARDUINO_ARCH_ESP8266)
- #include <ESP8266WiFi.h>
- #include <ESP8266HTTPClient.h>
- #define GET_CHIPID() (ESP.getChipId())
- #elif defined(ARDUINO_ARCH_ESP32)
- #include <WiFi.h>
- #include <HTTPClient.h>
- #define GET_CHIPID() ((uint16_t)(ESP.getEfuseMac()>>32))
- #endif
- #include <PubSubClient.h>
- #include <AutoConnect.h>
- #define AUX_SETTING_URI "/mqtt_setting"
- #define AUX_SAVE_URI "/mqtt_save"
- #define AUX_CLEAR_URI "/mqtt_clear"
- // Adjusting WebServer class with between ESP8266 and ESP32.
- #if defined(ARDUINO_ARCH_ESP8266)
- typedef ESP8266WebServer WiFiWebServer;
- #elif defined(ARDUINO_ARCH_ESP32)
- typedef WebServer WiFiWebServer;
- #endif
- // This example shows a sketch that realizes the equivalent operation
- // of mqttRSSI without using JSON.
- // By comparing this example with the example using JSON, mqttRSSI or
- // mqttRSSI_FS, you will better understand AutoConnect's custom Web page
- // facility.
- // Declare AutoConnectElements for the page asf /mqtt_setting
- ACStyle(style, "label+input,label+select{position:sticky;left:120px;width:230px!important;box-sizing:border-box;}");
- ACText(header, "<h2>MQTT broker settings</h2>", "text-align:center;color:#2f4f4f;padding:10px;");
- ACText(caption, "Publishing the WiFi signal strength to MQTT channel. RSSI value of ESP8266 to the channel created on ThingSpeak", "font-family:serif;color:#4682b4;");
- ACInput(mqttserver, "", "Server", "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$", "MQTT broker server");
- ACInput(channelid, "", "Channel ID", "^[0-9]{6}$");
- ACInput(userkey, "", "User Key");
- ACInput(apikey, "", "API Key");
- ACElement(newline, "<hr>");
- ACRadio(period, { "30 sec.", "60 sec.", "180 sec." }, "Update period", AC_Vertical, 1);
- ACSubmit(save, "Start", AUX_SAVE_URI);
- ACSubmit(discard, "Discard", "/");
- // Declare the custom Web page as /mqtt_setting and contains the AutoConnectElements
- AutoConnectAux mqtt_setting(AUX_SETTING_URI, "MQTT Setting", true, {
- style,
- header,
- caption,
- mqttserver,
- channelid,
- userkey,
- apikey,
- newline,
- period,
- save,
- discard
- });
- // Declare AutoConnectElements for the page as /mqtt_save
- ACText(caption2, "<h4>Parameters available as:</h4>", "text-align:center;color:#2f4f4f;padding:10px;");
- ACText(parameters);
- ACSubmit(clear, "Clear channel", AUX_CLEAR_URI);
- // Declare the custom Web page as /mqtt_save and contains the AutoConnectElements
- AutoConnectAux mqtt_save(AUX_SAVE_URI, "MQTT Setting", false, {
- caption2,
- parameters,
- clear
- });
- AutoConnect portal;
- AutoConnectConfig config;
- WiFiClient wifiClient;
- PubSubClient mqttClient(wifiClient);
- unsigned int updateInterval = 0;
- unsigned long lastPub = 0;
- #define MQTT_USER_ID "anyone"
- bool mqttConnect() {
- static const char alphanum[] = "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"; // For random generation of client ID.
- char clientId[9];
- uint8_t retry = 3;
- while (!mqttClient.connected()) {
- if (mqttserver.value.length() <= 0)
- break;
- mqttClient.setServer(mqttserver.value.c_str(), 1883);
- Serial.println(String("Attempting MQTT broker:") + mqttserver.value);
- for (uint8_t i = 0; i < 8; i++) {
- clientId[i] = alphanum[random(62)];
- }
- clientId[8] = '\0';
- if (mqttClient.connect(clientId, MQTT_USER_ID, userkey.value.c_str())) {
- Serial.println("Established:" + String(clientId));
- return true;
- }
- else {
- Serial.println("Connection failed:" + String(mqttClient.state()));
- if (!--retry)
- break;
- delay(3000);
- }
- }
- return false;
- }
- void mqttPublish(String msg) {
- String path = String("channels/") + channelid.value + String("/publish/") + apikey.value;
- mqttClient.publish(path.c_str(), msg.c_str());
- }
- int getStrength(uint8_t points) {
- uint8_t sc = points;
- long rssi = 0;
- while (sc--) {
- rssi += WiFi.RSSI();
- delay(20);
- }
- return points ? static_cast<int>(rssi / points) : 0;
- }
- // Retreive the value of each element entered by '/mqtt_setting'.
- String saveParams(AutoConnectAux& aux, PageArgument& args) {
- mqttserver.value.trim();
- channelid.value.trim();
- userkey.value.trim();
- apikey.value.trim();
- updateInterval = period.value().substring(0, 2).toInt() * 1000;
- // Echo back saved parameters to AutoConnectAux page.
- String echo = "Server: " + mqttserver.value + "<br>";
- echo += "Channel ID: " + channelid.value + "<br>";
- echo += "User Key: " + userkey.value + "<br>";
- echo += "API Key: " + apikey.value + "<br>";
- echo += "Update period: " + String(updateInterval / 1000) + " sec.<br>";
- parameters.value = echo;
- return String("");
- }
- void handleRoot() {
- String content =
- "<html>"
- "<head>"
- "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
- "</head>"
- "<body>"
- "<iframe width=\"450\" height=\"260\" style=\"transform:scale(0.79);-o-transform:scale(0.79);-webkit-transform:scale(0.79);-moz-transform:scale(0.79);-ms-transform:scale(0.79);transform-origin:0 0;-o-transform-origin:0 0;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;border: 1px solid #cccccc;\" src=\"https://thingspeak.com/channels/{{CHANNEL}}/charts/1?bgcolor=%23ffffff&color=%23d62020&dynamic=true&type=line\"></iframe>"
- "<p style=\"padding-top:5px;text-align:center\">" AUTOCONNECT_LINK(COG_24) "</p>"
- "</body>"
- "</html>";
- content.replace("{{CHANNEL}}", channelid.value);
- WiFiWebServer& webServer = portal.host();
- webServer.send(200, "text/html", content);
- }
- // Clear channel using ThingSpeak's API.
- void handleClearChannel() {
- HTTPClient httpClient;
- String endpoint = mqttserver.value;
- endpoint.replace("mqtt", "api");
- String delUrl = "http://" + endpoint + "/channels/" + channelid.value + "/feeds.json?api_key=" + userkey.value;
- Serial.print("DELETE " + delUrl);
- if (httpClient.begin(wifiClient, delUrl)) {
- Serial.print(":");
- int resCode = httpClient.sendRequest("DELETE");
- const String& res = httpClient.getString();
- Serial.println(String(resCode) + String(",") + res);
- httpClient.end();
- }
- else
- Serial.println(" failed");
- // Returns the redirect response. The page is reloaded and its contents
- // are updated to the state after deletion.
- WiFiWebServer& webServer = portal.host();
- webServer.sendHeader("Location", String("http://") + webServer.client().localIP().toString() + String("/"));
- webServer.send(302, "text/plain", "");
- webServer.client().flush();
- webServer.client().stop();
- }
- void setup() {
- delay(1000);
- Serial.begin(115200);
- Serial.println();
- // Reconnect and continue publishing even if WiFi is disconnected.
- config.homeUri = "/";
- config.autoReconnect = true;
- config.reconnectInterval = 1;
- portal.config(config);
- // Join the custom Web pages and register /mqtt_save handler
- portal.join({ mqtt_setting, mqtt_save });
- portal.on(AUX_SAVE_URI, saveParams);
- Serial.print("WiFi ");
- if (portal.begin()) {
- config.bootUri = AC_ONBOOTURI_HOME;
- Serial.println("connected:" + WiFi.SSID());
- Serial.println("IP:" + WiFi.localIP().toString());
- }
- else {
- Serial.println("connection failed:" + String(WiFi.status()));
- Serial.println("Needs WiFi connection to start publishing messages");
- }
- WiFiWebServer& webServer = portal.host();
- webServer.on("/", handleRoot);
- webServer.on(AUX_CLEAR_URI, handleClearChannel);
- }
- void loop() {
- if (WiFi.status() == WL_CONNECTED) {
- // MQTT publish control
- if (updateInterval > 0) {
- if (millis() - lastPub > updateInterval) {
- if (!mqttClient.connected()) {
- mqttConnect();
- }
- String item = String("field1=") + String(getStrength(7));
- mqttPublish(item);
- mqttClient.loop();
- lastPub = millis();
- }
- }
- }
- portal.handleClient();
- }
|