diff --git a/examples/home-pages.json b/examples/home-pages.json new file mode 100644 index 0000000..d975af6 --- /dev/null +++ b/examples/home-pages.json @@ -0,0 +1,794 @@ +{ + "format": "flipdot-backup", + "version": 1, + "firmware": "2.5.0", + "exported": "2026-10-15T00:00:00Z", + "bitmaps": [ + { + "name": "weer sunny", + "data": "0400000000000000000000444000000000000000000020800000000000000000000e000000000000000000001f00000000000000000000df600000000000000000001f000000000000000000000e0000000000000000000020800000000000000000004440000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer clear-night", + "data": "0e00000000000000000000380000000000000000000070000000000000000000006040000000000000000000e000000000000000000000e000000000000000000000e000000000000000000000700000000000000000000078400000000000000000003f800000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer partlycloudy", + "data": "24000000000000000000000e000000000000000000005f000000000000000000001e00000000000000000000b3800000000000000000003fe00000000000000000007fe0000000000000000000ffe0000000000000000000ffe00000000000000000007fc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer cloudy", + "data": "0000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe00000000000000000007fc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer fog", + "data": "0000000000000000000000ffe000000000000000000000000000000000000000007fe00000000000000000000000000000000000000000ff8000000000000000000000000000000000000000003fe00000000000000000000000000000000000000000ff80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer rainy", + "data": "00000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe00000000000000000007fc0000000000000000000000000000000000000000044400000000000000000008880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer pouring", + "data": "00000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe00000000000000000007fc00000000000000000005540000000000000000000aa800000000000000000005540000000000000000000aa8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer lightning", + "data": "00000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe000000000000000000006000000000000000000000c000000000000000000001f0000000000000000000006000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer lightning-rainy", + "data": "00000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe000000000000000000046400000000000000000008c800000000000000000001f0000000000000000000046400000000000000000008c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer snowy", + "data": "00000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe00000000000000000007fc0000000000000000000444000000000000000000011000000000000000000004440000000000000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer snowy-rainy", + "data": "00000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe00000000000000000007fc0000000000000000000444000000000000000000088800000000000000000001100000000000000000000444000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer hail", + "data": "00000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe00000000000000000007fc0000000000000000000666000000000000000000066600000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer windy", + "data": "000000000000000000000003000000000000000000000080000000000000000000ff800000000000000000000000000000000000000000ffe00000000000000000000000000000000000000000fe0000000000000000000000800000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer windy-variant", + "data": "00000000000000000000000e0000000000000000000037800000000000000000007fc0000000000000000000ffe0000000000000000000ffe00000000000000000007fc00000000000000000000000000000000000000000ff8000000000000000000000000000000000000000003fe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer default", + "data": "04000000000000000000000a000000000000000000000a000000000000000000001500000000000000000000150000000000000000000024800000000000000000002480000000000000000000404000000000000000000044400000000000000000008020000000000000000000ffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "weer exceptional", + "data": "04000000000000000000000a000000000000000000000a000000000000000000001500000000000000000000150000000000000000000024800000000000000000002480000000000000000000404000000000000000000044400000000000000000008020000000000000000000ffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "bg energie", + "data": "06000000000000000000000c0000000000000000000018000000000000000000003e000000000000000000000c0000000000000000000018000000000000000000003000000000000000000000600000000000000000000000000000000000000000000000000000000000000000080000000000000000000041000000000000000000001c000000000000000000003e00000000000000000000be800000000000000000003e000000000000000000001c0000000000000000000041000000000000000000000800000000000000000000" + }, + { + "name": "bg printer", + "data": "ffe00000000000000000008020000000000000000000bfa00000000000000000008420000000000000000000842000000000000000000080200000000000000000008e200000000000000000009f20000000000000000000ffe00000000000000000008020000000000000000000ffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "bg binnen", + "data": "04000000000000000000000e000000000000000000001b00000000000000000000318000000000000000000060c0000000000000000000c060000000000000000000404000000000000000000058400000000000000000005b400000000000000000005b400000000000000000007fc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "bg verbruik", + "data": "080000000000000000000008000000000000000000001c000000000000000000001c000000000000000000003e000000000000000000007f000000000000000000007f000000000000000000007f000000000000000000003e000000000000000000001c00000000000000000000000000000000000000000006000000000000000000000c0000000000000000000018000000000000000000003e000000000000000000000c00000000000000000000180000000000000000000030000000000000000000006000000000000000000000" + }, + { + "name": "bg datum", + "data": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004100000000000000000000ffe00000000000000000008020000000000000000000ffe0000000000000000000aaa00000000000000000008020000000000000000000aaa00000000000000000008020000000000000000000aa200000000000000000008020000000000000000000ffe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "bg kerst", + "data": "00000000000000000000000000000000000000000000000000000000000000000004000000000000000000000e0000000000000000000004000000000000000000000e000000000000000000001f000000000000000000000e000000000000000000001f000000000000000000003f800000000000000000001f000000000000000000003f800000000000000000007fc000000000000000000004000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "bg dag", + "data": "0002000000000000000000002220000000000000000000104000000000000000000007000000000000000000000f800000000000000000006fb00000000000000000000f800000000000000000000700000000000000000000104000000000000000000022200000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "bg nacht", + "data": "0007000000000000000000001c008000000000000000403800000000000000000000302000000000000000000070020000000000000000007000000000000000000000700000000000000000000038001000000000000000003c200000000000000000101fc00000000000000000000700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "bg kader", + "data": "f8000000000000000001f080000000000000000000108000000000000000000010800000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000001080000000000000000000108000000000000000000010f8000000000000000001f0" + }, + { + "name": "bg vol", + "data": "fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0fffffffffffffffffffff0" + } + ], + "pages": [ + { + "name": "Weer", + "page": { + "slots": [], + "elements": [ + { + "type": "clock", + "x": 0, + "y": 0, + "align": "left", + "overlay": "top", + "font": "Full height", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "image", + "x": 55, + "y": 0, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "weer ", + "suffix": "", + "entity": "weather.knmi_home", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 84, + "y": 2, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": 0, + "text": "", + "suffix": "%", + "entity": "weather.knmi_home", + "attribute": "humidity", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 84, + "y": 13, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": 1, + "text": "", + "suffix": "°C", + "entity": "weather.knmi_home", + "attribute": "temperature", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + }, + { + "name": "Dag en nacht", + "page": { + "slots": [ + { + "start": "07:00", + "bitmap": "bg dag" + }, + { + "start": "19:00", + "bitmap": "bg nacht" + } + ], + "elements": [ + { + "type": "clock", + "x": 84, + "y": 0, + "align": "right", + "overlay": "top", + "font": "Full height", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "date", + "x": 0, + "y": 13, + "align": "left", + "overlay": "top", + "font": "Small", + "format": 1, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + }, + { + "name": "Energie", + "page": { + "slots": [ + { + "start": "00:00", + "bitmap": "bg energie" + } + ], + "elements": [ + { + "type": "ha", + "x": 10, + "y": 0, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": 0, + "text": "", + "suffix": " W", + "entity": "sensor.envoy_000000000000_current_net_power_consumption", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 11, + "y": 11, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": 1, + "text": "", + "suffix": " kWh", + "entity": "sensor.envoy_000000000000_today_s_energy_production", + "attribute": "", + "factor": 0.001, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "clock", + "x": 84, + "y": 0, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + }, + { + "name": "3D printer", + "page": { + "slots": [ + { + "start": "00:00", + "bitmap": "bg printer" + } + ], + "elements": [ + { + "type": "ha", + "x": 14, + "y": 0, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": 0, + "text": "", + "suffix": "%", + "entity": "sensor.mainsailos_progress", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 84, + "y": 0, + "align": "right", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": 0, + "text": "", + "suffix": "m", + "entity": "sensor.mainsailos_print_time_left", + "attribute": "", + "factor": 0.016666666666666666, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 14, + "y": 13, + "align": "left", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "sensor.mainsailos_current_display_message", + "attribute": "", + "factor": 1, + "scroll_width": 46, + "scroll_speed": 6, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 84, + "y": 13, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": 0, + "text": "", + "suffix": "°", + "entity": "sensor.mainsailos_extruder_temperature", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + }, + { + "name": "Binnen", + "page": { + "slots": [ + { + "start": "00:00", + "bitmap": "bg binnen" + } + ], + "elements": [ + { + "type": "ha", + "x": 14, + "y": 2, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": 1, + "text": "", + "suffix": "°", + "entity": "climate.home", + "attribute": "current_temperature", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "image", + "x": 49, + "y": 0, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "weer ", + "suffix": "", + "entity": "weather.knmi_home", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 84, + "y": 2, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": 1, + "text": "", + "suffix": "°", + "entity": "weather.knmi_home", + "attribute": "temperature", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 0, + "y": 13, + "align": "left", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": 0, + "text": "CO2 ", + "suffix": "ppm", + "entity": "sensor.eco2", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 84, + "y": 13, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "lucht ", + "suffix": "", + "entity": "sensor.air_quality_index_aqi_2", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + }, + { + "name": "Verbruik", + "page": { + "slots": [ + { + "start": "00:00", + "bitmap": "bg verbruik" + } + ], + "elements": [ + { + "type": "ha", + "x": 10, + "y": 1, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": 0, + "text": "", + "suffix": " l", + "entity": "sensor.util_water_usage_daily", + "attribute": "", + "factor": 1000, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 10, + "y": 11, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": 1, + "text": "", + "suffix": " kWh", + "entity": "sensor.envoy_000000000000_today_s_energy_consumption", + "attribute": "", + "factor": 0.001, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "clock", + "x": 84, + "y": 0, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "ha", + "x": 84, + "y": 13, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": 1, + "text": "zon ", + "suffix": "kWh", + "entity": "sensor.envoy_000000000000_today_s_energy_production", + "attribute": "", + "factor": 0.001, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + }, + { + "name": "Grote klok", + "page": { + "slots": [ + { + "start": "07:00", + "bitmap": "bg kader" + }, + { + "start": "22:00", + "bitmap": "bg vol" + } + ], + "elements": [ + { + "type": "clock", + "x": 42, + "y": 0, + "align": "center", + "overlay": "invert", + "font": "Full height", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + }, + { + "name": "Datum", + "page": { + "slots": [ + { + "start": "00:00", + "bitmap": "bg datum" + } + ], + "elements": [ + { + "type": "date", + "x": 14, + "y": 1, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 5, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "date", + "x": 14, + "y": 12, + "align": "left", + "overlay": "top", + "font": "Small", + "format": 2, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "clock", + "x": 84, + "y": 12, + "align": "right", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + }, + { + "name": "Aftellen", + "page": { + "slots": [ + { + "start": "00:00", + "bitmap": "bg kerst" + } + ], + "elements": [ + { + "type": "text", + "x": 14, + "y": 1, + "align": "left", + "overlay": "top", + "font": "Small", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "Kerst over", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + }, + { + "type": "countdown", + "x": 14, + "y": 10, + "align": "left", + "overlay": "top", + "font": "Normal", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "Vrolijk kerst!", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 70, + "scroll_speed": 8, + "target": "2026-12-25T00:00" + } + ] + } + }, + { + "name": "Stopwatch", + "page": { + "slots": [], + "elements": [ + { + "type": "stopwatch", + "x": 42, + "y": 0, + "align": "center", + "overlay": "top", + "font": "Full height", + "format": 0, + "language": "nl", + "decimals": -1, + "text": "", + "suffix": "", + "entity": "", + "attribute": "", + "factor": 1, + "scroll_width": 0, + "scroll_speed": 8, + "target": "2000-01-01T00:00" + } + ] + } + } + ], + "fonts": [] +} \ No newline at end of file diff --git a/tools/make_example_pages.py b/tools/make_example_pages.py new file mode 100644 index 0000000..fb4eb01 --- /dev/null +++ b/tools/make_example_pages.py @@ -0,0 +1,376 @@ +"""Builds examples/home-pages.json: icons, backgrounds and dynamic pages for this home (import it in the web UI, System tab). + + python tools/make_example_pages.py examples/home-pages.json +""" +import json +import sys + +W, H = 84, 19 + + +def blank(): + return [[0] * W for _ in range(H)] + + +def put(img, art, x0, y0): + for y, row in enumerate(art): + for x, c in enumerate(row): + if c == '#' and 0 <= x0 + x < W and 0 <= y0 + y < H: + img[y0 + y][x0 + x] = 1 + return img + + +def to_hex(img): + out = '' + for y in range(H): + for i in range(11): + v = 0 + for k in range(8): + x = i * 8 + k + if x < W and img[y][x]: + v |= 0x80 >> k + out += '%02x' % v + return out + + +CLOUD = [ + "...........", + "....###....", + "..##.####..", + ".#########.", + "###########", + "###########", + ".#########.", +] + +WEATHER = { + 'sunny': [ + ".....#.....", + ".#...#...#.", + "..#.....#..", + "....###....", + "...#####...", + "##.#####.##", + "...#####...", + "....###....", + "..#.....#..", + ".#...#...#.", + ".....#.....", + ], + 'clear-night': [ + "....###....", + "..###......", + ".###.......", + ".##......#.", + "###.......", + "###........", + "###........", + ".###.......", + ".####....#.", + "..#######..", + "....###....", + ], + 'partlycloudy': [ + "..#..#.....", + "....###....", + ".#.#####...", + "...####....", + "#.##..###..", + "..#########", + ".##########", + "###########", + "###########", + ".#########.", + "...........", + ], + 'cloudy': ["...........", "..........."] + CLOUD + ["..........."] * 2, + 'fog': [ + "...........", + "###########", + "...........", + ".##########", + "...........", + "#########..", + "...........", + "..#########", + "...........", + "#########..", + "...........", + ], + 'rainy': CLOUD + [ + "...........", + ".#...#...#.", + "#...#...#..", + "...........", + ], + 'pouring': CLOUD + [ + ".#.#.#.#.#.", + "#.#.#.#.#..", + ".#.#.#.#.#.", + "#.#.#.#.#..", + ], + 'lightning': CLOUD[:6] + [ + ".....##....", + "....##.....", + "...#####...", + ".....##....", + "....##.....", + ], + 'lightning-rainy': CLOUD[:6] + [ + ".#...##..#.", + "#...##..#..", + "...#####...", + ".#...##..#.", + "#...##..#..", + ], + 'snowy': CLOUD + [ + ".#...#...#.", + "...#...#...", + ".#...#...#.", + "...#...#...", + ], + 'snowy-rainy': CLOUD + [ + ".#...#...#.", + "#...#...#..", + "...#...#...", + ".#...#...#.", + ], + 'hail': CLOUD + [ + ".##..##..##", + ".##..##..##", + "...........", + "..##..##...", + ], + 'windy': [ + "...........", + "......##...", + "........#..", + "#########..", + "...........", + "###########", + "...........", + "#######....", + "........#..", + "......##...", + "...........", + ], + 'windy-variant': CLOUD + [ + "...........", + "#########..", + "...........", + "..#########", + ], + 'default': [ + ".....#.....", + "....#.#....", + "....#.#....", + "...#.#.#...", + "...#.#.#...", + "..#..#..#..", + "..#..#..#..", + ".#.......#.", + ".#...#...#.", + "#.........#", + "###########", + ], +} +WEATHER['exceptional'] = WEATHER['default'] + +BOLT = [ + "....##.", + "...##..", + "..##...", + ".#####.", + "...##..", + "..##...", + ".##....", + "##.....", +] +SUN_SMALL = [ + "....#....", + ".#.....#.", + "...###...", + "..#####..", + "#.#####.#", + "..#####..", + "...###...", + ".#.....#.", + "....#....", +] +DROP = [ + "...#...", + "...#...", + "..###..", + "..###..", + ".#####.", + "#######", + "#######", + "#######", + ".#####.", + "..###..", +] +HOUSE = [ + ".....#.....", + "....###....", + "...##.##...", + "..##...##..", + ".##.....##.", + "##.......##", + ".#.......#.", + ".#.##....#.", + ".#.##.##.#.", + ".#.##.##.#.", + ".#########.", +] +PRINTER = [ + "###########", + "#.........#", + "#.#######.#", + "#....#....#", + "#....#....#", + "#.........#", + "#...###...#", + "#..#####..#", + "###########", + "#.........#", + "###########", +] +CALENDAR = [ + ".#.....#...", + "###########", + "#.........#", + "###########", + "#.#.#.#.#.#", + "#.........#", + "#.#.#.#.#.#", + "#.........#", + "#.#.#.#...#", + "#.........#", + "###########", +] +TREE = [ + ".....#.....", + "....###....", + ".....#.....", + "....###....", + "...#####...", + "....###....", + "...#####...", + "..#######..", + "...#####...", + "..#######..", + ".#########.", + ".....#.....", + "....###....", +] +MOON = WEATHER['clear-night'] +STARS = [(1, 2), (24, 1), (27, 7), (3, 9), (22, 4)] +CORNER = ["#####", "#....", "#....", "#...."] + + +def corners(): + img = blank() + put(img, CORNER, 0, 0) + put(img, [r[::-1] for r in CORNER], W - 5, 0) + put(img, CORNER[::-1], 0, H - 4) + put(img, [r[::-1] for r in CORNER[::-1]], W - 5, H - 4) + return img + + +bitmaps = {} +for state, art in WEATHER.items(): + bitmaps['weer ' + state] = put(blank(), art, 0, 0) +bitmaps['bg energie'] = put(put(blank(), BOLT, 1, 0), SUN_SMALL, 0, 10) +bitmaps['bg printer'] = put(blank(), PRINTER, 0, 0) +bitmaps['bg binnen'] = put(blank(), HOUSE, 0, 0) +bitmaps['bg verbruik'] = put(put(blank(), DROP, 1, 0), BOLT, 1, 11) +bitmaps['bg datum'] = put(blank(), CALENDAR, 0, 4) +bitmaps['bg kerst'] = put(blank(), TREE, 0, 3) +bitmaps['bg dag'] = put(blank(), WEATHER['sunny'], 9, 0) +night = put(blank(), MOON, 9, 0) +for x, y in STARS: + night[y][x] = 1 +bitmaps['bg nacht'] = night +bitmaps['bg kader'] = corners() +bitmaps['bg vol'] = [[1] * W for _ in range(H)] + + +def el(type, x, y, font='Normal', **kw): + e = {'type': type, 'x': x, 'y': y, 'align': 'left', 'overlay': 'top', 'font': font, 'format': 0, + 'language': 'nl', 'decimals': -1, 'text': '', 'suffix': '', 'entity': '', 'attribute': '', + 'factor': 1, 'scroll_width': 0, 'scroll_speed': 8, 'target': '2000-01-01T00:00'} + e.update(kw) + return e + + +ENVOY = 'sensor.envoy_000000000000_' +pages = { + # 1. Weather clock: large clock, weather icon, outside humidity and temperature + 'Weer': {'slots': [], 'elements': [ + el('clock', 0, 0, 'Full height'), + el('image', 55, 0, text='weer ', entity='weather.knmi_home'), + el('ha', 84, 2, 'Small', align='right', entity='weather.knmi_home', attribute='humidity', suffix='%', decimals=0), + el('ha', 84, 13, 'Small', align='right', entity='weather.knmi_home', attribute='temperature', suffix='°C', decimals=1), + ]}, + # 2. Sun by day, moon and stars at night, large clock and the date + 'Dag en nacht': {'slots': [{'start': '07:00', 'bitmap': 'bg dag'}, {'start': '19:00', 'bitmap': 'bg nacht'}], 'elements': [ + el('clock', 84, 0, 'Full height', align='right'), + el('date', 0, 13, 'Small', format=1), + ]}, + # 3. Energy: net power now (negative = export), solar today, small clock + 'Energie': {'slots': [{'start': '00:00', 'bitmap': 'bg energie'}], 'elements': [ + el('ha', 10, 0, entity=ENVOY + 'current_net_power_consumption', suffix=' W', decimals=0), + el('ha', 11, 11, entity=ENVOY + 'today_s_energy_production', suffix=' kWh', decimals=1, factor=0.001), + el('clock', 84, 0, 'Small', align='right'), + ]}, + # 4. 3D printer: progress, time left, status message (scrolls), nozzle temperature + '3D printer': {'slots': [{'start': '00:00', 'bitmap': 'bg printer'}], 'elements': [ + el('ha', 14, 0, entity='sensor.mainsailos_progress', suffix='%', decimals=0), + el('ha', 84, 0, align='right', entity='sensor.mainsailos_print_time_left', suffix='m', decimals=0, factor=1 / 60), + el('ha', 14, 13, 'Small', entity='sensor.mainsailos_current_display_message', scroll_width=46, scroll_speed=6), + el('ha', 84, 13, 'Small', align='right', entity='sensor.mainsailos_extruder_temperature', suffix='°', decimals=0), + ]}, + # 5. Indoor climate: room temperature, outside, CO2 and air quality + 'Binnen': {'slots': [{'start': '00:00', 'bitmap': 'bg binnen'}], 'elements': [ + el('ha', 14, 2, entity='climate.home', attribute='current_temperature', suffix='°', decimals=1), + el('image', 49, 0, text='weer ', entity='weather.knmi_home'), + el('ha', 84, 2, 'Small', align='right', entity='weather.knmi_home', attribute='temperature', suffix='°', decimals=1), + el('ha', 0, 13, 'Small', entity='sensor.eco2', text='CO2 ', suffix='ppm', decimals=0), + el('ha', 84, 13, 'Small', align='right', entity='sensor.air_quality_index_aqi_2', text='lucht '), + ]}, + # 6. Today: water and energy use, solar production + 'Verbruik': {'slots': [{'start': '00:00', 'bitmap': 'bg verbruik'}], 'elements': [ + el('ha', 10, 1, entity='sensor.util_water_usage_daily', suffix=' l', decimals=0, factor=1000), + el('ha', 10, 11, entity=ENVOY + 'today_s_energy_consumption', suffix=' kWh', decimals=1, factor=0.001), + el('clock', 84, 0, 'Small', align='right'), + el('ha', 84, 13, 'Small', align='right', entity=ENVOY + 'today_s_energy_production', text='zon ', suffix='kWh', decimals=1, factor=0.001), + ]}, + # 7. Big clock in a frame; from 22:00 black digits on yellow + 'Grote klok': {'slots': [{'start': '07:00', 'bitmap': 'bg kader'}, {'start': '22:00', 'bitmap': 'bg vol'}], 'elements': [ + el('clock', 42, 0, 'Full height', align='center', overlay='invert'), + ]}, + # 8. The date in Dutch with a calendar + 'Datum': {'slots': [{'start': '00:00', 'bitmap': 'bg datum'}], 'elements': [ + el('date', 14, 1, format=5), + el('date', 14, 12, 'Small', format=2), + el('clock', 84, 12, 'Small', align='right'), + ]}, + # Countdown to Christmas + 'Aftellen': {'slots': [{'start': '00:00', 'bitmap': 'bg kerst'}], 'elements': [ + el('text', 14, 1, 'Small', text='Kerst over'), + el('countdown', 14, 10, target='2026-12-25T00:00', suffix='Vrolijk kerst!', scroll_width=70, scroll_speed=8), + ]}, + # Stopwatch, large + 'Stopwatch': {'slots': [], 'elements': [ + el('stopwatch', 42, 0, 'Full height', align='center'), + ]}, +} + +backup = { + 'format': 'flipdot-backup', 'version': 1, 'firmware': '2.5.0', 'exported': '2026-10-15T00:00:00Z', + 'bitmaps': [{'name': n, 'data': to_hex(b)} for n, b in bitmaps.items()], + 'pages': [{'name': n, 'page': p} for n, p in pages.items()], + 'fonts': [], +} +json.dump(backup, open(sys.argv[1], 'w', encoding='utf-8'), ensure_ascii=False, indent=1) +print(len(bitmaps), 'bitmaps,', len(pages), 'pages')