Всё сдаюсь.. нужна помощь.

Тема в разделе "Arduino & Shields", создана пользователем Securbond, 30 янв 2018.

  1. Securbond

    Securbond Гуру

    Давно не сидел в ArduinoIDE а тут чего то залип и никак не могу победить...
    Код в основе своей взят у http://forum.amperka.ru/members/ivanua.13613/ Прошу прощения, до сих пор не научился тут имена вставлять правильно .
    Внизу код... упорно не могу заставить работать функцию - void callback ()
    При обновлении топика ничего не происходит.. и как сделать что бы ESP держала соединение с MQTT сервером и не переподключалась постоянно ?

    Код (C++):
    #include <Adafruit_GFX.h>
    #include <Adafruit_NeoMatrix.h>
    #include <Adafruit_NeoPixel.h>
    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    #include <PubSubClient.h>
    #include <ESP8266HTTPUpdateServer.h>

    String ssid = "XXXXXXX";
    String password = "XXXXXXXXXXXXX";
    String ssidAP = "WiFi-Clock";
    String passwordAP = "";

    char mqtt_server[21] = "192.168.0.106";
    int  mqtt_port = 1883;
    char mqtt_user[7] = "XXXXXXXXXXXX";
    char mqtt_pass[7] = "XXXXXXXXXXXXX";
    char mqtt_name[21] = "ESP-12_informer";
    char mqtt_sub_temp[24] = "/pogoda/sensors/";
    char mqtt_sub_mes[16] = "/matrix/";

    WiFiClient ESPclient;
    PubSubClient MQTTclient(ESPclient);
    ESP8266HTTPUpdateServer httpUpdater;
    IPAddress apIP(192, 168, 4, 1);
    IPAddress timeServerIP;
    String ntpServerName = "ntp2.stratum2.ru";
    const int NTP_PACKET_SIZE = 48;
    byte packetBuffer[ NTP_PACKET_SIZE];
    unsigned int localPort = 2390;

    #define PIN 2 //Пин на который подключена лента
    #define printCom 1
    #define LEAP_YEAR(Y) (((1970 + Y) > 0 ) && !((1970 + Y) % 4) && (((1970 + Y) % 100) || !((1970 + Y) % 400)))
    String date;
    String txtInfo = "";
    int txtInfoLen;
    String dw, _month;
    char TimeStr[13];
    int year = 2017;
    int timeZone = 3;
    long localEpoc = 0;
    int secFr, lastSecond;
    uint8_t speedLine = 40;
    bool statusUpdateNtpTime = 0;
    long localMillisAtUpdate = 0;
    bool isDayLightSaving = false;
    boolean WIFI_connected = false;
    uint8_t hourTest[3], minuteTest[3];
    String y, mon, wd, d, h, m, s, mes;
    int hour = 7, minute = 52, second = 0, month = 6, day = 14,dayOfWeek = 4;
    static const uint8_t monthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    //-----
    WiFiUDP udp;
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(144, PIN, NEO_GRB + NEO_KHZ800);
    Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(12, 12, PIN,
      NEO_MATRIX_BOTTOM + NEO_MATRIX_LEFT +  NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
      NEO_GRB           + NEO_KHZ800);
    int x    = matrix.width();

                                             
    //------------ Функция подсчета локального времени
    void updateTime() {
      long curEpoch = localEpoc + ((millis() - localMillisAtUpdate) / 1000);
      long epoch = round(curEpoch + 86400L) % 86400L;
      hour = ((epoch % 86400L) / 3600) % 24;
      minute = (epoch % 3600) / 60;
      second = epoch % 60;
    }

    void timeUpdateNTP() {
      if(!WIFI_connected) return;
      statusUpdateNtpTime = 1;
      for(int timeTest = 0; timeTest < 3; timeTest++) {
        if(printCom) Serial.print("Proba #");
        if(printCom) Serial.println(timeTest + 1);
        updateTime();
        getNTPtime();
        hourTest[timeTest] = hour;
        minuteTest[timeTest] = minute;
        if(statusUpdateNtpTime == 0) {
          if(printCom) Serial.print("ERROR TIME!!!\r\n");
            return;
        }
        if(timeTest > 0) {
          if((hourTest[timeTest] != hourTest[timeTest - 1] || minuteTest[timeTest] != minuteTest[timeTest - 1])) {
            statusUpdateNtpTime = 0;
            if(printCom) Serial.print("ERROR TIME!!!\r\n");
            return;
          }
        }
      }
      statusUpdateNtpTime = 1;
      localMillisAtUpdate = millis();
      localEpoc = (hour * 60 * 60 + minute * 60 + second);
      convertDw();
      convertMonth();
      date = "     " + dw + ", " + String(day) + " " + _month + " " + String(year) + "р.          ";
      if(printCom) Serial.print(String(hour) + ":" + String(minute) + ":" + String(second) + " ");
      if(printCom) Serial.print(String(day) + "-" + String(month) + "-" + String(year) + " DW=" + String(dayOfWeek) + "\r\n");
      if(printCom) Serial.println("Time update OK");
    }

    //--Функция получения времени с ntp сервера --
    void getNTPtime() {
      WiFi.hostByName(ntpServerName.c_str(), timeServerIP);
      int cb;
      for(int i = 0; i < 3; i++){
        memset(packetBuffer, 0, NTP_PACKET_SIZE);
        packetBuffer[0] = 0b11100011;
        packetBuffer[1] = 0;
        packetBuffer[2] = 6;
        packetBuffer[3] = 0xEC;
        packetBuffer[12] = 49;
        packetBuffer[13] = 0x4E;
        packetBuffer[14] = 49;
        packetBuffer[15] = 52;
        udp.beginPacket(timeServerIP, 123);
        udp.write(packetBuffer, NTP_PACKET_SIZE);
        udp.endPacket();
        delay(800);
        cb = udp.parsePacket();
        if(!cb && printCom) Serial.println("no packet yet..." + String (i + 1));
        if(!cb && i == 2) {
          statusUpdateNtpTime = 0;
          return;
        }
        if(cb) i = 3;
      }
      if(cb) {
        udp.read(packetBuffer, NTP_PACKET_SIZE);
        unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
        unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
        unsigned long secsSince1900 = highWord << 16 | lowWord;
        const unsigned long seventyYears = 2208988800UL;      
        unsigned long epoch = secsSince1900 - seventyYears;
        boolean summerTime;
        if(month < 3 || month > 10) summerTime = false;
        if(month > 3 && month < 10) summerTime = true;
        if(month == 3 && (hour + 24 * day) >= (3 + 24 * (31 - (5 * year / 4 + 4) % 7)) || month == 10 && (hour + 24 * day) < (3 + 24 * (31 - (5 * year / 4 + 1) % 7))) summerTime = true;
        epoch = epoch + timeZone * 3600 + (3600 * (isDayLightSaving && summerTime));    
        year = 0;
        int days = 0;
        uint32_t time;
        time = epoch / 86400;
        hour = (epoch % 86400L) / 3600;
        minute = (epoch % 3600) / 60;
        second = epoch % 60;
        dayOfWeek = (((time) + 4) % 7) + 1;
        while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
          year++;
        }
        days -= LEAP_YEAR(year) ? 366 : 365;
        time -= days;
        days = 0;
        month = 0;
        uint8_t monthLength = 0;
        for(month = 0; month < 12; month++) {
          if(month == 1) {
            if(LEAP_YEAR(year)) monthLength = 29;
            else monthLength = 28;
          }
          else monthLength = monthDays[month];
          if(time >= monthLength) time -= monthLength;
          else break;
        }
        month = month + 1;
        day = time + 1;
        year += 1970;
        return;
      }
      if(printCom) Serial.println("Nie ma czasu(((");
    }

    // ------------Отображение русского шрифта-------------
    String utf8rus(String source)
    {
      int i,k;
      String target;
      unsigned char n;
      char m[2] = { '0', '\0' };

      k = source.length(); i = 0;

      while (i < k) {
        n = source[i]; i++;

        if (n >= 0xC0) {
          switch (n) {
            case 0xD0: {
              n = source[i]; i++;
              if (n == 0x81) { n = 0xA8; break; }
              if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
              break;
            }
            case 0xD1: {
              n = source[i]; i++;
              if (n == 0x91) { n = 0xB8; break; }
              if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
              break;
            }
          }
        }
        m[0] = n; target = target + String(m);
      }
    return target;
    }

    void showText( String t, uint16_t color, int wait, int len){
      matrix.setTextColor(color);
      while (--x > (len*(-1)))
      {
        matrix.fillScreen(0);
        matrix.setCursor(x, 4);
        matrix.print(utf8rus(t));
        matrix.show();
        delay(wait);
      }
        x = matrix.width();
    }
    void DisplayTime(void){
       int m = minute;
       int h = hour ;
     
    if (minute < 10) {
       Serial.print("Time: ");
       Serial.print(h);
       Serial.print(":0");
       Serial.println(m);
       sprintf(TimeStr,"   %d:0%d ",h,m );
       showText(TimeStr,matrix.Color((random(255)),(random(255)),(random(255))), 120, 150);  
       }
       else {
       Serial.print("Time: ");
       Serial.print(h);
       Serial.print(":");
       Serial.println(m);
       sprintf(TimeStr,"   %d:%d ",h,m );
       showText(TimeStr,matrix.Color((random(255)),(random(255)),(random(255))), 120, 150);
       }
    }
    void convertDw(){
      switch(dayOfWeek){
        case 2 : dw = "Понедельник"; break;
        case 3 : dw = "Вторник"; break;
        case 4 : dw = "Среда"; break;
        case 5 : dw = "Четверг"; break;
        case 6 : dw = "Пятница"; break;
        case 7 : dw = "Суббота"; break;
        case 1 : dw = "Воскресенье"; break;
      }
    }
    // ============================= Перевод месяцев на русский язык
    void convertMonth(){
      switch(month){
        case 1 : _month = "января"; break;
        case 2 : _month = "февраля"; break;
        case 3 : _month = "марта"; break;
        case 4 : _month = "апреля"; break;
        case 5 : _month = "мая"; break;
        case 6 : _month = "июня"; break;
        case 7 : _month = "июля"; break;
        case 8 : _month = "августа"; break;
        case 9 : _month = "сентября"; break;
        case 10 : _month = "октября"; break;
        case 11 : _month = "ноября"; break;
        case 12 : _month = "декабря"; break;
      }
    }
    //**************
    void wifiConnect(){
      if(printCom) Serial.print("Connecting WiFi ");
      WiFi.disconnect();
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid.c_str(), password.c_str());
      for(int i = 0; i < 15; i++){
        if(WiFi.status() == WL_CONNECTED){
          WIFI_connected = true;
          if(printCom) Serial.print("IP address:       ");
          if(printCom) Serial.println(WiFi.localIP());
          String aaa=WiFi.localIP().toString();
          Serial.println("IP address: ");
          Serial.println(aaa.c_str());
          timeUpdateNTP();
          return;
        }
        if(printCom) Serial.print(".");
        int j = 0;
        while(j < 500){
          if(j % 10 == 0) Serial.print(i);
          j++;
          delay(1);
        }

      }
      Serial.println("Setting AP mode default parameters");
      WiFi.disconnect();
      WiFi.mode(WIFI_AP);
      WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
      WiFi.softAP(ssidAP.c_str(), passwordAP.c_str());
      Serial.print("Подключитесь к точке доступа WiFi-Clock и зайдите по адресу адресу: 192.168.4.1         ");
      if(printCom) Serial.print("Wifi ip:");
      if(printCom) Serial.println(WiFi.softAPIP());
    }

     

    Понимаю что код - портянка, но буду благодарен за помощь.
     
  2. Securbond

    Securbond Гуру

    Продолжение кода... в одно сообщение не влез
    Код (C++):
    void setup(){
    Serial.begin(115200);
    Serial.println("Starting UDP");
       udp.begin(localPort);
       Serial.print("Local port: ");
       Serial.println(udp.localPort());
       delay(200);
    wifiConnect();
      if(printCom) Serial.println("");
      if(printCom) Serial.print("Connected: ");
      if(printCom) Serial.println(WiFi.localIP());

    // *********** MQTT client
      MQTTclient.setServer(mqtt_server, mqtt_port);
      MQTTclient.setCallback(callback);
      MQTTclient.connect(mqtt_name);
      MQTTclient.subscribe("/pogoda/sensors/");
      MQTTclient.subscribe("/matrix/");

      matrix.cp437(true);
      strip.begin();
      matrix.begin();
      matrix.setTextWrap(false);
      matrix.setBrightness(50);
      matrix.setTextColor(matrix.Color(245,0,0));
    // Инициализация UDP соединения с NTP сервером
    }
    void callback(char* topic, byte* payload, unsigned int length) {                  
      if (String(topic) == "/matrix/inform/") {
        txtInfoLen =  length;
        txtInfo = "";
        for (int i = 0; i < length; i++) {                                            
       txtInfo += ((char)payload[i]);
        }                                                                                                                                       //
       txtInfoLen = (txtInfoLen*6);
       showText(txtInfo,matrix.Color(48, 23, 99), 120, txtInfoLen);
        }
    }

    void reconnect(){
      if(!ESPclient.connected() && WiFi.status() == WL_CONNECTED) {
        Serial.print("Attempting MQTT connection...");
        if(MQTTclient.connect(mqtt_name, mqtt_user, mqtt_pass)) {
          Serial.println("MQTT connected");
          MQTTclient.subscribe(mqtt_sub_mes);
          MQTTclient.subscribe(mqtt_sub_temp);
        }
        else {
          Serial.print("failed, rc= ");
          Serial.println(MQTTclient.state());
        }
      }
    }

    void loop() {
      updateTime();
       if(!MQTTclient.connected()) {
            Serial.print("not connect MQTT ");
            reconnect();
          }
    MQTTclient.loop();
      if(second != lastSecond) {
        lastSecond = second;
        secFr = 0;
      } else secFr++;
       if(minute == 0 && second == 0 && secFr == 0 && (hour >= 7 && hour <= 23)) {
        Serial.print("Not Time(( ");
      }
      // ---------- 25 сек. Выводит на матрицу время -----------------------------------
      if(second == 25  && statusUpdateNtpTime == 1 && secFr == 0) {
        DisplayTime();    
       }

    // ---------- 10 сек. Тыц в MQTT -----------------------------------
      if(second == 10  && statusUpdateNtpTime == 1 && secFr == 0) {
          if(!MQTTclient.connected()) {
            reconnect();
            MQTTclient.publish("/matrix/off/","Тыц");
          }
          if(MQTTclient.connected()) {
          Serial.println("Ok MQTT ");    
          MQTTclient.publish("/matrix/on/","Тыц");      
          }
      }
      // ---------- 41 сек. проверка доступности Wi-Fi сети -----------------------------------
      if(second == 41 && secFr == 00 && WiFi.status() != WL_CONNECTED && WIFI_connected != false) {
        WIFI_connected = false;
      }
    // ---------- 42 сек. повторное подключение к wi-Fi каждую 1, 6, 11, 16...56 минуту ---
      if(!WIFI_connected && second == 42 && (minute % 5 == 1)) {
        wifiConnect();
      }
    // ---------- когда сеть WiFi доступна то вызываем следующую функцию ----------------------------
      if(WIFI_connected) {
      }
    // ---------- 43 сек. обновления времени по сети -------------------------------------
        if((statusUpdateNtpTime == 0 && second == 43) || (minute == 5 && second == 43)) timeUpdateNTP();
       if (WiFi.status() == WL_CONNECTED && second == 55 && secFr == 0) {            
        if (!MQTTclient.connected()) reconnect();                                        
      }
    }