Badge WHY2025: Meshtastic

Écrit par l'équipe HackGyver – Septembre 2025

1: Introduction

Dans ce tutoriel nous allons voir comment installer Meshtastic sur le badge de la WHY2025.
Après tout nous avons un module LoRa dessus, il serait dommage de ne pas essayer de l'exploiter un peu.


Attention tout de même, le firmware Meshtastic du badge est loin d'être au point et est appelé à
Potentiellement évoluer dans le futur.
Ce tutoriel a été réalisé en septembre 2025 et comporte de nombreux hacks qui ne sont peut-être plus
valables à l'heure où vous lisez ce tutoriel.
l'exercice a été jugé suffisamment intéressant pour en faire une procédure pas à pas.
De plus, le wiki de la WHY2025 reste relativement vague sur l'installation de Meshtastic.

Nous allons donc devoir reflasher ESP32-C6 qui gère la partie radio LoRa.
Ainsi que ESP32-C4 qui gère l'interface graphique.

meshtastic-firmware-why2025-carrier est celui qu'on doit utiliser pour C6.
Les autres ne marchent pas actuellement, ou bien n'intègrent pas le signal PWM qui doit être envoyé à
l'écran pour le rétroéclairage.

On se retrouve avec une dalle noir (bien que les logs montrent que le firmware arrive à instancier le réseau
Meshtastic et les paquets radio sont bien reçus et transmis)

Si vous vous faites du souci à propos de flasher C6, sachez que ce n'est pas un voyage sans retour.
Vous pouvez remettre le firmware de base (BadgeVMS) si Meshtastic ne vous convient pas.



2: Soudage sur le badge

Nous aurons une modification minime à faire: souder deux GPIO sur la radio LoRa vers l'ESP32-C6.
Utilisez de préférence du fil AWG 30, suffisamment fin et flexible pour ce type de travail.
À défaut, un fil provenant d'un câble téléphonique RJ45 peut convenir également.
Pour les longueurs, coupez un fil d'environ 4,5 cm et un autre de 4,8 cm.

Avant l'opération, retirez les piles du badge.

PCB2

Pour le soudage des fils, n'hésitez pas à souder légèrement sur le dessus de l'ESP sans toucher au capot bien
sûr, qui est relié à la masse.
Faites une vérification des courts-circuits, puis soudez le connecteur de l'antenne.

Pour le connecteur, au minimum, il faudra souder la broche centrale (signal) et une broche GND, vous pouvez
souder le reste pour offrir plus de rigidité.

PCB2

Les broches les plus délicates à souder seront les GND 3 et 2, très proches de l'écran.
Mettez un petit bout de Kapton pour éviter les projections de flux sur celui-ci.

⚠️ Ne démarrer pas le badge flashé Meshtastic sans son antenne, il y a des risques de
prendre un retour d'onde pas cool, et de manière générale en radio: toujours brancher l'antenne avant la mise en service.

PCB2

3: Compilation des firmwares Meshtastic

On commence en premier par compiler le firmware de l'ESP32-C6, pour par la suite pouvoir compiler C4.

⚠️ Pendant la compilation du projet pour le C4, le CMakeLists.txt de meshtastic-ui-why-m2\main\CMakeLists.txt
a tendance a vouloir télécharger en arrière-plan le firmware précompilé du C6 depuis GitHub (on a besoin des blobs C6 pour compilé C4).
Ce processus se fait automatiquement, sans que l'utilisateur en soit informé explicitement.

Personnellement, je trouve cette façon de faire discutable, même si c'est open-source.
Voilà pourquoi on commence par compiler le C6 avant de s'occuper du C4,
nous corrigerons le fichier CMakeLists.txt plus tard.

PCB2

Je n'ai pas réussi à compiler C6 avec Windows, on va faire ça dans une machine virtuelle Kali.
On commence par télécharger le code du firmware Carrier depuis GitHub et installer l'environnement.


