MeshCore fork

MeshCore Car Node

This is a mobile MeshCore repeater for a vehicle. It reports where it stops. When the vehicle stops for a few minutes, the node sends its GPS location to Meshtastic and MeshCore together. The node then shows on both maps, at the location where you stopped.

Boards: Heltec V4 · Heltec T114 · Seeed T1000-E Firmware v1.17.1+carnode Build 75b523f8 · 16 Aug 2026

# What it is

This is a fork of the meshtastic_beacon project. It uses the same Meshtastic interop code, with no changes. It replaces the fixed-interval beacon with a park-triggered beacon. The beacon updates the two networks together.

mtbeaconcar node
Location sourcea location that you set (fixed)the live GPS location when the vehicle stops
Triggera fixed interval (minutes)the vehicle stops (more than park seconds); a small presence also goes out each interval minutes
Networks updatedMeshtastic onlyMeshtastic and MeshCore together
While drivingit sends a beacon at intervalsit sends a presence only (NodeInfo, no location) each interval
CLI commandmtbeacon …carnode …
Configuration file/mtbeacon/carnode

🅿️ Park-triggered

The node sends a location update when the GPS location does not move for park seconds (default 5 minutes). A small presence keeps the node visible between updates.

🔗 Both maps together

The same GPS location updates the Meshtastic beacon and sends a new MeshCore advert. This occurs in one event.

🛰️ One-way presence

The node shows as a named node and a map point. It can also send text. The node does not route or repeat traffic.

😴 Hold to hibernate

Hold the user button near 3 seconds to put the node into its lowest-power state. Push the button to wake the node.

🏠 Quiet zones

carnode zone add <name> stores a place where you stop frequently (up to 4). When you stop in a zone, the node sets repeat to off and stops all transmissions. That location does not go on the air.

🚫 Channel block list

block #dispatches stops the repeater from repeating a #hashtag channel. Use the name only; you do not need a key. The firmware calculates the channel hash from the name.

🛡️ Self-recovery

nRF52 boards start a hardware watchdog. If the node stops, it starts again; it does not continue dead. get pwrmgt.bootreason shows the cause of the last reset.

✅ Confirmed transmits

If the radio does not report the TxDone interrupt, the node reads the chip status flag. The node then knows if the update transmitted, and sends the failed updates again. After several dead transmits, the node starts the radio again. mtbeacon stats shows the totals.

🔋 Battery on the map

Each transmission includes Meshtastic telemetry. A vehicle that stops for days shows its battery decrease in a Meshtastic client.

# The park model

The node monitors its GPS location. When the location moves more than radius metres, the node is driving and sends no location. When the location stays in radius for park seconds (default 5 minutes), the vehicle is parked. The node then sends one update:

  1. The node sends a Meshtastic beacon (NodeInfo, Position, and text).
  2. The node sends a MeshCore update. It writes the location to its NodePrefs and sends a new advert, so all MeshCore nodes know where you stopped.
The two updates use the same location from one park event. The Meshtastic beacon goes first. The MeshCore advert goes near 10 seconds later, so they do not collide. If you stop in the same place again, the node does not transmit again (radius removes duplicates). mtbeacon send sends an update immediately. The node keeps the MeshCore location in flash, so it stays after a restart while parked.
Stable location: the park logic and the transmitted location use the median of the last 9 locations (near 27 seconds). Thus one bad location that moves hundreds of metres (a GPS in the trunk, or reflections) is ignored. Movement must then continue more than radius for near 15 seconds before the node is driving. carnode status shows the live data (d<n>m = the distance of the filtered location from the park point; (raw) while the filter starts; <n>min = the time the vehicle has been stopped). If the node changes to driving while the vehicle is stopped, increase carnode radius.
Periodic presence: between park events, the node sends a small presence each interval minutes (default 30; 0 = park only). This keeps the node in the Meshtastic node lists. When the vehicle is parked, the presence includes Position and refreshes the point. When the vehicle is driving, or there is no location, the node sends NodeInfo only. Thus the map point does not move to a location in the middle of a drive. The location updates only when the vehicle parks.
Chat text: the mtbeacon text message is event-driven. When the repeater sends a MeshCore advert (the park advert, the periodic advert, or the CLI advert command), the text goes out on a Meshtastic burst a few seconds later. Each park at a new location sends its text. The advert command is also a good test. mtbeacon status shows the schedule, for example txt1x~47h(due 13h), or (due now) when a text is ready. At home, the node transmits nothing. A ready text waits until you drive away.
Repeat sleep: after the vehicle is stopped for sleep hours (default 20), the node stops repeating. Remote status shows it as disabled, and it is not in node-discover. A vehicle that is parked for a day is usually in a place where no person needs a mobile repeater. The node still receives, answers its own commands, sends adverts, and beacons. It repeats again when it detects movement. A GPS loss while parked (an underground garage) does not wake it; only movement wakes it. carnode sleep 0 stops this function.
Suppression does not change your settings. The sleep and quiet-zone functions operate over the set repeat on|off setting; they do not write to it. Thus get repeat always shows your selection, and no sleep state writes to flash. The node always starts awake after a restart. carnode status shows rpt:off while suppression is active. This is the one place where the two can be different.

