树莓派通过MQTT发布网络时间和B站粉丝数给ESP32,同时在ESP32上外接ST7789显示屏显示

先上效果图:

看到标题很多人会疑惑,ESP32不是直接可以http获取网络时间和B站粉丝数吗?为什么要多加一层跟树莓派通过MQTT通信。

这是因为刚了解了MQTT的相关知识,想实践一下,所以就一起用上了。

整体的软件框架图如下:

接下来分树莓派端和ESP32端来讲解各个细节。

一:树莓派

首先,在树莓派上使用mosquito工具建立MQTT服务器,将树莓派作MQTT模型中的服务器,此外树莓派也同时作为MQTT通信中的发布者(publisher)。发布者实现的方法是通过python脚本,而服务器的建立直接通过命令行。此外通过python请求http拉取网络时间和b站粉丝数,具体实现步骤如下:

在python脚本中,使用Requests模块请求http连接,(1)首先是获取网络时间,这里用到的url是http://time1909.beijing-time.org/time.asp,获取到字符串后进行字符串分割,最后得到时间数据,具体代码如下,注意要import requests:

def getNetTime():
    head = {'User-Agent' : 'Mozilla/5.0'}
    url = r'http://time1909.beijing-time.org/time.asp'
    r = requests.get(url=url,headers=head)
    if r.status_code ==200 :
        result = r.text
        print('r.text:',r.text) #拉下来的字符串
        data = result.split(";")
        year = data[1].split('=')[1]   #获得year数据
        month = data[2].split('=')[1]  #获得month数据
        day = data[3].split('=')[1]    #获得day数据
        hrs = data[5].split('=')[1]    #获得hour数据
        minute = data[6].split('=')[1] #获得minute数据
        sec = data[7].split('=')[1]    #获得second数据
        timestr = "%s/%s/%s %s:%s:%s" % (year, month, day, hrs, minute, sec)
        print(timestr)
        return (timestr)

(2)获取完时间后,紧接着就是获取bilibili的粉丝数,道理一样,requests.get返回后的text元素是json格式,应该使用json.loads()转成字典,代码如下(注意要import json):

Bilibili_UID 改成你自己b站的uid

Bilibili_UID = 13675014 #改成你自己b站的uid
def getBilibliFan():
    url = 'https://api.bilibili.com/x/web-interface/card?mid=%d'%(Bilibili_UID)
    r = requests.get(url)
    temp = json.loads(r.text)
    follower = temp['data']['follower']
    print(follower)
    return (follower)

 (3)时间和粉丝数获取之后,最后就是将树莓派作为MQTT服务器同时作为发布者,使用的python模块是paho.mqtt.client,可以通过以下命令安装

pip3 install paho.mqtt

 具体代码如下:

HOST="192.168.xxx.xxx"  #您树莓派的IP地址
PORT=1883      #MQTT端口,默认就行
USER="admin"      #修改成您MQTT服务器登入的用户名
PASSWD="1234"  #修改成您MQTT服务器登入的密码
TOPIC="esp32"  #修改成您想发布的话题名

if  __name__ =="__main__":
    mqttc = mqtt.Client("Raspi")         #以Raspi昵称登入MQTT服务器
    mqttc.username_pw_set(USER,PASSWD)   #设置登入的用户和密码
    mqttc.connect(HOST,PORT,60)          #建立MQTT连接
    mqttc.publish(TOPIC,"HELLO WORLD",0) #向TOPIC话题发布一条消息
    mqttc.loop()                         #保持连接mqttc.connect()中的第三个参数是60,所以60s内要loop一下或者发布一条消息

(4)最后将时间和粉丝数量发送给ESP32就行了,总代码如下:

import json
import time
import requests
import paho.mqtt.client as mqtt

HOST="192.168.xxx.xxx"  #改成你的树莓派ip
PORT=1883     
USER="admin"            #改成你MQTT服务器的用户名
PASSWD="1234"           #改成你MQTT服务器的密码
TOPIC="esp32"           #改成你MQTT想发布的话题
Bilibili_UID = 13675014 #改成你自己b站的uid

