Current guideLocal + cloud

Build and operate connected devices with less friction

Dexmod combines an Arduino-focused code workspace, AI assistance, dependency-aware libraries, browser flashing, local serial tools, cloud telemetry, remote controls, schedules, and telemetry automation in one workflow.

01

Create

Select a board and write or generate code.

02

Verify

Compile with the project's complete dependency set.

03

Operate

Monitor telemetry and control connected devices.

First project

Quick start

  1. 1

    Create an account

    Register with email and password, Google, or GitHub.

  2. 2

    Create a project

    Open Project Manager, choose New project, name it, and select the target board.

  3. 3

    Write or ask AI

    Edit main.ino directly or ask the AI Assistant to explain, diagnose, or generate code.

  4. 4

    Add dependencies

    Open Libraries to install a registry library or upload a compatible ZIP library.

  5. 5

    Save and test

    Changes are autosaved. Use Problems, Output, and Serial Monitor to inspect the project.

Workspace

Projects and the editor

Use the panel toggle beside the file tabs to open Project Explorer. Find files by name, open them, or use each file's menu to rename, duplicate, or delete. Add new files from the Explorer header. The main file cannot be deleted. Explorer displays the existing flat project files; nested folders are not supported.

Each project stores its name, selected board, source files, installed libraries, and project-specific AI conversation history. The editor remembers the active file during navigation and saves file changes automatically.

Project Manager

Create, import, rename, duplicate, delete, and open projects. Plan limits determine the maximum number of stored projects.

Editor workspace

Work with multiple Arduino and header files, select a target board, manage libraries, export code, and open the AI panel.

Collaboration

Workspace team

Open Settings → Workspace team. Every plan supports a team: Free allows 2 people, Starter/Maker 3, Pro 5, and Scale/Team 10, including Owner. Pending invitations reserve seats and expire after 7 days. Invite by email; the invited person signs in with that verified email and accepts in Settings. This release does not send invitation emails.

Viewer can see dashboards and telemetry, but not source code or credentials. Editor can read and change all project source and dashboard layouts, including arduino_secrets.h and secrets embedded in code. Owner must confirm the scope warning before inviting or changing someone to Editor. Editor does not inherit command access. Operator can view dashboards and send manual device commands, but cannot edit source or dashboard layouts.

Open an accepted workspace under Settings → Shared workspaces. Shared source editing uses normal autosave, not simultaneous collaborative editing; coordinate changes to the same file. Owner retains billing, member management, device creation/deletion, token rotation, audit protection, schedules, automation, AI, GitHub, and compile/upload. Shared Editors can edit files and board settings; project creation, deletion, archive, and export remain Owner-managed in this first release.

The Owner's package determines team seats, device quota, and telemetry retention. When a subscription ends or the plan shrinks, the oldest accepted members retain available seats. Extra members lose access until seats are available again; no projects or devices are deleted. Owner can remove members and invitations at any time.

Plans and release scope

Features and plan limits

Every plan includes the Free Studio and Dashboard allowances. Project Explorer, official examples, dashboard statistics, comparison, Scenes, opt-in email notifications, and telemetry integration templates are not separate paid add-ons. Your plan still limits projects, devices, retention, publishing interval, AI credits and team seats. Dashboard Pro/Scale and Complete Pro/Team add scheduled CSV exports. See Pricing for exact limits.

Studio → More → Examples creates a new project, saves your current editor first, and respects project quotas. Basic telemetry and Safe LED control use DexmodIoT 0.3.1 with credential placeholders. Existing projects keep their installed version. Fill your own credentials and check board-specific GPIOs before uploading. The HTTPS OTA example is a restricted pilot, not an ordinary control example.

Read the guides below for workspace roles, analytics, Scenes and integration limits. Background emails are opt-in and advisory, not safety alarms. Scenes run sequentially and cannot undo earlier actions. External integration templates currently send telemetry only. AI, billing and compile/upload remain Owner-managed; team membership does not pool members' personal AI wallets.

Assisted coding

AI Assistant

AvailableUses AI credits