Builds before 4769627a wrote the setting directly. MeshCore keeps all settings as one block. Thus a change to any setting while parked in a quiet zone saved the suppressed value. The wake function then read it as your selection and did not start repeating again. If a node is quiet, use set repeat on one time while parked outside all zones. This corrects it.
Quiet zones: park where the vehicle usually stays and use carnode zone add home. The node stores the current location with that name (kept in flash). After this, when you park in the zone radius (default 100 m), the node sets repeat to off immediately. It does not wait for the sleep timer. It keeps the node radio-quiet: the park burst, the MeshCore advert, and the periodic presence are all off. That location does not go on the air (carnode send still transmits if you ask). When you drive away, the node starts all functions again. You can set up to 4 zones — home, work, a frequent location — each with its own radius. carnode zone lists them and shows the zone you are in. carnode home is a short form for the zone with the name home. A home from an older build moves across automatically.
Hop limit: Meshtastic packets go out at hops 0. Direct neighbours receive them; other nodes do not repeat them. A car node transmits from where it parks, so it is not good manners to send its location across another person's mesh. mtbeacon hops <0-3> increases the limit if you need more range.
If the mesh is busy: the two parts of a park are independent after they start. If the repeater cannot queue the MeshCore advert (the packet pool or the send queue is full while it forwards a burst), the node tries the advert again with a delay. It does not lose the park. It does not change the periodic advert timer, so the next advert still includes the location. carnode status shows adv!N if the node stopped a park advert fully. Usually it is not shown.

# Download the firmware

These are the firmware files for the three boards. The two Heltec boards need an external NMEA GPS module on the GPS UART pins. The T1000-E has a GPS on the board. The GPS is on by default.

Heltec V4 ESP32-S3 · SX1262

  • A new or erased board (or it restarts with invalid header: 0xffffff): install the -full file at 0x0. It includes the bootloader and the partition table.
  • To update a board that has this firmware: install the app .bin file at 0x10000.
  • Hibernate with the button only. The node stays asleep during LoRa traffic.

esptool.py write_flash 0x0 heltec_v4_carnode-75b523f8-full.bin  # new board

esptool.py write_flash 0x10000 heltec_v4_carnode-75b523f8.bin  # update

Heltec T114 nRF52840 · SX1262

  • Install the DFU .zip file with adafruit-nrfutil on the serial port. Or install the .hex file with a debugger.
  • System-off hibernate. The GPS is off.
  • The node sets its clock from the GPS, like the other boards (corrected in v0.2.8). Earlier T114 builds kept the map-point and telemetry times on the software clock until you set the time manually.

adafruit-nrfutil dfu serial -pkg heltec_t114_carnode-dfu.zip -p /dev/ttyACM0 -b 115200

Seeed T1000-E nRF52840 · LR1110 · dual-mode

  • Dual-mode: press the button 5 times to change between the car node (repeater mode) and a companion node with a phone. 2 beeps = repeater. 1 beep = companion.
  • The GPS is on the board. No external hardware is necessary. The node starts in companion mode. Press the button 5 times to start the car node.
  • To install: hold the button, then connect the magnetic cable two times, quickly. The T1000-E USB drive shows. Copy the .uf2 file to it. This keeps the standard bootloader.
  • System-off hibernate (hold near 3 seconds in repeater mode). The GPS is off.

bootloader mode → copy t1000e_dualmode_carnode-75b523f8.uf2 to the T1000-E drive

Checksums: SHA256SUMS.txt · Built from the carnode branch (commit 75b523f8). This is not an official MeshCore release. After you install it, the ver command shows v1.17.1+carnode-75b523f8. Check it to make sure that you have this build.

# Runtime control

Use the USB serial port or an admin remote-CLI session. There are two command groups, but one beacon engine (no second transmitter). mtbeacon sets the Meshtastic beacon. carnode sets the park behaviour.

🛰️ mtbeacon — the Meshtastic beacon (RF and appearance)

