diff --git a/components/qrcode/CMakeLists.txt b/components/qrcode/CMakeLists.txt index 8c50a1a..04b13f2 100644 --- a/components/qrcode/CMakeLists.txt +++ b/components/qrcode/CMakeLists.txt @@ -1,4 +1,4 @@ -idf_component_register(SRCS ./src/qrcodegen.c ./src/qrcode.c +idf_component_register(SRCS ./src/qrcodegen.c ./src/esp_qrcode_main.c ./src/esp_qrcode_wrapper.c INCLUDE_DIRS include REQUIRES PRIV_REQUIRES ) diff --git a/components/qrcode/README.md b/components/qrcode/README.md new file mode 100644 index 0000000..e0e7df2 --- /dev/null +++ b/components/qrcode/README.md @@ -0,0 +1,5 @@ +# QR Code generator component + +This directory contains a QR code generator component written in C. This component is based on [QR-Code-generator](https://github.com/nayuki/QR-Code-generator). + +To learn more about how to use this component, please check API Documentation from header file [qrcode.h](./include/qrcode.h). diff --git a/components/qrcode/include/qrcode.h b/components/qrcode/include/qrcode.h index 94076ac..27de85f 100644 --- a/components/qrcode/include/qrcode.h +++ b/components/qrcode/include/qrcode.h @@ -26,6 +26,8 @@ extern "C" { * @attention 1. Can successfully encode a UTF-8 string of up to 2953 bytes or an alphanumeric * string of up to 4296 characters or any digit string of up to 7089 characters * + * @note This API is kept for backward compatibility + * * @param text string to encode into a QR Code. * * @return @@ -35,6 +37,86 @@ extern "C" { */ esp_err_t qrcode_display(const char *text); +/** + * @brief QR Code handle used by the display function + */ +typedef const uint8_t * esp_qrcode_handle_t; + +/** + * @brief QR Code configuration options + */ +typedef struct { + void (*display_func)(esp_qrcode_handle_t qrcode); /**< Function called for displaying the QR Code after encoding is complete */ + int max_qrcode_version; /**< Max QR Code Version to be used. Range: 2 - 40 */ + int qrcode_ecc_level; /**< Error Correction Level for QR Code */ +} esp_qrcode_config_t; + +/** + * @brief Error Correction Level in a QR Code Symbol + */ +enum { + ESP_QRCODE_ECC_LOW, /**< QR Code Error Tolerance of 7% */ + ESP_QRCODE_ECC_MED, /**< QR Code Error Tolerance of 15% */ + ESP_QRCODE_ECC_QUART, /**< QR Code Error Tolerance of 25% */ + ESP_QRCODE_ECC_HIGH /**< QR Code Error Tolerance of 30% */ +}; + +/** + * @brief Encodes the given string into a QR Code and calls the display function + * + * @attention 1. Can successfully encode a UTF-8 string of up to 2953 bytes or an alphanumeric + * string of up to 4296 characters or any digit string of up to 7089 characters + * + * @param cfg Configuration used for QR Code encoding. + * @param text String to encode into a QR Code. + * + * @return + * - ESP_OK: succeed + * - ESP_FAIL: Failed to encode string into a QR Code + * - ESP_ERR_NO_MEM: Failed to allocate buffer for given max_qrcode_version + */ +esp_err_t esp_qrcode_generate(esp_qrcode_config_t *cfg, const char *text); + +/** + * @brief Displays QR Code on the console + * + * @param qrcode QR Code handle used by the display function. + */ +void esp_qrcode_print_console(esp_qrcode_handle_t qrcode); + +/** + * @brief Returns the side length of the given QR Code + * + * @param qrcode QR Code handle used by the display function. + * + * @return + * - val[21, 177]: Side length of QR Code + */ +int esp_qrcode_get_size(esp_qrcode_handle_t qrcode); + +/** + * @brief Returns the Pixel value for the given coordinates + * False indicates White and True indicates Black + * + * @attention 1. Coordinates for top left corner are (x=0, y=0) + * @attention 2. For out of bound coordinates false (White) is returned + * + * @param qrcode QR Code handle used by the display function. + * @param x X-Coordinate of QR Code module + * @param y Y-Coordinate of QR Code module + * + * @return + * - true: (x, y) Pixel is Black + * - false: (x, y) Pixel is White + */ +bool esp_qrcode_get_module(esp_qrcode_handle_t qrcode, int x, int y); + +#define ESP_QRCODE_CONFIG_DEFAULT() (esp_qrcode_config_t) { \ + .display_func = esp_qrcode_print_console, \ + .max_qrcode_version = 10, \ + .qrcode_ecc_level = ESP_QRCODE_ECC_LOW, \ +} + #ifdef __cplusplus } #endif diff --git a/components/qrcode/src/qrcode.c b/components/qrcode/src/esp_qrcode_main.c similarity index 54% rename from components/qrcode/src/qrcode.c rename to components/qrcode/src/esp_qrcode_main.c index ab5bda5..20e8db4 100644 --- a/components/qrcode/src/qrcode.c +++ b/components/qrcode/src/esp_qrcode_main.c @@ -1,4 +1,4 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,10 +14,12 @@ #include #include +#include "esp_log.h" #include "qrcodegen.h" +#include "qrcode.h" -#define MAX_QRCODE_VERSION 5 +static const char *TAG = "qrcode"; static const char *lt[] = { /* 0 */ " ", @@ -38,13 +40,8 @@ static const char *lt[] = { /* 15 */ "\u2588\u2588", }; -void print_qr_char(unsigned char n) +void esp_qrcode_print_console(esp_qrcode_handle_t qrcode) { - printf("%s", lt[n]); -} - -extern void print_qr_char(unsigned char); -static void printQr(const uint8_t qrcode[]) { int size = qrcodegen_getSize(qrcode); int border = 2; unsigned char num = 0; @@ -64,38 +61,69 @@ static void printQr(const uint8_t qrcode[]) { if ((x < size + border) && (y < size + border) && qrcodegen_getModule(qrcode, x+1, y+1)) { num |= 1 << 3; } - print_qr_char(num); + printf("%s", lt[num]); } printf("\n"); } printf("\n"); } -esp_err_t qrcode_display(const char *text) +esp_err_t esp_qrcode_generate(esp_qrcode_config_t *cfg, const char *text) { - enum qrcodegen_Ecc errCorLvl = qrcodegen_Ecc_LOW; - uint8_t *qrcode, *tempBuffer; + enum qrcodegen_Ecc ecc_lvl; + uint8_t *qrcode, *tempbuf; esp_err_t err = ESP_FAIL; - qrcode = calloc(1, qrcodegen_BUFFER_LEN_FOR_VERSION(MAX_QRCODE_VERSION)); - if (!qrcode) + qrcode = calloc(1, qrcodegen_BUFFER_LEN_FOR_VERSION(cfg->max_qrcode_version)); + if (!qrcode) { return ESP_ERR_NO_MEM; + } - tempBuffer = calloc(1, qrcodegen_BUFFER_LEN_FOR_VERSION(MAX_QRCODE_VERSION)); - if (!tempBuffer) { + tempbuf = calloc(1, qrcodegen_BUFFER_LEN_FOR_VERSION(cfg->max_qrcode_version)); + if (!tempbuf) { free(qrcode); return ESP_ERR_NO_MEM; } - // Make and print the QR Code symbol - bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode, errCorLvl, - qrcodegen_VERSION_MIN, MAX_QRCODE_VERSION, qrcodegen_Mask_AUTO, true); - if (ok) { - printQr(qrcode); + switch(cfg->qrcode_ecc_level) { + case ESP_QRCODE_ECC_LOW: + ecc_lvl = qrcodegen_Ecc_LOW; + break; + case ESP_QRCODE_ECC_MED: + ecc_lvl = qrcodegen_Ecc_MEDIUM; + break; + case ESP_QRCODE_ECC_QUART: + ecc_lvl = qrcodegen_Ecc_QUARTILE; + break; + case ESP_QRCODE_ECC_HIGH: + ecc_lvl = qrcodegen_Ecc_HIGH; + break; + default: + ecc_lvl = qrcodegen_Ecc_LOW; + break; + } + + ESP_LOGD(TAG, "Encoding below text with ECC LVL %d & QR Code Version %d", + ecc_lvl, cfg->max_qrcode_version); + ESP_LOGD(TAG, "%s", text); + // Make and print the QR Code symbol + bool ok = qrcodegen_encodeText(text, tempbuf, qrcode, ecc_lvl, + qrcodegen_VERSION_MIN, cfg->max_qrcode_version, + qrcodegen_Mask_AUTO, true); + if (ok && cfg->display_func) { + cfg->display_func((esp_qrcode_handle_t)qrcode); err = ESP_OK; } free(qrcode); - free(tempBuffer); + free(tempbuf); return err; } + +esp_err_t qrcode_display(const char *text) +{ +#define MAX_QRCODE_VERSION 5 + esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT(); + cfg.max_qrcode_version = MAX_QRCODE_VERSION; + return esp_qrcode_generate(&cfg, text); +} diff --git a/components/qrcode/src/esp_qrcode_wrapper.c b/components/qrcode/src/esp_qrcode_wrapper.c new file mode 100644 index 0000000..cde5165 --- /dev/null +++ b/components/qrcode/src/esp_qrcode_wrapper.c @@ -0,0 +1,29 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "qrcodegen.h" +#include "qrcode.h" + +int esp_qrcode_get_size(esp_qrcode_handle_t qrcode) +{ + return qrcodegen_getSize(qrcode); +} + +bool esp_qrcode_get_module(esp_qrcode_handle_t qrcode, int x, int y) +{ + return qrcodegen_getModule(qrcode, x, y); +}