The assistant receives the project manifest and a plan-limited set of relevant files selected from the active file, local includes, compiler diagnostics, and file names mentioned in the request. Credential files such as secrets.h and arduino_secrets.h are listed only as protected files: their contents are excluded and AI changes cannot modify them. Sending is a single action; use Review context when you want to inspect the selected files before sending. Consultation costs 1 credit, optional AI analysis costs 2 credits, and code updates cost 5 credits. Verify compilation itself is free. For Fix Verify errors, Dexmod compiles the proposed correction before charging, automatically retries once with the new diagnostics, and charges 5 credits only when the correction compiles. If both attempts fail, no user credits are charged. For project edits, inspect the before/after preview for every create, update, or delete operation, then choose Apply all; Undo remains available until another change replaces that preview. Review pin assignments, hardware assumptions, and safety-related behavior before uploading.

  • Use precise hardware names, board type, pins, libraries, and expected behavior.
  • Ask for telemetry output when the project will use Serial Dashboard.
  • Use Undo after an applied response if the generated code is not suitable.
  • AI output can be incorrect; compilation and hardware validation remain necessary.
cpp
Create an ESP32 temperature monitor using a DHT22 on GPIO 4.
Print temperature and humidity as one JSON object every second
so Dexmod Serial Dashboard can visualize both values.

Hardware targets

Boards and libraries

Choose the exact board that matches the physical target before compiling or uploading. Dexmod builds its catalog from the Arduino AVR and Espressif ESP32 cores installed on the server. This includes classic ESP32, ESP32-S3, ESP32C3 Dev Module, and Nologo ESP32C3 Super Mini. Boards marked compile-supported still require validation on the physical hardware.

Library sourceUsage
Arduino registrySearch and install
External ZIPUpload up to 10 MB

Local telemetry

Serial Monitor and Dashboard

AvailableBrowser local

Serial Monitor connects directly to an authorized device port. Console displays raw text, while Dashboard recognizes numeric telemetry and generates value cards and live charts automatically.

  1. Open the Serial Monitor tab below the editor.
  2. Select the same baud rate used by Serial.begin().
  3. Click Connect and choose the correct USB serial device.
  4. Switch from Console to Dashboard.
  5. Use Record to capture parsed samples, then Export CSV.
cpp
void setup() {
  Serial.begin(115200);
}

void loop() {
  float temperature = 28.4;
  float humidity = 72.0;

  Serial.print("{\"temperature\":");
  Serial.print(temperature);
  Serial.print(",\"humidity\":");
  Serial.print(humidity);
  Serial.println("}");
  delay(1000);
}

Dashboard Builder

After telemetry is detected, choose Customize to rename metrics, add units, select Line, Number, Gauge, or Status widgets, hide metrics, and reorder the layout. Select Save layout to store the configuration for the current project in this browser.

Metric and widget count

The Dashboard is not limited to three labels. The demo creates three widgets because it sends only temperature, humidity, and motorRpm. Every new numeric telemetry key automatically creates another configurable widget after its first sample arrives.

text
{"temperature":28.4,"humidity":72,"pressure":1012,"motorRpm":1250,"voltage":12.3,"current":1.8}

This sample creates six metrics. There is currently no fixed widget limit, but keeping approximately 12–20 visible widgets per dashboard is recommended for readability and browser performance. Hide less important metrics or split very large systems into focused dashboards.

Data reference

Supported telemetry formats

Send one complete sample per line. JSON is recommended because metric names remain explicit and values stay synchronized.

JSON — recommended

text
{"temperature":28.4,"humidity":72,"motor":true}

Numbers and numeric strings become chart values. JSON booleans become 1 or 0.

Key-value

text
temperature=28.4 humidity=72 motorRpm=1280

CSV with header

text
temperature,humidity,motorRpm
28.4,72,1280
28.7,71,1310

Cloud telemetry · Phase 2

Remote IoT Monitoring

AvailableHTTPS + MQTT

