610 lines
22 KiB
Python
610 lines
22 KiB
Python
from argparse import Namespace
|
|
import logging
|
|
import io
|
|
import requests
|
|
|
|
from esphome import core, automation
|
|
from esphome.components import display, font, time
|
|
import esphome.components.image as espImage
|
|
import esphome.config_validation as cv
|
|
import esphome.codegen as cg
|
|
from esphome.const import CONF_BLUE, CONF_GREEN, CONF_RED, CONF_FILE, CONF_ID, CONF_BRIGHTNESS, CONF_RAW_DATA_ID, CONF_TIME, CONF_DURATION, CONF_TRIGGER_ID
|
|
from esphome.core import CORE, HexInt
|
|
from esphome.cpp_generator import RawExpression
|
|
from .select import EHMTXSelect
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
DEPENDENCIES = ["display", "light", "api"]
|
|
AUTO_LOAD = ["ehmtx"]
|
|
IMAGE_TYPE_RGB565 = 4
|
|
MAXFRAMES = 20
|
|
MAXICONS = 72
|
|
ICONWIDTH = 8
|
|
ICONHEIGHT = 8
|
|
ICONBUFFERSIZE = ICONWIDTH * ICONHEIGHT
|
|
ICONSIZE = [ICONWIDTH,ICONHEIGHT]
|
|
SVG_START = '<svg width="80px" height="80px" viewBox="0 0 80 80">'
|
|
|
|
SVG_END = "</svg>"
|
|
|
|
def rgb888_svg(x,y,r,g,b):
|
|
return f"<rect style=\"fill:rgb({r},{g},{b});\" x=\"{x*10}\" y=\"{y*10}\" width=\"10\" height=\"10\"/>"
|
|
|
|
def rgb565_svg(x,y,r,g,b):
|
|
return f"<rect style=\"fill:rgb({(r << 3) | (r >> 2)},{(g << 2) | (g >> 4)},{(b << 3) | (b >> 2)});\" x=\"{x*10}\" y=\"{y*10}\" width=\"10\" height=\"10\"/>"
|
|
|
|
ehmtx_ns = cg.esphome_ns.namespace("esphome")
|
|
EHMTX_ = ehmtx_ns.class_("EHMTX", cg.Component)
|
|
Icons_ = ehmtx_ns.class_("EHMTX_Icon")
|
|
|
|
NextScreenTrigger = ehmtx_ns.class_(
|
|
"EHMTXNextScreenTrigger", automation.Trigger.template(cg.std_string)
|
|
)
|
|
|
|
CONF_SHOWCLOCK = "show_clock"
|
|
CONF_SHOWSCREEN = "show_screen"
|
|
CONF_EHMTX = "ehmtx"
|
|
CONF_URL = "url"
|
|
CONF_FLAG = "flag"
|
|
CONF_LAMEID = "lameid"
|
|
CONF_AWTRIXID = "awtrixid"
|
|
CONF_ICONS = "icons"
|
|
CONF_SHOWDOW = "dayofweek"
|
|
CONF_SHOWDATE = "show_date"
|
|
CONF_DISPLAY = "display8x32"
|
|
CONF_HTML = "html"
|
|
CONF_SCROLLINTERVALL = "scroll_intervall"
|
|
CONF_ANIMINTERVALL = "anim_intervall"
|
|
CONF_FONT_ID = "font_id"
|
|
CONF_YOFFSET = "yoffset"
|
|
CONF_XOFFSET = "xoffset"
|
|
CONF_PINGPONG = "pingpong"
|
|
CONF_TIME_FORMAT = "time_format"
|
|
CONF_DATE_FORMAT = "date_format"
|
|
CONF_SELECT = "ehmtxselect"
|
|
CONF_ON_NEXT_SCREEN = "on_next_screen"
|
|
CONF_WEEK_ON_MONDAY = "week_start_monday"
|
|
CONF_ICON = "icon_name"
|
|
CONF_TEXT = "text"
|
|
CONF_ALARM = "alarm"
|
|
|
|
EHMTX_SCHEMA = cv.Schema({
|
|
cv.Required(CONF_ID): cv.declare_id(EHMTX_),
|
|
cv.Required(CONF_TIME): cv.use_id(time),
|
|
cv.Required(CONF_DISPLAY): cv.use_id(display),
|
|
cv.Required(CONF_FONT_ID): cv.use_id(font),
|
|
cv.Optional(
|
|
CONF_SHOWCLOCK, default="5"
|
|
): cv.templatable(cv.positive_int),
|
|
cv.Optional(
|
|
CONF_SELECT,
|
|
): cv.use_id(EHMTXSelect),
|
|
cv.Optional(
|
|
CONF_YOFFSET, default="6"
|
|
): cv.templatable(cv.int_range(min=-32, max=32)),
|
|
cv.Optional(
|
|
CONF_HTML, default=False
|
|
): cv.boolean,
|
|
cv.Optional(
|
|
CONF_SHOWDATE, default=True
|
|
): cv.boolean,
|
|
cv.Optional(
|
|
CONF_WEEK_ON_MONDAY, default=True
|
|
): cv.boolean,
|
|
cv.Optional(
|
|
CONF_SHOWDOW, default=True
|
|
): cv.boolean,
|
|
cv.Optional(
|
|
CONF_TIME_FORMAT, default="%H:%M"
|
|
): cv.string,
|
|
cv.Optional(
|
|
CONF_DATE_FORMAT, default="%d.%m."
|
|
): cv.string,
|
|
cv.Optional(
|
|
CONF_XOFFSET, default="1"
|
|
): cv.templatable(cv.int_range(min=-32, max=32)),
|
|
cv.Optional(CONF_SCROLLINTERVALL, default="80"
|
|
): cv.templatable(cv.positive_int),
|
|
cv.Optional(
|
|
CONF_ANIMINTERVALL, default="192"
|
|
): cv.templatable(cv.positive_int),
|
|
cv.Optional(
|
|
CONF_SHOWSCREEN, default="8"
|
|
): cv.templatable(cv.positive_int),
|
|
cv.Optional(CONF_BRIGHTNESS, default=80): cv.templatable(cv.int_range(min=0, max=255)),
|
|
cv.Optional(
|
|
CONF_DURATION, default="5"
|
|
): cv.templatable(cv.positive_int),
|
|
cv.Optional(CONF_ON_NEXT_SCREEN): automation.validate_automation(
|
|
{
|
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(NextScreenTrigger),
|
|
}
|
|
),
|
|
cv.Required(CONF_ICONS): cv.All(
|
|
cv.ensure_list(
|
|
{
|
|
cv.Required(CONF_ID): cv.declare_id(Icons_),
|
|
|
|
cv.Exclusive(CONF_FILE,"uri"): cv.file_,
|
|
cv.Exclusive(CONF_URL,"uri"): cv.url,
|
|
cv.Exclusive(CONF_LAMEID,"uri"): cv.string,
|
|
cv.Exclusive(CONF_AWTRIXID,"uri"): cv.string,
|
|
cv.Optional(
|
|
CONF_DURATION, default="0"
|
|
): cv.templatable(cv.positive_int),
|
|
cv.Optional(
|
|
CONF_PINGPONG, default=False
|
|
): cv.boolean,
|
|
cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8),
|
|
}
|
|
),
|
|
cv.Length(max=MAXICONS),
|
|
)})
|
|
|
|
CONFIG_SCHEMA = cv.All(font.validate_pillow_installed, EHMTX_SCHEMA)
|
|
|
|
ADD_SCREEN_ACTION_SCHEMA = cv.Schema(
|
|
{
|
|
cv.GenerateID(): cv.use_id(EHMTX_),
|
|
cv.Required(CONF_ICON): cv.templatable(cv.string),
|
|
cv.Required(CONF_TEXT): cv.templatable(cv.string),
|
|
cv.Optional(CONF_DURATION): cv.templatable(cv.positive_int),
|
|
cv.Optional(CONF_ALARM, default=False): cv.templatable(cv.boolean),
|
|
}
|
|
)
|
|
|
|
|
|
NextScreenTrigger = ehmtx_ns.class_(
|
|
"EHMTXNextScreenTrigger", automation.Trigger.template(cg.std_string)
|
|
)
|
|
|
|
AddScreenAction = ehmtx_ns.class_("AddScreenAction", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.add.screen", AddScreenAction, ADD_SCREEN_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_add_screen_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
|
|
template_ = await cg.templatable(config[CONF_ICON], args, cg.std_string)
|
|
cg.add(var.set_icon(template_))
|
|
|
|
template_ = await cg.templatable(config[CONF_TEXT], args, cg.std_string)
|
|
cg.add(var.set_text(template_))
|
|
|
|
if CONF_DURATION in config:
|
|
template_ = await cg.templatable(config[CONF_DURATION], args, cg.uint8)
|
|
cg.add(var.set_duration(template_))
|
|
|
|
template_ = await cg.templatable(config[CONF_ALARM], args, bool)
|
|
cg.add(var.set_alarm(template_))
|
|
return var
|
|
|
|
SET_BRIGHTNESS_ACTION_SCHEMA = cv.Schema(
|
|
{
|
|
cv.GenerateID(): cv.use_id(EHMTX_),
|
|
cv.Optional(CONF_BRIGHTNESS, default=80): cv.templatable(cv.int_range(min=0, max=255)),
|
|
}
|
|
)
|
|
|
|
SetBrightnessAction = ehmtx_ns.class_("SetBrightnessAction", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.set.brightness", SetBrightnessAction, SET_BRIGHTNESS_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_set_brightness_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_BRIGHTNESS], args, cg.int_)
|
|
cg.add(var.set_brightness(template_))
|
|
|
|
return var
|
|
|
|
SET_COLOR_ACTION_SCHEMA = cv.Schema(
|
|
{
|
|
cv.GenerateID(): cv.use_id(EHMTX_),
|
|
cv.Optional(CONF_RED,default=80): cv.templatable(cv.uint8_t,),
|
|
cv.Optional(CONF_BLUE,default=80): cv.templatable(cv.uint8_t,),
|
|
cv.Optional(CONF_GREEN,default=80): cv.templatable(cv.uint8_t,),
|
|
}
|
|
)
|
|
|
|
SetClockColorAction = ehmtx_ns.class_("SetClockColor", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.clock.color", SetClockColorAction, SET_COLOR_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_set_clock_color_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_RED], args, cg.int_)
|
|
cg.add(var.set_red(template_))
|
|
template_ = await cg.templatable(config[CONF_GREEN], args, cg.int_)
|
|
cg.add(var.set_green(template_))
|
|
template_ = await cg.templatable(config[CONF_BLUE], args, cg.int_)
|
|
cg.add(var.set_blue(template_))
|
|
|
|
return var
|
|
|
|
SetTextColorAction = ehmtx_ns.class_("SetTextColor", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.text.color", SetTextColorAction, SET_COLOR_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_set_text_color_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_RED], args, cg.int_)
|
|
cg.add(var.set_red(template_))
|
|
template_ = await cg.templatable(config[CONF_GREEN], args, cg.int_)
|
|
cg.add(var.set_green(template_))
|
|
template_ = await cg.templatable(config[CONF_BLUE], args, cg.int_)
|
|
cg.add(var.set_blue(template_))
|
|
|
|
return var
|
|
|
|
SetAlarmColorAction = ehmtx_ns.class_("SetAlarmColor", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.alarm.color", SetAlarmColorAction, SET_COLOR_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_set_alarm_color_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_RED], args, cg.int_)
|
|
cg.add(var.set_red(template_))
|
|
template_ = await cg.templatable(config[CONF_GREEN], args, cg.int_)
|
|
cg.add(var.set_green(template_))
|
|
template_ = await cg.templatable(config[CONF_BLUE], args, cg.int_)
|
|
cg.add(var.set_blue(template_))
|
|
|
|
return var
|
|
|
|
SET_FLAG_ACTION_SCHEMA = cv.Schema(
|
|
{
|
|
cv.GenerateID(): cv.use_id(EHMTX_),
|
|
cv.Optional(CONF_FLAG,default=True): cv.templatable(cv.boolean),
|
|
}
|
|
)
|
|
|
|
SetShowDateAction = ehmtx_ns.class_("SetShowDate", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.show.date", SetShowDateAction, SET_FLAG_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_show_date_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_FLAG], args, cg.bool_)
|
|
cg.add(var.set_flag(template_))
|
|
|
|
return var
|
|
|
|
SetShowDayOfWeekAction = ehmtx_ns.class_("SetShowDayOfWeek", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.show.dayofweek", SetShowDayOfWeekAction, SET_FLAG_ACTION_SCHEMA
|
|
)
|
|
|
|
async def ehmtx_show_dayofweek_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_FLAG], args, cg.bool_)
|
|
cg.add(var.set_flag(template_))
|
|
|
|
return var
|
|
|
|
SetTodayColorAction = ehmtx_ns.class_("SetTodayColor", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.today.color", SetTodayColorAction, SET_COLOR_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_set_today_color_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_RED], args, cg.int_)
|
|
cg.add(var.set_red(template_))
|
|
template_ = await cg.templatable(config[CONF_GREEN], args, cg.int_)
|
|
cg.add(var.set_green(template_))
|
|
template_ = await cg.templatable(config[CONF_BLUE], args, cg.int_)
|
|
cg.add(var.set_blue(template_))
|
|
return var
|
|
|
|
SetWeekdayColorAction = ehmtx_ns.class_("SetWeekdayColor", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.weekday.color", SetWeekdayColorAction, SET_COLOR_ACTION_SCHEMA
|
|
)
|
|
|
|
async def ehmtx_set_week_color_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_RED], args, cg.int_)
|
|
cg.add(var.set_red(template_))
|
|
template_ = await cg.templatable(config[CONF_GREEN], args, cg.int_)
|
|
cg.add(var.set_green(template_))
|
|
template_ = await cg.templatable(config[CONF_BLUE], args, cg.int_)
|
|
cg.add(var.set_blue(template_))
|
|
|
|
return var
|
|
|
|
SetIndicatorOnAction = ehmtx_ns.class_("SetIndicatorOn", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.indicator.on", SetIndicatorOnAction, SET_COLOR_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_set_indicator_on_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_RED], args, cg.int_)
|
|
cg.add(var.set_red(template_))
|
|
template_ = await cg.templatable(config[CONF_GREEN], args, cg.int_)
|
|
cg.add(var.set_green(template_))
|
|
template_ = await cg.templatable(config[CONF_BLUE], args, cg.int_)
|
|
cg.add(var.set_blue(template_))
|
|
|
|
return var
|
|
|
|
DELETE_SCREEN_ACTION_SCHEMA = cv.Schema(
|
|
{
|
|
cv.GenerateID(): cv.use_id(EHMTX_),
|
|
cv.Required(CONF_ICON): cv.templatable(cv.string),
|
|
}
|
|
)
|
|
|
|
DeleteScreenAction = ehmtx_ns.class_("DeleteScreen", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.delete.screen", DeleteScreenAction, DELETE_SCREEN_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_delete_screen_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_ICON], args, cg.std_string)
|
|
cg.add(var.set_icon(template_))
|
|
|
|
return var
|
|
|
|
ForceScreenAction = ehmtx_ns.class_("ForceScreen", automation.Action)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.force.screen", ForceScreenAction, DELETE_SCREEN_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_force_screen_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
template_ = await cg.templatable(config[CONF_ICON], args, cg.std_string)
|
|
cg.add(var.set_icon(template_))
|
|
|
|
return var
|
|
|
|
SetIndicatorOffAction = ehmtx_ns.class_("SetIndicatorOff", automation.Action)
|
|
|
|
INDICATOR_OFF_ACTION_SCHEMA = cv.Schema(
|
|
{
|
|
cv.GenerateID(): cv.use_id(EHMTX_),
|
|
}
|
|
)
|
|
|
|
@automation.register_action(
|
|
"ehmtx.indicator.off", SetIndicatorOffAction, INDICATOR_OFF_ACTION_SCHEMA
|
|
)
|
|
async def ehmtx_set_indicator_off_action_to_code(config, action_id, template_arg, args):
|
|
paren = await cg.get_variable(config[CONF_ID])
|
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
|
|
|
return var
|
|
|
|
CODEOWNERS = ["@lubeda"]
|
|
|
|
async def to_code(config):
|
|
|
|
from PIL import Image
|
|
var = cg.new_Pvariable(config[CONF_ID])
|
|
html_string = F"<HTML><HEAD><TITLE>{CORE.config_path}</TITLE></HEAD>"
|
|
html_string += '''\
|
|
<STYLE>
|
|
</STYLE><BODY>\
|
|
'''
|
|
for conf in config[CONF_ICONS]:
|
|
|
|
if CONF_FILE in conf:
|
|
path = CORE.relative_config_path(conf[CONF_FILE])
|
|
try:
|
|
image = Image.open(path)
|
|
except Exception as e:
|
|
raise core.EsphomeError(f" ICONS: Could not load image file {path}: {e}")
|
|
elif CONF_LAMEID in conf:
|
|
r = requests.get("https://developer.lametric.com/content/apps/icon_thumbs/" + conf[CONF_LAMEID], timeout=4.0)
|
|
if r.status_code != requests.codes.ok:
|
|
raise core.EsphomeError(f" ICONS: Could not download image file {conf[CONF_LAMEID]}: {conf[CONF_ID]}")
|
|
image = Image.open(io.BytesIO(r.content))
|
|
elif CONF_AWTRIXID in conf:
|
|
r = requests.post("https://awtrix.blueforcer.de/icon",json={"reqType":"getIcon","ID":"" + conf[CONF_AWTRIXID] + ""} , timeout=4.0)
|
|
if r.status_code != requests.codes.ok:
|
|
raise core.EsphomeError(f" ICONS: Could not download awtrix data {conf[CONF_AWTRIXID]}: {conf[CONF_ID]}")
|
|
awtrixdata = r.json()
|
|
r = requests.get("https://awtrix.blueforcer.de/icons/"+conf[CONF_AWTRIXID], timeout=4.0)
|
|
if r.status_code != requests.codes.ok:
|
|
raise core.EsphomeError(f" ICONS: Could not download awtrix icon {conf[CONF_URL]}: {conf[CONF_ID]}")
|
|
image = Image.open(io.BytesIO(r.content))
|
|
elif CONF_URL in conf:
|
|
r = requests.get(conf[CONF_URL], timeout=4.0)
|
|
if r.status_code != requests.codes.ok:
|
|
raise core.EsphomeError(f" ICONS: Could not download image file {conf[CONF_URL]}: {conf[CONF_ID]}")
|
|
image = Image.open(io.BytesIO(r.content))
|
|
|
|
width, height = image.size
|
|
|
|
if (width != ICONWIDTH) or (height != ICONHEIGHT):
|
|
image = image.resize(ICONSIZE)
|
|
width, height = image.size
|
|
|
|
if hasattr(image, 'n_frames'):
|
|
frames = min(image.n_frames, MAXFRAMES)
|
|
else:
|
|
frames = 1
|
|
|
|
if (conf[CONF_DURATION] == 0):
|
|
try:
|
|
duration = image.info['duration']
|
|
except:
|
|
duration = config[CONF_ANIMINTERVALL]
|
|
else:
|
|
duration = conf[CONF_DURATION]
|
|
|
|
html_string += F"<BR><B>{conf[CONF_ID]}</B> - ({duration} ms):<BR>"
|
|
|
|
pos = 0
|
|
frameIndex = 0
|
|
html_string += f"<DIV ID={conf[CONF_ID]}>"
|
|
if CONF_AWTRIXID in conf:
|
|
if "data" in awtrixdata:
|
|
frames = len(awtrixdata["data"])
|
|
frameIndex = 0
|
|
data = [0 for _ in range(ICONBUFFERSIZE * 2 * frames)]
|
|
duration = awtrixdata["tick"]
|
|
for frame in awtrixdata["data"]:
|
|
if len(frame) != ICONBUFFERSIZE:
|
|
raise core.EsphomeError(
|
|
f"Unexpected number of pixels in awtrix"
|
|
)
|
|
i = 0
|
|
html_string += SVG_START
|
|
for pix in frame:
|
|
G = (pix & 0x07e0) >> 5
|
|
B = pix & 0x1f
|
|
R = (pix & 0xF800) >> 11
|
|
x = (i % ICONWIDTH)
|
|
y = i//ICONHEIGHT
|
|
i += 1
|
|
rgb = pix # (R << 11) | (G << 5) | B
|
|
html_string += rgb565_svg(x,y,R,G,B)
|
|
data[pos] = rgb >> 8
|
|
pos += 1
|
|
data[pos] = rgb & 255
|
|
pos += 1
|
|
frameIndex += 1
|
|
html_string += SVG_END
|
|
else:
|
|
frames = 1
|
|
i = 0
|
|
data = [0 for _ in range(ICONBUFFERSIZE * 2)]
|
|
html_string += SVG_START
|
|
for pix in awtrixdata:
|
|
x = (i % ICONWIDTH)
|
|
y = i//ICONHEIGHT
|
|
i +=1
|
|
rgb = pix
|
|
G = (pix & 0x07e0) >> 5
|
|
B = pix & 0x1f
|
|
R = (pix & 0xF800) >> 11
|
|
|
|
html_string += rgb565_svg(x,y,R,G,B)
|
|
|
|
data[pos] = rgb >> 8
|
|
pos += 1
|
|
data[pos] = rgb & 255
|
|
pos += 1
|
|
html_string += SVG_END
|
|
else:
|
|
data = [0 for _ in range(ICONBUFFERSIZE * 2 * frames)]
|
|
for frameIndex in range(frames):
|
|
html_string += SVG_START
|
|
image.seek(frameIndex)
|
|
frame = image.convert("RGB")
|
|
pixels = list(frame.getdata())
|
|
if len(pixels) != ICONBUFFERSIZE:
|
|
raise core.EsphomeError(
|
|
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
|
|
)
|
|
i = 0
|
|
for pix in pixels:
|
|
R = pix[0] >> 3
|
|
G = pix[1] >> 2
|
|
B = pix[2] >> 3
|
|
x = (i % ICONWIDTH)
|
|
y = i//ICONHEIGHT
|
|
i +=1
|
|
rgb = (R << 11) | (G << 5) | B
|
|
html_string += rgb565_svg(x,y,R,G,B)
|
|
data[pos] = rgb >> 8
|
|
pos += 1
|
|
data[pos] = rgb & 255
|
|
pos += 1
|
|
html_string += SVG_END
|
|
html_string += f"</DIV>"
|
|
|
|
rhs = [HexInt(x) for x in data]
|
|
|
|
prog_arr = cg.progmem_array(conf[CONF_RAW_DATA_ID], rhs)
|
|
|
|
cg.new_Pvariable(
|
|
conf[CONF_ID],
|
|
prog_arr,
|
|
width,
|
|
height,
|
|
frames,
|
|
espImage.IMAGE_TYPE["RGB565"],
|
|
str(conf[CONF_ID]),
|
|
conf[CONF_PINGPONG],
|
|
duration,
|
|
)
|
|
|
|
cg.add(var.add_icon(RawExpression(str(conf[CONF_ID]))))
|
|
|
|
html_string += "</BODY></HTML>"
|
|
|
|
if config[CONF_HTML]:
|
|
try:
|
|
with open(CORE.config_path.replace(".yaml","") + ".html", 'w') as f:
|
|
f.truncate()
|
|
f.write(html_string)
|
|
f.close()
|
|
except:
|
|
print("Error writing HTML file")
|
|
|
|
cg.add(var.set_clock_time(config[CONF_SHOWCLOCK]))
|
|
cg.add(var.set_default_brightness(config[CONF_BRIGHTNESS]))
|
|
cg.add(var.set_screen_time(config[CONF_SHOWSCREEN]))
|
|
cg.add(var.set_duration(config[CONF_DURATION]))
|
|
cg.add(var.set_scroll_intervall(config[CONF_SCROLLINTERVALL]))
|
|
cg.add(var.set_anim_intervall(config[CONF_ANIMINTERVALL]))
|
|
cg.add(var.set_week_start(config[CONF_WEEK_ON_MONDAY]))
|
|
cg.add(var.set_time_format(config[CONF_TIME_FORMAT]))
|
|
cg.add(var.set_date_format(config[CONF_DATE_FORMAT]))
|
|
cg.add(var.set_show_day_of_week(config[CONF_SHOWDOW]))
|
|
cg.add(var.set_show_date(config[CONF_SHOWDATE]))
|
|
cg.add(var.set_font_offset(config[CONF_XOFFSET], config[CONF_YOFFSET]))
|
|
|
|
disp = await cg.get_variable(config[CONF_DISPLAY])
|
|
cg.add(var.set_display(disp))
|
|
|
|
f = await cg.get_variable(config[CONF_FONT_ID])
|
|
cg.add(var.set_font(f))
|
|
|
|
ehmtxtime = await cg.get_variable(config[CONF_TIME])
|
|
cg.add(var.set_clock(ehmtxtime))
|
|
|
|
if (config.get(CONF_SELECT)):
|
|
ehmtxselect = await cg.get_variable(config[CONF_SELECT])
|
|
cg.add(var.set_select(ehmtxselect))
|
|
|
|
for conf in config.get(CONF_ON_NEXT_SCREEN, []):
|
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
|
await automation.build_automation(trigger, [(cg.std_string, "x"), (cg.std_string, "y")], conf)
|
|
|
|
await cg.register_component(var, config)
|