{"id":26667474,"url":"https://github.com/berg0162/simcline-v2","last_synced_at":"2026-01-03T11:28:15.257Z","repository":{"id":282714988,"uuid":"914267421","full_name":"Berg0162/Simcline-V2","owner":"Berg0162","description":"Arduino Library for Simulation of Changing Road Inclination for Indoor Cycling","archived":false,"fork":false,"pushed_at":"2025-03-16T13:46:39.000Z","size":9504,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-16T14:26:07.509Z","etag":null,"topics":["arduino-library","ble","climb","cycling","elite","esp32","ftms","inclination","indoor","lift","road","simcline","simulation","tacx","trainer","wahoo","zwift"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Berg0162.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-09T09:13:18.000Z","updated_at":"2025-03-16T13:33:34.000Z","dependencies_parsed_at":"2025-03-16T14:36:22.038Z","dependency_job_id":null,"html_url":"https://github.com/Berg0162/Simcline-V2","commit_stats":null,"previous_names":["berg0162/simcline-v2"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Berg0162%2FSimcline-V2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Berg0162%2FSimcline-V2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Berg0162%2FSimcline-V2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Berg0162%2FSimcline-V2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Berg0162","download_url":"https://codeload.github.com/Berg0162/Simcline-V2/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245533297,"owners_count":20631107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino-library","ble","climb","cycling","elite","esp32","ftms","inclination","indoor","lift","road","simcline","simulation","tacx","trainer","wahoo","zwift"],"created_at":"2025-03-25T19:38:18.812Z","updated_at":"2026-01-03T11:28:15.251Z","avatar_url":"https://github.com/Berg0162.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg src=\"./images/SC_logo.png\" width=\"64\" height=\"64\" alt=\"SIMCLINE Icon\"\u003e \u0026nbsp; SIMCLINE-V2 for Smart Trainers\n\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Berg0162/Simcline-V2?sort=semver)](https://github.com/Berg0162/Simcline-V2/releases)\n[![Platform: ESP32](https://img.shields.io/badge/platform-ESP32-orange)](https://www.espressif.com/en/products/socs/esp32)\n[![GitHub issues](https://img.shields.io/github/issues/Berg0162/Simcline-V2)](https://github.com/Berg0162/Simcline-V2/issues)\n[![GitHub Discussions](https://img.shields.io/github/discussions/Berg0162/Simcline-V2)](https://github.com/Berg0162/Simcline-V2/discussions)\n\n# Simulation of Changing Road Inclination for Indoor Cycling\u003cbr\u003e\n\u003cimg src=\"./images/Simcline_2_0.jpg\" width=\"300\" height=\"300\" ALIGN=\"left\" alt=\"Mechanical SIMCLINE 2\"\u003e\nThe SIMCLINE physically adjusts the bike position to mimic hilly roads, climbing and descending. This allows the rider to naturally change position on the bike, engage climbing muscles, and improve pedaling technique to become a more efficient and powerful climber.\u003cbr\u003e\nWithout user intervention the SIMCLINE will replicate inclines and declines depicted in (online \u0026 offline) training programs (like \u003cb\u003eZwift, Rouvy, VeloReality, myWhoosh\u003c/b\u003e and many others) that adjust accordingly the resistance of the indoor trainer.\u003cbr\u003e\nThe SIMCLINE auto connects at power up with a Smart trainer and let's relive the ascents and descents from favorite rides or routes while training indoors. The physical reach is: 20% maximum incline and -10% maximum decline. However, the reach that the rider is comfortable with can be adjusted! The SIMCLINE pairs directly to the Smart trainer and with your PC/Laptop/Tablet with (Zwift) training App for a connection that notifies the SIMCLINE to simulate autonomous the (change in) physical grade of the road during an indoor ride. During operation an OLED display shows the road grade in digits and in graphics. \u003cbr clear=\"left\"\u003e \u003cbr\u003e\nNotice that the description on how to build SIMCLINE consists of two parts:\n\n+ \u003cb\u003eMechanical SIMCLINE 2.0\u003c/b\u003e\u003cbr\u003e \n\u003cimg src=\"https://www.instructables.com/assets/img/instructables-logo-v2.png\" width=\"32\" height=\"48\" align=\"left\" alt=\"Instructables\"\u003e \u0026nbsp; [SIMCLINE 2.0 Instructables](https://www.instructables.com/SIMCLINE-20-Easy-Simulation-of-Road-Incline/) \n\u003cbr clear=\"left\"\u003e\n\n+ \u003cb\u003ePresent Simcline-V2 Library\u003c/b\u003e\u003cbr\u003e\nThe Simcline-V2 library comes with an Android companion app for configuring and controlling its features. See: [Companion App](android/readme.md) \u003cbr\u003e\n\n# Simcline-V2 Library is optimised for ESP32 and NimBLE-Arduino 2.x!\u003cbr\u003e\nThe \u003cb\u003eESP32\u003c/b\u003e family has a series of low-cost and low-power System on a Chip (SoC) microcontrollers developed by Espressif that include Wi-Fi and Bluetooth wireless capabilities and dual-core processor. See for an introduction: [Random Nerds Tutorials](https://randomnerdtutorials.com/getting-started-with-esp32/). Particularly the multiprocessing capabilities of the dual-core processor make the ESP32 a very attractive choice for the project! See: \u0026nbsp;[FAQ #5](docs/Frequently_Asked_Questions.md#5)\u003cbr\u003e\n- To benefit of the same formfactor (fit with the Mechanical SIMCLINE 2.0 component box!), the \u003cb\u003eAdafruit Feather ESP32 V2 plus Oled display\u003c/b\u003e is still the preferred board and display for the project. See: [Adafruit Feather ESP32 V2](docs/Adafruit%20Feather%20ESP32-V2.md) for settings, wiring scheme and more.\u003cbr\u003e\n\nNotice that other members of the ESP32 (particularly \u003cb\u003eESP32S3\u003c/b\u003e) will do the job perfectly, when the development boards come with extra flash and psram memory! See: \u0026nbsp;[FAQ #7](docs/Frequently_Asked_Questions.md#7). \u0026nbsp; \u003cbr\u003e\n- For example SIMCLINE works successfully with the \u003cb\u003eLilygo esp32s3 T-Display\u003c/b\u003e board, however that Lilygo-board needs another size component box! See: [Lilygo esp32s3 T-Display](docs/LILYGO%20ESP32S3%20T-Display.md) for settings, wiring scheme and more.\u003cbr\u003e \n- Another attractive example is the \u003cb\u003eSeeed Studio XIAO ESP32S3 (plus Oled display)\u003c/b\u003e that has been tested to work fine in service of the SIMCLINE 2.0 with the present library. Due to its thumb-size, it fits definitely in the component box, however it needs some special care to mount it stably. For settings, wiring scheme and more, see: [Seeed Studio XIAO ESP32S3](docs/XIAO_ESP32S3_Sense.md)\u003cbr\u003e\n\nSimcline-V2 library builds on the experience, knowledge and code of Simcline projects since \u003cb\u003e2020\u003c/b\u003e. The original Simcline code has been revisited and redesigned completely for better stability, robustness and modularity. It was transformed to a C++ Object model that handles the many BLE services and hides most of the Simcline's internal operation. The Simcline community is very diverse when it comes to programming skills. The present Simcline-V2 library matches this much better! It also meets the urge for a greater variety in ESP32 boards and displays to work with.\u003cbr\u003e\n\n# The Simcline-V2 design separates completely:\n+ presentation (display types/properties)\n+ specific ESP32 board properties (pinout and initialization)\n+ BLE operation\u003cbr\u003e\n\nTo achieve this the design has implemented Abstract Base Classes for ESP32 board and Display. As a consequence the \u003cb\u003enovice programmer/user\u003c/b\u003e only has to change config settings to select between \u003cb\u003estandard\u003c/b\u003e board- and display-types that are supplied with Simcline-V2. However, a \u003cb\u003eproficient programmer/user\u003c/b\u003e can implement Concrete Classes for ESP32-board-type and Display-type of his/her choice easily without interfering with the Simcline BLE operational code.\u003cbr\u003e\nBenefits of this Approach:\n+ Scalability: Easily add new display types by creating new concrete classes implementing the IDisplay interface.\n+ Maintainability: Changes to one display type do not affect others.\n+ Flexibility: Change the display type used by the Presentation class without modifying its implementation.\u003cbr\u003e\n\nAs a result the Arduino ino-files that the user will access, in the `Simcline-V2/examples` folder, are very concise in comparison with the old code files. \u003cbr\u003e\n\n# Simcline-V2 has central configuration\nAll configuration settings have been gathered in one config directory `../documents/arduino/libaries/Simcline-V2/src/config` for \u003cb\u003eBoard\u003c/b\u003e-, \u003cb\u003eDebug\u003c/b\u003e-, \u003cb\u003eDisplay\u003c/b\u003e-, \u003cb\u003eNimBLE\u003c/b\u003e- and \u003cb\u003eSimcline\u003c/b\u003e-configurations. Check this out:  [Simcline-V2 Configuration](src/config/README.md)\u003cbr\u003e\n\n# NimBLE-Arduino 2.x\nThe Simcline project heavily leans on the \u003cb\u003eNimBLE-Arduino\u003c/b\u003e library for Bluetooth handling, see: [H2Zero/NimBE-Arduino](https://github.com/h2zero/NimBLE-Arduino). \u003cb\u003eNimBLE-Arduino\u003c/b\u003e is structured for compilation with Arduino and for use with ESP32! Simcline-V2 works only (!) with the latest version: \u003cb\u003eNimBLE-Arduino Version 2.x\u003c/b\u003e!\u003cbr\u003e\n\n# FiTness Machine Service a Bluetooth Service Specification\nFrom 2015 to 2017 the Sports and Fitness Working Group (SIG) designed a Bluetooth Service specification. This service exposes training-related data in the sports and fitness environment, which allows a Server (e.g., a fitness machine) to send training-related data to a Client. In Februari 2017 the service specification reached a stable version: [Fitness Machine Service 1.0](https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/) when it was adopted by the Bluetooth SIG Board of Directors. Have a look at the document to appreciate the effort of all the contributors and the companies they represented!\u003cbr\u003e\n\u003cb\u003eFTMS\u003c/b\u003e is an open (nonproprietary) protocol that is not owned by any particular company and not limited to a particular company's product. It can be compared in that respect with FE-C over ANT+, however \u003cb\u003eFTMS\u003c/b\u003e is targeted to control fitness equipment over \u003cb\u003eBluetooth\u003c/b\u003e! Today \u003cb\u003eBluetooth Smart FTMS\u003c/b\u003e is the absolute industry standard for indoor trainers and Simcline-V2 is primarily targeted at \u003cb\u003eFTMS\u003c/b\u003e! \u003cbr\u003e\n\n# Simcline-V2 is fully supporting:\n|Trainer  |Supported protocols|\n|-----------|-------------------------------------------------------------------------------------| \n|Elite |Bluetooth Smart FTMS on all 2020 smart trainers.|\n|Gravat |Bluetooth Smart FTMS on all 2020 smart trainers|\n|JetBlack |Bluetooth Smart FTMS with HRM.\u0026nbsp;[FAQ #3](docs/Frequently_Asked_Questions.md#3)|\n|Kinetic |Bluetooth Smart FTMS on all 2020 smart trainers.|\n|Minoura |Bluetooth Smart FTMS on all 2020 smart trainers.|\n|Saris |Bluetooth Smart FTMS on all 2020 smart trainers.|\n|STAC |Bluetooth Smart FTMS on all 2020 smart trainers.|\n|Tacx |Bluetooth Smart FTMS on all 2020 smart trainers \u003cb\u003eand\u003c/b\u003e legacy Tacx (ANT+) FE-C over BLE |\n|Wahoo |Bluetooth Smart FTMS on all 2020 smart trainers \u003cb\u003eand\u003c/b\u003e legacy Wahoo Bluetooth Smart Control.|\n|Zwift Hub|Bluetooth Smart FTMS with HRM.\u0026nbsp;[FAQ #3](docs/Frequently_Asked_Questions.md#3)|\n\n# Zwift Virtual Shifting (VS): an Emerging De-Facto Standard\n\nVirtual Shifting has rapidly become a dominant hardware trend for indoor cycling in 2025. While it currently complements—rather than fully replaces—traditional mechanical cassettes, its adoption is accelerating across both trainers and control devices.\n\nVirtual Shifting allows riders to “change gears” on a smart trainer without interacting with the bicycle’s drivetrain. Instead of physically moving the chain across sprockets, software simulates different gear ratios and dynamically adjusts trainer resistance. From the rider’s perspective, shifting is now handled entirely by the trainer and the training platform, rather than by mechanical components on the bike.\n\n## Current Market Standing\n\n**Industry Adoption**  \nMajor manufacturers including **Elite**, **JetBlack**, **Wahoo**, and **Garmin (Tacx)** now support Virtual Shifting on their latest trainer models, often marketed as *“Zwift Ready”*.\n\n- Garmin (Tacx) considered the 2025 Virtual Shifting firmware update so significant that, in their most recent firmware releases, the traditional **FTMS service has been replaced by the Zwift Virtual Shifting service**.\n\n**Ecosystem Lock-In**  \nAlthough platforms such as [Rouvy](https://rouvy.com/virtual-shifting) have added support, Virtual Shifting remains largely tied to the **Zwift BLE protocol**. Most other training platforms still rely on a physical cassette for gear changes.\n\n**Legacy Hardware Constraints**  \nSupport for Virtual Shifting is firmware-dependent. Many older trainers (e.g. Tacx Neo, Zwift Hub One, Wahoo KICKR v5, and others) cannot be updated to support Virtual Shifting and therefore remain limited to conventional shifting via FTMS.\n\n## Simcline-V2 and Zwift Virtual Shifting\n\nWithin the **Zwift BLE protocol**, the current road inclination —just as with FTMS— is transmitted to the trainer. This data can be intercepted by a **Man-In-The-Middle (MITM)** implementation and redirected to a secondary target: the mechanical Simcline device.\n\nFrom a Simcline-V2 perspective, the principle is unchanged:\n\n- **FTMS** and **Zwift Virtual Shifting** both transport trainer-related data over BLE.\n- Zwift Virtual Shifting is simply an **additional BLE service** with a different data model.\n- Inclination data remains available and can be processed in exactly the same way as with **FTMS**.\n\nThe latest Simcline-V2 version therefore adds support for **Zwift Virtual Shifting**, enabling Simcline actuation when Virtual Shifting is active.\n\n\u003e **Important:** Zwift Virtual Shifting support requires a trainer running the firmware that explicitly supports the **Zwift Virtual Shifting** protocol.\n\n## ⚠️Virtual Shifting Code Dependency\nTo run the optional Virtual Shifting BLE Service, **Simcline-V2** needs installation of the **ULEB128 Library** → Unsigned little endian base 128 implementation for encoding and decoding ZVS-data-streams\n  - [uleb128](https://github.com/bolderflight/uleb128)\n\n# Man-In-The-Middle (MITM) software pattern\u003cbr\u003e\n\u003cimg src= \"./images/FTMS_MITM.jpg\" align=\"left\" width=\"1000\" height=\"500\" alt=\"Man in the Middle\"\u003e\u003cbr\u003e\n\u003cb\u003eMan-In-The-Middle\u003c/b\u003e is a powerful software engineering pattern that is applied in many software designs. Unfortunately it is also known for a negative application in communication traffic: MITM is a common type of cybersecurity attack that allows attackers to eavesdrop on the communication between two targets.\nWe have applied the very principle: the Simcline is strategicly positioned in between the BLE communication of the Smart Trainer and the training App (like Zwift) running on the PC/Laptop, all communication traffic can be inspected in that MITM position, when it is passed on from one to the other, in both directions. When Zwift sends resistance information (like the road inclination) to the Smart trainer, this information can be intercepted and applied to determine the up/down positioning of the Simcline. \u003cbr\u003e\n\n# How to start?\u003cbr\u003e\n+ Install the [Arduino IDE 2](https://www.arduino.cc/en/software#experimental-software)\n+ Install [uleb128](https://github.com/bolderflight/uleb128), when you intend to run Simcline-V2 with **Zwift Virtual Shifting**  \n+ Install your [ESP32 board](https://randomnerdtutorials.com/installing-esp32-arduino-ide-2-0/) in the Arduino environment\n+ Install [Adafruit OLED and GFX Libraries](https://makeabilitylab.github.io/physcomp/advancedio/oled-libraries.html)\n+ Install the ESP32 NimBLE-Arduino library (\u003cb\u003eVersion 2.#.#\u003c/b\u003e), in \u003cb\u003eArduino IDE\u003c/b\u003e go to `Sketch menu` -\u003e `Include Library` -\u003e `Manage Libraries`, search for NimBLE-Arduino and install. [Ref](https://github.com/h2zero/NimBLE-Arduino#arduino-installation)\n+ Install the Simcline-V2 library from this repository. Download as `.zip` and extract to `Arduino/libraries` folder, or \u003cbr\u003ein \u003cb\u003eArduino IDE\u003c/b\u003e from `Sketch menu` -\u003e `Include library` -\u003e `Add .Zip library`\u003cbr\u003e\n\n# How to make it work?\u003cbr\u003e\nThe requirements in this phase are simple: \n+ running Zwift, Rouvy or myWhoosh app or alike, \n+ working Feather ESP32-V2 (or other ESP32S3) development board and \n+ working Smart Trainer (see above support list)\n+ running Simcline-V2 library and Smart-MITM application.\u003cbr\u003e\n\n# Testing is Knowing!\u003cbr\u003e\nI can understand and respect that you have some reserve: Is this really working in my situation? Better test if it is working, before buying all components and start building.\nIn the Simcline-V2 Library \u003cb\u003eExamples\u003c/b\u003e section (see `..documents/arduino/libraries/Simcline-V2/examples`) you will find the appropriate applications for testing and running SIMCLINE that come with the library. The one you should start with in this stage is \u003cb\u003eSmart-MITM\u003c/b\u003e It is developed with the only intention to allow you to check if the MITM solution is delivering in your specific situation. Within the Arduino IDE 2 select on the top bar menu: `File \u003e Examples \u003e Simcline-V2 \u003e Smart-MITM`\u003cbr\u003e\n\n\u003cb\u003eWhat it does in short:\u003c/b\u003e\u003cbr\u003e\n\u003cimg src=\"./images/Feather_FTMS.jpg\" align=\"middle\" width=\"1000\" height=\"500\" alt=\"Simcline in the Middle\"\u003e\u003cbr\u003e\nA working \u003cb\u003eMITM\u003c/b\u003e implementation links a bike trainer (BLE Server FTMS) and a PC/Laptop (BLE Client running Zwift) with the Feather ESP32, like a \u003cb\u003ebridge\u003c/b\u003e in between. The MITM bridge can pass on, control, filter and alter the interchanged trafic data! The \u003cb\u003eMITM\u003c/b\u003e code is fully ignorant of mechanical or electronic components that drive the Simcline construction.\u003cbr\u003e\n```\nIt simply estabishes a virtual BLE bridge and allows you to ride the bike on the Smart Trainer and \nfeel the resistance that comes with the route you have choosen, thanks to Zwift.\nThe experience should not differ from a normal direct one-to-one connection, Zwift - Smart Trainer!\n```\nAll Bluetooth Smart FTMS indoor trainers expose your efforts on the bike in 2 additional BLE services: Cyling Power (CPS) and Speed \u0026 Cadence (CSC). These services are detected and applied by many training app's and are therefore an integral part of the present design of the MITM bridge. Training app's simply expect, when they connect to the Bluetooth Smart FTMS trainer, that the CPS and CSC services are available in one go! The Zwift pairing screen is a good example: it expects Power Souce (CPS), Resistance (FTMS) and Cadence (CSC) to be connected...\n+ The client-side (Feather ESP32) scans for (a trainer) and connects with \u003cb\u003eFTMS, CPS and CSC\u003c/b\u003e and collects cyling power, speed and cadence data like Zwift would do! The \u003cb\u003eSimcline Client\u003c/b\u003e is doing just that at the left side of the \"bridge\"!\n+ The Server-side (Feather ESP32) advertises and enables connection with training/cycling/game apps like Zwift and collects relevant resistance data, it simulates as if an active \u003cb\u003eFTMS\u003c/b\u003e enabled trainer is connected to Zwift or alike! Notice that the Server-side also exposes active \u003cb\u003eCPS\u003c/b\u003e and \u003cb\u003eCSC\u003c/b\u003e services. The \u003cb\u003eSimcline Server\u003c/b\u003e is doing just that at the right side of the \"bridge\"!\n+ The \u003cb\u003eSimcline MITM\u003c/b\u003e code is connecting both sides at the same time: a full-blown working bridge\u003cbr clear=\"left\"\u003e\n\n# Load Smart-MITM application in Arduino IDE 2\nWithin the Arduino IDE 2.x select on the top bar menu: `File \u003e Examples \u003e Simcline-V2 \u003e Smart-MITM`\u003cbr\u003e\nThe default Simcline-V2 configuration settings for Smart-MITM when using \u003cb\u003eany ESP32 board (without display attached)\u003c/b\u003e are: \n+ Display: \u003cb\u003eNODISPLAY\u003c/b\u003e\n+ ESP32 board: \u003cb\u003eYOUR_ESP32_BOARD\u003c/b\u003e\n+ NimBLE: \u003cb\u003eFTMS\u003c/b\u003e and \u003cb\u003eCSC\u003c/b\u003e\n+ Debug:  \u003cb\u003eDefined\u003c/b\u003e\n\nOptionally:\n+ Users with a \u003cb\u003eAdafruit Feather ESP32 V2\u003c/b\u003e can setup their board and display now! See: [Setup Adafruit Feather ESP32 V2 plus Oled display](docs/Adafruit%20Feather%20ESP32-V2.md)\u003cbr\u003e\n+ Users with a \u003cb\u003eLilygo esp32s3 T-Display\u003c/b\u003e can setup the board and display now! See: [Setup Lilygo esp32s3 T-Display](docs/LILYGO%20ESP32S3%20T-Display.md)\u003cbr\u003e\n+ Users with a \u003cb\u003eXIAO ESP32S3\u003c/b\u003e can setup their board and display now! See: [Setup XIAO ESP32S3 plus Oled display](docs/XIAO_ESP32S3_Sense.md)\u003cbr\u003e\n\nMandatory:\n+ Users of \u003cb\u003eLegacy Wahoo KICKR\u003c/b\u003e smart trainers (\u003cb\u003eNOT supporting FTMS\u003c/b\u003e) must make changes now! See: [Setup for Legacy Wahoo KICKR](docs/Setup_Legacy_Wahoo_KICKR.md).\n+ Users of \u003cb\u003eLegacy Tacx FE-C\u003c/b\u003e smart trainers (\u003cb\u003eNOT supporting FTMS\u003c/b\u003e) must make changes now! See: [Setup for Legacy Tacx FE-C](docs/Setup_Legacy_Tacx_FEC.md).\n+ Users of \u003cb\u003eZwift Enabled\u003c/b\u003e smart trainers must make changes now! See: [Setup Virtual Shifting](docs/Setup_Zwift_Virtual_Shifting.md)\n\n\u003cb\u003eSmart-MITM\u003c/b\u003e is default in Debug mode: using Serial Monitor (logging on the PC-screen) to show you what is happening!\u003cbr\u003e\n\nWhen the settings are conforming your desired setup, it is time to run Smart-MITM!\n\n# Compile and Upload Smart-MITM to your ESP32 board\nA recipe for success: follow \u003cb\u003eALWAYS\u003c/b\u003e the instructions and procedure at the top of the respective program codes!\n```\n/* -----------------------------------------------------------------------------------------------------\n *             This code should work with all indoor cycling trainers that fully support,\n *        Fitness Machine Service, Cycling Power Service and Cycling Speed \u0026 Cadence Service\n * ------------------------------------------------------------------------------------------------------\n * NOTICE: that you need to have set first all config file settings in accordance with your specific setup!\n *         see: ../Documents/Arduino/libraries/FTMS-Simcline/src/config\n *\n *  The code links a BLE Server (a Peripheral to Zwift) and a BLE Client (a Central to the Trainer) with a bridge \n *  in between, the ESP32 being man-in-the-middle (MITM). The ESP32 is an integral part of the Simcline design,\n *  that interprets the exchanged road grade and moves the front wheel up and down with the change in inclination.\n *  The ESP32-bridge can control, filter and alter the bi-directional interchanged data!\n *  The client-side (central) scans and connects with the Trainer relevant services: CPS and FTMS. It collects \n *  all cyling data of the services and passes these on to the server-side....  \n *  The client-side supplies the Indoor Trainer with target and resistance control data.\n *  The server-side (peripheral) advertises and enables connection with cycling apps like Zwift and collects the app's  \n *  control commands, target and resistance data. It passes these on to the client-side....  \n *  The server-side supplies the app with the generated cycling data in return. \n *  \n *  The client plus server (MITM) are transparent to the Indoor Trainer as well as to the training app Zwift or alike!\n *  \n *  Requirements: Zwift app or alike, ESP32 board (NO display required) and a supported Indoor Trainer\n *  0) Upload and Run this code on your ESP32 board\n *  1) Start the Serial Monitor to catch debugging info\n *  2) The code will do basic testing of electronic parts and settings\n *  3) Start/Power On the Indoor Trainer  \n *  4) Your ESP32 and Trainer will pair as reported in the output\n *  5) Start Zwift on your computer or tablet and wait....\n *  6) Search on the Zwift pairing screens for your ESP32 a.k.a. \u003cSIM32\u003e\n *  7) Pair: Power Source, Resistance and Cadence one after another with \u003cSIM32\u003e\n *  8) Optionally one can pair as well devices for heartrate and/or steering (Sterzo)\n *  9) Start the default Zwift ride or any ride you wish\n * 10) Make Serial Monitor output window visible on top of the Zwift window \n * 11) Hop on the bike: do the work and feel resistance change with the road\n * 12) Inspect the info presented by Serial Monitor.....\n *  \n *   This device is identified with the name \u003cSIM32\u003e. You will see this only when connecting to Zwift on the \n *   pairing screens! Notice: Zwift extends device names with additional numbers for identification!\n *  \n*/ \n```\n# Points of Interest\n+ Be aware of undesirebly \u003cb\u003eautoconnect\u003c/b\u003e of Zwift with your trainer using ANT+ or BLE Smart before \u003cb\u003eSmart-MITM\u003c/b\u003e can establish a connection: always \u003cb\u003estart\u003c/b\u003e Zwift \u003cb\u003eAFTER\u003c/b\u003e Smart-MITM and trainer have connected successfully! The \u003cb\u003eSmart-MITM\u003c/b\u003e code will than fail to connect, that does not help you getting representative results during the reconnaisance! Only one client can control at the same time: 2 captains on one ship is a recipe for disaster! See for more info [FAQ #1](docs/Frequently_Asked_Questions.md#1) and [FAQ #6](docs/Frequently_Asked_Questions.md#6)\n+ Please write down the presented MAC/Device Addresses of a) your Smart trainer and b) your Desktop/Laptop with Zwift. These showup in the Serial Monitor output when running the Smart-MITM test code. This is for your own convenience since it helps you to identify later both devices by MAC Addresses! The Smart-MITM detects the Mac addresses and stores these in ESP32 NVS (Non-Volatile-Storage) for later use to unmistakingly establish a BLE connection with the targeted devices. See [FAQ #9](docs/Frequently_Asked_Questions.md#9)\n+ When you see different road grade values in the Zwift window compared with the Simcline display or in the Serial Monitor output, this can have different reasons! See: [FAQ #8](docs/Frequently_Asked_Questions.md#8)\n# What's next?\nWhen you are pleased with the results sofar, you can consider to setup the complete SIMCLINE mechatronic system.\u003cbr\u003e\n+ Mechanical Assembly \u003cbr\u003e\n\u003cimg src=\"https://www.instructables.com/assets/img/instructables-logo-v2.png\" width=\"32\" height=\"48\" align=\"left\" alt=\"Instructables\"\u003e \u0026nbsp; [SIMCLINE 2.0 Instructables](https://www.instructables.com/SIMCLINE-20-Easy-Simulation-of-Road-Incline/) \n\u003cbr clear=\"left\"\u003e\n\n+ Embedded Control System \u003cbr\u003e\n[Setup Simcline Control System](docs/Setup_SIMCLINE.md)\u003cbr\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fberg0162%2Fsimcline-v2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fberg0162%2Fsimcline-v2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fberg0162%2Fsimcline-v2/lists"}