esphome: name: display friendly_name: DISPLAY esp32: board: esp32dev framework: type: arduino # Enable logging logger: level: WARN # Enable Home Assistant API api: encryption: key: "S9zpaMdXsTbjQE5QTWJ2SN3sdSlTEnSomw/PnbwyMZc=" ota: platform: esphome password: !secret ota wifi: ssid: !secret wifi_ssid password: !secret wifi_password ap: ssid: "Display Fallback Hotspot" password: "ajRx8MZPIszl" spi: clk_pin: 18 mosi_pin: 23 miso_pin: 19 # Display configuration display: - platform: ili9xxx model: st7789v dimensions: height: 320 width: 240 offset_height: 0 offset_width: 0 rotation: 0 color_order: bgr invert_colors: false data_rate: 80MHz cs_pin: 5 dc_pin: 16 reset_pin: 4 lambda: |- // Define row positions int margin = 5; int y_step = 30; int screen_width = 240; int row_y = margin + 25; int col_offset = margin + 25; int icon_size = y_step * 0.75; int col; // Calculate column and row positions int col_array[] = {margin, col_offset + y_step, col_offset + y_step * 2, col_offset + y_step * 3, col_offset + y_step * 5, col_offset + y_step * 7}; // Clear screen it.fill(Color(0, 0, 0)); // Function to calculate row position auto row_calc = [&](int row_in) { if (row_in == 0) { return margin; } else { return row_y + y_step * (row_in - 1); } }; // Function to handle all state conditions auto handle_state = [&](int col_index, int row_index, std::string text, std::string type) { // Calculate center of column int center = ((col_array[col_index] + col_array[col_index + 1]) / 2) - 10; // Check if text is a number and add unit if (text != "unavailable" && text != "unknown" && text != "") { if (type == "temperature") { text = text + "°C"; } else if (type == "humidity") { text = text + "%"; } } if (text == "unavailable" || text == "unknown") { if (id(triangle_visible)) { it.filled_triangle(center, row_calc(row_index) + icon_size, center + icon_size, row_calc(row_index) + icon_size, center + (icon_size / 2), row_calc(row_index), Color(255, 0, 0)); it.print((center + icon_size / 3) + 1, row_calc(row_index), id(my_font), Color(255, 255, 255), "!"); } } else if (text == "" && type == "door" || text == "" && type == "motion") { it.filled_rectangle(col_array[col_index], row_calc(row_index), icon_size, icon_size, Color(128, 128, 128)); } else if (text == "on") { it.filled_rectangle(col_array[col_index], row_calc(row_index), icon_size, icon_size, Color(0, 255, 0)); } else if (text == "off") { it.filled_rectangle(col_array[col_index], row_calc(row_index), icon_size, icon_size, Color(255, 0, 0)); } else if (type == "icon") { it.print(center, row_calc(row_index), id(icon_font), Color(255, 255, 255), text.c_str()); } else { it.print(col_array[col_index], row_calc(row_index), id(my_font), Color(255, 255, 255), text.c_str()); } }; // Room names (column 0) col = 0; handle_state(col,0, "󰚡", "icon"); handle_state(col,1, "Bath", "name"); handle_state(col,2, "Hall", "name"); handle_state(col,3, "Kitch", "name");; handle_state(col,4, "Tom", "name"); handle_state(col,5, "Mate", "name"); // Door status (column 1) col = 1; handle_state(col, 0, "󰠚", "icon"); handle_state(col, 1, id(bath_door_status).state, "door"); handle_state(col, 2, id(hall_door_status).state, "door"); handle_state(col, 3, "", "door"); handle_state(col, 4, id(tomek_door_status).state, "door"); handle_state(col, 5, id(mateusz_door_status).state, "door"); // Motion status (column 2) col = 2; handle_state(col, 0, "󰶑", "icon"); handle_state(col, 1, id(bath_motion_status).state, "motion"); handle_state(col, 2, id(hall_motion_status).state, "motion"); handle_state(col, 3, id(kitchen_motion_status).state, "motion"); handle_state(col, 4, "", "motion"); handle_state(col, 5, "", "motion"); // Temperature (column 3) col = 3; handle_state(col, 0, "󰔏", "icon"); handle_state(col, 1, id(bath_temperature).state, "temperature"); handle_state(col, 2, id(hall_temperature).state, "temperature"); handle_state(col, 3, id(kitchen_temperature).state, "temperature"); handle_state(col, 4, id(tomek_temperature).state, "temperature"); handle_state(col, 5, id(mateusz_temperature).state, "temperature"); // Humidity (column 4) col = 4; handle_state(col, 0, "󰖌", "icon"); handle_state(col, 1, id(bath_humidity).state, "humidity"); handle_state(col, 2, id(hall_humidity).state, "humidity"); handle_state(col, 3, id(kitchen_humidity).state, "humidity"); handle_state(col, 4, id(tomek_humidity).state, "humidity"); handle_state(col, 5, id(mateusz_humidity).state, "humidity"); // 3D Printer variables int progress_width = screen_width - (2 * margin) - 120; int progress = (atoi(id(octo_prog).state.c_str()) / 100) * progress_width; // 3D Printer progress bar if (id(octo_state).state == "Printing") { it.print(margin, row_calc(6), id(my_font), Color(255, 255, 255), "3D Printer:"); it.filled_rectangle(margin + 90, row_calc(6), progress, 20, Color(0, 255, 0)); it.rectangle(margin + 90, row_calc(6), progress_width, 20, Color(255, 255, 255)); } // 3D Printer light status if (id(printer_light).state == "on" && id(octo_state).state == "Printing" ) { it.print(margin + 90 + progress_width + 10, row_calc(6), id(icon_font), Color(255, 255, 255), "󰖨"); } else if (id(printer_light).state == "on") { it.print(margin, row_calc(6), id(my_font), Color(255, 255, 255), "3D Printer Light On"); } # Home Assistant integration text_sensor: - platform: homeassistant entity_id: binary_sensor.bathroom_door_opening id: bath_door_status - platform: homeassistant entity_id: binary_sensor.entrance_door_opening id: hall_door_status # - platform: homeassistant # entity_id: binary_sensor.kitchen_door_status # id: kitchen_door_status - platform: homeassistant entity_id: binary_sensor.tomasz_s_door_opening id: tomek_door_status - platform: homeassistant entity_id: binary_sensor.mateusz_s_door_opening id: mateusz_door_status - platform: homeassistant entity_id: binary_sensor.bathroom_motion_occupancy id: bath_motion_status - platform: homeassistant entity_id: binary_sensor.hall_motion_occupancy id: hall_motion_status - platform: homeassistant entity_id: binary_sensor.kitchen_motion_occupancy id: kitchen_motion_status # - platform: homeassistant # entity_id: binary_sensor.tomek_motion_sensor # id: tomek_motion_status # - platform: homeassistant # entity_id: binary_sensor.mateusz_motion_sensor # id: mateusz_motion_status - platform: homeassistant entity_id: sensor.bathroom_sensor_temperature id: bath_temperature - platform: homeassistant entity_id: sensor.hall_sensor_temperature id: hall_temperature - platform: homeassistant entity_id: sensor.kitchen_sensor_temperature id: kitchen_temperature - platform: homeassistant entity_id: sensor.t_h_sensor_temperature id: tomek_temperature - platform: homeassistant entity_id: sensor.mateusz_s_room_sensor_temperature id: mateusz_temperature - platform: homeassistant entity_id: sensor.bathroom_sensor_humidity id: bath_humidity - platform: homeassistant entity_id: sensor.hall_sensor_humidity id: hall_humidity - platform: homeassistant entity_id: sensor.kitchen_sensor_humidity id: kitchen_humidity - platform: homeassistant entity_id: sensor.t_h_sensor_humidity id: tomek_humidity - platform: homeassistant entity_id: sensor.mateusz_s_room_sensor_humidity id: mateusz_humidity - platform: homeassistant entity_id: sensor.octoprint_job_percentage id: octo_prog - platform: homeassistant entity_id: sensor.octoprint_current_state id: octo_state - platform: homeassistant entity_id: switch.3d_printer_light id: printer_light font: - id: my_font file: "fonts/Roboto.ttf" size: 20 - id: icon_font file: "fonts/JetBrains.ttf" size: 20 glyphs: [ "󰚡", "󰠚", "󰶑", "󰔏", "󰖌", "󰖨" ] interval: - interval: 1s then: lambda: |- static bool toggle = false; toggle = !toggle; id(triangle_visible) = toggle; globals: - id: triangle_visible type: bool restore_value: no initial_value: 'true'