интернет часы с погодой на esp8266, P10 LegMatrix

lean_74
Offline
Зарегистрирован: 22.12.2015

Обещал выложить часики на светодиодной матрице

/*  подключение
Pin on  DMD P10     GPIO      NODEMCU               
        2  A        GPIO16    D0                                
        8  CLK      GPIO14    D5                           
        4  B        GPIO12    D6                                              -     
        10 SCK      GPIO0     D3                          
        12 R        GPIO13    D7
        1  NOE      GPIO15    D8
        3  GND      GND       GND
*/

#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager
#include <WiFiClient.h>                   // Библиотека для связи с сетевыми хостами (локальными и интернет)
#include <TimeLib.h>                      // Библиотека для работы с временем
#include <SPI.h>
#include <DMD2.h>
#include <fonts/Droid_Sans_16.h>
#include <fonts/Arial_Black_16_ISO_8859_1.h> //Arial_Black_16_ISO_8859_1.h

//SoftDMD dmd(1,1);  // DMD controls the entire display
SPIDMD dmd(1,1);  // DMD controls the entire display
DMD_TextBox box(dmd, 0, 0, 32, 16);

String regionID = "11207";                  // Код региона по Yandex для выбора часового пояса https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/

String SunriseTime, SunsetTime, Temperature;
char icon[20];

WiFiClient client;                        // Создаём объект для работы с удалёнными хостами

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
   Serial.println("\n\n");
 
  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;
  //reset settings - for testing
  //wifiManager.resetSettings();

  //sets timeout until configuration portal gets turned off
  //useful to make it all retry or go to sleep
  //in seconds
  wifiManager.setTimeout(180);
  
  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  if(!wifiManager.autoConnect("AutoConnectAP")) {
    Serial.println("failed to connect and hit timeout");
    delay(500);
    //reset and try again, or maybe put it to deep sleep
//    ESP.reset();
//    delay(5000);
  } 
  dmd.setBrightness(50);
  dmd.selectFont(Arial_Black_16_ISO_8859_1);
  dmd.begin();
  //if you get here you have connected to the WiFi
  Serial.println("connected...yeey :)");
  while (!TimeAndWeather())                                   // Синхронизируем время микроконтроллера с реальным временем и получаем информацию о погоде
    delay(500);
  digitalClockDisplay();                                      // Выводим дату и время
}

static boolean flagSec = 0;
String DataTime;
boolean rejim=0;
boolean flag=1;
unsigned long halfSecondMillis = millis();
unsigned long lastMillis = millis();
unsigned long lastMillisRejim = millis();

void loop() {
  // put your main code here, to run repeatedly:
     if (flag == 0){
      byte i1=0;
   while (!TimeAndWeather()){  delay(500); i1++; if (i1==10) break; }            // Синхронизируем время микроконтроллера с реальным временем и получаем информацию о погоде        
      lastMillis = millis(); flag = 1;
         }
    if (millis() - lastMillis >= 5 * 1000*60) {  //  ОБНОВЛЯЕМ ДАННЫЕ РАЗ В ПЯТЬ МИНУТ
      flag = 0;
    }
  if (millis() - lastMillisRejim >= 17000){rejim=!rejim; lastMillisRejim = millis(); box.clear(); }
   
  if (rejim==0){
      dmd.selectFont(Arial_Black_16_ISO_8859_1);  
    digitalClockDisplay();
}else{
      dmd.selectFont(Droid_Sans_16); 
String ret=WeatherDisplay();
//  DataTime="Сегодня "+leadNull(day())+"."+leadNull(month())+"."+year()+" "+" на улице "+ Temperature + " C "+ret+  " Восход в " + SunriseTime+" Закат в " + SunsetTime;
  DataTime="Today "+leadNull(day())+"."+leadNull(month())+"."+year()+" "+" on the street "+ Temperature + "C "+ret+  " Sunrise " + SunriseTime+" Sunset " + SunsetTime;
scroll_text();
  }
}


