Added highly WIP epaper frame, including a bunch of fonts.
This commit is contained in:
parent
7a364af59e
commit
04a77061ca
388
esphome/epaperframe.yaml
Normal file
388
esphome/epaperframe.yaml
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
esphome:
|
||||||
|
name: epaperframe
|
||||||
|
platform: ESP32
|
||||||
|
board: nodemcu-32s
|
||||||
|
on_boot:
|
||||||
|
priority: -10
|
||||||
|
then:
|
||||||
|
- delay: 10s
|
||||||
|
- component.update: epaper
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: "Voltage-legacy"
|
||||||
|
password: !secret voltage_legacy_psk
|
||||||
|
use_address: epaperframe.home
|
||||||
|
power_save_mode: high
|
||||||
|
fast_connect: on
|
||||||
|
|
||||||
|
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||||
|
ap:
|
||||||
|
ssid: "Epaperframe Fallback Hotspot"
|
||||||
|
password: !secret fallback_psk
|
||||||
|
|
||||||
|
captive_portal:
|
||||||
|
|
||||||
|
# Enable logging
|
||||||
|
logger:
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
password: !secret api
|
||||||
|
encryption:
|
||||||
|
key: !secret apikey
|
||||||
|
|
||||||
|
ota:
|
||||||
|
password: !secret ota
|
||||||
|
|
||||||
|
# Refresh screen on button click
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
pin:
|
||||||
|
number: GPIO18
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: True
|
||||||
|
name: "Refresh screen"
|
||||||
|
internal: True
|
||||||
|
on_click:
|
||||||
|
then:
|
||||||
|
- logger.log:
|
||||||
|
level: INFO
|
||||||
|
format: 'Button pressed, refreshing screen!'
|
||||||
|
- component.update: epaper
|
||||||
|
|
||||||
|
# DHT22 sensor
|
||||||
|
sensor:
|
||||||
|
- platform: dht
|
||||||
|
model: dht22
|
||||||
|
pin: 22
|
||||||
|
temperature:
|
||||||
|
name: "Temperatur"
|
||||||
|
humidity:
|
||||||
|
name: "Luftfeuchtigkeit"
|
||||||
|
update_interval: 60s
|
||||||
|
|
||||||
|
# WiFi signal strength
|
||||||
|
- platform: wifi_signal
|
||||||
|
name: "WiFi Signalstärke"
|
||||||
|
id: wifisignal
|
||||||
|
update_interval: 60s
|
||||||
|
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: sensor.wohnzimmer_feinstaub_pm_2_5um
|
||||||
|
id: pm25_livingroom
|
||||||
|
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: sensor.wohnzimmer_temperatur
|
||||||
|
id: temp_livingroom
|
||||||
|
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: sensor.wohnzimmer_luftfeuchtigkeit
|
||||||
|
id: humid_livingroom
|
||||||
|
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: sensor.temperatur_aussen
|
||||||
|
id: temp_outdoor
|
||||||
|
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: sensor.luftfeuchtigkeit_aussen
|
||||||
|
id: humid_outdoor
|
||||||
|
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: sensor.schlafzimmer_luftdruck
|
||||||
|
id: airpressure
|
||||||
|
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: zone.home
|
||||||
|
attribute: latitude
|
||||||
|
id: home_lat
|
||||||
|
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: zone.home
|
||||||
|
attribute: longitude
|
||||||
|
id: home_long
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
- platform: homeassistant
|
||||||
|
entity_id: sun.sun
|
||||||
|
id: sun_state
|
||||||
|
internal: True
|
||||||
|
|
||||||
|
# - platform: homeassistant
|
||||||
|
# entity_id: sun.sun
|
||||||
|
# id: sun_rise
|
||||||
|
# attribute: next_rising
|
||||||
|
# internal: True
|
||||||
|
|
||||||
|
# - platform: homeassistant
|
||||||
|
# entity_id: sun.sun
|
||||||
|
# id: sun_set
|
||||||
|
# attribute: next_setting
|
||||||
|
# internal: True
|
||||||
|
|
||||||
|
- platform: sun
|
||||||
|
name: "Nächster Sonnenaufgang"
|
||||||
|
id: sun_rise
|
||||||
|
type: sunrise
|
||||||
|
format: "%H:%M"
|
||||||
|
internal: True
|
||||||
|
|
||||||
|
- platform: sun
|
||||||
|
name: "Nächster Sonnenuntergang"
|
||||||
|
id: sun_set
|
||||||
|
type: sunset
|
||||||
|
format: "%H:%M"
|
||||||
|
internal: True
|
||||||
|
|
||||||
|
# Webserver configuration entry
|
||||||
|
web_server:
|
||||||
|
port: 80
|
||||||
|
# css_include: "esphome-docs/_static/webserver-v1.min.css"
|
||||||
|
# css_url: ""
|
||||||
|
# js_include: "../../../esphome-docs/_static/webserver-v1.min.js"
|
||||||
|
# js_url: ""
|
||||||
|
auth:
|
||||||
|
username: admin
|
||||||
|
password: !secret web_server_password
|
||||||
|
|
||||||
|
sun:
|
||||||
|
latitude: id(home_lat)
|
||||||
|
longitude: id(home_long)
|
||||||
|
id: sun_sun
|
||||||
|
|
||||||
|
time:
|
||||||
|
- platform: homeassistant
|
||||||
|
id: homeassistant_time
|
||||||
|
|
||||||
|
# Font definitions
|
||||||
|
font:
|
||||||
|
- file: 'fonts/Roboto-Medium.ttf'
|
||||||
|
id: roboto_med_30
|
||||||
|
size: 30
|
||||||
|
|
||||||
|
- file: 'fonts/Roboto-Regular.ttf'
|
||||||
|
id: footer_font
|
||||||
|
size: 15
|
||||||
|
glyphs:
|
||||||
|
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
|
||||||
|
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
|
||||||
|
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||||
|
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||||
|
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/','º','µ','³','ß']
|
||||||
|
|
||||||
|
- file: 'fonts/Roboto-Regular.ttf'
|
||||||
|
id: big_sensor_unit
|
||||||
|
size: 20
|
||||||
|
glyphs:
|
||||||
|
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
|
||||||
|
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
|
||||||
|
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||||
|
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||||
|
'u', 'v', 'w', 'x', 'y', 'z', 'å', 'ä', 'ö', '/','º','µ','³','ß']
|
||||||
|
|
||||||
|
- file: 'fonts/Roboto-Medium.ttf'
|
||||||
|
id: sub_sensor_font
|
||||||
|
size: 30
|
||||||
|
glyphs:
|
||||||
|
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
|
||||||
|
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
|
||||||
|
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||||
|
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||||
|
'u', 'v', 'w', 'x', 'y', 'z', 'å', 'ä', 'ö', '/','º','µ','³','ß']
|
||||||
|
|
||||||
|
- file: 'fonts/Roboto-Bold.ttf'
|
||||||
|
id: big_sensor_font
|
||||||
|
size: 80
|
||||||
|
|
||||||
|
- file: 'fonts/materialdesignicons-webfont.ttf'
|
||||||
|
id: mdi_small
|
||||||
|
size: 31
|
||||||
|
glyphs: [
|
||||||
|
'', # mdi-themometer
|
||||||
|
'', # mdi-water-percent
|
||||||
|
'', # mdi-blur (pm2.5)
|
||||||
|
'', # mdi-co2
|
||||||
|
'', # mdi-gauge (air pressure)
|
||||||
|
'', # mdi-weather-sunny
|
||||||
|
'', # mdi-weather-sunset-down
|
||||||
|
'', # mdi-weather-sunset-up
|
||||||
|
'', # mdi-moon-first-quarter
|
||||||
|
'', # mdi-moon-full
|
||||||
|
'', # mdi-moon-last-quarter
|
||||||
|
'', # mdi-moon-new
|
||||||
|
'', # mdi-moon-waning-crescent
|
||||||
|
'', # mdi-moon-waning-gibbous
|
||||||
|
'', # mdi-moon-waxing-crescent
|
||||||
|
'', # mdi-moon-waxing-gibbous
|
||||||
|
]
|
||||||
|
|
||||||
|
- file: 'fonts/materialdesignicons-webfont.ttf'
|
||||||
|
id: mdi_wifi
|
||||||
|
size: 20
|
||||||
|
glyphs: [
|
||||||
|
# Wifi
|
||||||
|
'', # mdi-wifi-strength-alert-outline
|
||||||
|
'', # mdi-wifi-strength-1
|
||||||
|
'', # mdi-wifi-strength-2
|
||||||
|
'', # mdi-wifi-strength-3
|
||||||
|
'' # mdi-wifi-strength-4
|
||||||
|
]
|
||||||
|
|
||||||
|
- file: 'fonts/materialdesignicons-webfont.ttf'
|
||||||
|
id: mdi_med
|
||||||
|
size: 33
|
||||||
|
glyphs: [
|
||||||
|
'' # mdi-alert
|
||||||
|
]
|
||||||
|
|
||||||
|
spi:
|
||||||
|
clk_pin: 23
|
||||||
|
mosi_pin: 32
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: waveshare_epaper
|
||||||
|
id: epaper
|
||||||
|
cs_pin: 27
|
||||||
|
dc_pin: 26
|
||||||
|
busy_pin: 33
|
||||||
|
reset_pin: 25
|
||||||
|
model: 7.50in
|
||||||
|
# full_update_every: 30 # not supported on this display
|
||||||
|
update_interval: never
|
||||||
|
lambda: |-
|
||||||
|
|
||||||
|
int pm25_danger_thres = 40;
|
||||||
|
|
||||||
|
float outdoor_temp = id(temp_outdoor).state;
|
||||||
|
int outdoor_humid = int(id(humid_outdoor).state);
|
||||||
|
float air_pressure = id(airpressure).state;
|
||||||
|
float livingroom_temp = id(temp_livingroom).state;
|
||||||
|
int livingroom_humid = int(id(humid_livingroom).state);
|
||||||
|
int livingroom_pm25 = int(id(pm25_livingroom).state);
|
||||||
|
|
||||||
|
// Format: 2021-10-08T05:40:47.467076+00:00
|
||||||
|
//struct tm tm;
|
||||||
|
//strptime(id(sun_rise).state.c_str(), '%Y-%m-%dT%H:%M:%S.%f%z');
|
||||||
|
//std::string sunrise = printf("%d:%d", tm.tm_hour, tm.tm_min);
|
||||||
|
|
||||||
|
/* OUTSIDE */
|
||||||
|
it.print(10, 10, id(big_sensor_unit), "Umwelt");
|
||||||
|
// Draw the outline of a rectangle with the top left at [78,21], a width of 305 and a height of 3
|
||||||
|
it.filled_rectangle(78, 21, 305, 3);
|
||||||
|
if(id(sun_state).has_state()) {
|
||||||
|
ESP_LOGI("Sun", "State of the sun: %s", id(sun_state).state.c_str());
|
||||||
|
ESP_LOGD("Sun", "Sunset: %s", id(sun_set).state.c_str());
|
||||||
|
ESP_LOGD("Sun", "Sunrise ESPHOME: %s", id(sun_rise).state.c_str());
|
||||||
|
//ESP_LOGD("Sun", "Sunrise ESPHOME: %s, Sunrise HA: %s", id(sun_rise).state.c_str(), sunrise.c_str());
|
||||||
|
//ESP_LOGD("Location", "Latitude: %f, Longitude: %f", id(home_lat).state, id(home_long).state);
|
||||||
|
|
||||||
|
//if(id(sun_state).state == "above_horizon") {
|
||||||
|
it.print(10, 75, id(mdi_small), TextAlign::BASELINE_LEFT, ""); //sun-up
|
||||||
|
it.printf(50, 75, id(sub_sensor_font), TextAlign::BASELINE_LEFT, "%s", id(sun_rise).state.c_str());
|
||||||
|
it.print(135, 75, id(mdi_small), TextAlign::BASELINE_LEFT, ""); //sun-down
|
||||||
|
it.printf(175, 75, id(sub_sensor_font), TextAlign::BASELINE_LEFT, "%s", id(sun_set).state.c_str());
|
||||||
|
//it.strftime(50, 75, id(footer_font), TextAlign::BASELINE_LEFT, "Nächster Sonnenuntergang %d.%m.%Y %H:%M", id(sun_set).state.c_str());
|
||||||
|
//}
|
||||||
|
//else {
|
||||||
|
//it.print(10, 75, id(mdi_small), TextAlign::BASELINE_LEFT, ""); //sun-down
|
||||||
|
//it.strftime(50, 75, id(footer_font), TextAlign::BASELINE_LEFT, "Nächster Sonnenaufgang %d.%m.%Y %H:%M", id(sun_rise));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
it.print(10, 115, id(mdi_small), TextAlign::BASELINE_LEFT, ""); //air-pressure
|
||||||
|
it.print(375, 75, id(mdi_small), TextAlign::BASELINE_CENTER, ""); //thermometer
|
||||||
|
it.print(375, 115, id(mdi_small), TextAlign::BASELINE_CENTER, ""); //water-percent
|
||||||
|
|
||||||
|
if(outdoor_temp > -100 && outdoor_temp < 100) {
|
||||||
|
it.printf(357, 75, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1fºC", outdoor_temp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it.print(357, 75, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - ºC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(outdoor_humid >=0 && outdoor_humid <= 100) {
|
||||||
|
it.printf(357, 115, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%3d%%", outdoor_humid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it.print(357, 115, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - %");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(air_pressure < 1200 && air_pressure >=800) { //Has valid value
|
||||||
|
it.printf(50, 115, id(sub_sensor_font), TextAlign::BASELINE_LEFT, "%4.1fhPa", air_pressure);
|
||||||
|
}
|
||||||
|
else { //Invalid or error value
|
||||||
|
it.print(50, 115, id(sub_sensor_font), TextAlign::BASELINE_LEFT, "- hPa");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* INSIDE */
|
||||||
|
|
||||||
|
int offsetY = 137;
|
||||||
|
it.print(10, 10 + offsetY, id(big_sensor_unit), "INSIDE");
|
||||||
|
it.filled_rectangle(78, 21 + offsetY, 305, 3);
|
||||||
|
it.print(10, 114 + offsetY, id(big_sensor_unit), TextAlign::BASELINE_LEFT, "PM2.5");
|
||||||
|
it.print(375, 75 + offsetY, id(mdi_small), TextAlign::BASELINE_CENTER, ""); //thermometer
|
||||||
|
it.print(375, 115 + offsetY, id(mdi_small), TextAlign::BASELINE_CENTER, ""); //water-percent
|
||||||
|
|
||||||
|
if(livingroom_temp > -100 && livingroom_temp < 100){
|
||||||
|
it.printf(357, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT , "%2.1fºC", livingroom_temp);
|
||||||
|
}else{
|
||||||
|
it.print(357, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT , " - ºC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(livingroom_humid >=0 && livingroom_humid <= 100){
|
||||||
|
it.printf(357, 115 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT , "%3d%%", livingroom_humid);
|
||||||
|
}else{
|
||||||
|
it.print(357, 115 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT , " - %");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(livingroom_pm25 < 255 && livingroom_pm25 >=0){
|
||||||
|
if (livingroom_pm25 > 99){
|
||||||
|
it.printf(205, 114 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT , "%3d", livingroom_pm25);
|
||||||
|
it.print(210, 114 + offsetY, id(big_sensor_unit),TextAlign::BASELINE_LEFT, "µg/m³");
|
||||||
|
}else{
|
||||||
|
it.printf(175, 114 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT , "%2d", livingroom_pm25);
|
||||||
|
it.print(180, 114 + offsetY, id(big_sensor_unit),TextAlign::BASELINE_LEFT, "µg/m³");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(livingroom_pm25 >= pm25_danger_thres){
|
||||||
|
it.print(37, 87 + offsetY, id(mdi_med), TextAlign::BASELINE_CENTER, ""); //warning
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
it.print(175, 114 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT , "- ");
|
||||||
|
it.print(180, 114 + offsetY, id(big_sensor_unit),TextAlign::BASELINE_LEFT, "µg/m³");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* FOOTER */
|
||||||
|
it.strftime(610, 374 , id(footer_font), TextAlign::BASELINE_RIGHT , "Letzte Aktualisierung %d.%m.%Y %H:%M", id(homeassistant_time).now());
|
||||||
|
|
||||||
|
/* WiFi Signal Strenght */
|
||||||
|
if(id(wifisignal).has_state()) {
|
||||||
|
int x = 626;
|
||||||
|
int y = 376;
|
||||||
|
if (id(wifisignal).state >= -50) {
|
||||||
|
//Excellent
|
||||||
|
it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "");
|
||||||
|
ESP_LOGI("WiFi", "Excellent");
|
||||||
|
} else if (id(wifisignal).state >= -60) {
|
||||||
|
//Good
|
||||||
|
it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "");
|
||||||
|
ESP_LOGI("WiFi", "Good");
|
||||||
|
} else if (id(wifisignal).state >= -75) {
|
||||||
|
//Fair
|
||||||
|
it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "");
|
||||||
|
ESP_LOGI("WiFi", "Fair");
|
||||||
|
} else if (id(wifisignal).state >= -100) {
|
||||||
|
//Weak
|
||||||
|
it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "");
|
||||||
|
ESP_LOGI("WiFi", "Weak");
|
||||||
|
} else {
|
||||||
|
//Unlikely working signal
|
||||||
|
it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "");
|
||||||
|
ESP_LOGI("WiFi", "Unlikely");
|
||||||
|
}
|
||||||
|
}
|
BIN
esphome/fonts/Roboto-Black.ttf
Normal file
BIN
esphome/fonts/Roboto-Black.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-BlackItalic.ttf
Normal file
BIN
esphome/fonts/Roboto-BlackItalic.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-Bold.ttf
Normal file
BIN
esphome/fonts/Roboto-Bold.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-BoldItalic.ttf
Normal file
BIN
esphome/fonts/Roboto-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-Italic.ttf
Normal file
BIN
esphome/fonts/Roboto-Italic.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-Light.ttf
Normal file
BIN
esphome/fonts/Roboto-Light.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-LightItalic.ttf
Normal file
BIN
esphome/fonts/Roboto-LightItalic.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-Medium.ttf
Normal file
BIN
esphome/fonts/Roboto-Medium.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-MediumItalic.ttf
Normal file
BIN
esphome/fonts/Roboto-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-Regular.ttf
Normal file
BIN
esphome/fonts/Roboto-Regular.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-Thin.ttf
Normal file
BIN
esphome/fonts/Roboto-Thin.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/Roboto-ThinItalic.ttf
Normal file
BIN
esphome/fonts/Roboto-ThinItalic.ttf
Normal file
Binary file not shown.
BIN
esphome/fonts/materialdesignicons-webfont.ttf
Normal file
BIN
esphome/fonts/materialdesignicons-webfont.ttf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user