def getBilibliFan():
    url = 'https://api.bilibili.com/x/web-interface/card?mid=%d'%(Bilibili_UID)
    r = requests.get(url)
    temp = json.loads(r.text)
    follower = temp['data']['follower']
    print(follower)
    return (follower)

def getNetTime():
    head = {'User-Agent' : 'Mozilla/5.0'}
    url = r'http://time1909.beijing-time.org/time.asp'
    r = requests.get(url=url,headers=head)
    if r.status_code ==200 :
        result = r.text
        print('r.text:',r.text) #拉下来的字符串
        data = result.split(";")
        year = data[1].split('=')[1]   #获得year数据
        month = data[2].split('=')[1]  #获得month数据
        day = data[3].split('=')[1]    #获得day数据
        hrs = data[5].split('=')[1]    #获得hour数据
        minute = data[6].split('=')[1] #获得minute数据
        sec = data[7].split('=')[1]    #获得second数据
        timestr = "%s/%s/%s %s:%s:%s" % (year, month, day, hrs, minute, sec)
        print(timestr)
        return (timestr)

if  __name__ =="__main__":
    mqttc = mqtt.Client("Raspi")
    mqttc.username_pw_set(USER,PASSWD)
    mqttc.connect(HOST,PORT,60)
    mqttc.publish(TOPIC,"HEELO WORLD",0)
    mqttc.loop()
    print('now timer:',getNetTime())
    while 1:
        mqttc.publish(TOPIC,getNetTime()+'|'+str(getBilibliFan()),0)
        time.sleep(1)

二:ESP32

首先,先将ESP32连接网络,注意要和你的树莓派在同一网段中。用到的MQTT库是这个:

用到的显示屏驱动库是:

 然后由于我的显示器驱动芯片是ST7789,所以还需要安装Adafruit的ST7789库:

此外,如果你需要一些额外的字体,中文,图形库的话我这里使用了U8g2,U8g2有专门争对Adafruit系类的接口,所以使用起来十分方便。

 至此,所有需要用到的arduino库安装完成,下面只剩ESP32的软件部分。直接上代码,总体思路就是连接树莓派的MQTT服务器,同时订阅树莓派发布的话题(注意ESP32订阅的和树莓派发布的话题要完全一样),然后在订阅的回调函数里处理数据然后显示出来。


/*
 * ESP32 <---> 树莓派   MQTT
 */


//定义屏幕的宽、高
#define SCREEN_WIDTH  240
#define SCREEN_HEIGHT 240 

//定义颜色
#define  BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h> 
#include <U8g2_for_Adafruit_GFX.h>
#include <SPI.h>
#include "MyBitMap.h"  //这里面定义了几张B站的logo bitmap数组


/*
 * 选择软件SPI或者硬件SPI,硬件SPI会更快
 * 
 */
#define SCLK_PIN 18   //选择硬件SPI的话可以不定义,默认是18,选择软件SPI的话可随意定义
#define MOSI_PIN 23   //选择硬件SPI的话可以不定义,默认是23,选择软件SPI的话可随意定义
#define DC_PIN   27   //一定要定义
#define CS_PIN   5    //一定要定义
#define RST_PIN  15   //一定要定义
Adafruit_ST7789 mqtt_display = Adafruit_ST7789(CS_PIN, DC_PIN, RST_PIN); //选择硬件SPI
//Adafruit_ST7789 mqtt_display = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); //选择软件SPI

U8G2_FOR_ADAFRUIT_GFX my_u8g2;

const char* ssid = "xxx";  //你的WIFI名
const char* password = "xxxxxxxxx";  //你的WIFI密码
const char* mqtt_server = "192.168.xxx.xxx";  //树莓派的IP地址
const char *mqttUser="admin";   //登录MQTT服务器所需的用户名
const char *mqttPsw="1234";   //密码

WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  randomSeed(micros());
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  String BilibiliFan;
  String str_year;
  String str_time;
  String temp;
  int flag=1;
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    temp+=(char)payload[i];
  }
    int num_2 = temp.indexOf('|');
    BilibiliFan = temp.substring(num_2+1);
    int num = temp.indexOf(' ');
    str_year = temp.substring(0,num);
    str_time = temp.substring(num+1,num_2);

  //Serial.printf("\r\nstr_time:%s",str_time);
    Serial.println(str_year);
    Serial.println(str_time);  
    Serial.println(BilibiliFan);  

