def hex_int_(value): if isinstance(value, integer_types): return HexInt(value) value = string_strict(value).lower() if value.startswith('0x'): return HexInt(int(value, 16)) return HexInt(int(value))
def to_code(config): from PIL import Image path = CORE.relative_config_path(config[CONF_FILE]) try: image = Image.open(path) except Exception as e: raise core.EsphomeError(f"Could not load image file {path}: {e}") if CONF_RESIZE in config: image.thumbnail(config[CONF_RESIZE]) if config[CONF_TYPE].startswith('RGB565'): width, height = image.size image = image.convert('RGB') pixels = list(image.getdata()) data = [0 for _ in range(height * width * 2)] pos = 0 for pix in pixels: r = (pix[0] >> 3) & 0x1F g = (pix[1] >> 2) & 0x3F b = (pix[2] >> 3) & 0x1F p = (r << 11) + (g << 5) + b data[pos] = (p >> 8) & 0xFF pos += 1 data[pos] = p & 0xFF pos += 1 rhs = [HexInt(x) for x in data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.new_Pvariable(config[CONF_ID], prog_arr, width, height, 1) else: image = image.convert('1', dither=Image.NONE) width, height = image.size if width > 500 or height > 500: _LOGGER.warning( "The image you requested is very big. Please consider using the resize " "parameter") width8 = ((width + 7) // 8) * 8 data = [0 for _ in range(height * width8 // 8)] for y in range(height): for x in range(width): if image.getpixel((x, y)): continue pos = x + y * width8 data[pos // 8] |= 0x80 >> (pos % 8) rhs = [HexInt(x) for x in data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.new_Pvariable(config[CONF_ID], prog_arr, width, height)
def to_code(config): from PIL import Image path = CORE.relative_config_path(config[CONF_FILE]) try: image = Image.open(path) except Exception as e: raise core.EsphomeError(u"Could not load image file {}: {}".format( path, e)) if CONF_RESIZE in config: image.thumbnail(config[CONF_RESIZE]) image = image.convert('1', dither=Image.NONE) width, height = image.size if width > 500 or height > 500: _LOGGER.warning( "The image you requested is very big. Please consider using the resize " "parameter") width8 = ((width + 7) // 8) * 8 data = [0 for _ in range(height * width8 // 8)] for y in range(height): for x in range(width): if image.getpixel((x, y)): continue pos = x + y * width8 data[pos // 8] |= 0x80 >> (pos % 8) rhs = [HexInt(x) for x in data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.new_Pvariable(config[CONF_ID], prog_arr, width, height)
async def to_code(config): var = await binary_sensor.new_binary_sensor(config) hub = await cg.get_variable(config[CONF_PN532_ID]) cg.add(hub.register_tag(var)) addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split("-")] cg.add(var.set_uid(addr))
async def to_code(config): from PIL import Image path = CORE.relative_config_path(config[CONF_FILE]) try: image = Image.open(path) except Exception as e: raise core.EsphomeError(f"Could not load image file {path}: {e}") width, height = image.size if CONF_RESIZE in config: image.thumbnail(config[CONF_RESIZE]) width, height = image.size else: if width > 500 or height > 500: _LOGGER.warning( "The image you requested is very big. Please consider using" " the resize parameter.") dither = Image.NONE if config[ CONF_DITHER] == "NONE" else Image.FLOYDSTEINBERG if config[CONF_TYPE] == "GRAYSCALE": image = image.convert("L", dither=dither) pixels = list(image.getdata()) data = [0 for _ in range(height * width)] pos = 0 for pix in pixels: data[pos] = pix pos += 1 elif config[CONF_TYPE] == "RGB24": image = image.convert("RGB") pixels = list(image.getdata()) data = [0 for _ in range(height * width * 3)] pos = 0 for pix in pixels: data[pos] = pix[0] pos += 1 data[pos] = pix[1] pos += 1 data[pos] = pix[2] pos += 1 elif config[CONF_TYPE] == "BINARY": image = image.convert("1", dither=dither) width8 = ((width + 7) // 8) * 8 data = [0 for _ in range(height * width8 // 8)] for y in range(height): for x in range(width): if image.getpixel((x, y)): continue pos = x + y * width8 data[pos // 8] |= 0x80 >> (pos % 8) rhs = [HexInt(x) for x in data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.new_Pvariable(config[CONF_ID], prog_arr, width, height, IMAGE_TYPE[config[CONF_TYPE]])
def peer_to_code(config): var = cg.new_Pvariable(config[ehc.CONF_ID]) cg.add(var.set_bssid([HexInt(i) for i in config[ehc.CONF_BSSID].parts])) if ehc.CONF_PASSWORD in config: cg.add(var.set_aeskey(get_md5sum_hexint(config[ehc.CONF_PASSWORD]))) if c.CONF_AESKEY in config: cg.add(var.set_aeskey(*config[c.CONF_AESKEY].as_hex_int())) yield var
def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield binary_sensor.register_binary_sensor(var, config) hub = yield cg.get_variable(config[CONF_PN532_ID]) cg.add(hub.register_tag(var)) addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split("-")] cg.add(var.set_uid(addr))
def to_code(config): for uart_ in get_variable(config[CONF_UART_ID]): yield data = config[CONF_DATA] if isinstance(data, str): data = [HexInt(ord(x)) for x in data] rhs = App.make_uart_switch(uart_, config[CONF_NAME], data) var = Pvariable(config[CONF_ID], rhs) switch.setup_switch(var, config)
async def to_code(config): from PIL import ImageFont conf = config[CONF_FILE] if conf[CONF_TYPE] == TYPE_LOCAL: path = CORE.relative_config_path(conf[CONF_PATH]) elif conf[CONF_TYPE] == TYPE_GFONTS: path = _compute_gfonts_local_path(conf) try: font = ImageFont.truetype(str(path), config[CONF_SIZE]) except Exception as e: raise core.EsphomeError(f"Could not load truetype file {path}: {e}") ascent, descent = font.getmetrics() glyph_args = {} data = [] for glyph in config[CONF_GLYPHS]: mask = font.getmask(glyph, mode="1") _, (offset_x, offset_y) = font.font.getsize(glyph) width, height = mask.size width8 = ((width + 7) // 8) * 8 glyph_data = [0] * (height * width8 // 8) for y in range(height): for x in range(width): if not mask.getpixel((x, y)): continue pos = x + y * width8 glyph_data[pos // 8] |= 0x80 >> (pos % 8) glyph_args[glyph] = (len(data), offset_x, offset_y, width, height) data += glyph_data rhs = [HexInt(x) for x in data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) glyph_initializer = [] for glyph in config[CONF_GLYPHS]: glyph_initializer.append( cg.StructInitializer( GlyphData, ("a_char", glyph), ( "data", cg.RawExpression( f"{str(prog_arr)} + {str(glyph_args[glyph][0])}"), ), ("offset_x", glyph_args[glyph][1]), ("offset_y", glyph_args[glyph][2]), ("width", glyph_args[glyph][3]), ("height", glyph_args[glyph][4]), )) glyphs = cg.static_const_array(config[CONF_RAW_GLYPH_ID], glyph_initializer) cg.new_Pvariable(config[CONF_ID], glyphs, len(glyph_initializer), ascent, ascent + descent)
def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) yield switch.register_switch(var, config) yield uart.register_uart_device(var, config) data = config[CONF_DATA] if isinstance(data, bytes): data = [HexInt(x) for x in data] cg.add(var.set_data(data))
async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await switch.register_switch(var, config) await uart.register_uart_device(var, config) data = config[CONF_DATA] if isinstance(data, bytes): data = [HexInt(x) for x in data] cg.add(var.set_data(data)) if CONF_SEND_EVERY in config: cg.add(var.set_send_every(config[CONF_SEND_EVERY]))
async def to_code(config): if config[CONF_MODEL] == "M5STACK": lcd_type = ILI9341M5Stack if config[CONF_MODEL] == "TFT_2.4": lcd_type = ILI9341TFT24 if config[CONF_MODEL] == "TFT_2.4R": lcd_type = ILI9341TFT24R rhs = lcd_type.new() var = cg.Pvariable(config[CONF_ID], rhs) await cg.register_component(var, config) await display.register_display(var, config) await spi.register_spi_device(var, config) cg.add(var.set_model(config[CONF_MODEL])) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) if CONF_LAMBDA in config: lambda_ = await cg.process_lambda(config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void) cg.add(var.set_writer(lambda_)) if CONF_RESET_PIN in config: reset = await cg.gpio_pin_expression(config[CONF_RESET_PIN]) cg.add(var.set_reset_pin(reset)) if CONF_LED_PIN in config: led_pin = await cg.gpio_pin_expression(config[CONF_LED_PIN]) cg.add(var.set_led_pin(led_pin)) if config[CONF_COLOR_PALETTE] == "GRAYSCALE": cg.add(var.set_buffer_color_mode(ILI9341ColorMode.BITS_8_INDEXED)) rhs = [] for x in range(256): rhs.extend([HexInt(x), HexInt(x), HexInt(x)]) prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_palette(prog_arr)) else: pass
def wifi_network(config, static_ip): ap = variable(config[CONF_ID], WiFiAP()) if CONF_SSID in config: add(ap.set_ssid(config[CONF_SSID])) if CONF_PASSWORD in config: add(ap.set_password(config[CONF_PASSWORD])) if CONF_BSSID in config: add(ap.set_bssid([HexInt(i) for i in config[CONF_BSSID].parts])) if CONF_HIDDEN in config: add(ap.set_hidden(config[CONF_HIDDEN])) if CONF_CHANNEL in config: add(ap.set_channel(config[CONF_CHANNEL])) if static_ip is not None: add(ap.set_manual_ip(manual_ip(static_ip))) return ap
def wifi_network(config, static_ip): ap = cg.variable(config[CONF_ID], WiFiAP()) if CONF_SSID in config: cg.add(ap.set_ssid(config[CONF_SSID])) if CONF_PASSWORD in config: cg.add(ap.set_password(config[CONF_PASSWORD])) if CONF_EAP in config: cg.add(ap.set_eap(eap_auth(config[CONF_EAP]))) cg.add_define("ESPHOME_WIFI_WPA2_EAP") if CONF_BSSID in config: cg.add(ap.set_bssid([HexInt(i) for i in config[CONF_BSSID].parts])) if CONF_HIDDEN in config: cg.add(ap.set_hidden(config[CONF_HIDDEN])) if CONF_CHANNEL in config: cg.add(ap.set_channel(config[CONF_CHANNEL])) if static_ip is not None: cg.add(ap.set_manual_ip(manual_ip(static_ip))) if CONF_PRIORITY in config: cg.add(ap.set_priority(config[CONF_PRIORITY])) return ap
def to_code(config): from PIL import ImageFont path = CORE.relative_path(config[CONF_FILE]) try: font = ImageFont.truetype(path, config[CONF_SIZE]) except Exception as e: raise core.EsphomeError(u"Could not load truetype file {}: {}".format( path, e)) ascent, descent = font.getmetrics() glyph_args = {} data = [] for glyph in config[CONF_GLYPHS]: mask = font.getmask(glyph, mode='1') _, (offset_x, offset_y) = font.font.getsize(glyph) width, height = mask.size width8 = ((width + 7) // 8) * 8 glyph_data = [0 for _ in range(height * width8 // 8)] # noqa: F812 for y in range(height): for x in range(width): if not mask.getpixel((x, y)): continue pos = x + y * width8 glyph_data[pos // 8] |= 0x80 >> (pos % 8) glyph_args[glyph] = (len(data), offset_x, offset_y, width, height) data += glyph_data rhs = safe_exp([HexInt(x) for x in data]) prog_arr = progmem_array(config[CONF_RAW_DATA_ID], rhs) glyphs = [] for glyph in config[CONF_GLYPHS]: glyphs.append(Glyph(glyph, prog_arr, *glyph_args[glyph])) rhs = App.make_font(glyphs, ascent, ascent + descent) Pvariable(config[CONF_ID], rhs)
def get_firmware(value): if not value[CONF_UPDATE]: return None def dl(url): try: req = requests.get(url) req.raise_for_status() except requests.exceptions.RequestException as e: raise cv.Invalid(f"Could not download firmware file ({url}): {e}") h = hashlib.new("sha256") h.update(req.content) return req.content, h.hexdigest() url = value[CONF_URL] if CONF_SHA256 in value: # we have a hash, enable caching path = (Path(CORE.config_dir) / ".esphome" / DOMAIN / (value[CONF_SHA256] + "_fw_stm.bin")) if not path.is_file(): firmware_data, dl_hash = dl(url) if dl_hash != value[CONF_SHA256]: raise cv.Invalid( f"Hash mismatch for {url}: {dl_hash} != {value[CONF_SHA256]}" ) path.parent.mkdir(exist_ok=True, parents=True) path.write_bytes(firmware_data) else: firmware_data = path.read_bytes() else: # no caching, download every time firmware_data, dl_hash = dl(url) return [HexInt(x) for x in firmware_data]
def __init__(self, i): # type: (int) -> None super(HexIntLiteral, self).__init__() self.i = HexInt(i)
def as_hex_int(self): return [HexInt(i) for i in self.parts]
def hex_int(value): """Validate the given value to be a hex integer. This is mostly for cosmetic purposes of the generated code. """ return HexInt(int_(value))
def to_code(config): from PIL import Image path = CORE.relative_config_path(config[CONF_FILE]) try: image = Image.open(path) except Exception as e: raise core.EsphomeError(f"Could not load image file {path}: {e}") width, height = image.size frames = image.n_frames if CONF_RESIZE in config: image.thumbnail(config[CONF_RESIZE]) width, height = image.size else: if width > 500 or height > 500: _LOGGER.warning( "The image you requested is very big. Please consider using" " the resize parameter.") if config[CONF_TYPE] == 'GRAYSCALE': data = [0 for _ in range(height * width * frames)] pos = 0 for frameIndex in range(frames): image.seek(frameIndex) frame = image.convert('L', dither=Image.NONE) pixels = list(frame.getdata()) for pix in pixels: data[pos] = pix pos += 1 elif config[CONF_TYPE] == 'RGB24': data = [0 for _ in range(height * width * 3 * frames)] pos = 0 for frameIndex in range(frames): image.seek(frameIndex) frame = image.convert('RGB') pixels = list(frame.getdata()) for pix in pixels: data[pos] = pix[0] pos += 1 data[pos] = pix[1] pos += 1 data[pos] = pix[2] pos += 1 elif config[CONF_TYPE] == 'BINARY': width8 = ((width + 7) // 8) * 8 data = [0 for _ in range((height * width8 // 8) * frames)] for frameIndex in range(frames): image.seek(frameIndex) frame = image.convert('1', dither=Image.NONE) for y in range(height): for x in range(width): if frame.getpixel((x, y)): continue pos = x + y * width8 + (height * width8 * frameIndex) data[pos // 8] |= 0x80 >> (pos % 8) rhs = [HexInt(x) for x in data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.new_Pvariable(config[CONF_ID], prog_arr, width, height, frames, espImage.IMAGE_TYPE[config[CONF_TYPE]])
def __init__(self, i): # type: (int) -> None super().__init__() self.i = HexInt(i)
def to_code(config): for hub in get_variable(config[CONF_PN532_ID]): yield addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split('-')] rhs = hub.make_tag(config[CONF_NAME], addr) binary_sensor.register_binary_sensor(rhs, config)
def __init__(self, i: int): super().__init__() self.i = HexInt(i)
async def to_code(config): from PIL import Image path = CORE.relative_config_path(config[CONF_FILE]) try: image = Image.open(path) except Exception as e: raise core.EsphomeError(f"Could not load image file {path}: {e}") width, height = image.size frames = image.n_frames if CONF_RESIZE in config: new_width_max, new_height_max = config[CONF_RESIZE] ratio = min(new_width_max / width, new_height_max / height) width, height = int(width * ratio), int(height * ratio) else: if width > 500 or height > 500: _LOGGER.warning( "The image you requested is very big. Please consider using" " the resize parameter.") if config[CONF_TYPE] == "GRAYSCALE": data = [0 for _ in range(height * width * frames)] pos = 0 for frameIndex in range(frames): image.seek(frameIndex) frame = image.convert("L", dither=Image.NONE) if CONF_RESIZE in config: frame = frame.resize([width, height]) pixels = list(frame.getdata()) if len(pixels) != height * width: raise core.EsphomeError( f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})" ) for pix in pixels: data[pos] = pix pos += 1 elif config[CONF_TYPE] == "RGB24": data = [0 for _ in range(height * width * 3 * frames)] pos = 0 for frameIndex in range(frames): image.seek(frameIndex) frame = image.convert("RGB") if CONF_RESIZE in config: frame = frame.resize([width, height]) pixels = list(frame.getdata()) if len(pixels) != height * width: raise core.EsphomeError( f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})" ) for pix in pixels: data[pos] = pix[0] pos += 1 data[pos] = pix[1] pos += 1 data[pos] = pix[2] pos += 1 elif config[CONF_TYPE] == "RGB565": data = [0 for _ in range(height * width * 2 * frames)] pos = 0 for frameIndex in range(frames): image.seek(frameIndex) frame = image.convert("RGB") if CONF_RESIZE in config: frame = frame.resize([width, height]) pixels = list(frame.getdata()) if len(pixels) != height * width: raise core.EsphomeError( f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})" ) for pix in pixels: R = pix[0] >> 3 G = pix[1] >> 2 B = pix[2] >> 3 rgb = (R << 11) | (G << 5) | B data[pos] = rgb >> 8 pos += 1 data[pos] = rgb & 255 pos += 1 elif config[CONF_TYPE] == "BINARY": width8 = ((width + 7) // 8) * 8 data = [0 for _ in range((height * width8 // 8) * frames)] for frameIndex in range(frames): image.seek(frameIndex) frame = image.convert("1", dither=Image.NONE) if CONF_RESIZE in config: frame = frame.resize([width, height]) for y in range(height): for x in range(width): if frame.getpixel((x, y)): continue pos = x + y * width8 + (height * width8 * frameIndex) data[pos // 8] |= 0x80 >> (pos % 8) rhs = [HexInt(x) for x in data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.new_Pvariable( config[CONF_ID], prog_arr, width, height, frames, espImage.IMAGE_TYPE[config[CONF_TYPE]], )
def get_md5sum_hexint(text, length=None): parts = get_md5sum(text) if length is not None: parts = parts[:length] return [HexInt(i) for i in parts]
def make_address_array(address): return [HexInt(i) for i in address.parts]
def binary_code(value): code = 0 for val in value: code <<= 1 code |= val == '1' return HexInt(code)