Remote IoT Monitoring lets an internet-connected device send numeric telemetry to Dexmod without remaining connected to the browser by USB. Open Device Fleet and create a standalone dashboard device. Linking an Arduino code project is optional. Dexmod displays the secret token only once and stores only a cryptographic hash.

The Canvas places every telemetry metric and direct control as an independent widget. Select the settings button on a widget to configure its canvas presentation. A telemetry widget includes its display name, unit, visualization, size, and visibility. A control widget adds tabs for its control definition and schedules. Control setup and Automation remain available for managing several controls at once, while Audit log retains command and rule activity. Edit mode supports drag and resize; Live mode prevents accidental rearrangement. Dexmod saves the layout per account and device.

  1. Create a standalone device from Device Fleet.
  2. Copy the one-time token into secure device configuration.
  3. POST a flat JSON object to /api/iot/ingest with the token as a Bearer credential.
  4. Keep the dashboard open to receive live updates through its authenticated stream.
  5. Customize labels, units, ranges, and widget types on the dashboard canvas.

To rename a telemetry widget without changing its device key, select the widget settings button. Enter a display name such as Room temperature and a unit such as °C. Dexmod saves these display settings per account and device; telemetry, CSV fields, and automation rules continue using the original key such as temperature.

http
POST /api/iot/ingest HTTP/1.1
Authorization: Bearer dxm_DEVICE_ID.SECRET
Content-Type: application/json
Idempotency-Key: boot-42-sample-1001

{"temperature":28.4,"humidity":72,"pump":true}

A sample may contain 1–32 metrics. Metric names must start with a letter and values must be finite numbers or booleans. Each request is limited to 8 KB.

Recommended: DexmodIoT for ESP32

In Arduino IDE, install the DexmodIoT library and open File → Examples → DexmodIoT → BasicTelemetry. In Dexmod Studio, select More → Examples → Basic telemetry to create a new ESP32 project with credential placeholders. The default is 40 seconds, suitable for Free. The bundled version 0.3.1 manages the public CA, Wi-Fi reconnects, clock synchronization, MQTT over TLS, device topics, message IDs, typed telemetry, command acknowledgements, and the plan's minimum publishing interval. Its telemetry/control API remains compatible with 0.2.3; existing projects are not automatically upgraded. Keep Wi-Fi and device credentials in arduino_secrets.h.

cpp
#include <DexmodIoT.h>

#include "arduino_secrets.h"

DexmodIoT dexmod;
uint32_t lastSampleAt = 0;

void setup() {
  Serial.begin(115200);
  dexmod.begin(
    WIFI_SSID,
    WIFI_PASSWORD,
    DEXMOD_DEVICE_ID,
    DEXMOD_DEVICE_TOKEN,
    40 // Match the interval shown in Remote Monitor
  );
  dexmod.waitUntilReady(30000);
}

void loop() {
  dexmod.loop(); // Required for reconnects and remote commands

  if (millis() - lastSampleAt < 40000) return;
  lastSampleAt = millis();

  DexmodTelemetry sample;
  sample.add("temperature", 29.1);
  sample.add("pump", true);
  dexmod.publish(sample);
}

Manual HTTPS integration

Use this lower-level example when you intentionally do not use DexmodIoT. Replace the Wi-Fi values, endpoint, and one-time device token before uploading.

cpp
#include <WiFi.h>
#include <HTTPClient.h>

const char* WIFI_NAME = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

// Use your laptop's LAN IP, not localhost.
const char* DEXMOD_URL =
  "http://192.168.1.10:3000/api/iot/ingest";

const char* DEVICE_TOKEN =
  "dxm_DEVICE_ID.SECRET";

