Advertisement
Guest User

epaper Weather YAML for esphome

a guest
Jan 1st, 2025
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.48 KB | None | 0 0
  1. substitutions:
  2. esp_name: lilygo-epaper
  3. run_time: 5min
  4. sleep_time: 20min
  5. night_sleep_time: 8h
  6.  
  7. esphome:
  8. name: lilygo-epaper
  9. external_components:
  10. - source: github://ashald/esphome@lilygo-t5-47
  11. components: ["lilygo_t5_47"]
  12.  
  13. esp32:
  14. board: esp32dev
  15. framework:
  16. type: arduino
  17.  
  18. # Enable logging
  19. logger:
  20.  
  21. # Enable Home Assistant API
  22. api:
  23. encryption:
  24. key: ""
  25.  
  26. ota:
  27. - platform: esphome
  28. password: ""
  29.  
  30. wifi:
  31. ssid: !secret wifi_ssid
  32. password: !secret wifi_password
  33.  
  34. # Enable fallback hotspot (captive portal) in case wifi connection fails
  35. ap:
  36. ssid: "Lilygo-Epaper Fallback Hotspot"
  37. password: ""
  38.  
  39. captive_portal:
  40.  
  41. deep_sleep:
  42. run_duration: ${run_time}
  43. sleep_duration: ${sleep_time}
  44. id: deep_sleep_1
  45. # esp32_ext1_wakeup:
  46. # pins: GPIO39
  47. # mode: ALL_LOW
  48.  
  49. spi:
  50. clk_pin: 18
  51. mosi_pin: 23
  52.  
  53. button:
  54. - platform: restart
  55. name: "${esp_name} Restart"
  56.  
  57. - platform: template
  58. name: "${esp_name} Refresh"
  59. icon: "mdi:update"
  60. on_press:
  61. then:
  62. - component.update: t5_display
  63.  
  64. script:
  65. - id: all_data_received
  66. then:
  67. - component.update: batt_volt
  68. - component.update: batt
  69. - component.update: t5_display
  70. - script.execute: enter_sleep
  71.  
  72. - id: enter_sleep
  73. then:
  74. - if:
  75. condition:
  76. lambda: |-
  77. auto time = id(ntp).now();
  78. if (!time.is_valid()) {
  79. return false;
  80. }
  81. return (time.hour < 6);
  82. then:
  83. - logger.log: "It's nighttime, entering long sleep for ${night_sleep_time}"
  84. - deep_sleep.enter:
  85. id: deep_sleep_1
  86. sleep_duration: ${night_sleep_time}
  87. else:
  88. - logger.log: "It's daytime, entering short sleep for ${sleep_time}"
  89. - deep_sleep.enter:
  90. id: deep_sleep_1
  91. sleep_duration: ${sleep_time}
  92. sensor:
  93. - platform: adc
  94. pin: GPIO36
  95. name: "${esp_name} Battery Voltage"
  96. id: batt_volt
  97. attenuation: 11db
  98. update_interval: never
  99. filters:
  100. - multiply: 2
  101.  
  102. - platform: homeassistant
  103. entity_id: sensor.city_temperature
  104. id: ext_temp
  105. internal: true
  106.  
  107. - platform: homeassistant
  108. entity_id: sensor.city_wind_chill
  109. id: feels_like
  110. internal: true
  111.  
  112.  
  113.  
  114. - platform: template
  115. name: "Windchill"
  116. id: windchill
  117. internal: true
  118. # lambda: |-
  119. # if (id(feels_like).state == "unknown") {return "--";} else {return id(feels_like).state;};
  120.  
  121. - platform: template
  122. name: "${esp_name} Battery"
  123. id: batt
  124. unit_of_measurement: "%"
  125. accuracy_decimals: 0
  126. device_class: battery
  127. lambda: |-
  128. int y = (1-(4.1-id(batt_volt).state)/(4.1-3.3))*100;
  129. if (y < 100) {return y;} else {return 100;};
  130. update_interval: never
  131.  
  132. binary_sensor:
  133. - platform: gpio
  134. pin:
  135. number: GPIO39
  136. inverted: true
  137. name: "${esp_name} Button 1"
  138. on_press:
  139. then:
  140. - component.update: t5_display
  141.  
  142. - platform: gpio
  143. pin:
  144. number: GPIO34
  145. inverted: true
  146. name: "${esp_name} Button 2"
  147.  
  148. - platform: gpio
  149. pin:
  150. number: GPIO35
  151. inverted: true
  152. name: "${esp_name} Button 3"
  153. text_sensor:
  154. - platform: homeassistant
  155. id: yyc_weather
  156. name: "Weather Forecast"
  157. entity_id: "sensor.city_forecast"
  158. internal: True
  159.  
  160.  
  161. - platform: homeassistant
  162. entity_id: "weather.city"
  163. id: forecast_0
  164. internal: True
  165. attribute: temperature_unit
  166. on_value: # Actions to perform once data for the last sensor has been received
  167. then:
  168. - script.execute: all_data_received
  169. time:
  170. - platform: homeassistant
  171. id: ntp
  172. timezone: "America/Timezone"
  173.  
  174. display:
  175. - platform: lilygo_t5_47
  176. full_update_every: 1 # optional (default: 1): 0 - never, 1 (default) - every, 2+ - throttled
  177. cycles_render: 20 # optional (default: 20): higher number -> less ghosting, crisper image, more time
  178. cycles_invert: 20 # optional (default: 20): higher number -> more timef or full update, but mor burn-in protection
  179. id: t5_display
  180. rotation: 270
  181. update_interval: never
  182. lambda: |-
  183. #define xres 540
  184. #define yres 960
  185. #define x_pad 10 // border padding
  186. #define y_pad 10 // border padding
  187. #define cat_pad 85 // padding before category
  188. #define val_pad 70 // padding before value
  189. #define icon_pad 35 //padding after icons
  190. #define x1n 20 //x position 1st column name
  191. #define x1v 25 //x position 1st column value
  192. #define x1i 50 //x position 1st column icon
  193. #define x2n xres/2 //x position 2nd column name
  194. #define x2v xres/2 //x position 2nd column value
  195. #define x2i xres/2 //x position 1st column icon
  196.  
  197. int y = 0;
  198.  
  199. // Date
  200. it.strftime(xres/2, y+y_pad, id(font_name), TextAlign::TOP_CENTER, "%A %d/%b/%Y", id(ntp).now());
  201. y+=val_pad+cat_pad+10;
  202.  
  203. //external temperature
  204. it.print(x1n, y, id(font_name), TextAlign::BASELINE_LEFT, "Outside");
  205. it.print(x2n, y, id(font_name), TextAlign::BASELINE_LEFT, "Feels Like");
  206. y+=val_pad;
  207. it.printf(x1v, y, id(font_value), TextAlign::BASELINE_LEFT, "%.1f °C", id(ext_temp).state);
  208. it.printf(x2v, y, id(font_value), TextAlign::BASELINE_LEFT, "%.1f °C", id(feels_like).state);
  209. #define div_pad 40
  210. #define div_thickness 4
  211. it.filled_rectangle(x_pad, y+div_pad, xres-2*x_pad, div_thickness);
  212.  
  213. //word wrap weather
  214.  
  215. std::string s = id(city_weather).state;
  216. int limit = 35;
  217.  
  218. int space = 0;
  219. int i = 0;
  220. int line = 0;
  221. y= 305; // start Y
  222.  
  223. while(i<s.length()){ //loop through string, counting all the spaces, and replacing the last one with ~ [marked by space variable] if the count exceeds limit of 35
  224. if(s.substr(i,1) == " "){space = i; }
  225. if(line>limit-1){s=s.substr(0,space)+"~"+s.substr(space+1);line = 0;}
  226. i++;line++;}
  227. size_t pos = s.find("~"); //find the first line break
  228.  
  229. int linecount = 1; //need number of lines to store the break positions in an array
  230. int breakpositions[10]; //store breakpositions [the '~']
  231. breakpositions[0] = -1; // start at -1 cause we need to truncate the replaced characters and without this will cut off 1st character of message
  232. while ( pos != std::string::npos) //loop through replacing the ~ with CR - though this doesnt matter here it will never be displayed, but need to change them to keep the loop from repeating at the start
  233. {
  234. s.replace(pos,1, "\n");
  235. breakpositions[linecount] = pos; //store the position of the break in an array
  236. pos = s.find("~"); // move forward
  237.  
  238. linecount++; // we have a new line, count it
  239. }
  240.  
  241. breakpositions[linecount] = s.length(); //set the last entry in array to the length of string for calculation below
  242. std::string singleline; //this will be the line we print
  243.  
  244. i = 0;
  245. while (i < linecount ) { // count through the lines
  246. singleline = s.substr(breakpositions[i]+1,(breakpositions[i+1]-breakpositions[i]-1)); //extract each line of text from the string - strip off the CRLF and the space.
  247. it.printf(10, y, id(font_footer), "%s", singleline.c_str()); //print it!
  248. y=y+30; // increment y to print properly on display
  249. i++;
  250. }
  251.  
  252. //bottom divisor
  253. it.filled_rectangle(x_pad, (y+30), xres-2*x_pad, div_thickness);
  254. //test
  255. it.printf(x_pad, (y+50), id(font_footer), "%s", id(forecast_0).state.c_str());
  256.  
  257. y+=div_pad*3+div_thickness;
  258. // Footer
  259. it.strftime(x_pad, yres-y_pad/2, id(font_footer), TextAlign::BASELINE_LEFT, "Updated: %H:%M", id(ntp).now());
  260. it.printf(xres-x_pad, yres-y_pad/2, id(font_footer), TextAlign::BASELINE_RIGHT, "%.2fV/%.0f%%", id(batt_volt).state, id(batt).state);
  261.  
  262. font:
  263. - file: "GoogleSans-Bold.ttf"
  264. id: font_name
  265. size: 38
  266. - file: "GoogleSans-Medium.ttf"
  267. id: font_value
  268. size: 56
  269. - file: "GoogleSans-Medium.ttf"
  270. id: font_footer
  271. size: 28
  272.  
  273. # https://pictogrammers.github.io/@mdi/font/5.3.45/
  274. - file: 'materialdesignicons-webfont.ttf'
  275. id: font_icons
  276. size: 160
  277. glyphs:
  278. - "\U000F0594" # clear-night
  279. - "\U000F0590" # cloudy
  280. - "\U000F0595" # partlycloudy
  281. - "\U000F0591" # fog
  282. - "\U000F0592" # hail
  283. - "\U000F0593" # lightning
  284. - "\U000F067E" # lightning-rainy
  285. - "\U000F0596" # pouring
  286. - "\U000F0597" # rainy
  287. - "\U000F0F36" # snowy
  288. - "\U000F067F" # snowy-rainy
  289. - "\U000F0599" # sunny
  290. - "\U000F059D" # windy
  291. - "\U000F059E" # windy-variant
  292. - "\U000F0F38" # exceptional
  293.  
  294. - file: 'materialdesignicons-webfont.ttf'
  295. id: font_icons_small
  296. size: 56
  297. glyphs:
  298. - "\U000F10C2" # Temperature High
  299. - "\U000F10C3" # Temperature Low
  300. - "\U000F07E4" # CO2
  301. - "\U000F054B" # umbrella
  302. - "\U000F0592" # hail
  303. - "\U000F0593" # lightning
  304. - "\U000F067E" # lightning-rainy
  305. - "\U000F0597" # rainy
  306. - "\U000F0F36" # snowy
  307. - "\U000F0594" # clear-night
  308. - "\U000F0599" # sunny
  309. - "\U000F07CA" # fuel
  310. - "\U000F024A" # flower
  311. - "\U000F051F" # time-remaining
  312. - "\U000F140B" # Energy
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement