Open-source ESP-IDF firmware for ESP32 cellular IoT devices. The first hardware-tested profile supports the LilyGO T-SIM7000G with a SIM7000 modem, PPPoS connectivity over UART, NB-IoT/LTE-M/GPRS, GNSS, BME280 and secure WebSocket telemetry.
The firmware boots the board, connects the cellular modem over PPP, reads the configured I2C sensor, requests device configuration from SensMonitor and sends samples to the SensMonitor WebSocket endpoint.
SensMonitor Web App | LilyGO T-SIM7000G integration guide | Roadmap | Contributing
| Board | Modem | Connection | Sensor | Status |
|---|---|---|---|---|
| LilyGO T-SIM7000G | SIM7000G | UART/PPPoS | BME280 | Hardware-tested |
| LilyGO T-SIM7080 S3 | SIM7080G | UART/PPPoS | Configurable I2C | Build-tested |
| LilyGO T-SIM7670G S3 | SIM7670G | UART/PPPoS | Configurable I2C | Build-tested |
| Generic ESP32 + UART | SIM7000 | UART/PPPoS | Configurable I2C | Build-tested |
The tested build uses ESP-IDF 5.5.4. Additional board and modem profiles are planned; they are not considered supported until their complete PPP and telemetry flow has been verified on physical hardware.
The LilyGO T-SIM7080 S3 profile targets ESP32-S3 with SIM7080G Cat-M/NB-IoT
data and GNSS. It uses the LilyGO T-SIM7080G-S3 pinout with ESP UART TX/RX
GPIO5/GPIO4, PWRKEY GPIO41 and external sensor I2C pins GPIO13/GPIO21 when
the camera interface is not used. The onboard PMU I2C bus uses GPIO15/GPIO7
internally and those pins are not exposed for external sensors. The
*-S3-Standard variants can use a different default I2C mapping and should
be handled as separate board profiles after hardware verification.
The LilyGO T-SIM7670G S3 profile targets ESP32-S3 with the SIM7670G LTE Cat-1 modem and GNSS. It uses the T-SIM7670G-S3 pinout with ESP UART TX/RX GPIO11/GPIO10, PWRKEY GPIO18 and DTR GPIO9. External sensor I2C currently defaults to GPIO13/GPIO21 to match the T-SIM7080 S3 profile during hardware testing.
The generic profile exposes UART, optional PWRKEY and I2C wiring through Kconfig. It is a configurable integration starting point, not a claim that every ESP32/SIM7000 board combination has been physically verified.
At runtime the application:
- Derives a device serial from the ESP32 factory eFuse MAC.
- Initializes the configured I2C sensor.
- Powers and configures the SIM7000 modem.
- Opens a PPP data connection.
- Synchronizes system time using SNTP.
- Connects to the SensMonitor WebSocket endpoint.
- Requests device configuration by serial number.
- Applies sensor and digital I/O configuration received from the server.
- Reads sensor values and sends samples continuously.
The generated serial has this format:
SM-ESP32-A1B2C3D4E5F6
The serial identifies the physical device in SensMonitor. It is not a secret.
If the serial is not registered on the server, firmware logs
DEVICE_NOT_REGISTERED. Register that serial in the SensMonitor application,
then restart the device so it requests configuration again.
ESP-IDF Component Manager downloads the SensMonitor components from the ESP Component Registry automatically:
sensmonitor/smonitor-modemsensmonitor/smonitor-i2c
They are declared in main/idf_component.yml and installed under
managed_components/. Users do not need sibling repository checkouts.
The manifest uses registry component versions, and dependencies.lock records
the complete resolved dependency graph for reproducible builds. Component
source included in the registry packages is installed locally under
managed_components/ during the ESP-IDF build.
During local component development, main/idf_component.yml may use
override_path to point sensmonitor/smonitor-modem at a sibling checkout.
Do not commit a dependencies.lock file that resolves the component to an
absolute local path.
- Microsoft Visual Studio Code with the Espressif IDF extension, or a command line ESP-IDF 5.5.4 installation
- Git
- LilyGO T-SIM7000G board
- SIM card with data enabled
- APN for the mobile operator
- LTE antenna connected before powering the modem
- BME280 connected over I2C
- USB data cable
The default LilyGO/BME280 wiring used by this project is:
| Signal | GPIO |
|---|---|
| Modem TX | 27 |
| Modem RX | 26 |
| Modem RTS | 25 |
| Modem CTS | 23 |
| Modem PWRKEY | 4 |
| I2C SDA | 21 |
| I2C SCL | 22 |
The default BME280 address is 0x76.
Visual Studio Code with the official Espressif IDF extension is the recommended setup for the first build.
- Install Microsoft Visual Studio Code.
- Open Extensions with
Ctrl+Shift+X. - Search for and install the official Espressif IDF extension.
- Open the Command Palette with
Ctrl+Shift+P. - Run
ESP-IDF: Open ESP-IDF Installation Manager. - Install ESP-IDF 5.5.4 and its tools.
- Run
ESP-IDF: Select Current ESP-IDF Versionand select the installed ESP-IDF 5.5.4 setup.
Use ESP-IDF: Doctor Command if the extension reports a tool or environment
problem. See the official
ESP-IDF extension installation guide
for platform-specific setup details.
Clone the repository:
git clone https://github.com/sensmonitor/smonitor-iot.git
cd smonitor-iotIn Visual Studio Code, select File > Open Folder and open the cloned
smonitor-iot directory. The extension detects this repository as a standard
ESP-IDF project.
Open the Command Palette and run:
ESP-IDF: Set Espressif Device Target
Select the target that matches the board profile. The root/default
configuration follows current ESP32-S3 development. Use esp32s3 for
LilyGO T-SIM7080G-S3 and esp32 for LilyGO T-SIM7000G WROVER-B. Then run:
ESP-IDF: Select Port to Use
Select the serial port for the board, such as COM5 on Windows or
/dev/ttyUSB0 on Linux. The exact port depends on the host and board
revision.
Copy the local configuration template:
cp sdkconfig.defaults.local.example sdkconfig.defaults.localOn Windows PowerShell, use:
Copy-Item sdkconfig.defaults.local.example sdkconfig.defaults.localThe local file is ignored by Git. Enter the APN and other operator-specific settings there, then run:
ESP-IDF: SDK Configuration Editor
Review the options under SensMonitor IoT, especially the APN, PPP authentication, preferred mobile network and LPWA band. Do not commit mobile operator credentials.
Run these commands from the Command Palette in order:
ESP-IDF: Build your Project
ESP-IDF: Flash your Project
ESP-IDF: Monitor your Device
The first build requires internet access so ESP-IDF Component Manager can download the pinned dependencies. A successful boot follows the sequence shown in Expected Log Flow.
Activate ESP-IDF 5.5.4, then build. Internet access is required during the first build so Component Manager can download dependencies:
cd smonitor-iot
idf.py set-target esp32s3
cp sdkconfig.defaults.local.example sdkconfig.defaults.localFill in the mobile network settings in sdkconfig.defaults.local. The local
file is ignored by Git and is loaded automatically after the shared
sdkconfig.defaults. For the ESP32-based T-SIM7000G WROVER-B profile, use
idf.py set-target esp32 or the example defaults in
examples/lilygo_sim7000g/sdkconfig.defaults.
idf.py buildFlash and monitor:
idf.py -p /dev/ttyACM0 flash monitorUse the serial port for your board if it differs.
Configuration is stored in ESP-IDF sdkconfig. You can edit it through
idf.py menuconfig or edit the generated sdkconfig file directly for local
testing.
For a clean user build, start from the project defaults and configure the operator APN before building.
Menu path:
SensMonitor IoT
Important options:
| Option | Meaning |
|---|---|
CONFIG_SMONITOR_MODEM_APN |
Mobile operator APN. Required. Empty by default. |
CONFIG_SMONITOR_MODEM_USERNAME |
PPP username. Often empty. |
CONFIG_SMONITOR_MODEM_PASSWORD |
PPP password. Often empty. |
CONFIG_SMONITOR_MODEM_AUTH_NONE |
Disable PPP authentication. Default for LilyGO/SIM7000G profile. |
CONFIG_SMONITOR_MODEM_AUTH_PAP |
Use PAP with the configured username/password. |
CONFIG_SMONITOR_MODEM_NETWORK_AUTO |
Let modem/operator choose automatically. Default for first bring-up. |
CONFIG_SMONITOR_MODEM_NETWORK_NB_IOT |
Prefer NB-IoT when supported by the SIM/operator. |
CONFIG_SMONITOR_MODEM_NETWORK_LTE_M |
Prefer LTE-M when supported by the SIM/operator. |
CONFIG_SMONITOR_MODEM_CONNECT_TIMEOUT_MS |
PPP connection timeout. Default 180000. |
Example operator configuration:
CONFIG_SMONITOR_MODEM_APN="your-apn"
CONFIG_SMONITOR_MODEM_USERNAME=""
CONFIG_SMONITOR_MODEM_PASSWORD=""
CONFIG_SMONITOR_MODEM_AUTH_NONE=y
CONFIG_SMONITOR_MODEM_NETWORK_AUTO=y
CONFIG_SMONITOR_MODEM_LPWA_BAND=20
Use the APN, authentication mode, network technology and radio band supplied
by your mobile operator. Keep AUTO for initial modem bring-up, then select
NB-IoT or LTE-M explicitly if the deployment/operator requires it. Enable PAP
only if the operator requires it.
Menu path:
SensMonitor IoT > I2C sensor
Important options:
| Option | Meaning |
|---|---|
CONFIG_SMONITOR_I2C_SENSOR_BME280 |
Select BME280. Currently the supported profile. |
CONFIG_SMONITOR_I2C_PORT |
ESP32 I2C controller. Default 0. |
CONFIG_SMONITOR_I2C_SDA_PIN |
SDA GPIO. Default 21. |
CONFIG_SMONITOR_I2C_SCL_PIN |
SCL GPIO. Default 22. |
CONFIG_SMONITOR_I2C_FREQUENCY_HZ |
I2C frequency. Default 100000. |
CONFIG_SMONITOR_I2C_INTERNAL_PULLUPS |
Enables internal pull-ups. Useful for development. |
CONFIG_SMONITOR_I2C_DEVICE_ADDRESS |
Sensor address. Default 0x76. |
GPIO 21/22 are the current board profile, not universal ESP32 I2C pins. Change them if your wiring differs.
Menu path:
SensMonitor client
Important options:
| Option | Meaning |
|---|---|
CONFIG_SMONITOR_WEBSOCKET_URI |
SensMonitor WebSocket endpoint. |
CONFIG_SMONITOR_CLIENT_TIME_SYNC_RETRIES |
SNTP retries before continuing. |
CONFIG_SMONITOR_SAMPLE_INTERVAL_MS |
Sample loop period. Default 5000. |
The default WebSocket URI points to the production SensMonitor endpoint.
Board profile examples are provided in:
examples/lilygo_sim7000g/sdkconfig.defaults
examples/lilygo_sim7080_s3/sdkconfig.defaults
examples/lilygo_sim7670_s3/sdkconfig.defaults
examples/generic_esp32_uart_modem/sdkconfig.defaults
The LilyGO profiles define their tested modem UART, PWRKEY, I2C and power
wiring. lilygo_sim7000g targets the ESP32-based WROVER-B board, while
lilygo_sim7080_s3 and lilygo_sim7670_s3 target ESP32-S3. The generic
ESP32 UART modem profile uses SIM7000 as its current default modem profile,
but the folder name describes the reusable board architecture: ESP32 plus a
cellular modem over UART. It defaults to UART GPIO17/GPIO16, no hardware flow
control, an externally powered modem, disabled battery monitoring and
disabled LilyGO-specific active GPS antenna power.
To use GPIO PWRKEY control with the generic profile, select:
SensMonitor IoT > Cellular modem hardware > Modem power control > GPIO PWRKEY
Then configure the PWRKEY GPIO, active level, pulse duration and startup delay for the exact modem board. Verify all generic pin and power settings against the target board schematic before powering the hardware.
APN, sensor choice and mobile network settings remain outside the board profiles.
To use it manually, copy or merge the relevant values into your local
sdkconfig or use it as a reference when running idf.py menuconfig.
A healthy boot should look like this at a high level:
smonitor_iot: Device serial: SM-ESP32-...
smonitor_sensor: Initializing BME280 on I2C0, SDA=21, SCL=22, address=0x76
smonitor_sensor: BME280 initialized successfully
smonitor_modem: PPP authentication: none
smonitor_modem: Power on the modem
smonitor_modem: Initializing esp_modem for SIM7000
smonitor_modem: PPP event ... phase establish
smonitor_modem: PPP event ... phase network
smonitor_modem: PPP event ... phase running
smonitor_modem: Modem connected to PPP server
smonitor_modem: IP : ...
time_sync: System time set.
smonitor_client: WebSocket connected
smonitor_client: Sent device-config-request for: SM-ESP32-...
smonitor_client: Received device config with ... active sensors.
smonitor_iot: environment/temperature = ...
smonitor_client: Sent data: ...
smonitor_client: Received device-sample-ack.
If the device is not registered:
DEVICE_NOT_REGISTERED: Register SM-ESP32-... in the SensMonitor application.
Log:
APN is empty. Configure SensMonitor IoT > Mobile network APN.
Set CONFIG_SMONITOR_MODEM_APN in sdkconfig or idf.py menuconfig.
Check:
- APN is correct.
- SIM card has data enabled.
- Antenna is connected.
- Selected network mode is supported by the SIM/operator.
- Band is correct for your region/operator.
- PPP authentication mode matches the operator.
For the tested LilyGO/SIM7000G profile use:
CONFIG_SMONITOR_MODEM_AUTH_NONE=y
CONFIG_SMONITOR_MODEM_NETWORK_AUTO=y
CONFIG_SMONITOR_MODEM_LPWA_BAND=20
PPP failures are logged by name, for example:
PPP error 7: authentication failed
PPP error 9: peer timeout
Check:
- SDA/SCL wiring.
- Sensor power.
- I2C address:
0x76or0x77. - Pull-ups. External pull-ups are recommended for reliable hardware.
The Espressif i2c_bus component may log a probe message before creating the
bus. The important line is:
BME280 initialized successfully
Check:
- PPP has an IP first.
- System time is synchronized.
CONFIG_SMONITOR_WEBSOCKET_URIis correct.- TLS certificate bundle in
smonitor_clientis present.
The firmware derives the serial from ESP32 eFuse MAC. Register the logged serial in the SensMonitor application:
SM-ESP32-A1B2C3D4E5F6
smonitor-iot/
main/
app_main.cpp
app_controller.cpp
device_identity.cpp
sensor_runtime.cpp
Kconfig.projbuild
components/
smonitor_client/
include/smonitor_client.h
websocket_client.cpp
json_client.cpp
device_config.cpp
gpio_control.cpp
time_sync.cpp
Kconfig
examples/
generic_esp32_uart_modem/
sdkconfig.defaults
lilygo_sim7000g/
sdkconfig.defaults
lilygo_sim7080_s3/
sdkconfig.defaults
main owns the application flow, board pin assignments and modem power
sequencing. components/smonitor_client owns the SensMonitor TLS WebSocket
protocol, device configuration, JSON sample formatting, digital I/O updates
and SNTP synchronization.
The external smonitor-modem component owns SIM7000 AT setup and PPP
connectivity. The external smonitor-i2c component owns I2C bus access,
sensor profiles and decoding.
- BME280 is the only configured sensor profile.
- LilyGO T-SIM7000G/SIM7000 is the only hardware-tested modem board profile.
- The generic ESP32/UART SIM7000 profile is build-tested only.
- Runtime provisioning is not yet stored in NVS; configuration is build-time
through
sdkconfig. - The SensMonitor client is currently built from source inside this repo. It can later be distributed as a precompiled component if needed.
Licensed under the Apache License 2.0.