void setup() {
  Serial.begin(115200);
  WiFi.begin(WIFI_NAME, WIFI_PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("Wi-Fi connected");
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    WiFiClient client;
    HTTPClient http;

    http.begin(client, DEXMOD_URL);
    http.addHeader("Content-Type", "application/json");
    http.addHeader(
      "Authorization",
      String("Bearer ") + DEVICE_TOKEN
    );

    float temperature = 28.4;
    int humidity = 72;
    bool pump = true;

    String payload =
      "{\"temperature\":" + String(temperature, 1) +
      ",\"humidity\":" + String(humidity) +
      ",\"pump\":" + String(pump ? "true" : "false") +
      "}";

    int statusCode = http.POST(payload);
    Serial.print("Dexmod response: ");
    Serial.println(statusCode);
    Serial.println(http.getString());
    http.end();
  }

  delay(40000); // Free plan: minimum 40 seconds
}

Production HTTPS

For manual HTTPS clients, use https://dexmodapp.com/api/iot/ingest with WiFiClientSecure. Validate the server certificate with the certificate authority used by the deployed domain.

cpp
#include <WiFiClientSecure.h>

const char* DEXMOD_URL =
  "https://dexmodapp.com/api/iot/ingest";

WiFiClientSecure secureClient;
HTTPClient http;

// ROOT_CA must contain the trusted CA certificate.
secureClient.setCACert(ROOT_CA);
http.begin(secureClient, DEXMOD_URL);

Mosquitto MQTT over TLS

MQTT devices publish to the project-independent topic below. Replace DEVICE_ID with the ID shown in Remote Monitor. The token inside the message must belong to the same device ID.

text
Topic:
dexmod/devices/DEVICE_ID/telemetry

Payload:
{"token":"dxm_DEVICE_ID.SECRET","messageId":"boot-42-sample-1001","metrics":{"temperature":28.4,"humidity":72,"pump":true}}

Use a new stable messageId for each logical sample. If QoS 1 delivers the same ID and payload again, Dexmod acknowledges it without storing another row. Reusing an ID with different metrics is rejected.

Connect to mqtt.dexmodapp.com with MQTT over TLS on port 8883. Use the device ID as both Client ID and username, and use the one-time device token as the MQTT password. The same token remains in the payload so Dexmod can authorize and audit the telemetry.

Test with MQTTX

  1. Create or rotate a device and keep its one-time token available.
  2. Create an MQTTX connection to mqtt.dexmodapp.com.
  3. Select mqtts://, port 8883, and keep certificate validation enabled.
  4. Set Client ID and username to the device ID, then set password to the full one-time device token.
  5. Publish with QoS 1 and Retain disabled to the device topic shown above.
text
Protocol: mqtts://
Host: mqtt.dexmodapp.com
Port: 8883
Client ID: DEVICE_ID
Username: DEVICE_ID
Password: ONE_TIME_DEVICE_TOKEN
Topic: dexmod/devices/DEVICE_ID/telemetry
QoS: 1
Retain: off
cpp
WiFiClientSecure tlsClient;
PubSubClient mqtt(tlsClient);

tlsClient.setCACert(ROOT_CA);
mqtt.setServer("mqtt.dexmodapp.com", 8883);
mqtt.connect(DEVICE_ID, DEVICE_ID, DEVICE_TOKEN);

String topic = "dexmod/devices/" + String(DEVICE_ID) + "/telemetry";
String messageId = "boot-" + String(esp_random(), HEX);
String payload =
  "{\"token\":\"" + String(DEVICE_TOKEN) +
  "\",\"messageId\":\"" + messageId +
  "\",\"metrics\":{\"temperature\":28.4,\"humidity\":72}}";
mqtt.publish(topic.c_str(), payload.c_str());

Response codes

CodeMeaningWhat the device should do
202Sample acceptedWait for the plan interval, then send the next sample.
401Token invalid, rotated, or revokedStop retrying and install a new device token.
422Telemetry format invalidCheck metric names and ensure values are numbers or booleans.
423Device paused by its ownerStop publishing until the owner resumes the device.
429Messages sent too quicklyRead Retry-After or increase the loop delay.
5xxTemporary server problemRetry later with increasing delays; do not retry continuously.

History, fleet, and CSV

