Skip to content

Commit

Permalink
Create new page item for 'delete' entities
Browse files Browse the repository at this point in the history
This required refactoring page_type to avoid 'undefined reference' linker errors.
Closes #11
  • Loading branch information
olicooper committed May 2, 2024
1 parent 3391673 commit f49e84c
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 52 deletions.
41 changes: 26 additions & 15 deletions components/nspanel_lovelace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,9 @@ def validate_config(config):
if entity_arr[1] not in card_ids:
raise cv.Invalid(f'navigation entity_id invalid, no card has the id "{entity_arr[1]}"')
# Add all valid HA entities to global entity list for later processing
# elif not (entity_id.startswith('iText') or entity_id.startswith('delete')):
add_entity_id(entity_id)
# if not (entity_id.startswith('iText') or entity_id.startswith('delete')):
if not entity_id.startswith('delete'):
add_entity_id(entity_id)
if CONF_CARD_ALARM_ENTITY_ID in card_config:
add_entity_id(card_config.get(CONF_CARD_ALARM_ENTITY_ID))

Expand Down Expand Up @@ -377,21 +378,24 @@ def validate_config(config):
QRCard = nspanel_lovelace_ns.class_("QRCard")
AlarmCard = nspanel_lovelace_ns.class_("AlarmCard")

DeleteItem = nspanel_lovelace_ns.class_("DeleteItem")
NavigationItem = nspanel_lovelace_ns.class_("NavigationItem")
StatusIconItem = nspanel_lovelace_ns.class_("StatusIconItem")
WeatherItem = nspanel_lovelace_ns.class_("WeatherItem")
EntitiesCardEntityItem = nspanel_lovelace_ns.class_("EntitiesCardEntityItem")
GridCardEntityItem = nspanel_lovelace_ns.class_("GridCardEntityItem")
AlarmButtonItem = nspanel_lovelace_ns.class_("AlarmButtonItem")

PageType = nspanel_lovelace_ns.enum("page_type", True)

PAGE_MAP = {
# [config type] : [c++ variable name prefix], [card class], [entity class]
CONF_SCREENSAVER: ["nspanel_screensaver", Screensaver, WeatherItem],
CARD_ENTITIES: ["nspanel_card_", EntitiesCard, EntitiesCardEntityItem],
CARD_GRID: ["nspanel_card_", GridCard, GridCardEntityItem],
# CARD_GRID2: ["nspanel_card_", GridCard2, GridCardEntityItem],
CARD_QR: ["nspanel_card_", QRCard, EntitiesCardEntityItem],
CARD_ALARM: ["nspanel_card_", AlarmCard, AlarmButtonItem]
CONF_SCREENSAVER: ["nspanel_screensaver", Screensaver, PageType.screensaver, WeatherItem],
CARD_ENTITIES: ["nspanel_card_", EntitiesCard, PageType.cardEntities, EntitiesCardEntityItem],
CARD_GRID: ["nspanel_card_", GridCard, PageType.cardGrid, GridCardEntityItem],
# CARD_GRID2: ["nspanel_card_", GridCard2, PageType.cardGrid2, GridCardEntityItem],
CARD_QR: ["nspanel_card_", QRCard, PageType.cardQR, EntitiesCardEntityItem],
CARD_ALARM: ["nspanel_card_", AlarmCard, PageType.cardAlarm, AlarmButtonItem]
}

