123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- 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
- Also, this example uses AutoConnectAux menu customization which stored in SPIFFS.
- To evaluate this example, you upload the contents as mqtt_setting.json of
- the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu
- in Arduino IDE).
- This example is based on the thinkspeak.com environment as of Dec. 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 <WebServer.h>
- #include <SPIFFS.h>
- #include <HTTPClient.h>
- #define GET_CHIPID() ((uint16_t)(ESP.getEfuseMac()>>32))
- #endif
- #include <PubSubClient.h>
- #include <AutoConnect.h>
- /*
- AC_USE_SPIFFS indicates SPIFFS or LittleFS as available file systems that
- will become the AUTOCONNECT_USE_SPIFFS identifier and is exported as showng
- the valid file system. After including AutoConnect.h, the Sketch can determine
- whether to use FS.h or LittleFS.h by AUTOCONNECT_USE_SPIFFS definition.
- */
- #include <FS.h>
- #if defined(ARDUINO_ARCH_ESP8266)
- #ifdef AUTOCONNECT_USE_SPIFFS
- FS& FlashFS = SPIFFS;
- #else
- #include <LittleFS.h>
- FS& FlashFS = LittleFS;
- #endif
- #elif defined(ARDUINO_ARCH_ESP32)
- #include <SPIFFS.h>
- fs::SPIFFSFS& FlashFS = SPIFFS;
- #endif
- #define PARAM_FILE "/param.json"
- #define AUX_MQTTSETTING "/mqtt_setting"
- #define AUX_MQTTSAVE "/mqtt_save"
- #define AUX_MQTTCLEAR "/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
- AutoConnect portal;
- AutoConnectConfig config;
- WiFiClient wifiClient;
- PubSubClient mqttClient(wifiClient);
- String serverName;
- String channelId;
- String userKey;
- String apiKey;
- String apid;
- String hostName;
- 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 (serverName.length() <= 0)
- break;
- mqttClient.setServer(serverName.c_str(), 1883);
- Serial.println(String("Attempting MQTT broker:") + serverName);
- for (uint8_t i = 0; i < 8; i++) {
- clientId[i] = alphanum[random(62)];
- }
- clientId[8] = '\0';
- if (mqttClient.connect(clientId, MQTT_USER_ID, userKey.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 + String("/publish/") + apiKey;
- 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;
- }
- String loadParams(AutoConnectAux& aux, PageArgument& args) {
- (void)(args);
- File param = FlashFS.open(PARAM_FILE, "r");
- if (param) {
- aux.loadElement(param);
- param.close();
- }
- else
- Serial.println(PARAM_FILE " open failed");
- return String("");
- }
- String saveParams(AutoConnectAux& aux, PageArgument& args) {
- serverName = args.arg("mqttserver");
- serverName.trim();
- channelId = args.arg("channelid");
- channelId.trim();
-
- userKey = args.arg("userkey");
- userKey.trim();
-
- apiKey = args.arg("apikey");
- apiKey.trim();
-
- String upd = args.arg("period");
- updateInterval = upd.substring(0, 2).toInt() * 1000;
- String uniqueid = args.arg("uniqueid");
- hostName = args.arg("hostname");
- hostName.trim();
-
- // The entered value is owned by AutoConnectAux of /mqtt_setting.
- // To retrieve the elements of /mqtt_setting, it is necessary to get
- // the AutoConnectAux object of /mqtt_setting.
- File param = FlashFS.open(PARAM_FILE, "w");
- portal.aux("/mqtt_setting")->saveElement(param, { "mqttserver", "channelid", "userkey", "apikey", "period", "uniqueid", "hostname" });
- param.close();
- // Echo back saved parameters to AutoConnectAux page.
- AutoConnectText& echo = aux["parameters"].as<AutoConnectText>();
- echo.value = "Server: " + serverName + "<br>";
- echo.value += "Channel ID: " + channelId + "<br>";
- echo.value += "User Key: " + userKey + "<br>";
- echo.value += "API Key: " + apiKey + "<br>";
- echo.value += "Update period: " + String(updateInterval / 1000) + " sec.<br>";
- echo.value += "Use APID unique: " + uniqueid + "<br>";
- echo.value += "ESP host name: " + hostName + "<br>";
- 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);
- WiFiWebServer& webServer = portal.host();
- webServer.send(200, "text/html", content);
- }
- // Clear channel using Thingspeak's API.
- void handleClearChannel() {
- HTTPClient httpClient;
- String endpoint = serverName;
- endpoint.replace("mqtt", "api");
- String delUrl = "http://" + endpoint + "/channels/" + channelId + "/feeds.json?api_key=" + userKey;
- 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();
- }
- // Load AutoConnectAux JSON from the flash on the board.
- bool loadAux(const String auxName) {
- bool rc = false;
- String fn = auxName + ".json";
- File fs = FlashFS.open(fn.c_str(), "r");
- if (fs) {
- rc = portal.load(fs);
- fs.close();
- }
- else
- Serial.println("Filesystem open failed: " + fn);
- return rc;
- }
- void setup() {
- delay(1000);
- Serial.begin(115200);
- Serial.println();
- #if defined(ARDUINO_ARCH_ESP8266)
- FlashFS.begin();
- #elif defined(ARDUINO_ARCH_ESP32)
- FlashFS.begin(true);
- #endif
- loadAux(AUX_MQTTSETTING);
- loadAux(AUX_MQTTSAVE);
- AutoConnectAux* setting = portal.aux(AUX_MQTTSETTING);
- if (setting) {
- PageArgument args;
- AutoConnectAux& mqtt_setting = *setting;
- loadParams(mqtt_setting, args);
- AutoConnectCheckbox& uniqueidElm = mqtt_setting["uniqueid"].as<AutoConnectCheckbox>();
- AutoConnectInput& hostnameElm = mqtt_setting["hostname"].as<AutoConnectInput>();
- if (uniqueidElm.checked) {
- config.apid = String("ESP") + "-" + String(GET_CHIPID(), HEX);
- Serial.println("apid set to " + config.apid);
- }
- if (hostnameElm.value.length()) {
- config.hostName = hostnameElm.value;
- Serial.println("hostname set to " + config.hostName);
- }
- config.homeUri = "/";
- portal.on(AUX_MQTTSETTING, loadParams);
- portal.on(AUX_MQTTSAVE, saveParams);
- }
- else
- Serial.println("aux. load error");
- // Reconnect and continue publishing even if WiFi is disconnected.
- config.autoReconnect = true;
- config.reconnectInterval = 1;
- portal.config(config);
- 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()));
- while (1) {
- delay(100);
- yield();
- }
- }
- WiFiWebServer& webServer = portal.host();
- webServer.on("/", handleRoot);
- webServer.on(AUX_MQTTCLEAR, handleClearChannel);
- }
- void loop() {
- portal.handleClient();
- if (updateInterval > 0) {
- if (millis() - lastPub > updateInterval) {
- if (!mqttClient.connected()) {
- mqttConnect();
- }
- String item = String("field1=") + String(getStrength(7));
- mqttPublish(item);
- mqttClient.loop();
- lastPub = millis();
- }
- }
- }
|