Device Fleet is the account-level home for every device, including standalone dashboards and devices optionally linked to code projects. Use it to create, search, filter, pause, resume, and open any dashboard. History controls select the available time window. Open the Telemetry settings gear between fullscreen and Export CSV for a fixed local-time date range, min/max/average from all stored records in that range, and a sampled trend comparison of up to four metrics. Comparison lines use separate normalized 0–100% scales, not comparable absolute units. Retention limits still apply; Export CSV downloads the filtered samples. Dashboard Pro, Dashboard Scale, Complete Pro, and Complete Team can also email a daily or weekly CSV automatically from Canvas settings.

Dashboard entitlementDevicesRetentionMinimum interval
Free17 days40 seconds
Starter / Complete Maker530 days15 seconds
Pro / Complete Pro1090 days5 seconds
Scale / Complete Team251 year1 second

Cloud control

Device controls and automation

Scenes

Open Scenes from the Device Fleet navigation. Create a named set of 2–8 different controls on one device, select their target values, then save. Up to 20 scenes can be stored per device. Momentary buttons and confirmation-required controls are excluded.

Run scene requires confirmation and recent telemetry from an active device. Commands use the existing validation, expiry, audit log, and rate limits. They are submitted sequentially, not atomically. A submission failure stops later actions but does not undo earlier actions. Each action displays its own status; delivered is not acknowledged and does not prove a physical output changed. If the response is uncertain, retry the same scene without reloading the page to retrieve its existing run rather than resending. Recent runs are retained when a scene is deleted and are included in audit CSV export.

AvailableMQTT acknowledgement

Remote Monitor can send typed commands to an online ESP32 and separately display the requested state and the state acknowledged by the device. Commands use MQTT over TLS, expire quickly, are deduplicated, and remain in an audit history. AI credits are not required for device controls. Audit protection is enabled by default. Open Audit log to download the complete CSV or disable protection when permanent deletion is required.

1. Prepare the sketch

Arduino IDE: open File → Examples → DexmodIoT → SafeLedControl. Dexmod Studio: select More → Examples → Safe LED control. This creates a new ESP32 project and preserves your current sketch. Fill in arduino_secrets.h before uploading. Register a short command callback before dexmod.begin(), validate the control name and value type, apply the output, then acknowledge the state actually applied.

cpp
void handleCommand(DexmodIoT& client,
                   const DexmodCommand& command) {
  if (strcmp(command.control(), "lamp") != 0 ||
      command.valueType() != DexmodCommandValueType::Boolean) {
    client.fail(command, "UNSUPPORTED_COMMAND", "Expected lamp boolean");
    return;
  }

  bool enabled = command.booleanValue();
  digitalWrite(LED_BUILTIN, enabled ? HIGH : LOW);
  client.acknowledge(command, enabled);
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  dexmod.onCommand(handleCommand);
  dexmod.begin(WIFI_SSID, WIFI_PASSWORD,
               DEXMOD_DEVICE_ID, DEXMOD_DEVICE_TOKEN, 60);
}

2. Create a control

Select Add control in Remote Monitor. The control name must exactly match command.control() in the sketch. Switch and button controls use booleans; number and slider controls use bounded numeric values; select controls use one of the configured string options.

WidgetValue sentUse it forRequired settings
SwitchBooleanPersistent on/off state such as a lamp or pump.Name and label.
Momentary buttontrueOne action such as reset, pulse, or dispense.Name and label. The device decides how long the action lasts.
Numeric targetNumberAn exact setpoint such as 24 °C or 1200 RPM.Minimum, maximum, step, and optional unit.
SliderNumberFast adjustment within a range such as brightness or motor speed.Minimum, maximum, step, and optional unit.
Mode selectorStringA fixed choice such as auto, manual, or off.Two or more comma-separated options.

After saving, use the widget in Canvas. Its settings button opens the widget presentation, control definition, and schedules together. Control setup remains available for bulk management. The ESP32 receives the selected value through DexmodCommand. Validate command.valueType(), apply the value, then call the matching acknowledge() overload for a boolean, number, or string.

  • Requested is the latest value Dexmod attempted to send.
  • Device reported is authoritative only after the ESP32 acknowledges or reports telemetry.
  • Pending means delivery or acknowledgement has not completed yet.
  • Expired means the device did not confirm the command before its deadline.