def get_new_uuid(prefix: str = ""):
Expand Down Expand Up @@ -430,13 +434,20 @@ def generate_icon_config(icon_config, parent_class: cg.MockObj = None) -> Union[
if parent_class is None:
return attrs

def gen_card_entities(entities_config, card_class: cg.MockObjClass, id_prefix: str, entity_type: cg.MockObjClass):
def gen_card_entities(entities_config, card_class: cg.MockObjClass, card_variable: cg.MockObjClass, entity_type: cg.MockObjClass):
for i, entity_config in enumerate(entities_config):
variable_name = id_prefix + "_item_" + str(i + 1)
variable_name = card_variable.__str__() + "_item_" + str(i + 1)
entity_class = cg.global_ns.class_(variable_name)
entity_class.op = "->"

entity_id = get_entity_id(entity_config.get(CONF_ENTITY_ID, "delete"))
if entity_config.get(CONF_ENTITY_ID, "delete").startswith('delete'):
cg.add(cg.RawExpression(
f"auto {variable_name} = "
f"{make_shared.template(DeleteItem).__call__(card_class)}"))
cg.add(card_variable.add_item(entity_class))
continue

entity_id = get_entity_id(entity_config.get(CONF_ENTITY_ID))
display_name = entity_config.get(CONF_CARD_ENTITIES_NAME, None)
# if display_name != None:
# entity_class = cg.new_Pvariable(variable_name, entity_config[CONF_CARD_ENTITIES_ID], entity_config[CONF_CARD_ENTITIES_NAME])
Expand All @@ -448,7 +459,7 @@ def gen_card_entities(entities_config, card_class: cg.MockObjClass, id_prefix: s

generate_icon_config(entity_config.get(CONF_ICON, None), entity_class)

cg.add(card_class.add_item(entity_class))
cg.add(card_variable.add_item(entity_class))

def get_status_icon_statement(icon_config, icon_class: cg.MockObjClass, default_icon_value: str = 'alert-circle-outline'):
entity_id = get_entity_id(icon_config.get(CONF_ENTITY_ID))
Expand Down Expand Up @@ -596,7 +607,7 @@ async def to_code(config):
screensaver_items = []
# 1 main weather item + 4 forecast items
for i in range(0,5):
screensaver_items.append(make_shared.template(screensaver_info[2]).__call__(get_new_uuid()))
screensaver_items.append(make_shared.template(screensaver_info[3]).__call__(get_new_uuid()))
cg.add(screensaver_class.add_item_range(screensaver_items))

cg.add(cg.RawStatement("}"))
Expand Down Expand Up @@ -696,9 +707,9 @@ async def to_code(config):

gen_card_entities(
card_config.get(CONF_CARD_ENTITIES, []),
page_info[2],
card_class,
card_variable,
page_info[2])
page_info[3])

cg.add(cg.RawStatement("}"))

Expand Down
6 changes: 3 additions & 3 deletions components/nspanel_lovelace/card_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ namespace nspanel_lovelace {
* =============== Card ===============
*/

Card::Card(const char *type, const std::string &uuid) :
Card::Card(page_type type, const std::string &uuid) :
Page(type, uuid) {}

Card::Card(const char *type, const std::string &uuid,
Card::Card(page_type type, const std::string &uuid,
const std::string &title) : Page(type, uuid, title) {}

Card::Card(
const char *type, const std::string &uuid,
page_type type, const std::string &uuid,
const std::string &title, const uint16_t sleep_timeout) :
Page(type, uuid, title, sleep_timeout) {}

Expand Down
6 changes: 3 additions & 3 deletions components/nspanel_lovelace/card_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace nspanel_lovelace {
class Card : public Page {

public:
Card(const char *type, const std::string &uuid);
Card(const char *type, const std::string &uuid, const std::string &title);
Card(const char *type, const std::string &uuid,
Card(page_type type, const std::string &uuid);
Card(page_type type, const std::string &uuid, const std::string &title);
Card(page_type type, const std::string &uuid,
const std::string &title, const uint16_t sleep_timeout);
virtual ~Card() {}

Expand Down
4 changes: 2 additions & 2 deletions components/nspanel_lovelace/nspanel_lovelace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ void NSPanelLovelace::render_current_page_() {

this->command_buffer_.assign("pageType")
.append(1, SEPARATOR)
.append(this->current_page_->get_type());
.append(this->current_page_->get_type_str());
this->send_buffered_command_();
this->popup_page_current_uuid_.clear();

Expand Down Expand Up @@ -974,7 +974,7 @@ void NSPanelLovelace::process_button_press_(
}

// Screen tapped when on the screensaver, show the default card or use the first card in the config.
if (internal_id == page_type::screensaver && button_type == button_type::bExit) {
if (internal_id == to_string(page_type::screensaver) && button_type == button_type::bExit) {
// todo: make a note of last used card
//
// config.get("screensaver.defaultCard")
Expand Down
20 changes: 11 additions & 9 deletions components/nspanel_lovelace/page_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ namespace nspanel_lovelace {
*/

Page::Page() :
uuid_(""), type_(nullptr), hidden_(false),
uuid_(""), type_(page_type::unknown), hidden_(false),
sleep_timeout_(DEFAULT_SLEEP_TIMEOUT_S) {}

Page::Page(const char *type, const std::string &uuid) :
Page::Page(page_type type, const std::string &uuid) :
uuid_(uuid), type_(type), hidden_(false),
sleep_timeout_(DEFAULT_SLEEP_TIMEOUT_S) {}

Page::Page(
const char *type, const std::string &uuid, const std::string &title) :
page_type type, const std::string &uuid, const std::string &title) :
uuid_(uuid),
type_(type), title_(title), hidden_(false),
sleep_timeout_(DEFAULT_SLEEP_TIMEOUT_S) {}

Page::Page(
const char *type, const std::string &uuid, const std::string &title,
page_type type, const std::string &uuid, const std::string &title,
const uint16_t sleep_timeout) :
uuid_(uuid),
type_(type), title_(title), hidden_(false), sleep_timeout_(sleep_timeout) {}
Expand All @@ -37,8 +37,8 @@ Page::Page(const Page &other) :

void Page::accept(PageVisitor& visitor) { visitor.visit(*this); }

bool Page::is_type(const char *type) const {
return this->type_ == type || std::strcmp(this->type_, type) == 0;
bool Page::is_type(page_type type) const {
return this->type_ == type;
}

void Page::set_items_render_invalid() {
Expand All @@ -53,9 +53,11 @@ void Page::set_on_item_added_callback(
}

void Page::add_item(const std::shared_ptr<PageItem> &item) {
for (auto &i : this->items_) {
if (i->get_uuid() == item->get_uuid())
return;
if (item->get_uuid() != entity_type::delete_) {
for (auto &i : this->items_) {
if (i->get_uuid() == item->get_uuid())
return;
}
}
this->items_.push_back(item);
this->on_item_added_(item);
Expand Down
12 changes: 6 additions & 6 deletions components/nspanel_lovelace/page_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ namespace nspanel_lovelace {

class Page {
public:
Page(const char *type, const std::string &uuid);
Page(const char *type, const std::string &uuid, const std::string &title);
Page(page_type type, const std::string &uuid);
Page(page_type type, const std::string &uuid, const std::string &title);
Page(
const char *type, const std::string &uuid, const std::string &title,
page_type type, const std::string &uuid, const std::string &title,
const uint16_t sleep_timeout);
Page(const Page &other);
virtual ~Page() {}
Expand All @@ -32,8 +32,8 @@ class Page {

const std::string &get_uuid() const { return this->uuid_; }
const std::string &get_title() const { return this->title_; }
bool is_type(const char *type) const;
const char *get_type() const { return this->type_; }
bool is_type(page_type type) const;
const char *get_type_str() const { return to_string(this->type_); }
bool is_hidden() const { return this->hidden_; }
uint16_t get_sleep_timeout() const { return this->sleep_timeout_; }

Expand Down Expand Up @@ -74,7 +74,7 @@ class Page {
virtual void on_item_added_(const std::shared_ptr<PageItem> &item);

std::string uuid_;
const char *type_;
page_type type_;
std::string title_;
bool hidden_;
uint16_t sleep_timeout_;
Expand Down
3 changes: 3 additions & 0 deletions components/nspanel_lovelace/page_item_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ namespace esphome {
namespace nspanel_lovelace {

bool InheritancePageItemVisitor::visit(PageItem &item) { return false; }
bool InheritancePageItemVisitor::visit(DeleteItem &item) {
return visit(static_cast<PageItem &>(item));
}
bool InheritancePageItemVisitor::visit(NavigationItem &item) {
return visit(static_cast<PageItem &>(item));
}
Expand Down
3 changes: 3 additions & 0 deletions components/nspanel_lovelace/page_item_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace nspanel_lovelace {
*/

class PageItem;
class DeleteItem;
class NavigationItem;
class StatusIconItem;
class WeatherItem;
Expand All @@ -23,6 +24,7 @@ class EntitiesCardEntityItem;
class PageItemVisitor {
public:
virtual bool visit(PageItem &) = 0;
virtual bool visit(DeleteItem &) = 0;
virtual bool visit(NavigationItem &) = 0;
virtual bool visit(StatusIconItem &) = 0;
virtual bool visit(WeatherItem &) = 0;
Expand All @@ -37,6 +39,7 @@ class PageItemVisitor {
class InheritancePageItemVisitor : public PageItemVisitor {
public:
virtual bool visit(PageItem &);
virtual bool visit(DeleteItem &);
virtual bool visit(NavigationItem &);
virtual bool visit(StatusIconItem &);
virtual bool visit(WeatherItem &);
Expand Down
22 changes: 22 additions & 0 deletions components/nspanel_lovelace/page_items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,27 @@ std::string &AlarmIconItem::render_(std::string &buffer) {
return PageItem_Icon::render_(buffer);
}

/*
* =============== DeleteItem ===============
*/

DeleteItem::DeleteItem(page_type page_type) :
PageItem(entity_type::delete_) {
// Currently all page_types that accept delete entities
// have the same separator quantity
this->uuid_.append(5, SEPARATOR);
}

DeleteItem::DeleteItem(uint8_t separator_quantity) :
PageItem(entity_type::delete_) {
this->uuid_.append(separator_quantity, SEPARATOR);
}

void DeleteItem::accept(PageItemVisitor& visitor) { visitor.visit(*this); }

std::string &DeleteItem::render_(std::string &buffer) {
return buffer.append(this->uuid_);
}

} // namespace nspanel_lovelace
} // namespace esphome
18 changes: 18 additions & 0 deletions components/nspanel_lovelace/page_items.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,23 @@ class AlarmIconItem :
std::string &render_(std::string &buffer) override;
};


/*
* =============== AlarmIconItem ===============
*/

class DeleteItem : public PageItem {
public:
DeleteItem(page_type page_type);
DeleteItem(uint8_t separator_quantity);
// virtual ~DeleteItem() {}

void accept(PageItemVisitor& visitor) override;

protected:
// output: delete~ (seperator quantity varies based on page_type/separator_quantity)
std::string &render_(std::string &buffer) override;
};

} // namespace nspanel_lovelace
} // namespace esphome
49 changes: 35 additions & 14 deletions components/nspanel_lovelace/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,22 +405,43 @@ struct sensor_type {
static constexpr const char* window = "window";
};

struct page_type {
static constexpr const char* screensaver = "screensaver";
static constexpr const char* screensaver2 = "screensaver2";
static constexpr const char* cardGrid = "cardGrid";
static constexpr const char* cardGrid2 = "cardGrid2";
static constexpr const char* cardEntities = "cardEntities";
static constexpr const char* cardThermo = "cardThermo";
static constexpr const char* cardMedia = "cardMedia";
static constexpr const char* cardUnlock = "cardUnlock";
static constexpr const char* cardQR = "cardQR";
static constexpr const char* cardPower = "cardPower";
static constexpr const char* cardAlarm = "cardAlarm";

static constexpr const char* popupLight = "popupLight";
enum class page_type : uint8_t {
unknown,
screensaver,
screensaver2,
cardGrid,
cardGrid2,
cardEntities,
cardThermo,
cardMedia,
cardUnlock,
cardQR,
cardPower,
cardAlarm,
popupLight,
};
static constexpr const char* page_type_names [] = {
"",
"screensaver",
"screensaver2",
"cardGrid",
"cardGrid2",
"cardEntities",
"cardThermo",
"cardMedia",
"cardUnlock",
"cardQR",
"cardPower",
"cardAlarm",
"popupLight",
};

inline const char *to_string(page_type type) {
if ((size_t)type >= (sizeof(page_type_names) / sizeof(*page_type_names)))
return nullptr;
return page_type_names[(uint8_t)type];
}

struct action_type {
static constexpr const char* buttonPress2 = "buttonPress2";
static constexpr const char* pageOpenDetail = "pageOpenDetail";
Expand Down
2 changes: 2 additions & 0 deletions test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
# - Simulate TFT reboot (EU model, firmware version 53): `event,startup,53,eu`
# - Navigate to Extras 1 Card: `event,buttonPress2,navigate.uuid.extras_1_card,button`
# - Navigate to screensaver: `event,buttonPress2,navigate.uuid.1,button`
# - Navigate to first card: `event,buttonPress2,screensaver,bExit`
# - Close the current page / go back to screensaver: `event,sleepReached,`
# - Open a popupPage (open the page where the entity exists first):
# - Timer: `event,pageOpenDetail,popupTimer,uuid.15`
# - Start timer with time 0:35:40: `event,buttonPress2,uuid.15,timer-start,0:35:40`
# - RGBW Light: `event,pageOpenDetail,popupLight,uuid.12`

substitutions:
Expand Down

0 comments on commit f49e84c

Please sign in to comment.