#include "star_code.h" #include #include #include #include #include #include "drivers/bottom_half.h" static const char* TAG = "star_code"; volatile bool handling_new_starcodes = false; static bool system_initialized = false; static volatile SemaphoreHandle_t star_codes_sem; static std::vector star_codes; static TaskHandle_t task_handle; static void star_code_task(void* param) { KeypadKey key; int current_idx = 0; char current[STRING_MAX_LEN+1] = {0}; while (1) { while (get_keypad_pressed(&key)) { if (key == KeypadKey::star) { current[0] = '*'; for (int i = 1; i < STRING_MAX_LEN; i++) { current[i] = 0; } current_idx = 1; } else if (key == KeypadKey::pound) { // submit if (current[0] == '\0') { continue; } bool hit = false; for (int i = 0; i < star_codes_len; i++) { StarCodeHandler sch = star_codes[i]; if (strcmp(current, sch.code) == 0) { hit = true; lcd_print(1, 2, sch.display_text); vTaskDelay(pdMS_TO_TICKS(2000)); if (sch.callback != nullptr) { (sch.callback)(); } if (sch.should_exit) { return; } break; } } if (!hit) { lcd_print(1, 2, "Invalid Star Code"); vTaskDelay(pdMS_TO_TICKS(2000)); } // clear for (int i = 0; i < STRING_MAX_LEN; i++) { current[i] = 0; } current_idx = 0; } else { // out of room. skip if (current_idx >= STRING_MAX_LEN) break; // no code started. if (current[0] != '*') continue; char c = char_of_keypad_key(key); current[current_idx++] = c; } // ESP_LOGI(STEP0_TAG, "Pressed: %c", c); lcd_clear(); lcd_print(1, 1, current); } vTaskDelay(pdMS_TO_TICKS(10)); } } void init_star_code_system() { star_codes_sem = xSemaphoreCreateBinary(); xSemaphoreGive(star_codes_sem); xTaskCreate(star_code_task, "star_code", 2048, nullptr, 1, &task_handle); handling_new_starcodes = true; system_initialized = true; } /// Checks if a triggered code matches an expected code. /// @return true iff the codes match, where '*'s in the expected code can match any character in the triggered code static bool check_code_match(const char* triggered, const char* expected) { size_t triggered_len = strlen(triggered); size_t match_len = strlen(triggered); if (triggered_len != match_len) return false; for (int i = 0; i < triggered_len; i++) { if (!(expected[i] == '*' || expected[i] == triggered[i])) { return false; } } return true; } bool add_star_code(StarCodeEntry code) { if (code.code == nullptr || strlen(code.code) > STARCODE_MAX_LEN) { return false; } if (code.display_text != nullptr && strlen(code.display_text) > STARCODE_MAX_LEN + 1) { return false; } // check for a existing entry auto it = std::find_if(star_codes.begin(), star_codes.end(), [&](const StarCodeEntry& other) { return check_code_match(code.code, other.code); }); if (it != star_codes.end()) { // existing star code found! ESP_LOGW(TAG, "Failed to add star code %s", code.code); return false; } star_codes.push_back(code); return true; } bool add_star_codes(const StarCodeEntry* codes, size_t len) { bool success = true; for (int i = 0; i < len; i++) { if (!add_star_code(codes[i])) { success = false; } } return success; } bool rm_star_code(const char* code){ auto it = std::find_if(star_codes.begin(), star_codes.end(), [&](const StarCodeEntry& star_code) { return strcmp(code, star_code.code) == 0; }); if (it == star_codes.end()) { ESP_LOGW(TAG, "Failed to remove star code %s", code); return false; } star_codes.erase(it); return true; } bool rm_star_codes(const StarCodeEntry* codes, size_t len) { bool success = true; for (int i = 0; i < len; i++) { if (!rm_star_code(codes[i].code)) { success = false; } } return success; } bool rm_star_codes_str(const char** codes, size_t len) { bool success = true; for (int i = 0; i < len; i++) { if (!rm_star_code(codes[i])) { success = false; } } return success; } void clear_star_codes() { star_codes.clear(); } bool trigger_star_code(const char* code) { auto it = std::find_if(star_codes.begin(), star_codes.end(), [&](const StarCodeEntry& other) { return check_code_match(code, other.code); }); if (it == star_codes.end()) { return false; } if (it->callback != nullptr) (it->callback)(); return true; } void pause_star_code_system() { handling_new_starcodes = false; } void resume_star_code_system() { handling_new_starcodes = system_initialized; }