Update the reported state with telemetry

Acknowledgement confirms one command. Telemetry keeps the dashboard synchronized after a physical button, sensor, reboot, or reconnect changes the device independently. Publish a telemetry field whose key exactly matches the control Name and whose value matches the widget type.

cpp
DexmodTelemetry state;
state.add("lamp", lampEnabled);        // Switch: boolean
state.add("targetTemp", targetTemp);   // Number or slider: number
dexmod.publish(state);

Include current boolean and numeric control states in each periodic telemetry heartbeat. Dexmod reads the latest accepted sample, converts numeric 0/1 to booleans when needed, validates configured ranges, and labels a newer matching value as Device reported · telemetry. A mismatched key or value type does not update the reported state. Telemetry accepts numbers and booleans; update a mode selector by acknowledging its string command with acknowledge(command, currentMode).

3. Schedules

Use Schedule for a one-time command, a daily local time, or selected weekdays. Recurring schedules use the selected IANA time zone. A failed, paused, offline, archived, or unsafe target stops safely instead of retrying an old command indefinitely. Cancel a pending or recurring schedule from Scheduled commands.

4. Telemetry rules

After the device has sent a numeric metric, select Add rule. A rule supports >, ≥, <, or ≤, one trigger action, and an optional reset action.

text
Example:
temperature > 40  → lamp On
temperature <= 35 → lamp Off
cooldown: 5 minutes

Reset threshold creates hysteresis so a noisy value around 40 does not rapidly toggle the output. Cooldown is the minimum interval before another trigger is allowed; it does not automatically turn the output off. Rules run only on accepted, non-duplicate telemetry and cannot target controls marked safety-sensitive.

5. Rule alerts

Remote Monitor shows a rule alert as active after its trigger action succeeds, then resolves it when the metric crosses the reset threshold and the rule re-arms. Open Audit log to review command history, triggers, resolutions, and failures.

Edit, disable, archive, and restore

Edit changes the thresholds, action, reset action, target, or cooldown. Disable preserves the rule without evaluating it. Archive removes it from the active list while retaining history. Open Archived rules and select Restore to bring it back. A restored rule always returns as Disabled; review it before selecting Enable. Restore is blocked while its target control remains archived or has become safety-sensitive.

Gateway telemetry

Node-RED and Home Assistant

Open Device Fleet, select a device, then choose Integrations. Download or copy the Node-RED JSON flow or Home Assistant YAML. Templates send external sensor telemetry to Dexmod over HTTPS; they do not read Dexmod history or operate Dexmod controls.

Node-RED reads DEXMOD_DEVICE_TOKEN from its runtime environment. Home Assistant reads a Bearer token from secrets.yaml. Exports contain no real token. Replace sample values or entity IDs, validate the configuration, then enable the integration yourself.

Node-RED documentation · Home Assistant REST command documentation

Opt-in · Owner only

Firmware OTA pilot

OTA is a restricted pilot, disabled by default. An administrator must enable the pilot for your Owner account. Viewer, Editor and Operator roles cannot create releases. Use DexmodIoT 0.3.1: search for DexmodIoT in Libraries and install the bundled version; older sketches continue using their configured library version. Install the updated receiver on the device as well as in the candidate project. Version 0.3.1 retries interrupted-update failure reports after reconnection; acknowledgement does not automatically release maintenance.

Start from Projects → New project → HTTPS OTA pilot (no actuators), or Studio → More → New project from example. One new project is created with its example files; no blank project is needed first, and existing projects are preserved. This example has no actuators. Upload the initial receiver by USB. Both the running and candidate sketch need DexmodOTA, a safe-state callback, and a real startup self-test. For relays, adapt the callback to turn every output safely off and stop local timers. Check C3-specific GPIO assignments.

Device ID and token

The combined DexmodIoT + OTA example requires both the Device ID and Device Token from the same registered device. Keep them, along with Wi-Fi credentials, in arduino_secrets.h. DexmodIoT uses both values for connectivity and telemetry; DexmodOTA uses only the token for its authenticated OTA requests. A token alone is not sufficient for the complete example.

