Skip to content

Commit

Permalink
Merge pull request #140 from andrewjswan/2023.9.1-Add_Bitmap_stack_sc…
Browse files Browse the repository at this point in the history
…reen

2023.9.1: Add Bitmap Stack screen
  • Loading branch information
lubeda authored Nov 10, 2023
2 parents 5cc2f16 + 23e8008 commit c3350db
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 7 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
- Added `bitmap_small` and `rainbow_bitmap_small` screen.
- Added a pseudo-icon `blank` - empty icon, no display.
- Added screen with scroll icon along with long text, `icon_text_screen`, `rainbow_icon_text_screen`.
- Added `bitmap_stack`screen. Screen that allows you to display from 1 to 64 icons described in the configuration.

### EspHoMaTriX 2023.9.0
- Added the ability to display graph as defined in the YAML file
Expand Down Expand Up @@ -768,13 +769,15 @@ Numerous features are accessible with services from home assistant and lambdas t
|`rainbow_bitmap_small`|"icon", "text", "lifetime", "screen_time", "default_font"|show 8x8 image as text, and text in rainbow colors|
|`icon_text_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"|show the specified icon with text and scroll icon along with long text|
|`rainbow_icon_text_screen`|"icon_name", "text", "lifetime", "screen_time", "default_font"|show the specified icon with text in rainbow color and scroll icon along with long text|
|`bitmap_stack`|"icons", "lifetime", "screen_time"|show or scroll from 1 to 64 icons described in the configuration|

#### Parameter description

- **r, g, b**: Color components for red, green, and blue 0..255
- **size**: The size of the rindicator or alarm, 1-3
- **percent**: values from 0..100
- **icon_name**: the id of the icon to show, as defined in the YAML file (or pseudo-icon `blank` - empty icon), it is also possible to set the arbitrary [screen identifier](#screen_id), for example `icon_name|screen_id`
- **icons**: the list of id of the icon to show, as defined in the YAML file, like: icon1,icon2.
- **text**: a text message to display
- **lifetime**: how long does this screen stay in the queue (minutes)
- **screen_time**: how long is this screen display in the loop (seconds). For short text without scrolling it is shown the defined time, longer text is scrolled at least `scroll_count` times.
Expand Down Expand Up @@ -1036,6 +1039,7 @@ For example, if you have multiple icons named weather_sunny, weather_rain & weat
|MODE_RAINBOW_BITMAP_SMALL| 20|
|MODE_ICON_TEXT_SCREEN| 21|
|MODE_RAINBOW_ICON_TEXT_SCREEN| 22|
|MODE_BITMAP_STACK_SCREEN| 23|

**(D)** Service **display_on** / **display_off**

Expand Down Expand Up @@ -1345,6 +1349,31 @@ sensor:
            }
```

### bitmap_stack example

```
ehmtxv2:
icons:
- id: skull
lameid: 11241
```
```
service: esphome.esp_hall_pixel_clock_bitmap_stack
data:
icons: "skull,skull,skull"
lifetime: 1
screen_time: 10
```
```
service: esphome.esp_hall_pixel_clock_bitmap_stack
data:
icons: "skull,skull,skull|two"
lifetime: 1
screen_time: 10
```
## Breaking changes
### 2023.8.0
Expand Down
117 changes: 115 additions & 2 deletions components/ehmtxv2/EHMTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <sstream>
#include <vector>
#include <algorithm>
#include <string>

namespace esphome
{
Expand Down Expand Up @@ -334,6 +335,101 @@ namespace esphome
}
screen->status();
}

std::string trim(std::string const& s)
{
auto const first{ s.find_first_not_of(' ') };
if (first == std::string::npos)
return {};
auto const last{ s.find_last_not_of(' ') };
return s.substr(first, (last - first + 1));
}

void EHMTX::bitmap_stack(std::string icons, int lifetime, int screen_time)
{
icons.erase(remove(icons.begin(), icons.end(), ' '), icons.end());

std::string ic = get_icon_name(icons);
std::string id = "";

if (icons.find("|") != std::string::npos)
{
id = get_screen_id(icons);
}

std::stringstream stream(ic);
std::string icon;
std::vector<std::string> tokens;
uint8_t count = 0;

while (std::getline(stream, icon, ','))
{
icon = trim(icon);
if (!icon.empty())
{
tokens.push_back(icon);
count++;
}
if (count >= 64)
{
break;
}
}
if (count == 0)
{
ESP_LOGW(TAG, "bitmap stack: icons list [%s] empty", ic.c_str());
return;
}

EHMTX_queue *screen = this->find_mode_queue_element(MODE_BITMAP_STACK_SCREEN);
if (screen->sbitmap == NULL)
{
screen->sbitmap = new Color[64];
}

uint8_t real_count = 0;
for (uint8_t i = 0; i < count; i++)
{
uint8_t icon = this->find_icon(tokens[i].c_str());

if (icon == MAXICONS)
{
ESP_LOGW(TAG, "icon %d/%s not found => skip", icon, tokens[i].c_str());
for (auto *t : on_icon_error_triggers_)
{
t->process(tokens[i]);
}
}
else
{
screen->sbitmap[real_count] = Color(127, 255, icon, 5); // int16_t 32767 = uint8_t(127,255)
real_count++;
}
}
if (real_count == 0)
{
delete [] screen->sbitmap;
screen->sbitmap = nullptr;

ESP_LOGW(TAG, "bitmap stack: icons list [%s] does not contain any known icons.", ic.c_str());
return;
}

screen->icon = real_count;
screen->mode = MODE_BITMAP_STACK_SCREEN;
screen->icon_name = id;
screen->text = ic;
screen->progress = (id == "two") ? 1 : 0; // 0 - one side scroll (right to left), 1 - two side (outside to center) if supported
screen->default_font = false;
screen->calc_scroll_time(screen->icon, screen_time);
screen->endtime = this->get_tick() + (lifetime > 0 ? lifetime * 60000.0 : screen->screen_time_);
for (auto *t : on_add_screen_triggers_)
{
t->process(screen->text, (uint8_t)screen->mode);
}
ESP_LOGD(TAG, "bitmap stack: has %d icons from: [%s] screen_time: %d", screen->icon, icons.c_str(), screen_time);
screen->status();
}
#endif