bool TimeAndWeather () {                                                    // Функция синхронизации времени работы программы с реальным временем и получения информации о погоде
  if (client.connect("yandex.com",443)) {                                   // Если удаётся установить соединение с указанным хостом (Порт 443 для https)
    client.println("GET /time/sync.json?geo=" + regionID + " HTTP/1.1\r\nHost: yandex.com\r\nConnection: close\r\n\r\n"); // Отправляем параметры запроса
    delay(200);                                                             // Даём серверу время, чтобы обработать запрос
    char endOfHeaders[] = "\r\n\r\n";                                       // Системные заголовки ответа сервера отделяются от остального содержимого двойным переводом строки
    if (!client.find(endOfHeaders)) {                                       // Отбрасываем системные заголовки ответа сервера
      Serial.println("Invalid response");                                   // Если ответ сервера не содержит системных заголовков, значит что-то пошло не так
      return false;                                                         // и пора прекращать всё это дело
    }
 
    Serial.println("chitaem dannie");  
  String line2;
  while ( client.available() )
  {
    char c = client.read();
    line2 += c;
  }
    Serial.print("line2= "); 
    Serial.println(line2);
 String StringCurrentTime = line2.substring(8,18);
   
    int n_offset=line2.indexOf("offset"); 
    int  k_offset = line2.indexOf(',',n_offset);
    String StringOffset= line2.substring(n_offset+8,k_offset); //18000000
    

    int n_sunrise=line2.indexOf("sunrise"); 
    int  k_sunrise = line2.indexOf(',',n_sunrise);
    SunriseTime= line2.substring(n_sunrise+9,k_sunrise); //18000000
   
    int n_sunset=line2.indexOf("sunset"); 
    int  k_sunset = line2.indexOf(',',n_sunset);
    SunsetTime= line2.substring(n_sunset+8,k_sunset); //18000000

    int n_temp=line2.indexOf("temp"); 
    int  k_temp = line2.indexOf(',',n_temp);
    Temperature= line2.substring(n_temp+6,k_temp); //18000000

    int n_icon=line2.indexOf("icon"); 
    int  k_icon = line2.indexOf(',',n_icon);
    String Stringicon= line2.substring(n_icon+6,k_icon); //18000000
      Serial.print("Stringicon= "); 
    Serial.println(Stringicon); 
    client.stop();                                                          // Разрываем соединение с сервером
    strcpy(icon,Stringicon.c_str());       // Достаём иконку - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> icon
      Serial.print("icon= "); 
    Serial.println(icon); 
   
    unsigned long CurrentTime = StringToULong(StringCurrentTime);           // Переводим значение реального времени в секундах, считанное с Яндекса, из String в unsigned long
    unsigned long Offset = StringToULong(StringOffset) / 1000;              // Переводим значение смещения времени по часовому поясу, считанное с Яндекса, из String в unsigned long и переводим его в секунды
    setTime(CurrentTime + Offset);                                          // Синхронизируем время
    
    return true;
  }
}

unsigned long StringToULong(String Str) {                     // Эта функция преобразует String в unsigned long
  unsigned long ULong = 0;
  for (int i = 0; i < Str.length(); i++) {                    // В цикле посимвольно переводим строку в unsigned long
     char c = Str.charAt(i);
     if (c < '0' || c > '9') break;
     ULong *= 10;
     ULong += (c - '0');
  }
  return ULong;
}

void scroll_text(){
    const char *next = DataTime.c_str();
  while(*next) {
//    Serial.print(*next);
    box.print(*next);
    delay(300);
    next++;
  }
}

void digitalClockDisplay(){                                   // Эта функция выводит время
 if (millis() - halfSecondMillis > 500) {
  halfSecondMillis=millis();
  int uiTime=hour()*100+minute();
   box.clear();
   dmd.drawChar(  0,  0,'0'+((uiTime%10000)/1000), GRAPHICS_ON );   // thousands
   dmd.drawChar(  8,  0, '0'+((uiTime%1000) /100),  GRAPHICS_ON );   // hundreds
   dmd.drawChar( 17,  0, '0'+((uiTime%100)  /10),   GRAPHICS_ON );   // tens
   dmd.drawChar( 25,  0, '0'+ (uiTime%10),          GRAPHICS_ON );   // units
  flagSec =! flagSec; //Инверсия признака
  if (flagSec) {
     dmd.setPixel(15,4,GRAPHICS_ON);
     dmd.setPixel(15,5,GRAPHICS_ON);
     dmd.setPixel(15,11,GRAPHICS_ON);
     dmd.setPixel(15,12,GRAPHICS_ON);
     dmd.setPixel(16,4,GRAPHICS_ON);
     dmd.setPixel(16,5,GRAPHICS_ON);
     dmd.setPixel(16,11,GRAPHICS_ON);
     dmd.setPixel(16,12,GRAPHICS_ON);
  }else{
      dmd.setPixel(15,4,GRAPHICS_OFF);
      dmd.setPixel(15,5,GRAPHICS_OFF);
      dmd.setPixel(15,11,GRAPHICS_OFF);
      dmd.setPixel(15,12,GRAPHICS_OFF);
      dmd.setPixel(16,4,GRAPHICS_OFF);
      dmd.setPixel(16,5,GRAPHICS_OFF);
      dmd.setPixel(16,11,GRAPHICS_OFF);
      dmd.setPixel(16,12,GRAPHICS_OFF);   
  }  
}  
}

String leadNull(int digits){                                    // Функция добавляет ведущий ноль
  String out = "";
  if(digits < 10)
    out += "0";                                               
  return out + String(digits);
}