//u8g2_font_profont17_tf  这个字体可以画空格
    my_u8g2.setFont(u8g2_font_profont29_mf);  // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
    my_u8g2.setForegroundColor(BLUE);      // apply Adafruit GFX color
    my_u8g2.setCursor(45,20);                // start writing at this position
    my_u8g2.print(str_year);
    
    my_u8g2.setFont(u8g2_font_profont22_mf);  // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
    my_u8g2.setForegroundColor(WHITE);      // apply Adafruit GFX color
    my_u8g2.setCursor(70,50);                // start writing at this position
    my_u8g2.print(str_time+' '+' ');
    
    my_u8g2.setForegroundColor(MAGENTA);      
    my_u8g2.setCursor(45,145);                
    my_u8g2.print("BiliBili:"+BilibiliFan+' '+' ');
    
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect("MYESP32",mqttUser,mqttPsw)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("esp32");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
    Serial.begin(115200);
    setup_wifi();
    client.setServer(mqtt_server, 1883); 
    client.setCallback(callback);
    
    mqtt_display.init(240, 240);  //初始化屏幕
    mqtt_display.setSPISpeed(80000000); //这里设置SPI速度,不过好像没什么用
    my_u8g2.begin(mqtt_display);        
    Serial.println("ST7789-LCD Init!");
  
    mqtt_display.fillScreen(BLACK);
    //u8g2_font_helvR18_tf
    my_u8g2.setFont(u8g2_font_helvR24_tf);  
    my_u8g2.setFontMode(1);                 // use u8g2 transparent mode (this is default)
    my_u8g2.setFontDirection(0);            // left to right (this is default)
    my_u8g2.setForegroundColor(WHITE);      // apply Adafruit GFX color
    my_u8g2.setCursor(80,80);                // start writing at this position
    my_u8g2.print("MQTT");
    my_u8g2.setFont(u8g2_font_helvR24_tf);  // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
    my_u8g2.setForegroundColor(YELLOW);      // apply Adafruit GFX color
    my_u8g2.setCursor(50,120);                // start writing at this position
    my_u8g2.print("Raspiberry");
    my_u8g2.setCursor(50,157);
    my_u8g2.print("--> Esp32");

    mqtt_display.drawBitmap(0,0,(uint8_t *)bilibili_bitmap_leftup,60,60,BLUE);
    mqtt_display.drawBitmap(180,180,(uint8_t *)bilibili_bitmap_rightdown,60,60,MAGENTA);
    mqtt_display.drawBitmap(171,0,(uint8_t *)bilibili_bitmap_rightup,69,60,CYAN);
    mqtt_display.drawBitmap(0,180,(uint8_t *)bilibili_bitmap_leftdown,68,60,RED);

    delay(2000);
    mqtt_display.fillScreen(BLACK);
    //时钟页面
    mediabuttons();
    mqtt_display.drawRoundRect(30,10,175,50,8,YELLOW);
    mqtt_display.drawBitmap(85,68,(uint8_t *)BiliBili_1,60,60,MAGENTA);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

void mediabuttons() {
  // play
  mqtt_display.fillScreen(ST77XX_BLACK);
  mqtt_display.fillRoundRect(30, 160, 78, 60, 8, ST77XX_WHITE);
  mqtt_display.fillTriangle(47, 170, 47, 210, 95, 190, ST77XX_BLUE);
//  delay(500);
  // pause
  mqtt_display.fillRoundRect(130, 160, 78, 60, 8, ST77XX_WHITE);
  mqtt_display.fillRoundRect(144, 168, 20, 45, 5, ST77XX_GREEN);
  mqtt_display.fillRoundRect(174, 168, 20, 45, 5, ST77XX_GREEN);
//  delay(500);
}

没了,有什么问题可以留言 

记录几个好用的网站:

各种类型的图像转化: https://www.online-utility.org/image_converter.jsp

图像(可有颜色)转bitmap数组 :http://javl.github.io/image2cpp/

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值