#ifdef USE_ESP8266
Expand All @@ -349,6 +445,10 @@ namespace esphome
{
ESP_LOGW(TAG, "bitmap_screen_rainbow is not available on ESP8266");
}
void EHMTX::bitmap_stack(std::string i, int l, int s)
{
ESP_LOGW(TAG, "bitmap_stack is not available on ESP8266");
}
#endif

uint8_t EHMTX::find_icon(std::string name)
Expand Down Expand Up @@ -534,6 +634,7 @@ namespace esphome
register_service(&EHMTX::bitmap_screen, "bitmap_screen", {"icon", "lifetime", "screen_time"});
register_service(&EHMTX::bitmap_small, "bitmap_small", {"icon", "text", "lifetime", "screen_time", "default_font", "r", "g", "b"});
register_service(&EHMTX::rainbow_bitmap_small, "rainbow_bitmap_small", {"icon", "text", "lifetime", "screen_time", "default_font"});
register_service(&EHMTX::bitmap_stack, "bitmap_stack", {"icons", "lifetime", "screen_time"});
#endif

#ifdef USE_Fireplugin
Expand Down Expand Up @@ -783,11 +884,14 @@ namespace esphome
break;
case MODE_BITMAP_SMALL:
case MODE_RAINBOW_BITMAP_SMALL:
infotext = ("BITMAP_SMALL:" + this->queue[i]->icon_name).c_str();
infotext = ("BITMAP_SMALL: " + this->queue[i]->icon_name).c_str();
break;
case MODE_BITMAP_SCREEN:
infotext = "BITMAP";
break;
case MODE_BITMAP_STACK_SCREEN:
infotext = ("BITMAP_STACK: " + this->queue[i]->text).c_str();
break;
case MODE_FIRE:
infotext = "FIRE";
break;
Expand Down Expand Up @@ -882,7 +986,16 @@ namespace esphome
{
this->queue[this->screen_pointer]->last_time = ts + this->queue[this->screen_pointer]->screen_time_;
// todo nur bei animationen
if (this->queue[this->screen_pointer]->icon < this->icon_count)
if (this->queue[this->screen_pointer]->mode == MODE_BITMAP_STACK_SCREEN && this->queue[this->screen_pointer]->sbitmap != NULL)
{
for (uint8_t i = 0; i < this->queue[this->screen_pointer]->icon; i++)
{
this->icons[this->queue[this->screen_pointer]->sbitmap[i].b]->set_frame(0);
this->queue[this->screen_pointer]->sbitmap[i] = Color(127, 255, this->queue[this->screen_pointer]->sbitmap[i].b, 5);
this->queue[this->screen_pointer]->default_font = false;
}
}
else if (this->queue[this->screen_pointer]->icon < this->icon_count)
{
this->icons[this->queue[this->screen_pointer]->icon]->set_frame(0);
}
Expand Down
11 changes: 9 additions & 2 deletions components/ehmtxv2/EHMTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ enum show_mode : uint8_t
MODE_ICON_PROGRESS = 19,
MODE_RAINBOW_BITMAP_SMALL = 20,
MODE_ICON_TEXT_SCREEN = 21,
MODE_RAINBOW_ICON_TEXT_SCREEN = 22
MODE_RAINBOW_ICON_TEXT_SCREEN = 22,
MODE_BITMAP_STACK_SCREEN = 23
};

namespace esphome
Expand Down Expand Up @@ -214,6 +215,8 @@ namespace esphome
void icon_text_screen(std::string icon, std::string text, int lifetime = D_LIFETIME, int screen_time = D_SCREEN_TIME, bool default_font = true, int r = C_RED, int g = C_GREEN, int b = C_BLUE);
void rainbow_icon_text_screen(std::string icon, std::string text, int lifetime = D_LIFETIME, int screen_time = D_SCREEN_TIME, bool default_font = true);

void bitmap_stack(std::string icons, int lifetime = D_LIFETIME, int screen_time = D_SCREEN_TIME);

void bitmap_screen(std::string text, int lifetime = D_LIFETIME, int screen_time = D_SCREEN_TIME);
void color_gauge(std::string text);
void bitmap_small(std::string icon, std::string text, int lifetime = D_LIFETIME, int screen_time = D_SCREEN_TIME, bool default_font = true, int r = C_RED, int g = C_GREEN, int b = C_BLUE);
Expand Down Expand Up @@ -293,8 +296,12 @@ namespace esphome
bool update_slot(uint8_t _icon);
void update_screen();
void hold_slot(uint8_t _sec);
void calc_scroll_time(std::string, uint16_t);
void calc_scroll_time(std::string text, uint16_t screen_time);
void calc_scroll_time(uint8_t icon_count, uint16_t screen_time);
int xpos();
int xpos(uint8_t item);
int ypos();
int ypos(uint8_t item);
};

class EHMTXNextScreenTrigger : public Trigger<std::string, std::string>
Expand Down
Loading

0 comments on commit c3350db

Please sign in to comment.