cd ~/projects
[ ! -d meshtastic-firmware-why2025-carrier ] && git clone https://github.com/pkoryzna/meshtastic-firmware-why2025-carrier.git
cd meshtastic-firmware-why2025-carrier     
sudo apt update
sudo apt install -y pipx python3-venv

Mettre pipx dans le PATH et recharger le shell


pipx ensurepath
exec $SHELL -l

Installer PlatformIO


pipx install platformio

Compiler le firmware


pio run -e why2025-carrier -j 1

Une fois compilé, exécuter ceci pour produire les blobs C6 destinés au C4:


SRC=~/projects/meshtastic-firmware-why2025-carrier/.pio/build/why2025-carrier
OUT=~/projects/c6_blobs
mkdir -p "$OUT"

# Copié/renommé pour l'UI
cp "$SRC/bootloader.bin"        "$OUT/c6-bootloader.bin"
cp "$SRC/boot_app0.bin"         "$OUT/c6-boot_app0.bin"
if [ -f "$SRC/partition-table.bin" ]; then
  cp "$SRC/partition-table.bin" "$OUT/c6-partitions.bin"
else
  cp "$SRC/partitions.bin"      "$OUT/c6-partitions.bin"
fi
cp "$SRC/firmware.bin"          "$OUT/c6-firmware.bin"

# MD5 (hex minuscule, sans rien d'autre)
for f in c6-bootloader.bin c6-boot_app0.bin c6-partitions.bin c6-firmware.bin; do
  md5sum "$OUT/$f" | awk '{print tolower($1)}' > "$OUT/$f.md5"
done

On créé notre archive pour par la suite mettre notre archive dans l'hote Windows.


tar -czf ~/Downloads/c6_blobs_for_ui.tgz -C "$OUT"

Niquel, maintenant on gitclone pour l'ESP-C4.


git clone --recursive https://github.com/pkoryzna/meshtastic-ui-why-m2.git
cd meshtastic-ui-why-m2
git submodule update --init --recursive
git lfs pull
p -aL meshtastic-ui-why-m2 meshtastic-ui-why-m2-win
tar -czf ~/Downloads/meshtastic-ui-why-m2-win.tgz -C ~/projects meshtastic-ui-why-m2-win

