ESP8266 + Slack (ssl->need_bytes=16432 > 6859)
Я пытаюсь подключить Adafruit Huzzah ESP8266 к Slack.
У меня возникла проблема с подключением, и мне нужна помощь или совет. Мне иногда удается установить соединение, но иногда на начальном этапе, когда я устанавливаю первое соединение, возникают ошибки, и оно полностью терпит неудачу, повторяя соединение/разъединение снова и снова.
Обычно я получаю следующую ошибку:
ssl->need_bytes=16432 > 6859
Устранение неполадок на данный момент
Согласно этой проблеме с github: https://github.com/esp8266/Arduino/issues/1375
Насколько я понимаю, ошибка вызвана слишком большим SSL-сертификатом Slack. Это имеет смысл, но иногда мой код (см. ниже) действительно работает, поэтому я запутался.
Когда это работает, обычно сначала пару раз происходит сбой, прежде чем поддерживать постоянный пинг со Slack. В этот момент он работает так, как ожидалось, и я могу безошибочно отправлять команды из Slack на плату.
Кто-нибудь знает, почему это иногда работает, а иногда нет?
Я предполагаю, что это как-то связано со слишком большим размером SSL-сертификата, но если это так, то почему бы ему не сбоить каждый раз, а иногда работать?
Любая помощь приветствуется.
Ошибки в Serial Monitor
Вот что я вижу в журнале Serial Monitor:
⸮scandone
f r0, scandone
f r0, scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 7
cnt
connected with 2WIRE952, channel 3
dhcp client start...
ip:192.168.1.73,mask:255.255.255.0,gw:192.168.1.254
Waiting for time sync
please start sntp first !
.please start sntp first !
.Sun Apr 16 06:57:35 2017
Time is synced
ssl->need_bytes=16432 > 6859
WebSocket Host=mpmulti-4pcb.slack-msgs.com Path=/websocket/Z5ZDermv9h2Q7HL88ukG5ddIvY--zrBAVCN4423KOy5t_6wN3AW859grAYCYr6L-0l0leeXA3AhlO1VmIxcCopS1pJ-IkrVOdmel50tgcA7hBJwEIkpI-biYnraTFc88K4F6wqL3TE_gi1jU0SJHhR6_aD5435yE8FRALEflTkY=
[WebSocket] Connected to: /websocket/Z5ZDermv9h2Q7HL88ukG5ddIvY--zrBAVCN4423KOy5t_6wN3AW859grAYCYr6L-0l0leeXA3AhlO1VmIxcCopS1pJ-IkrVOdmel50tgcA7hBJwEIkpI-biYnraTFc88K4F6wqL3TE_gi1jU0SJHhR6_aD5435yE8FRALEflTkY=
[WebSocket] Disconnected :-(
ssl->need_bytes=16432 > 6859
WebSocket Host=mpmulti-eavp.slack-msgs.com Path=/websocket/HjuUTJUL4ghmBCthwdFxOYNWD0wGjWbCgQZwnum546F5Nj8rrJ7LJgeyVOLqSv9sBHtkZBrCBLyxdM2oMB85-GXGwtIgg9anVYFL66vMB8yEN9Xout7OMmqlEewZsL7n2vqJyvx_qAnQ9M8UwOnZwETkNYJ51XrUvR6EjIAvAQE=
[WebSocket] Connected to: /websocket/HjuUTJUL4ghmBCthwdFxOYNWD0wGjWbCgQZwnum546F5Nj8rrJ7LJgeyVOLqSv9sBHtkZBrCBLyxdM2oMB85-GXGwtIgg9anVYFL66vMB8yEN9Xout7OMmqlEewZsL7n2vqJyvx_qAnQ9M8UwOnZwETkNYJ51XrUvR6EjIAvAQE=
[WebSocket] Disconnected :-(
ssl->need_bytes=8496 > 6859
Мой код скетча
Файл Sketch, который я компилирую с помощью Arduino IDE.
Примечание: обязательно обновите Wifi + Slack Bot Token при тестировании 8-)
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <time.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WebSocketsClient.h>
#include <ArduinoJson.h>
#define SLACK_SSL_FINGERPRINT "AC 95 5A 58 B8 4E 0B CD B3 97 D2 88 68 F5 CA C1 0A 81 E3 6E" // Если Slack изменит свой отпечаток SSL, вам нужно будет обновить это
#define WIFI_SSID ""
#define WIFI_PASSWORD ""
String SLACK_BOT_TOKEN = ""; // Получите токен, создав новую интеграцию с ботом на https://my.slack.com/services/new/bot
#define WORD_SEPERATORS "., \"'()[]<>;:-+&?!\n\t"
ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
long nextCmdId = 1;
bool connected = false;
//Настройки часового пояса
const int timezone = 9;
const int dst = 0; //дневного сбережения
/**
Sends a ping message to Slack. Call this function immediately after establishing
the WebSocket connection, and then every 5 seconds to keep the connection alive.
*/
void sendPing() {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["type"] = "ping";
root["id"] = nextCmdId++;
String json;
root.printTo(json);
webSocket.sendTXT(json);
}
/**
Looks for color names in the incoming slack messages and
animates the ring accordingly. You can include several
colors in a single message, e.g. `red blue zebra black yellow rainbow`
*/
void processSlackMessage(char *payload) {
char *nextWord = NULL;
bool zebra = false;
for (nextWord = strtok(payload, WORD_SEPERATORS); nextWord; nextWord = strtok(NULL, WORD_SEPERATORS)) {
if (strcasecmp(nextWord, "red") == 0) {
Serial.printf("Yay! Its red.");
}
}
}
/**
Called on each web socket event. Handles disconnection, and also
incoming messages from slack.
*/
void webSocketEvent(WStype_t type, uint8_t *payload, size_t len) {
switch (type) {
case WStype_DISCONNECTED:
Serial.printf("[WebSocket] Disconnected :-( \n");
connected = false;
break;
case WStype_CONNECTED:
Serial.printf("[WebSocket] Connected to: %s\n", payload);
sendPing();
break;
case WStype_TEXT:
Serial.printf("[WebSocket] Message: %s\n", payload);
processSlackMessage((char*)payload);
break;
}
}
/**
Establishes a bot connection to Slack:
1. Performs a REST call to get the WebSocket URL
2. Conencts the WebSocket
Returns true if the connection was established successfully.
*/
bool connectToSlack() {
// Шаг 1: Найдите адрес WebSocket через RTM API (https://api.slack.com/methods/rtm.start)
HTTPClient http;
http.begin("https://slack.com/api/rtm.start?token=" + SLACK_BOT_TOKEN, SLACK_SSL_FINGERPRINT);
int httpCode = http.GET();
if (httpCode != HTTP_CODE_OK) {
Serial.printf("HTTP GET failed with code %d\n", httpCode);
return false;
}
WiFiClient *client = http.getStreamPtr();
client->find("wss:\\/\\/");
String host = client->readStringUntil('\\');
String path = client->readStringUntil('"');
path.replace("\\/", "/");
// Шаг 2: Откройте соединение WebSocket и зарегистрируйте обработчик событий
Serial.println("WebSocket Host=" + host + " Path=" + path);
webSocket.beginSSL(host, 443, path, "", "");
webSocket.onEvent(webSocketEvent);
return true;
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
WiFiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);
while (WiFiMulti.run() != WL_CONNECTED) {
delay(500);
}
//настраиваем протокол сетевого времени (ntp)
configTime(timezone * 3600, dst, "pool.ntp.org", "time.nist.gov"); //configtime — это функция esp8266
Serial.println("\nWaiting for time sync");
while (!time(nullptr)) {
Serial.print(".");
delay(1000);
}
Serial.println("Time is synced");
delay(500);
}
unsigned long lastPing = 0;
/**
Sends a ping every 5 seconds, and handles reconnections
*/
void loop() {
webSocket.loop();
if (connected) {
// Отправлять ping каждые 5 секунд, чтобы поддерживать соединение
if (millis() - lastPing > 5000) {
sendPing();
lastPing = millis();
}
} else {
// Пытаемся подключиться/переподключиться к slack
connected = connectToSlack();
if (!connected) {
delay(500);
}
}
}
@Axel, 👍1
Обсуждение1 ответ
замените rtm.start
на rtm.connect
согласно журналу последних обновлений за апрель 2017 г.
- Проблема с отправкой POST-запроса с использованием библиотеки WiFiEsp
- http.POST не отправляет данные на локальную веб-страницу
- esp8266 WiFi не может подключиться к PHP- серверу
- Как читать и записывать EEPROM в ESP8266
- Как сделать выводы Tx и Rx на ESP-8266-01 в выводах GPIO?
- Как навсегда изменить скорость передачи данных ESP8266 (12e)?
- Как заставить 5-вольтовое реле работать с NodeMCU
- Как исправить: Invalid conversion from 'const char*' to 'char*' [-fpermissive]
это, вероятно, работает _иногда_, потому что в этот момент у вас достаточно оперативной памяти. Вы можете попробовать уменьшить использование оперативной памяти с помощью макроса
F()
для длинных строк и удалить все ненужные вам библиотеки. Надежный способ - передать запрос в slack, используя что-то вроде php-сервера с меньшим SSL-сертификатом; затем вы говорите с блоком PHP вместо slack, и он передает запрос/ответ обратно в ESP., @dandavis@dandavis - я думаю, ты попал в точку. Уменьшение количества кода в Sketch и повторное тестирование делают его более надежным, но все же этого недостаточно для обеспечения 100% надежности. Ответ от Slack просто слишком велик для обработки. Я просто собираюсь использовать Raspberry Pi для связи со Slack, а затем отправлять команды на Arduino., @Axel
@Axel, PI на самом деле также имеет контакты GPIO (3,3 В!) И должен иметь возможность обрабатывать базовые операции ввода-вывода, так что вы можете даже рассмотреть возможность выпуска Arduino., @Paul
@Paul - Я фактически закончил тем, что использовал Raspberry PI Zero W, который в конечном итоге имел требования к памяти, которые могли обрабатывать мои вызовы API, и все другие встроенные функции, такие как контакты WIFI и GPIO. Неплохо для доски за 10 долларов., @Axel
@Axel Arduino - это платы для разработки микроконтроллеров, а это совсем другое. Если вы собираетесь производить массово, использование микроконтроллеров (чип на самой Arduino) работает очень хорошо (стабильно, надежно, дешево, мало)., @Paul
@Paul - я понимаю разницу. Но возвращаясь к теме моего вопроса: плата Arduino, которую я использовал, не имела требований к памяти для проекта, который я создавал. Моя проблема не имела ничего общего с наличием контактов GPIO 3,3 В, как указано в вашем первом комментарии. Я уже знал, что у Arduino есть такие: P, @Axel
Кроме того, это не для массового производства. Это был разовый проект для личного пользования ;), @Axel