String  WeatherDisplay(){  
  char * out = strtok(icon,"-");  // Выделяем первую часть из строки до символа '-'
String ret=" ";
  while (out != NULL) {                 // Выделяем последующие части строки в цикле, пока значение out не станет нулевым (пустым)
      if (String(out) == "skc"){         // Перебираем в условиях все возможные варианты, зашифрованные в названии иконки
//        Serial.println("Yasno");
//        ret=ret+"Ясно ";}
        ret=ret+"Yasno ";}
      else if (String(out) == "ovc"){
 //       Serial.println("Pasmurno");
 //       ret=ret+"Пасмурно ";}
        ret=ret+"Pasmurno ";}
        
      else if (String(out) == "bkn"){
//        Serial.println("Oblachno");
         ret=ret+"Облачно ";}
       
      else if (String(out) == "ra"){
 //       Serial.println("Dozhd'");
  //        ret=ret+"Дождь ";}
          ret=ret+"Dozhd ";}
       
      else if (String(out) == "ts"){
 //       Serial.println("Groza");
 //         ret=ret+"Гроза ";}
          ret=ret+"Groza ";}
       
      else if (String(out) == "sn"){
 //       Serial.println("Sneg");
 //        ret=ret+"Снег ";}
         ret=ret+"Sneg ";}
        
      else if (String(out) == "bl"){
 //       Serial.println("Metel'");
 //         ret=ret+"Метель ";}
          ret=ret+"Metel ";}
       
      else if (String(out) == "fg"){
 //       Serial.println("Tuman");
//         ret=ret+"Туман ";}
        ret=ret+"Tuman ";}
        
     else if (String(out) == "n"){
 //       Serial.println("\nTemno");
 //        ret=ret+"Ночь ";}
         ret=ret+"Temno ";}
        
      else if (String(out) == "d"){
 //       Serial.println("\nSvetlo");
 //         ret=ret+"День ";}
         ret=ret+"Svetlo ";}
      out = strtok(NULL,"-");              // Выделяем очередную часть
   }
   return ret;
}

 

https://www.youtube.com/watch?v=rtJUxVjv-0I

b707
Онлайн
Зарегистрирован: 26.05.2017

Неплохо, но можно пару комментариев?

- при выводе цифр нужно учитывать ширину символов, иначе выглядит неровно - на картинке цифра 1 явно слишком смещена влево.

- не понятно, почему только сообщение "Облачно" удостоилось быть показанным кириллицей, а все остальные в транслите...

И вопрос - библиотеку DMD2 для ЕСП пришлось допиливать или все заработало "из коробки" ?

Добавлю - Вы меня немного опередили, собирался делать точно такие же часы, но на СТМ32... а теперь, скорее всего, уже смысла нет.

lean_74
Offline
Зарегистрирован: 22.12.2015

b707 пишет:

Неплохо, но можно пару комментариев?

- при выводе цифр нужно учитывать ширину символов, иначе выглядит неровно - на картинке цифра 1 явно слишком смещена влево.

- не понятно, почему только сообщение "Облачно" удостоилось быть показанным кириллицей, а все остальные в транслите...

И вопрос - библиотеку DMD2 для ЕСП пришлось допиливать или все заработало "из коробки" ?

Добавлю - Вы меня немного опередили, собирался делать точно такие же часы, но на СТМ32... а теперь, скорее всего, уже смысла нет.

1. Да единичка смещена, по уму ее бы перерисивать на ширину 8 пикселей, да лень родилась чуть раньше меня :).

2. ну это чтобы юные копипастеры помучалсь... а кто в теме легко сам перепишет.

3. "DMD2 для ЕСП все заработало "из коробки" "

4. тогда с Вас шрифты для esp8266 под DMD2, как для СТМ32 сделали. это конечно, если время найдете.

 

lean_74
Offline
Зарегистрирован: 22.12.2015

единичку поправил, строки 187-190 надо заменить на 

   dmd.drawChar(  0+((((uiTime%10000)/1000)==1) ? 2:0),  0,'0'+((uiTime%10000)/1000), GRAPHICS_ON );   // thousands
   dmd.drawChar(  8+((((uiTime%1000) /100)==1)? 2:0),  0, '0'+((uiTime%1000) /100),  GRAPHICS_ON );   // hundreds
   dmd.drawChar( 17+((((uiTime%100) /10)==1)? 2:0),  0, '0'+((uiTime%100)  /10),   GRAPHICS_ON );   // tens
   dmd.drawChar( 25+((uiTime%10)==1 ? 2:0),  0, '0'+ (uiTime%10),          GRAPHICS_ON );   // units

 

lean_74
Offline
Зарегистрирован: 22.12.2015

бинарник  погода текушая для Копейска.