CommandFunction
mtbeacon / statusShow the beacon RF configuration.
stats / stats clearShow the transmit health from boot. / Set the counters to zero.
on / offSet the beacon to on. / Set the beacon to off.
sendSend a location update now (both networks).
interval <min>The presence interval between parks (0–1440; 0 = park only; default 30).
preset <name>The modem preset (LongFast, MediumFast, and others).
region <name>The region and band (US, EU_868, and others).
freq <MHz|auto>Set the frequency manually. auto calculates it again.
power <dBm>The TX power (−9 to 22). The region limit applies.
hops <0-3>The Meshtastic hop limit for the presence and text (default 0 = direct neighbours only).
text <string>The chat text (63 characters maximum).
text.mult <N>The text schedule. The text goes with each flood advert, and N−1 more times each period (0 = never).
short <str|auto>The Meshtastic short name / map label (4 characters maximum). auto = MC and 2 hex characters.
nodeinfo on/offInclude NodeInfo (the node name). Default on.
position on/offInclude Position (the map point). Default on.
telemetry on/offInclude Telemetry (battery and run time). Default on.
presets / regionsShow the available values.

🅿️ carnode — the park behaviour

CommandFunction
carnode / statusThe drive state (nofix/driving/parked/sleeping/zone) and the park configuration.
park <sec>The stopped time before an update (30–86400; default 300).
radius <m>Movement in this distance is "stopped" (5–2000; default 30).
advertdelay <sec>The time from the Meshtastic burst to the MeshCore advert (0–600; default 10).
sleep <hours>Parked this many hours → stop repeating until it drives again (0–720; 0 = never; default 20).
zoneShow the quiet zones (up to 4).
zone add <name>Make a quiet zone at the current location. Park in it → repeat off immediately, radio quiet.
zone del <name>Delete that zone.
zone radius <name> <m>The zone radius (5–2000; default 100).
home [clear|radius <m>]A short form for the zone with the name home.
Defaults: US LongFast · 5-minute park / 30 m radius · 30-minute presence · 22 dBm (region limit applies) · 20-hour repeat sleep · off until mtbeacon on. The OLED home screen shows CarNode driving / parked / sleeping / <zone name>.

🚫 block — channels this repeater does not repeat

CommandFunction
block / block listShow the blocked channels and their hash byte.
block #dispatchesStop the repeat of that #hashtag channel (up to 8).
unblock #dispatchesStart the repeat of it again.
This is a standard repeater function. It is in every build; it is not only for the car node. MeshCore #hashtag channels calculate their key from the name (SHA-256("#name")[:16]). Thus the firmware calculates the channel hash, and you type the name only — you do not paste a key. Two limits come from the wire format. First, it operates for #-name channels only (the firmware cannot calculate the key of a private channel with a random key). Second, the channel id on the air is one byte, so a block sometimes also stops a different channel with the same byte (near 1 in 256; the hash in the list makes a collision easy to see). Adverts, DMs, and ACKs do not change.

# Hibernate — hold the user button (near 3 s)

Hold the user button on the board for near 3 seconds. The node then goes to its lowest-power state with board.powerOff().

On the V4, the user button is GPIO0 (the BOOT pin). Thus the firmware waits for you to release the button before it sleeps. To wake the node, a short push is best. If you hold GPIO0 down through the reset, the chip can go into serial-download mode and not start.

# Build from source

Use PlatformIO with the carnode branch of the MeshCore-mtbeacon fork. The car node is in examples/car_node/.

pio run -e heltec_v4_carnode          # Heltec V4     (ESP32-S3, SX1262)
pio run -e Heltec_t114_carnode        # Heltec T114   (nRF52840, SX1262)
pio run -e t1000e_dualmode_carnode    # Seeed T1000-E (nRF52840, LR1110, dual-mode)

The env extends the repeater of the board and adds the car-node code. (The T114 env also sets -D ENV_INCLUDE_GPS=1.)

[env:heltec_v4_carnode]
extends = env:heltec_v4_repeater
build_flags = ${env:heltec_v4_repeater.build_flags}
  -D WITH_CAR_NODE
  -D MT_HW_MODEL=110
  -I examples/meshtastic_beacon
  -I examples/car_node
lib_deps = ${env:heltec_v4_repeater.lib_deps}

The project README has all the details.

# Scope and etiquette

This is a one-way presence only. The node shows as a named node and a map point, and it sends text. It does not route or repeat traffic. A park sends a MeshCore advert to all nodes and adds airtime to a shared public Meshtastic channel. Thus keep park at a sensible value. Obey the limits of your region. Do not beacon onto channels that you do not operate. The Meshtastic side uses hops 0 by default, so other persons' nodes do not repeat what it sends.