Wemos D1 + ILI9341 RBC News Box

Нет ответов
negavoid
Offline
Зарегистрирован: 09.07.2016

Стареть я стал, новости почитывать. Чтобы не отвлекаться от работы, собрал на клоне Wemos D1 и ILI9341 эдакий News Box, показывающий новости от РБК. Решил выложить, так как в соседней теме увидал интерес к этой плате.

Wemos D1 - $6 на али

Дисплей на ILI9341 - $3.5 на али

Провода dupont папа-мама - $0.61 за 60 штук на али

#include <ESP8266WiFi.h>

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341_fast.h"
#include <Fonts/DroidSerifBold18pt8b.h>

const char* ssid         = "network";
const char* password = "pass";
const char* host         = "myserver.com";

#define TFT_DC   D9
#define TFT_CS   D10
#define TFT_MOSI D7
#define TFT_CLK  D5
#define TFT_RST  D3
#define TFT_MISO D6

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
// Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup() {
  Serial.begin(115200);
  delay(10);

  // LED +3.3 V
  pinMode( D4, OUTPUT );
  digitalWrite( D4, HIGH );

  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9341_RED);
  tft.setFont(&DroidSerifBold18pt8b);
  tft.setTextSize(1);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void loop()
{
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    return;
  }

  String url = "/ardunews/";

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");

  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      client.stop();
      return;
    }
  }

  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(0, 15);

  bool drop_header = false;
  while (client.available()) {
    String line = client.readStringUntil('\r');
    line.trim();
    if ( line.length() == 0 ) drop_header = true;
    if ((drop_header) && ( line.length() != 0 ))
    {
      tft.print( utf8rus( line ) );
      tft.println();
      tft.println();
    }
    yield();
  }

  delay(120000);
}

На сервере стоит простенький скрипт, парсящий главную страницу RBC

<?php
$line = file_get_contents( "http://rbc.ru" );

$regex = "#<span class=\"news-feed__item__title\">(.*?)</span>#si";				
preg_match_all($regex, $line, $matches);

$regex = "#<span class=\"news-feed__item__date\">(.*?)</span>#si";
preg_match_all($regex, $line, $time_matches);

$news = [];
$i = 0;
foreach ( $matches[1] as $line )
{
	$long_time = trim( $time_matches[1][$i] );
	list( $rubric, $short_time ) = explode( ",", $long_time );
	
	// if ( !empty( trim( $short_time ) ) )
	{
		$line = trim( strip_tags( $line ) );
		$line = str_replace("&nbsp;", "", $line);
		$line = str_replace("«", "\"", $line);
		$line = str_replace("»", "\"", $line);
		$line = str_replace("\xA0\xC2", " ", $line);	// strange B letter instead of spacebar
		$line = str_replace("\xC2\xA0", " ", $line);
		
		// remove strange B [other way]
		$line = iconv("UTF-8","Windows-1251//IGNORE", $line );
		$line = iconv("Windows-1251", "UTF-8", $line );
		
		$news[] = trim( $short_time ) . " " . $line;
	}

	$i++;
}

for ( $i = 0; $i < 4; $i ++ )
{
	echo trim( $news[$i] ) . "\r\n";
}

 

Получилось вот так:

В планах - прикрутить фотку топ-новости для дисплея, показывать на нём попеременно то фотку с подписью, то список последних новостей. У ESP8266 1 мегабайт оперативки, на подготовленную для 320*240*2 фотку вполне хватит. Ещё думается прикрутить парсинг других сайтов, довести до ума русификацию через стандартные шрифты Adafruit GFX (сейчас использовал сконвертированный шрифт из соседней темы).