cpp
dexmod.begin(WIFI_SSID, WIFI_PASSWORD,
             DEXMOD_DEVICE_ID, DEXMOD_DEVICE_TOKEN, 40);
ota.begin(DEXMOD_DEVICE_TOKEN, prepareSafeState);

Prepare a file or send an update?

Studio → More → Prepare OTA firmware compiles an application-only .ota.bin and a downloadable JSON manifest containing the target board, size and SHA-256 digest. It does not send firmware to a device or prove compatibility and rollback safety. Do not use the merged USB image for OTA.

For the managed Dexmod pilot, use Device Fleet → Firmware OTA → Compile and queue pilot instead. That flow compiles and queues the selected project directly; you do not need to prepare or download files manually first.

Open Device Fleet → Firmware OTA. Wait for fresh readiness, choose an owned candidate project, confirm safe outputs and USB recovery, then compile and queue. Firmware must fit both installed OTA slots and match the chip and slot layout. OTA uses application-only binaries, never the merged USB image. Firmware downloads are private and authorized only for the release; rotating the device token revokes further download and staging.

Never share binaries containing credentials. Test wrong chip/hash, interrupted download, failed boot and rollback before using OTA on operating equipment. Production-core compilation, browser interaction and physical recovery validation are required before general release.

Source control

Upload projects to GitHub

Available

Connect GitHub in Account settings, then use the GitHub button in the editor. Select an existing repository or create a public/private repository, choose a branch and optional folder, and upload the project source as one commit. Sensitive credential files such as secrets.h are excluded automatically; public trust anchors such as root_ca.h remain included.

Dexmod also includes a .dexmod/project.json metadata file containing the board and library configuration. GitHub access tokens remain on the server and are never returned to the editor.

Physical hardware

Device upload

Local preview

Upload compiles every saved source file and installed project library as one Arduino sketch. ESP32 targets receive a merged binary and can be flashed directly from desktop Chrome or Edge through Web Serial. Dexmod verifies the connected ESP chip before writing. Other board families currently receive a compiled firmware download instead of an unsupported browser-flashing claim.

Help

Troubleshooting

No serial port appears+

Use desktop Chrome or Edge, reconnect the USB cable, install the board driver if required, and close other software using the port.

ESP32 does not enter flash mode+

Close Serial Monitor, reconnect USB, then hold BOOT while starting the upload. Release BOOT when Dexmod reports that it connected to the chip.

Console shows unreadable characters+

Set Dexmod baud rate to exactly the same value passed to Serial.begin().

Console works but Dashboard is empty+

Print numeric data as JSON, key=value, or CSV, and end every sample with a newline.

A metric does not update+

Check that the metric value is numeric. Free-form strings remain visible only in Console.

DexmodIoT cannot find PubSubClient.h+

Install PubSubClient 2.8 or newer. Dexmod installs declared dependencies for project ZIP libraries; Arduino IDE users may need to install PubSubClient from Library Manager.

ESP32 telemetry works but controls do not+

In Arduino IDE, open File → Examples → DexmodIoT → SafeLedControl. In Dexmod Studio, open More → Examples → Safe LED control. Register dexmod.onCommand() before begin(), call dexmod.loop() continuously, and make the control name exactly match the sketch.

Device reconnects but the output state is wrong+

Publish the actual output state as telemetry after reconnecting and acknowledge every applied command. Use a fail-safe default while disconnected.

ESP32-C3 LED is inverted or does not light+

Confirm the board LED pin and polarity. Many Super Mini boards use GPIO 8 with active-low logic; set DEXMOD_LED_ACTIVE_LOW accordingly.

GitHub requests repository permission+

Open Account settings and reconnect GitHub to grant the repository scope used for commits.

An AI response is incomplete+

Reduce the requested scope, provide the active board and libraries, and split large changes into smaller prompts.

Ready to build?

Create a project, choose your board, and start with a small verified circuit.