On va déposer nos deux fichiers .tgz sous Windows.
Déposez meshtastic-ui-why-m2-win dans C:\Espressif\projects\meshtastic-ui-why-m2-win
(On suppose ici que vous avez déjà installé l'outil Espressif sous Windows.)

Dans meshtastic-ui-why-m2-win, on va dropé nos firmwares C6 dans le dossier meshtastic-ui-why-m2-win/main/
Mettez bien les huit fichiers.

Ensuite toujours dans le dossier main, on va éditer le CMakeLists.txt.
On commente le add_custom_target() et add_dependencies()
Et on modifie les huit lignes target_add_binary_data

Voici le bloc complet, avec le bloc original commenté par des dièses:


#  add_custom_target(firmware-why2025-carrier
#          COMMAND ${COMPONENT_DIR}/get_firmware.sh ${MESHTASTIC_VER}
#          BYPRODUCTS
#          ${CMAKE_CURRENT_BINARY_DIR}/c6-boot_app0.bin
#          ${CMAKE_CURRENT_BINARY_DIR}/c6-boot_app0.bin.md5
#          ${CMAKE_CURRENT_BINARY_DIR}/c6-bootloader.bin
#          ${CMAKE_CURRENT_BINARY_DIR}/c6-bootloader.bin.md5
#          ${CMAKE_CURRENT_BINARY_DIR}/c6-partitions.bin
#          ${CMAKE_CURRENT_BINARY_DIR}/c6-partitions.bin.md5
#          ${CMAKE_CURRENT_BINARY_DIR}/c6-firmware.bin
#          ${CMAKE_CURRENT_BINARY_DIR}/c6-firmware.bin.md5
#  )
#  
#  add_dependencies(${COMPONENT_LIB} firmware-why2025-carrier)
#
#target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/c6-boot_app0.bin BINARY)
#target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/c6-boot_app0.bin.md5 TEXT)
#target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/c6-bootloader.bin BINARY)
#target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/c6-bootloader.bin.md5 TEXT)
#target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/c6-partitions.bin BINARY)
#target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/c6-partitions.bin.md5 TEXT)
#target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/c6-firmware.bin BINARY)
#target_add_binary_data(${COMPONENT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/c6-firmware.bin.md5 TEXT)

target_add_binary_data(${COMPONENT_LIB} ${COMPONENT_DIR}/c6-boot_app0.bin BINARY)
target_add_binary_data(${COMPONENT_LIB} ${COMPONENT_DIR}/c6-boot_app0.bin.md5 TEXT)
target_add_binary_data(${COMPONENT_LIB} ${COMPONENT_DIR}/c6-bootloader.bin BINARY)
target_add_binary_data(${COMPONENT_LIB} ${COMPONENT_DIR}/c6-bootloader.bin.md5 TEXT)
target_add_binary_data(${COMPONENT_LIB} ${COMPONENT_DIR}/c6-partitions.bin BINARY)
target_add_binary_data(${COMPONENT_LIB} ${COMPONENT_DIR}/c6-partitions.bin.md5 TEXT)
target_add_binary_data(${COMPONENT_LIB} ${COMPONENT_DIR}/c6-firmware.bin BINARY)
target_add_binary_data(${COMPONENT_LIB} ${COMPONENT_DIR}/c6-firmware.bin.md5 TEXT)

Ensuite, il y a encore un peu de bricolage à faire :
ouvrez le components/SdFat/CMakeLists.txt
et ajoutez : file(GLOB_RECURSE FSLIB_SOURCES "*/*.c" "*/*.cpp")

Sinon, il y a des risques de mauvaise intégration de la carte SD...

Une fois cela fait, lancez la compilation avec :

idf.py build -DCMAKE_CXX_FLAGS="-DHAS_SDCARD -DHAS_SD_MMC -DSD_MISO_PIN=13 -DSD_SCLK_PIN=12 -DSD_MOSI_PIN=11"

Les trois points importants : l'init --recursive, l'usage d'IDF pour compiler avec les bons GPIO afin que la carte SD soit
active, et les patchs des CMakeLists.txt.


On a enfin nos deux firmwares !



4: Flashage du badge

meshtastic-ui-why-m2 se flashe via le port lateral (ESP-C4)

On va s’occuper du M2 en premier. Rendez-vous dans votre dossier :
C:\Espressif\projects\meshtastic-ui-why-m2-win
puis exécutez simplement : idf.py flash

Normalement, vous n'avez plus rien à faire après cette étape, puisque le firmware du C4 embarque déjà les blobs du C6.
Celui-ci devrait comparer les empreintes MD5 sur le C6 et le reflasher automatiquement en UART si nécessaire.
Patientez 3 à 4 minutes le temps que l'écriture se termine sur C6: votre badge devrait ensuite redémarrer tout seul.

Néanmoins, si rien ne se passe, ou si pour une raison quelconque vous souhaitez flasher le C6 en premier, voici la suite...

meshtastic-firmware-why2025-carrier se flash sur le port en bas du badge (ESP-C6).

Pour C6, vu qu'on la importé depuis Kali, on va passer par esptool.py d'Espressif.
esptool.py --chip esp32c6 -p COM6 -b 460800 --before default_reset --after hard_reset write_flash 0x0000 "C:\Espressif\projects\meshtastic-ui-why-m2-win\main\c6-bootloader.bin" 0x8000 "C:\Espressif\projects\meshtastic-ui-why-m2-win\main\c6-partitions.bin" 0x10000 "C:\Espressif\projects\meshtastic-ui-why-m2-win\main\c6-firmware.bin"

N'oubliez pas d'adapter le port COM dans la commande.
Contrairement au script meshtastic-ui-why-m2-win/main/c6_fw_flasher.cpp,
on ne flashe pas c6-boot_app0.bin à 0xE000. Cette adresse est utilisée pour otadata (OTA)
le boot_app0 est déjà inclus dans le bootloader sur C6.

Essayez de démarrer le badge : si cela ne marche pas et que vous restez bloqué sur l'écran vert d'accueil
Meshtastic, essayez de diagnostiquer ce qu'il se passe avec le port USB du bas via idf.py monitor.

Au besoin, reflashez C4 et C6.

ℹ️ Comme le firmware M2 reflashe automatiquement le C6 si le MD5 ne correspond pas,
si vous souhaitez simplement effacer le C6 avec une commande comme esptool.py --chip esp32c6 -p COM6 erase_flash,
cela ne servira à rien, car le C4 le reprogrammera au prochain redémarrage.
En d'autres termes, vous devez d'abord réécrire le C4 avant toute chose.



5: Installation des tiles OSM

Puisqu'on a corrigé la carte SD, on va s'en servir pour afficher les tuiles OSM sur la carte
interactive des noeuds LoRa que l'on va capter.
Formatez une carte SD en FAT32, comme pour BadgeVMS.

Puis:


python3 -m pip install pillow requests
git clone https://github.com/JustDr00py/tdeck-maps.git
cd tdeck-maps

On télécharge les tiles de notre ville:


py meshtastic_tiles.py --city "Belfort, France" --min-zoom 1 --max-zoom 15

Cela va prendre un peu de temps.

À la racine de la carte SD, créez deux dossiers : \maps\osm\, puis copiez le contenu du dossier
généré (les sous-dossiers 0, 1, etc.) vers X:\maps\osm\.
La carte SD est prête.

À prendre en compte : le badge WHY n'a pas de module GPS ; la carte se centrera donc sur
l'un des noeuds que vous capterez.
Ce serait une bonne idée de coder en dur vos coordonnées GPS dans le firmware.
Le hackerspace se collera peut-être à la tâche pour proposer un correctif.
La carte interactive ne fonctionne pas très bien pour le moment : les boutons gauche/droite et
zoom/dézoom ne marchent pas encore.
La doc mentionne des appuis longs, mais nous ne les avons pas, en tout cas, aucune touche n'est
mappée pour ça... pour le moment.



6. Hacking du firmware


Le hackerspace vous propose ce patch à appliquer sur meshtastic-ui-why-m2-win/main/src/main.cpp

Pour envoyer une phrase aléatoire toutes les 20 secondes.
Attention: vos batteries se videront plus vite :o


#ifndef PIO_UNIT_TESTING

#include "Arduino.h"
#include "esp_loader.h"
#include "Log.h"
#include "comms/EthClient.h"
#include "comms/UARTClient.h"
#include "graphics/DeviceScreen.h"

#include "esp_timer.h"
#include "meshtastic/mesh.pb.h"
#include "pb_encode.h"
#include "util/ILog.h"

#ifndef meshtastic_PortNum_TEXT_MESSAGE_APP
#define meshtastic_PortNum_TEXT_MESSAGE_APP 6
#endif

// Assuming a global client pointer exists:
extern IClientBase* client;

#if defined(ARCH_PORTDUINO)
#include <thread>
#define FSBegin() true
#else
#include "LittleFS.h"
#define FSCom LittleFS
#define FSBegin() LittleFS.begin(true)
#endif

#if defined(I2C_SDA) || defined(I2C_SDA1)
#include "Wire.h"
#endif

// this is pulled in by the device-ui library
const char *firmware_version = "2.6.8";
esp_loader_error_t flash_c6_if_needed();

#ifdef USE_DUMMY_SERIAL
class DummyClient : public IClientBase
{
  public:
    DummyClient() = default;
    void init(void) override {}
    bool connect(void) override { return true; }
    bool disconnect(void) override { return true; }
    bool isConnected(void) override { return false; }
    bool send(meshtastic_ToRadio &&to) override { return false; }
    meshtastic_FromRadio receive(void) override
    {
        meshtastic_FromRadio dummy{};
        return dummy;
    }
    ~DummyClient(){};
} serial;
#else
IClientBase *client = nullptr;
#endif

DeviceScreen *screen = nullptr;

// Define your message list (you can customize this)
const char* message_list[] = {
    "Cyberpaix, maintenant.",
    "HackGyver libere ta curiosite",
    "Apprends. Bricole. Transmets",
    "HackGyver fabrique ta liberte.",
    "La vie privee est un droit humain fondamental",
    "Des livres, pas des bombes",
    "hackgyver.fr - Le hackerspace de Belfort",
    "Si tu peux l'ouvrir, tu peux le comprendre.",
    "Touche a tout, casse un peu, apprends beaucoup.",
    "Rien n'est magique, tout est logique.",
    "Le savoir se partage, HackGyver le prouve.",
    "Belfort + LoRa + hackers = HackGyver <3",
    "Makers de Belfort, unissez-vous.",
    "Fabrique ton monde, pas ta cage",
    "On ne pirate pas, on explore.",
    "L'erreur est juste le debut de la decouverte.",
    "HackGyver c'est pas un bug, c'est une feature de Belfort.",
    "Open hardware, open minds.",
    "HackGyver est la, et toi, t'es ou ?",
    "Ayez le courage de vous servir de votre propre entendement."
};

const int message_count = sizeof(message_list) / sizeof(message_list[0]);

void broadcast_random_message() {
    if (!client) return;
    
    // Select a random message from the list
    int random_index = rand() % message_count;
    const char* random_msg = message_list[random_index];
    
    meshtastic_ToRadio out_msg = meshtastic_ToRadio_init_default;
    out_msg.which_payload_variant = meshtastic_ToRadio_packet_tag;
    
    out_msg.packet.to = 0xFFFFFFFF;
    out_msg.packet.channel = 0;
    out_msg.packet.which_payload_variant = meshtastic_MeshPacket_decoded_tag;
    out_msg.packet.decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
    out_msg.packet.decoded.want_response = false;
    out_msg.packet.want_ack = false;
    out_msg.packet.id = rand() & 0xFFFF;
    
    size_t msg_len = strnlen(random_msg, sizeof(out_msg.packet.decoded.payload.bytes));
    memcpy(out_msg.packet.decoded.payload.bytes, random_msg, msg_len);
    out_msg.packet.decoded.payload.size = (unsigned short)msg_len;
    
    client->send(std::move(out_msg));
    ILOG_INFO("Broadcast random message [%d/%d]: %s", random_index + 1, message_count, random_msg);
}

void broadcast_message(const char* msg) {
    if (!client) return;
    
    meshtastic_ToRadio out_msg = meshtastic_ToRadio_init_default;
    out_msg.which_payload_variant = meshtastic_ToRadio_packet_tag;
    
    out_msg.packet.to = 0xFFFFFFFF;
    out_msg.packet.channel = 0;
    out_msg.packet.which_payload_variant = meshtastic_MeshPacket_decoded_tag;
    out_msg.packet.decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
    out_msg.packet.decoded.want_response = false;
    out_msg.packet.want_ack = false;
    out_msg.packet.id = rand() & 0xFFFF;
    
    size_t msg_len = strnlen(msg, sizeof(out_msg.packet.decoded.payload.bytes));
    memcpy(out_msg.packet.decoded.payload.bytes, msg, msg_len);
    out_msg.packet.decoded.payload.size = (unsigned short)msg_len;
    
    // Just send it and assume it works (since gqrx confirms it does)
    client->send(std::move(out_msg));
    ILOG_INFO("Broadcast transmitted: %s", msg);
}

void periodic_broadcast(void* arg) {
    //broadcast_message("Do you receive my messages? what is 40+2?");
    broadcast_random_message();
}

void setup()
{
#if defined(__APPLE__)
    pthread_setname_np("setup");
#elif defined(__linux__)
    pthread_setname_np(pthread_self(), "setup");
#endif
#ifdef KB_POWERON
    digitalWrite(KB_POWERON, HIGH);
    pinMode(KB_POWERON, OUTPUT);
    delay(200); // wait until keyboard mcu startup finished
#endif

#ifdef PWR_ON_PIN
    pinMode(PWR_ON_PIN, OUTPUT);
    digitalWrite(PWR_ON_PIN, HIGH);
#endif

#ifdef PWR_EN_PIN
    pinMode(PWR_EN_PIN, OUTPUT);
    digitalWrite(PWR_EN_PIN, HIGH);
#endif

#ifndef WHY_BADGE_CUSTOM_C6_FW
    esp_loader_error_t esp_loader_error = flash_c6_if_needed();
    if (esp_loader_error != ESP_LOADER_SUCCESS)
    {
        ILOG_CRIT("failed to flash c6 with error %d", esp_loader_error);
        return;
    }
#elif defined(WHY_BADGE)
    ILOG_INFO("Firmware compiled with WHY_BADGE_CUSTOM_C6_FW, skipping C6 flashing.");
#endif

#ifndef USE_SERIAL0
#ifdef WAIT_FOR_SERIAL0
    delay(2000);
#endif
    Serial.begin(115200);
#ifdef WAIT_FOR_SERIAL0
    time_t timeout = millis();
    while (!Serial && (millis() - timeout) < 2000)
        ;
#endif
    logger.setDebugLevel(ESP_LOG_DEBUG); // use ESP_LOG_VERBOSE for trace category
#else
    logger.setDebugLevel(ESP_LOG_NONE); // do not log when connected over serial0
#endif

#ifdef I2C_SDA
    if (!Wire.begin(I2C_SDA, I2C_SCL, 400000))
        ILOG_ERROR("*** Failed to access I2C0(%d, %d)", I2C_SDA, I2C_SCL);
#endif
#ifdef I2C_SDA1
    if (!Wire.begin(I2C_SDA1, I2C_SCL1, 400000))
        ILOG_ERROR("*** Failed to access I2C1(%d, %d)", I2C_SDA1, I2C_SCL1);
#endif

    ILOG_INFO("\n//\\ E S H T /\\ S T / C   U I\n");
#ifdef ARDUINO_ARCH_ESP32
    uint64_t chipid;
    chipid = ESP.getEfuseMac(); // The chip ID is essentially its MAC address(length: 6 bytes).
    ILOG_DEBUG("  ESP32 Chip ID = %04X %08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
    ILOG_DEBUG("  Flash size: %8d bytes", ESP.getFlashChipSize());
    ILOG_DEBUG("  Heap size : %8d bytes", ESP.getHeapSize());
    ILOG_DEBUG("  Free heap : %8d bytes", ESP.getFreeHeap());
    ILOG_DEBUG("  PSRAM     : %8d bytes", ESP.getFreePsram());
    ILOG_DEBUG("  PSRAM max : %8d bytes", heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM));
    ILOG_DEBUG("*****************************************");
#endif

    if (!FSBegin()) {
        ILOG_ERROR("LittleFS mount failed!");
    }

#ifdef ARCH_PORTDUINO
    const char *hostname = getenv("MUI_SERVER");
    if (hostname == nullptr) {
        client = new EthClient();
    } else {
        client = new EthClient(hostname);
    }
    int16_t x = 480;
    int16_t y = 480;
    const char *size = getenv("MUI_SIZE");
    if (size != nullptr) {
        sscanf(size, "%" PRId16 "x%" PRId16, &x, &y);
    }
    if (x < 320 || x > 800)
        x = 480;
    if (y < 240 || y > 800)
        y = 480;
    screen = &DeviceScreen::create(DisplayDriverConfig(DisplayDriverConfig::device_t::X11, x, y));
#elif defined(WHY_BADGE)
    client = new UARTClient();
    screen = &DeviceScreen::create(DisplayDriverConfig(DisplayDriverConfig::device_t::WHY2025_M2, 720, 720));
#else
    client = new UARTClient();
    screen = &DeviceScreen::create();
#endif

    screen->init(client);

#ifdef ARDUINO_ARCH_ESP32
    ILOG_DEBUG("Free heap : %8d bytes", ESP.getFreeHeap());
    ILOG_DEBUG("PSRAM     : %8d bytes", ESP.getFreePsram());
#endif

#ifdef ARCH_PORTDUINO
    // create separate thread to handle lvgl X11 GUI simulation
    // otherwise the GUI will slow down the main thread
    extern void tft_task_handler(void *param = nullptr);
    new std::thread([] {
#ifdef __APPLE__
        pthread_setname_np("tft");
#else
        pthread_setname_np(pthread_self(), "tft");
#endif
        tft_task_handler();
    });
#endif

 // Initialize random seed
    srand(esp_timer_get_time());

    // Add connection check
    if (client) {
        ILOG_DEBUG("Client initialized, attempting to connect...");
        if (client->connect()) {
            ILOG_INFO("Client connected successfully");
        } else {
            ILOG_ERROR("Client failed to connect");
        }
    } else {
        ILOG_ERROR("Client is null after initialization");
    }

// Create an esp_timer for broadcasting every 3 minutes (180000ms)
    const esp_timer_create_args_t broadcast_timer_args = {
        .callback = &periodic_broadcast,
        .name = "broadcast_timer"
    };
    esp_timer_handle_t broadcast_timer;
    esp_timer_create(&broadcast_timer_args, &broadcast_timer);
    esp_timer_start_periodic(broadcast_timer, 20000 /*180000*/ * 1000ULL); // period in microseconds


    ILOG_DEBUG("Setup done.");
#if defined(__APPLE__)
    pthread_setname_np("loop");
#elif defined(__linux__)
    pthread_setname_np(pthread_self(), "loop");
#endif
}

#if defined(ARCH_ESP32)
void loop()
{
    screen->task_handler();
    screen->sleep(5);
}

#elif defined(ARCH_PORTDUINO)
void loop()
{
    delay(1000);
    fflush(nullptr);
}

void tft_task_handler(void *)
{
    ILOG_INFO("tft_task_handler started");
    while (true) {
        screen->task_handler();
        screen->sleep(5);
    }
}
#else
#error "Unsupported architecture"
#endif

#endif

Si vous ne souhaitez pas activer le flashage automatique du C6 en UART,
vous pouvez simplement supprimer ces lignes :


Ligne 4: #include "esp_loader.h"
Ligne 37: esp_loader_error_t flash_c6_if_needed();

Lignes 165 à 174:
#ifndef WHY_BADGE_CUSTOM_C6_FW
    esp_loader_error_t esp_loader_error = flash_c6_if_needed();
    if (esp_loader_error != ESP_LOADER_SUCCESS)
    {
        ILOG_CRIT("failed to flash c6 with error %d", esp_loader_error);
        return;
    }
#elif defined(WHY_BADGE)
    ILOG_INFO("Firmware compiled with WHY_BADGE_CUSTOM_C6_FW, skipping C6 flashing.");
#endif


7. Prise en main du firmware Meshtastic sur le badge


Par défaut votre clé est configurable dans les options, puis en sélectionnant Channel: LongFast
Une fenêtre s'ouvre, appuyer sur entrer sur le channel primaire, vous pourrez le modifier ainsi que ça
clé pré-partagée (par défaut: AQ== qui est la clé universelle pour discuter avec tout le monde)
Voilà.. Bienvenue sur Meshtastic, vous devriez capter vos premiers noeuds d'ici peut.
Et recevoir vos premiers messages.

PCB2

Pour le reste, nous vous laissons prendre en main la bête, la doc officielle se trouvant ici.

PCB2