MeshCore – LoRa Mesh Netwerk Dordrecht

Gestopt
Taal
Thema
LoRa Mesh-netwerk

MeshCore

Kleine radio's geven berichten aan elkaar door, zonder internet, simkaart of centrale server. Off-grid communicatie voor Dordrecht & de Drechtsteden.

Documentatieversie 4.2 · laatst bijgewerkt op 09-08-2026

MeshCore is een LoRamesh-netwerk waarmee kleine radios berichten naar elkaar doorgeven, zonder internet, zonder simkaart, zonder centrale server.Nodes vormen automatisch een netwerk en kunnen berichten via tussenliggende nodes (repeaters) over grote afstanden sturen. Denk aan off-grid communicatie, noodhulp, outdoor activiteiten of gewoon experimenteren met mesh radio. Vergeleken met systemen zoals Meshtastic kiest MeshCore voor slim pad-gebaseerd routeren in plaats van flooding, wat resulteert in minder zendtijd en efficiënter gebruik van de beschikbare bandbreedte.

MeshCore is een veelzijdig, multiplatform systeem dat veilige, tekstgebaseerde communicatie mogelijk maakt via LoRa-radiohardware. Het is ontworpen voor toepassingen zoals off-grid communicatie, noodhulp en rampenherstel, outdoor activiteiten, tactische beveiliging (inclusief wetshandhaving en particuliere beveiliging) en IoT-sensornetwerken.


Hoe werkt MeshCore?

MeshCore maakt gebruik van LoRa (Long Range) technologie, een draadloos protocol dat lage vermogens en langeafstandscommunicatie combineert. Het creëert een gedecentraliseerd mesh-netwerk waarin apparaten (nodes) berichten kunnen verzenden en doorsturen naar andere nodes zonder afhankelijk te zijn van internet of mobiele netwerken.

Wat werkt er offline, en wat niet?

Die onafhankelijkheid geldt voor het berichtenverkeer zelf. Versturen en ontvangen, paden leren, kanalen gebruiken, een repeater configureren: dat gebeurt allemaal over de radio, rechtstreeks tussen de apparaten onderling. Je companion-app praat via Bluetooth of USB met je node en heeft daarvoor geen dataverbinding nodig. Valt het internet weg door een storing of stroomuitval, of sta je ergens zonder enige dekking, dan blijft het mesh gewoon doen wat het doet. Dát is de kern van het systeem.

Internet komt pas in beeld bij de diensten eromheen, en die zijn stuk voor stuk optioneel:

De scheidslijn is dus: alles wat een bericht van A naar B brengt werkt offline; alles wat je er achteraf over laat zíen loopt via internet. Wie een node in gebruik neemt zonder internetverbinding mist alleen de kaartjes en de updates, niet de communicatie.

Routing Protocol

MeshCore gebruikt geen flooding voor normale point-to-point berichten. In plaats daarvan werkt het met een slim routeringssysteem dat routes leert. Nodes vinden de beste paden door het mesh-netwerk en slaan deze op voor directe verzending. Flooding wordt wel gebruikt voor specifieke gevallen zoals advertisements (nodeinfo, position updates) en berichten naar algemene kanalen die voor iedereen bedoeld zijn. Client apparaten (Companion Radio's) sturen pakketten niet door, om te voorkomen dat er ongewenste routes ontstaan. Het systeem kan worden ingesteld met een maximum aantal hops (intern tot 64 hops bij 1-byte pad-hashing, 32 hops bij de aanbevolen 2-byte modus) om het netwerk efficiënt te houden en overmatig verkeer tegen te gaan. In de praktijk liggen bruikbare limieten lager door timing en omgevingsruis.

Multi-Hop Packet Routing met Path Learning

MeshCore combineert twee technieken: flooding voor ontdekking en direct routing voor alle vervolgberichten. Dat maakt het fundamenteel efficiënter dan pure flooding-protocollen zoals oudere Meshtastic-versies, met name in grote netwerken met veel repeaters.

Stap 1. Flood routing: eerste contact

Wanneer je een bericht stuurt naar iemand van wie je nog geen route kent (een nieuw contact, of na een netwerkwijziging), verzendt je companion het als een flood. Elk pakket dat via flooding verstuurd wordt, bevat een pad-sectie die aanvankelijk leeg is. Elke repeater die het pakket ontvangt, voegt een hash van zijn eigen publieke sleutel toe aan dat pad en stuurt het door. Zo bouwt het pakket onderweg automatisch een lijst op van alle repeaters die het gepasseerd heeft, en verspreidt het bericht zich als een golf door het netwerk, maximaal 64 hops bij 1-byte hashing, 32 hops bij 2-byte.

Flooding is robuust: het werkt ook als je geen enkel idee hebt van de topologie. De keerzijde is dat elke repeater in de buurt het pakket opnieuw uitzendt, wat airtime kost en congestie kan veroorzaken. Flooding wordt daarom bewust beperkt tot ontdekking en broadcast-achtige berichten (kanaalberichten, advertenties), niet voor elk privébericht.

Stap 2: Delivery report en path learning

Zodra de bestemming het bericht ontvangt, stuurt hij automatisch een delivery report terug. Dat rapport bevat het volledige pad dat het originele bericht heeft afgelegd: de geordende lijst van repeater-hashes. Het delivery report maakt de terugreis ook via flooding, zodat het de afzender bereikt ongeacht de netwerktopologie.

Jouw companion slaat dit pad nu op bij dat contact. Vanaf dit moment is er een werkende route bekend, en bij het volgende bericht naar dezelfde persoon hoeft er niet meer geflood te worden.

Stap 3. Direct routing: alle vervolgberichten

Bij elk volgend bericht naar hetzelfde contact zet je companion het opgeslagen pad expliciet in het pakket. Elke repeater onderweg voert een simpele check uit:

Alleen de repeaters op de bekende route sturen het bericht door. Alle andere repeaters in de buurt negeren het pakket volledig. Het resultaat is een gericht bericht dat langs een vaste route reist zonder onnodige rebroadcasts, een fractie van de airtime van een flood.

Automatische fallback

Netwerken veranderen. Repeaters vallen uit, signaalcondities wijzigen. Als een direct bericht niet aankomt, probeert de app het langs het bekende pad opnieuw; na 3 mislukte pogingen wordt het pad losgelaten en gaat het bericht bij de laatste poging als flood de lucht in. Het oude, gebroken pad wordt vervangen zodra een nieuw delivery report arriveert. Dit gedrag staat standaard aan en is in de app-instellingen uit te schakelen. (Bron: MeshCore FAQ, "What happens when a path breaks?")

Praktijkvoorbeeld

Jij → Repeater A → Repeater B → Repeater C → Doel
  1. Eerste bericht: flood. Het pakket passeert A, B en C. Het pad [A, B, C] wordt onderweg opgebouwd.
  2. Delivery report: het doel stuurt bevestiging terug met pad [A, B, C]. Jouw companion slaat de route op.
  3. Tweede bericht: direct routing. Het pakket bevat expliciet pad [A → B → C]. Alleen A, B en C sturen door. Alle andere repeaters doen niets.

Belangrijke details

Traceroute: kijken welk pad een bericht neemt

Wil je weten hoe een bericht daadwerkelijk loopt, dan hoef je niet te gokken. MeshCore heeft daar een eigen pakkettype voor: PAYLOAD_TYPE_TRACE. Een trace reist naar de bestemming en verzamelt per hop de SNR, zodat je terugkrijgt welke repeaters gepasseerd zijn én hoe sterk elke schakel was.

Dat maakt het hét gereedschap om te achterhalen waaróm een verbinding slecht is. Een pad van vier hops waarvan één schakel op −18 dB hangt, vertelt je precies waar het misgaat, informatie die je uit "het bericht komt soms niet aan" nooit had gehaald. De functie is bereikbaar via de MeshCore-app en via analysetools als LetsMesh Analyzer en MC Radar.

Let op dat een trace zelf ook airtime kost en langs alle tussenliggende repeaters loopt: gebruik het om een probleem te onderzoeken, niet als periodieke monitoring. (Bron: packet format, PAYLOAD_TYPE_TRACE.)

Off-grid mode: clients die wél doorsturen

Op één plek gaat de regel "clients forwarden niet" bewust niet op. In off-grid mode (ook client repeat mode genoemd) kunnen companion-apparaten zélf pakketten doorsturen, zodat een groepje mensen een werkend mesh vormt zónder dat er ook maar één repeater in de buurt staat. Bedoeld voor Search & Rescue en gebruik in afgelegen gebieden, ver buiten het publieke netwerk.

Dat het niet standaard aan staat is geen toeval. Scott Powell noemt "clients do not forward packets" een van de kenmerken waarmee MeshCore zich onderscheidt én waarmee het schaalt: zou iedere telefoon in een stad meedoen aan het doorsturen, dan verzuipt het netwerk in dubbele pakketten, precies het probleem dat MeshCore met path learning vermijdt.

Off-grid draait daarom op gereserveerde frequenties, niet op 869.618 MHz. Je stelt het in als een apart region-type in de app (Manage RegionsNew… → type Off-grid), waarna je alleen uit die voorbehouden frequenties kunt kiezen. Op een T-Pager kies je de regio uit de lijst en daarna Set as Home. Die scheiding is de kern van het ontwerp: ze voorkomt dat iemand zijn radio in repeat-modus laat staan, terugkeert in de bebouwde kom en daar de routes van het publieke mesh in de war schopt.

Voor Nederlandse gebruikers: zet off-grid mode dus niet aan op de NL-preset. Het is geen manier om je dekking thuis te verbeteren, daarvoor zet je een repeater neer. Het is een aparte bedrijfsmodus voor situaties waarin er helemaal geen infrastructuur is.

Ten tijde van de aankondiging (13 februari 2026) was de frequentiereservering nog niet definitief: het project was naar eigen zeggen "in the process of getting consensus on reserving a range". Er is sindsdien geen vervolgbericht verschenen, en in de CLI-referentie komt off-grid niet als commando voor. Het is een app- en region-instelling, geen set-opdracht. Controleer de actuele stand daarom in de app en op de officiële blog voordat je ermee aan de slag gaat.

Veel van wat hierboven staat (het pad dat onderweg wordt opgebouwd, de scope-tag, de hoplimiet), is makkelijker te volgen als je weet hoe een pakket van binnen in elkaar zit. Dat staat veld voor veld uitgeschreven in een eigen hoofdstuk: Opbouw van een pakket.

De rol van regions in routing

Regions voegen een scope-filter toe bovenop de routeringslogica. Een repeater die een pakket ontvangt, voert twee onafhankelijke checks uit:

  1. Routeringscheck. Ben ik de volgende hop op het pad? (of: is dit een flood die ik mag doorsturen?)
  2. Scope-check: past de regio-tag van dit pakket bij mijn geconfigureerde regions?

Beide checks moeten slagen voordat een repeater doorstuurt. Dit heeft verschillende gevolgen afhankelijk van het berichttype:

Flood-berichten (kanaalberichten, broadcasts)

Floods die een scope-tag dragen (bijv. nl-zh) worden alleen doorgestuurd door repeaters die precies die scope in hun config hebben staan én flooding voor die region toestaan. Er is geen overerving: een bericht op scope nl-zh-dor wordt níet doorgestuurd door een repeater die alleen nl-zh kent. Die dropt het stil.

De reden zit in de manier waarop de scope wordt meegestuurd. Het pakket draagt geen regionaam maar een transport code: een HMAC over de payload met een sleutel die is afgeleid van de regionaam (SHA256("#nl-zh-dor")). De repeater berekent die code voor elk van zijn eigen regions en vergelijkt. #nl-zh en #nl-zh-dor leveren compleet verschillende hashes op, dus er valt niets te erven en er is ook geen "meest specifieke" match. Het is exact of niets. (Bron: RegionMap::findMatch() en TransportKeyStore::getAutoKeyFor() in RegionMap.cpp en TransportKeyStore.cpp.)

Vanaf 18 juli 2026 (Fase 8) geldt voor repeaters met region denyf *: floods zonder scope-tag worden stilzwijgend weggegooid. Een kanaalchat zonder ingestelde scope bereikt dan alleen nog repeaters die nog geen region denyf * hebben. Stel daarom in je app per kanaal een scope in, zodat je berichten de juiste repeaters bereiken.

Direct Messages (privéberichten)

Een DM die over een geleerd pad loopt, ondergaat helemaal geen scope-check: die geldt alleen voor floods. De geleerde route wordt dus gevolgd ongeacht de region-configuratie van de tussenliggende repeaters, ook na Fase 8. Dit is een bewuste ontwerpkeuze: point-to-point communicatie mag nooit geblokkeerd worden door regiofiltering.

Let op de uitzondering: kent je node nog géén pad naar de bestemming, dan gaat de eerste DM als flood de lucht in, en die krijgt wél de scope van je companion mee (de per-bericht scope, anders de default). Voor dat eerste pakket gelden dezelfde regels als voor kanaalberichten. Pas als het pad geleerd is, valt de scope-check weg. (Bron: sendFloodScoped() in companion_radio/MyMesh.cpp.)

Advertenties van repeaters

Een repeater tagt zijn eigen flood-advertenties met de scope uit region default (bijv. nl-zh). Andere repeaters sturen die advertentie alleen door als ze die scope kennen. Hoe breder de region default, hoe verder de advertentie reist, en hoe zichtbaarder de repeater is voor nodes die een route willen leren. Dit is precies waarom region default nl-zh beter is dan nl-zh-dor: naburige repeaters in Papendrecht of Sliedrecht kennen nl-zh, maar kennen nl-zh-dor niet per se.

Samenvatting

BerichttypeScope-filter actief?Region denyf effect
Kanaalberichten / broadcastsJa, scope bepaalt welke repeaters forwardenZonder scope: gedropt na Fase 8
Direct Messages (DM)Alleen zolang het pad nog onbekend is (flood)Geen effect op een DM over een bekend pad
Repeater advertentiesJa. region default bepaalt reikwijdteZonder scope: gedropt na Fase 8

Opbouw van een pakket

Alles wat MeshCore doet komt uiteindelijk neer op één ding: bytes de lucht in sturen in een vaste volgorde. Dit hoofdstuk loopt die volgorde veld voor veld af, eerst de vijf velden op een rij, dan elk veld apart, en tot slot een echt opgevangen pakket byte voor byte uitgelopen. Wie dat eenmaal ziet, snapt ook waarom paden aangroeien, waarom een scope niet erft en waarom een bericht op 160 tekens vastloopt.

Om te beginnen: een pakket bestaat uit twee lagen die niets met elkaar te maken hebben.

De radiochip bouwt zijn eigen frame: preamble, sync word, een PHY-header en een CRC voor foutdetectie. Die velden zet hij er bij het zenden zelf omheen en haalt hij er bij ontvangst weer af. De MeshCore-firmware ziet ze nooit en kan er ook niets mee.

Wat de firmware wél ziet, is dit:

Opbouw van een MeshCore-pakket in twee varianten. Mét transport codes (routetypes 0x00 en 0x03): header 1 byte, transport codes 4 bytes, path_length 1 byte, path 0 tot 64 bytes, payload 0 tot 184 bytes, totaal 6 + N + M bytes. Zonder transport codes (routetypes 0x01 en 0x02) vervallen die 4 bytes en is het totaal 2 + N + M bytes. De headerbyte bevat de protocolversie (2 bits), het payloadtype (4 bits) en het routetype (2 bits).

Kijk liever mee dan dat je het naleest? Op Raw Packet Breakdown zie je precies dit live gebeuren. Elk pakket dat de Dordtse repeater opvangt wordt daar meteen ontleed: de hex-bytes in kleur per veld, een uitklapbare tabel met offset, veldnaam en betekenis van elke byte, en onderaan de gedecodeerde uitkomst. Alles wat hieronder in tabelvorm staat kun je daar dus aanwijzen op een echt pakket, inclusief de opdeling ván de payload, die per type verschilt. De stroom loopt realtime door, dus laat hem even openstaan en je ziet vanzelf adverts, kanaalberichten, acks en traces voorbijkomen.

Het pakket in vogelvlucht

Vijf velden, waarvan er één optioneel is en twee een variabele lengte hebben:

[header][transport_codes (optioneel)][path_length][path][payload]
#VeldGrootteWat het doet
1header1 byteRoutetype, payloadtype en payloadversie in één byte
2transport_codes4 bytes, optioneelDe regio-scope; alleen aanwezig bij twee van de vier routetypes
3path_length1 byteAantal hops én de hashgrootte, samengepakt in één byte
4path0 – 64 bytesDe route: één hash per hop
5payload0 – 184 bytesDe inhoud, bij vrijwel elk type versleuteld

Een pakket is dus minimaal 2 bytes en maximaal 253. Belangrijk om te snappen: geen enkel veld draagt zijn eigen lengte mee. Je leest ze strikt op volgorde, en elk veld vertelt je waar het volgende begint, de headerbyte zegt of die vier transport-bytes er staan, path_length zegt hoe lang het pad is, en wat daarna nog overblijft ís de payload. Eén verkeerd gelezen bit en de rest van het pakket schuift mee.

De eerste vier velden staan in klare taal in de lucht. Dat is geen slordigheid maar noodzaak: een repeater moet kunnen zien of hij het pakket moet doorsturen zonder de inhoud te kunnen lezen. Alleen de payload is versleuteld.

Eén detail met praktische gevolgen: het duplicaat-filter (hasSeen()) werkt op een SHA-256 over het payloadtype en de payload, niet over het pad. Hetzelfde bericht dat via twee verschillende routes binnenkomt wordt daardoor betrouwbaar als duplicaat herkend, ongeacht welke repeaters het onderweg is tegengekomen.

Veld 1: de headerbyte

Die ene byte doet drie dingen tegelijk. Van rechts naar links gelezen (bit 0 is de rechtse bit):

0b V V P P P P R R
   │   │       └──┴── bits 0–1: routetype
   │   └──────────────bits 2–5: payloadtype
   └──────────────────bits 6–7: payloadversie

Die nummering is niet willekeurig: elk bit heet naar zijn gewicht in de byte. Bit 7 is het most significant bit (msb) en telt voor 128, zet je juist dát bit om, dan verandert de waarde van de byte het meest. Bit 0 is het least significant bit (lsb) en telt voor 1. Daartussen halveert het gewicht telkens: 128, 64, 32, 16, 8, 4, 2, 1. Schrijf je de byte binair op, dan staat bit 7 dus links en bit 0 rechts, net zoals je bij een gewoon getal de honderdtallen links zet en de eenheden rechts.

Praktisch betekent dat: "de onderste bits" zijn de rechter bits van de byte, en een veld van meerdere bits is altijd een aaneengesloten reeks. Het routetype zit op de twee rechtse posities, de payloadversie op de twee linkse, en het payloadtype op de vier daartussen.

Uitlezen gaat in twee stappen: eerst opschuiven tot het laagste bit van het veld op positie 0 staat, dan maskeren om alles daarboven weg te gooien. Voor het payloadtype is dat (header >> 2) & 0x0F. Twee posities opschuiven, vier bits overhouden. De firmware doet het precies zo, met PH_TYPE_SHIFT 2 en PH_TYPE_MASK 0x0F. Het routetype heeft geen shift nodig (header & PH_ROUTE_MASK, masker0x03) en de payloadversie schuift 6 posities op. (Bron: de PH_-macro's en getRouteType() / getPayloadType() / getPayloadVer() in Packet.h.)

Let op wat deze nummering wél en niet zegt: ze beschrijft de plaats van een bit in de waarde van de byte, niet de volgorde waarin de radio de bits de lucht in stuurt. Dat laatste regelt de LoRa-chip zelf, en daar heeft de MeshCore-firmware geen zicht op.

Bits 0–1: het routetype. Dit bepaalt hoe het pakket door het netwerk reist, en meteen ook of de vier bytes transport codes aanwezig zijn, bij de twee "transport"-varianten wel, bij de andere twee ontbreken ze volledig en is het pakket dus vier bytes korter:

WaardeNaam in de firmwareRoutetypeTransport codes
0x00ROUTE_TYPE_TRANSPORT_FLOODFlood mét scopeAanwezig
0x01ROUTE_TYPE_FLOODFlood zonder scopeAfwezig
0x02ROUTE_TYPE_DIRECTDirect, pad meegegevenAfwezig
0x03ROUTE_TYPE_TRANSPORT_DIRECTDirect mét scopeAanwezig

Bits 2–5: het payloadtype. Vier bits, dus zestien mogelijkheden. Dit is het veld dat bepaalt hoe de payload verderop gelezen moet worden. Wat elk type inhoudt en hoe de bijbehorende payload is opgebouwd staat bij de payload hieronder.

Bits 6–7: de payloadversie. Bepaalt de veldgroottes binnen de payload:

WaardeVersieBetekenis
0b00v11-byte node-hashes, 2-byte MAC. Dit is wat er vandaag in de lucht zit
0b01v22-byte hashes, 4-byte MAC, gedefinieerd, nog niet in gebruik
0b10v3gereserveerd
0b11v4gereserveerd

Een voorbeeld: 0x14 is binair 0b00010100. Bits 0–1 zijn 00 → TransportFlood, dus er volgen vier bytes transport codes. Bits 2–5 zijn 0101 → payloadtype 5, een GroupText (kanaalbericht). Bits 6–7 zijn 00 → payloadversie 1.

Veld 2: de transport codes (optioneel)

Vier bytes, en alleen aanwezig als het routetype 0x00 of 0x03 is. Het zijn twee 16-bits getallen, little-endian opgeslagen:

BytesVeldInhoud
0–1transport_code_1De regio-scope: een HMAC berekend over de payload met een sleutel afgeleid van de regionaam
2–3transport_code_2Gereserveerd voor de thuisregio van de afzender; staat vooralsnog altijd op nul

Let op dat hier géén regionaam in staat, alleen een code. Een repeater kan die code niet opzoeken maar moet hem voor elk van zijn eigen regions herberekenen en vergelijken. Hoe dat filter precies werkt (en waarom nl-zh en nl-zh-dor niets van elkaar erven), staat in Regions en Scope.

Veld 3: de path_length-byte

Deze byte heet wel "lengte", maar is geen byte-telling. Er zitten twee waarden in gepropt:

0b H H C C C C C C
   │   └──┴──┴──┴──┴──┴── bits 0–5: aantal hops (0 t/m 63)
   └──────────────────────bits 6–7: hashgrootte, opgeslagen als "grootte min één"

De hashgrootte zegt hoeveel bytes elke hop in het pad inneemt:

Bits 6–7HashgrootteOpmerking
0b001 byteLegacy, en nog steeds de standaardmodus
0b012 bytesDe aanbevolen instelling in Nederland
0b103 bytesOndersteund in de huidige firmware
0b11:Gereserveerd / ongeldig

De werkelijke padlengte in bytes is dus hop_count × hash_size. Een paar voorbeelden om het gevoel te krijgen:

ByteBinairBetekenisPadlengte
0x0000 000000nul hops, 1-byte hashes0 bytes
0x0500 0001015 hops, 1-byte hashes5 bytes
0x4501 0001015 hops, 2-byte hashes10 bytes
0x8A10 00101010 hops, 3-byte hashes30 bytes

Waarom niet gewoon een byte-telling? Omdat de ontvanger dan niet zou weten waar de ene hop ophoudt en de volgende begint. Tien bytes pad kunnen tien hops van 1 byte zijn of vijf hops van 2 bytes, en dat verschil bepaalt of jouw hash er wel of niet in staat. Waarom die grootte überhaupt instelbaar is en wat de afweging is tussen 1, 2 en 3 bytes, staat verderop in Multi-byte Path Hash.

Veld 4: het path

Een lijst hashes, één per hop, in de volgorde waarin het pakket ze is gepasseerd. Zo'n hash is simpelweg het begin van de public key van die node: de eerste byte bij 1-byte hashing, de eerste twee bij 2-byte hashing, enzovoort. Geen adressen dus, maar herkenningsfragmenten: kort genoeg om weinig airtime te kosten, lang genoeg om meestal uniek te zijn.

Wat er met dit veld gebeurt hangt af van het routetype:

Het veld is maximaal 64 bytes (MAX_PATH_SIZE) en daar volgen de hoplimieten uit: 64 repeaters bij 1-byte hashing, 32 bij 2-byte, 21 bij 3-byte. In de praktijk loop je ruim daarvóór al tegen timing en ruis aan.

Veld 5: de payload

De velden hiervóór zijn voor iedereen leesbaar. Dat moet ook, anders weet een repeater niet wat hij met het pakket aan moet. Met de payload is het precies andersom: die draagt geen enkele aanwijzing over zijn eigen inhoud. Geen lengteveld, geen typemarkering, geen scheidingsteken tussen de velden. Het payloadtype uit de headerbyte is de énige sleutel tot de indeling; kies je die verkeerd, dan lees je vanaf de eerste byte de verkeerde velden en merk je dat pas als de uitkomst nergens op slaat.

Een decoder doet dan ook niets ingewikkelders dan dit: payloadtype uit de header halen, het bijbehorende schema erop leggen, byte voor byte aflopen.

Waar de payload begint. De payload is altijd de rest van het pakket; er is geen veld dat dat aangeeft. Het startpunt reken je uit met de vier velden ervóór:

offset = 1 (header)
       + 4 als het routetype 0x00 of 0x03 is (transport codes)
       + 1 (path_length)
       + hop_count × hash_size   (het pad)

Omdat het pad bij een flood onderweg aangroeit, verschuift dat beginpunt bij elke hop mee, dezelfde payload staat bij jouw buurman op een andere offset dan bij jou.

Vier bouwstenen komen steeds terug. Bijna elk payloadtype is opgebouwd uit combinaties van deze vier:

BouwsteenGrootteWat het is
Node hash1 byteDe eerste byte van de public key van een node, als afzender (source hash) of bestemming (destination hash). Eén byte, dus botsingen komen voor: 256 mogelijke waarden voor het hele netwerk.
Channel hash1 byteDe eerste byte van SHA-256 van de gedeelde kanaalsleutel. Zegt alleen welke sleutel je moet proberen, niet welk kanaal het is.
Cipher MAC2 bytesDe eerste 2 bytes van een HMAC-SHA256 over de ciphertext. Fungeert tegelijk als integriteitscheck én als "is dit voor mij?"-test: klopt de MAC met jouw sleutel, dan is de rest voor jou.
Ciphertextveelvoud van 16AES-128, blok voor blok, met nullen aangevuld tot een heel blok.

Let op dat de groottes in deze tabel gelden voor payloadversie 1, de versie uit bits 6–7 van de headerbyte, niet de hashgrootte uit path_length. Die twee hebben niets met elkaar te maken: een pakket met 2-byte pad-hashes heeft nog steeds 1-byte hashes ín de payload.

Dat de ciphertext altijd een veelvoud van 16 bytes is, is verrassend nuttig. Het betekent namelijk dat de lengte van de payload het type-schema erachter verraadt, je hebt de sleutel niet nodig om te zien tot welke familie een pakket hoort:

PayloadlengteVaste veldenWaarschijnlijk type
precies 4 bytes:Ack (0x03)
rest 3 bij deling door 161 + 2GroupText (0x05) of GroupData (0x06)
rest 4 bij deling door 161 + 1 + 2Request, Response, TextMessage of Path (0x00, 0x01, 0x02, 0x08)
rest 3, maar ≥ 35 bytes1 + 32 + 2AnonRequest (0x07), de 32-byte public key valt op
≥ 100 bytes, begint met 32 bytes sleutel32 + 4 + 64Advert (0x04)

De headerbyte vertelt het je gewoon, maar bij een half opgevangen of beschadigd pakket is dit een bruikbare tweede mening.

Het schema per type. De eerste veldnamen zijn genoeg om te herkennen wat je voor je hebt:

TypePayload-opbouwVersleuteld?
0x00 Requestdest hash (1) + src hash (1) + MAC (2) + ciphertextJa
0x01 Responsedest hash (1) + src hash (1) + MAC (2) + ciphertextJa
0x02 TextMessagedest hash (1) + src hash (1) + MAC (2) + ciphertextJa
0x03 Ackchecksum (4)Nee
0x04 Advertpublic key (32) + timestamp (4) + signature (64) + appdataNee, wél ondertekend
0x05 GroupTextchannel hash (1) + MAC (2) + ciphertextJa
0x06 GroupDatachannel hash (1) + MAC (2) + ciphertextJa
0x07 AnonRequestdest hash (1) + public key (32) + MAC (2) + ciphertextJa
0x08 Pathdest hash (1) + src hash (1) + MAC (2) + ciphertextJa
0x09 Tracetag (4) + auth code (4) + flags (1) + pad-hashesNee
0x0A Multipartflags/type (1) + ingepakte payloadVolgt het ingepakte type
0x0B Controlflags (1) + dataNee
0x0C0x0Egereserveerd:
0x0F RawCustomvrij formaat, eigen encryptieNaar keuze

Advert (0x04). Het enige type dat zichzelf bewijst. Een advertentie is volledig leesbaar: 32 bytes Ed25519 public key, een 4-byte unix-timestamp, en een 64-byte handtekening over die twee plus de appdata. Daarna volgt de appdata, die begint met een flagsbyte die vertelt welke velden erin staan: 0x10 betekent dat er 4 bytes breedtegraad en 4 bytes lengtegraad volgen (decimale graden × 1.000.000), 0x80 dat de rest van de payload de nodenaam is. De onderste bits zeggen wát voor node het is, 0x01 chat node, 0x02 repeater, 0x03room server, 0x04 sensor. Dat verklaart meteen waarom een advert het dikste pakket in de lucht is: 100 bytes staan al vast voordat naam en locatie erbij komen. De handtekening maakt hem als enige payloadtype controleerbaar: iedereen kan nalezen dat die naam en die coördinaten echt bij die sleutel horen.

GroupText (0x05). Het kanaalbericht. Eén byte channel hash, twee bytes MAC, en de rest versleuteld. Die ene byte identificeert het kanaal níet: er zijn 256 mogelijke waarden voor honderden kanalen, dus tientallen kanalen delen dezelfde hash. Welk kanaal het écht was blijkt pas uit de cipher MAC. Die klopt alleen met de juiste sleutel. Wie de sleutel heeft weet het dus zeker, wie hem niet heeft komt niet verder dan een lijstje kandidaten. Ontsleuteld ziet die rest er zo uit: 4 bytes timestamp, 1 byte type-en-pogingnummer, en dan de tekst, in de vorm naam: bericht. De afzendernaam zit dus gewoon ín de versleutelde tekst en is niet ondertekend: iedereen die de kanaalsleutel heeft kan elke willekeurige naam invullen. Voor een openbaar kanaal is dat prima, als identiteitsbewijs is het waardeloos. De firmware laat hier maximaal 165 bytes klaartekst toe (MAX_GROUP_DATA_LENGTH), inclusief die naam en de dubbele punt.

GroupData (0x06) heeft dezelfde buitenkant, maar binnenin geen tekst: 2 bytes datatype, 1 byte lengte, en dan de data. Zo reizen bijvoorbeeld telemetrie en sensorwaarden over een kanaal.

TextMessage (0x02). Het privébericht. Dest hash, src hash, MAC, ciphertext. De klaartekst begint weer met 4 bytes timestamp en één byte waarin de bovenste zes bits het teksttype zijn en de onderste twee het pogingnummer (0–3, want een herhaalde poging moet een ander pakket opleveren dan het origineel). Het teksttype bepaalt hoe je de rest leest:

WaardeBetekenisInhoud
0x00gewoon tekstberichtde tekst zelf
0x01CLI-commandode commandotekst. Zo praat je met een repeater
0x02ondertekend berichteerst 4 bytes sleutelprefix van de afzender, dan de tekst

Een DM is maximaal 160 bytes tekst (MAX_TEXT_LEN, tien AES-blokken). Request (0x00) en Response (0x01) delen dit omhulsel maar dragen applicatiedata: een 0x01 in de request betekent "geef je statistieken", een 0x02 is een keep-alive.

Ack (0x03). Vier bytes, verder niets. Geen hashes, geen encryptie: alleen een 4-byte CRC over de timestamp, de tekst en de public key van de afzender van het bevestigde bericht. Wie de oorspronkelijke tekst niet heeft, kan dus niet zien waar een ack bij hoort, en dat is precies de bedoeling. Alleen de afzender herkent zijn eigen checksum.

AnonRequest (0x07): de eerste keer aankloppen. Hier zit de volledige 32-byte public key van de afzender in het pakket, want de ontvanger kent hem nog niet en heeft hem nodig om het gedeelde geheim uit te rekenen. Zo logt een client in op een room server (timestamp + sync-timestamp + wachtwoord) of op een repeater (timestamp + wachtwoord).

Path (0x08). Het routeantwoord. Zelfde omhulsel als een DM, maar de klaartekst bevat een padlengte, dat pad aan node-hashes, en daarachter een ingepakt tweede pakket: een typebyte plus een complete payload van dat type. Meestal is dat een ack, die zo meelift op het routeantwoord in plaats van als apart pakket de lucht in te gaan.

Trace (0x09). De meetlat. Een 4-byte tag (waarmee de afzender het antwoord herkent), een 4-byte auth code, een flagsbyte, en dan de node-hashes van het pad dat de trace moet aflopen. Let op de flagsbyte: de onderste 2 bits geven de hashgrootte, maar hier als machtsverheffing, waarde 0 betekent 1 byte, 1 betekent 2 bytes, 2 betekent 4 bytes. Dat is een andere codering dan in path_length, waar dezelfde bits "grootte min één" betekenen. De SNR-metingen komen niet in de payload terecht maar in het path-veld, zoals hierboven beschreven.

Multipart (0x0A) en Control (0x0B). Een multipart-pakket begint met één byte waarvan de bovenste 4 bits zeggen hoeveel pakketten er nog volgen en de onderste 4 bits het payloadtype van wat erin verpakt zit; daarachter staat die payload gewoon in zijn normale vorm. In de huidige firmware wordt dat alleen voor gebundelde acks gebruikt. Control is onversleuteld: één flagsbyte waarvan de bovenste 4 bits het subtype zijn, 0x8 is een discovery-verzoek, 0x9 het antwoord daarop met SNR en node-ID.

Wat je zonder sleutels dus wél ziet. Van elk pakket dat je opvangt kun je zonder enige sleutel bepalen: het type, de route, hoeveel hops het heeft gemaakt en langs welke hash-fragmenten, de lengte van de inhoud (afgerond op 16 bytes), en bij adverts de complete identiteit inclusief locatie. Wat je níet ziet is de inhoud van welk versleuteld bericht dan ook, en bij een kanaalbericht ook niet wélk kanaal het is: de channel hash is één byte, dus zonder de bijbehorende sleutel houd je alleen kandidaten over. Het is een ontwerp dat metadata prijsgeeft en inhoud beschermt; wie meekijkt weet dus dat er verkeer is en hoeveel, maar niet waarover.

Een pakket uit de lucht, byte voor byte

Alle vijf velden achter elkaar, op een echt kanaalbericht van 67 bytes zoals het binnenkwam op de Dordtse repeater:

14 46A20000 45 DA2F 5FF7 1876 EE03 CB94 8B CC79 3CA788...

Van links naar rechts:

BytesWaardeVeldWat het betekent
00x14 = 0b00010100headerbits 0–1 = 00 → TransportFlood (dus transport codes aanwezig); bits 2–5 = 0101 → GroupText; bits 6–7 = 00 → payloadversie 1
1–446 A2 / 00 00transport codescode 1 = 0xA246 (de regio-scope, little-endian gelezen); code 2 = 0, gereserveerd
50x45 = 0b01000101path_lengthbits 6–7 = 01 → 2 bytes per hop; bits 0–5 = 000101 → 5 hops, dus 10 bytes pad
6–15DA2F 5FF7 1876 EE03 CB94pathde vijf repeaters die het bericht hebben doorgegeven, in volgorde
160x8Bpayloadchannel hash, eerste byte van SHA-256 van de kanaalsleutel
17–18CC 79payloadcipher MAC over de ciphertext
19–663C A7 88 …payload48 bytes ciphertext = precies 3 AES-blokken

Die laatste regel is de controle op je eigen rekenwerk: 48 is deelbaar door 16, dus de opdeling klopt. En de payloadlengte van 51 bytes geeft rest 3 bij deling door 16, precies wat de tabel hierboven voorspelt voor een GroupText. Ontsleuteld levert dat blok een 4-byte timestamp op, een flagsbyte 0x00 (gewoon tekstbericht), en daarachter naam: bericht.

Dit voorbeeld hoef je niet op mijn woord te geloven: op Raw Packet Breakdown rolt dezelfde ontleding er live uit voor elk pakket dat langskomt, zelfde kleuren, zelfde offsettabel, alleen dan met de bytes van dít moment.

(Bronnen voor dit hoofdstuk: packet_format.md en payloads.md uit de MeshCore-repository; Packet::writeTo() / readFrom() in Packet.cpp; Utils::encryptThenMAC() in Utils.cpp voor AES-128 + 2-byte HMAC; createGroupDatagram(), createTrace() en de multipart-afhandeling in Mesh.cpp; MAX_PATH_SIZE, MAX_PACKET_PAYLOAD en MAX_GROUP_DATA_LENGTH in MeshCore.h; MAX_TEXT_LEN in BaseChatMesh.h.)

Regions en Scope

Vanaf MeshCore versie 1.10.0 is er een systeem van regions en scope beschikbaar, waarmee je kunt bepalen hoe ver een bericht zich verspreidt door het netwerk. Dit helpt netwerkoverlast te verminderen en berichten lokaal te houden wanneer dat gewenst is. In 2026 is de firmware verder doorontwikkeld; de nieuwste versie is v1.17.1 (14 augustus 2026). Zie de GitHub releases pagina voor de meest actuele versie-informatie.

Let op: Regions zijn een experimentele functie in MeshCore. De naamgeving en hiërarchie zijn nog niet volledig gestandaardiseerd en kunnen in toekomstige updates veranderen. Check de MeshCore Discord voor de laatste stand van zaken.

Een region is een geografisch gebied dat je configureert op een repeater. Elke repeater kan tot 32 regions bevatten (MAX_REGION_ENTRIES), met namen tot 30 tekens. In Nederland wordt de ISO 3166-2:NL standaard aangehouden voor naamgeving: nl voor nationaal, nl-zh voor Zuid-Holland, nl-nh voor Noord-Holland enzovoort.

Dat is een afspraak, geen firmware-regel. De firmware kent ISO 3166 noch UN/LOCODE; ze accepteert vrijwel elke tekenreeks, hoofdletters, cijfers, -, en de bijzondere prefixen # en $ (zie hieronder). #wandelclub is technisch een volwaardige region. De kleine letters en koppeltekens zijn dus puur de Nederlandse conventie, en die volgen is verstandig omdat je anders door niemand gevonden wordt, maar verwacht geen foutmelding als je ervan afwijkt. (Bron: RegionMap::is_name_char() in RegionMap.cpp: c == '-' || c == '$' || c == '#' || (c >= '0' && c <= '9') || c >= 'A'.)

Regions worden hiërarchisch genoteerd, van grof naar fijn. De gangbare opbouw is:

eu                          ← Europa (continent)
nl                          ← land
nl-zh                       ← provincie (ISO 3166-2)
nl-zh-dor                   ← gemeente/stad (UN/LOCODE lowercase)
nl-zh-dor-stadspolders      ← wijk of sub-regio (vrij te kiezen)

Die boomstructuur is echter administratief, geen routeringsmechanisme. In de firmware wordt het parent-veld alleen gebruikt om de boom te tonen (region, region get), om een region def-regel te kunnen inlezen, en om te voorkomen dat je een region weggooit die nog kinderen heeft. Bij het matchen van pakketten wordt de parent niet geraadpleegd.

Een repeater die alleen nl-zh-dor-stadspolders kent, accepteert dus géén berichten op scope nl-zh-dor, nl-zh, nl of eu. Elk niveau dat je wilt ontvangen moet apart met region put in de config staan én apart met region allowf worden vrijgegeven, precies zoals in de voorbeeldconfiguratie hieronder, die alle lagen expliciet opsomt. De hiërarchie helpt je bij het overzicht en bij het opschrijven; ze doet niets voor je in de lucht.

Wat wél opgaat is de andere kant: wie scope nl-zh instelt bereikt alle repeaters in Zuid-Holland die nl-zh hebben geconfigureerd, ongeacht of ze daarnaast ook wijkniveaus kennen.

Naast de stads- en wijkhiërarchie kunnen lokale communities eigen samenwerkingscodes toevoegen, zoals nl-zh-drechtsteden voor de Drechtsteden-regio. Die staat op hetzelfde niveau als nl-zh-dor (beiden kind van nl-zh), maar groepeert meerdere gemeenten. Wie scope nl-zh-drechtsteden gebruikt bereikt alle repeaters in Dordrecht, Sliedrecht, Papendrecht, Alblasserdam, Hendrik-Ido-Ambacht en Zwijndrecht die deze code kennen, ook al liggen die gemeenten elk in hun eigen LOCODE-tak.

De scope stel je in op je companion device, per kanaal en zelfs per bericht. Stel je niets in, dan gaat het bericht ongetagd de lucht in en bepaalt de wildcard-instelling van de repeater (region allowf * / region denyf *) of hij doorstuurt. Zodra je wél een scope instelt, matcht de repeater alleen tegen zijn eigen geconfigureerde regions.

Belangrijk detail bij dat laatste: een repeater zonder geconfigureerde regions laat geen enkel gescoped bericht door. De wildcard geldt namelijk alleen voor ongetagde floods, niet voor gescopete, daar wordt uitsluitend tegen de eigen regionlijst gematcht. Elk niveau dat je wilt doorgeven moet dus echt in de config staan.

Over de flood-vlag bestaat verwarring, dus expliciet: op v1.16.0 zet de CLI een nieuwe region direct op toestaan. region put antwoordt letterlijk met OK - (flood allowed) en region def doet hetzelfde; de losse region allowf-regels in de voorbeeldconfiguratie hieronder zijn op deze firmware dus een bevestiging, geen vereiste. Twee uitzonderingen: de bulk-variant region load zet een region op weigeren tenzij je hem met een F markeert, en oudere firmware kende wél deny-als-default. Controleer daarom na het inrichten met region list allowed welke regions daadwerkelijk vrijgegeven zijn. (Bron: handleRegionCmd() in CommonCLI.cpp, region->flags = 0; // New default: enable flood.)

In je companion app kun je per kanaal een region scope instellen. Stel je voor kanaal #dordrecht de scope in op nl-zh-dor, dan worden berichten op dat kanaal alleen doorgestuurd door repeaters die nl-zh-dor kennen, de conversatie blijft lokaal zolang de repeaters in de regio correct geconfigureerd zijn en flood is toegestaan voor die scope.

Directe berichten (DM's) over een bekend pad ondergaan geen scope-check en passeren dus alle regiogrenzen, zodat point-to-point communicatie altijd werkt ongeacht de regio-indeling. Alleen de allereerste DM (als het pad nog geleerd moet worden en het bericht dus geflood wordt) draagt wél de scope van je companion.

Wat een scope niet is

Regions besparen airtime. Meer niet. Omdat het mechanisme eronder cryptografisch oogt, wordt er meer aan toegeschreven dan het waarmaakt, dus hier vier dingen die je moet weten voordat je een uitgebreide regioboom uitrolt.

Een scope is geen beslotenheid. De regiosleutel is SHA-256("#regionaam"). Dezelfde constructie als bij hashtag-kanalen. Zolang die naam uit een gepubliceerde lijst komt, en dat is bij de Nederlandse conventie per definitie zo, is het aantal kandidaten eindig en klein: pakweg 342 gemeenten, twaalf provincies, een handvol streekcodes. Iemand die meeluistert rekent die kandidaten in een fractie van een seconde door en weet daarmee bij elk opgevangen pakket uit welke regio het komt. Het HMAC-ontwerp is gebouwd voor namen die niemand kan raden; met een opzoekbare naam levert het die eigenschap in. Wil je dat níet, kies dan een naam die nergens gepubliceerd staat. Dat is technisch net zo goed een region. Vertrouwelijkheid van de inhoud komt hoe dan ook van de kanaalsleutel, nooit van de scope.

Het filter is statistisch, niet absoluut. De transport code is twee bytes. De kans dat een pakket uit een wildvreemde regio toevallig samenvalt met een van jouw sleutels is ongeveer 1 op 65.536, per sleutel, en findMatch() probeert ze allemaal. Bij tien regions praat je dus over grofweg 1 op 6.500 pakketten die onterecht wordt doorgestuurd, bij de maximale 32 regions over 1 op 2.000. Voor airtime besparen is dat ruim voldoende; als grens waar iets van afhangt is het dat niet.

Elke flood kost rekenwerk vóór er iets besloten is. De repeater kan de code niet opzoeken, hij moet hem herberekenen: een HMAC-SHA256 over de complete payload, per region, tot er één past. Bij 32 regions van elk maximaal vier sleutels zijn dat tot 128 hashberekeningen per pakket, op een nRF52 of ESP32. Een korte region list allowed is dus niet alleen overzichtelijker maar ook goedkoper.

Een verkeerde scope faalt geruisloos. Stel je een scope in die geen enkele repeater in je bereik kent, dan levert findMatch() niets op, blijft de regio leeg, weigert allowPacketForward() en verdwijnt je bericht. Geen foutmelding, geen bevestiging, niets: floods kennen geen terugkoppeling. Je bent dan slechter af dan met een ongescoped bericht, dat onder de wildcard tenminste nog een kans maakt. Test een nieuwe scope daarom altijd tegen een repeater waarvan je de configuratie kent.

Wat er nog niet is. Twee dingen die in de broncode wél zijn voorbereid maar in v1.16.0 niet werken. De $-regions. Met een sleutel uit een beveiligde keystore in plaats van uit de naam, precies wat een onraadbare regio zou opleveren, hangen aan een TransportKeyStore die nog een lege huls is: saveKeysFor() geeft onvoorwaardelijk false terug met een // TODO: update hardware keystore erboven. En het tweede codeveld in het pakket (transport_code_2) is gereserveerd voor de thuisregio van de afzender, maar wordt vooralsnog altijd op nul gezet. Er is bovendien geen enkele manier waarop nodes elkaar kunnen vragen welke regions ze draaien; de gepubliceerde codelijst ís het ontdekmechanisme. (Broncode: TransportKeyStore.cpp en sendFloodScoped() in simple_repeater/MyMesh.cpp.)

Regio-configuratie in Dordrecht en Drechtsteden

In en om Dordrecht zijn meerdere MeshCore-repeaters actief. De repeater in Dordrecht Oost (wijk Stadspolders) heeft de volgende region-configuratie:

region put nl
region put nl-zh nl
region put nl-dor nl
region put nl-nb nl
region put nl-zh-dor nl-zh
region put nl-nb-wkd nl-nb
region put nl-zh-pap nl-zh
region put nl-zh-sld nl-zh
region put nl-zh-drechtsteden nl-zh
region put nl-zh-dor-stadspolders nl-zh-dor

region allowf nl
region allowf nl-zh
region allowf nl-dor
region allowf nl-nb
region allowf nl-zh-dor
region allowf nl-nb-wkd
region allowf nl-zh-pap
region allowf nl-zh-sld
region allowf nl-zh-drechtsteden
region allowf nl-zh-dor-stadspolders

region allowf *

region home nl-zh-dor
region default nl-zh
region save

set flood.max.unscoped 3
set flood.max 20
set flood.max.advert 8

Op de laatste twee regels na is dit letterlijk wat de Regio Generator uitspuugt voor deze locatie: set flood.max 20 en set flood.max.advert 8 zijn eigen meetwerk en horen niet bij de standaarduitvoer.

Ter controle levert het kale commando region daarna precies deze boom op:

* F
 nl F
  nl-zh F
   nl-zh-dor^ F
    nl-zh-dor-stadspolders F
   nl-zh-pap F
   nl-zh-sld F
   nl-zh-drechtsteden F
  nl-dor F
  nl-nb F
   nl-nb-wkd F

Twee tekens om te herkennen: de F achter een naam betekent dat flooding voor die region is toegestaan, ontbreekt hij, dan staat er region denyf op. Het ^ markeert de thuisregio (region home), níet de default scope; die laatste zie je in de boom helemaal niet terug. De bovenste regel is de wildcard*, waar alles onder hangt. (Bron: RegionMap::printChildRegions() in RegionMap.cpp, parent->id == home_id ? "^" : "" en de F uit REGION_DENY_FLOOD.)

De grenzen onderaan zijn het resultaat van meten aan het verkeer dat de repeater in Stadspolders daadwerkelijk langs ziet komen, ruim duizend pakketten in een etmaal:

Ook de regionlijst zelf is korter geworden. eu is helemaal verdwenen: die stond al op denyf omdat er in een etmaal meten geen enkel pakket op die scope langskwam, en nu is de region zelf ook weg, nl hangt daardoor rechtstreeks onder de wildcard. Datzelfde geldt voor nl-zh-a2z (Oud-Alblas) en vr-vrzhz (Veiligheidsregio Zuid-Holland Zuid). Die laatste omdat DARES desgevraagd bevestigde dat MeshCore geen formele DARES-dienst is en er geen taak ligt om regiokenmerken in de naamgeving op te nemen; zie Veiligheidsregio's hieronder. Elke toegestane region kost de repeater immers tot vier HMAC-berekeningen per pakket vóór er iets besloten is; van de bovenlagen werden alleen nl (53×) en nl-zh (6×) werkelijk herkend.

Erbij gekomen is nl-dor. De kortere stadsregio-notatie zonder provincie ertussen, als kind van nl. Die vorm komt uit de meshwiki-naamgeving voor een bredere stadsregio en staat dus náást nl-zh-dor, niet in plaats daarvan: omdat regions niet overerven zijn het twee losse sleutels, en de repeater kent ze nu allebei. Wie een van beide als scope gebruikt, wordt hier doorgestuurd.

Deze configuratie dekt meerdere geografische lagen:

RegioCodeToelichting
NederlandnlLandniveau, hangt rechtstreeks onder de wildcard
Zuid-Hollandnl-zhEigen provincie
Dordrechtnl-zh-dorEigen gemeente, tevens de thuisregio (^ in de boom hierboven)
Stadspoldersnl-zh-dor-stadspoldersWijk in Dordrecht Oost, lokaalste scope
Papendrechtnl-zh-papNaburige gemeente in Zuid-Holland
Sliedrechtnl-zh-sldNaburige gemeente in Zuid-Holland
Drechtstedennl-zh-drechtstedenCommunity-regio die Dordrecht, Sliedrecht, Papendrecht, Alblasserdam, H-I-Ambacht en Zwijndrecht bundelt
Dordrecht (stadsregio)nl-dorKortere notatie zonder provincie, kind van nl
Noord-Brabantnl-nbBuurprovincie direct over de rivier (Hollands Diep)
Werkendamnl-nb-wkdNaburige gemeente in Noord-Brabant, over de Hollands Diep

region default nl-zh stelt Zuid-Holland in als scope waarmee de repeater zijn eigen advertenties tagt; region home nl-zh-dor legt daarnaast vast waar de node zelf thuishoort. Dat is de ^ in de boom. region save slaat de configuratie op, zonder dit verdwijnen alle instellingen bij een reboot.

region default versus region home

Twee commando's die op elkaar lijken maar iets anders doen, en die je makkelijk door elkaar haalt:

CommandoWat het instelt
region default <naam>De scope waarmee uitgaand verkeer van deze node getagd wordt: onder andere zijn eigen advertenties
region home <naam>De thuisregio van de node: waar hij zelf vindt dat hij hoort

Voor de meeste opstellingen is region default het commando dat je nodig hebt; dat bepaalt namelijk hoe ver je advertenties reizen. Zonder argument tonen beide de huidige waarde: region home alleen geeft antwoord in plaats van te wijzigen.

Controleren of het gelukt is

Na het plakken van een lange reeks commando's is het prettig om te verifiëren dat alles is aangekomen, een typefout levert stilletjes Err - unknown region op tussen de OK's:

region list allowed     → alle regions waarvoor flood is toegestaan
region list denied      → alle regions waarvoor flood geblokkeerd is
region get nl-zh-dor    → details van één region, inclusief parent
region                  → de volledige boom

Kortere notatie: region def

Sinds firmware v1.16.0 kun je een hele hiërarchie in één regel definiëren met region def, in plaats van de reeks losse region put-opdrachten hierboven. Handig als je een diep genest pad als eu → nl → nl-zh → nl-zh-dor → nl-zh-dor-stadspolders in één keer wilt neerzetten. De uitgeschreven variant blijft werken en is makkelijker te lezen als je hem later wilt aanpassen; de Regio Generator produceert daarom de expliciete vorm.

MeshCore Regio Generator

Het handmatig invoeren van de juiste region put en region allowf commando's voor een repeater is foutgevoelig, zeker als je ook naburige steden wil opnemen. Op TechSpeeltuin is daarom een interactieve Regio Generator beschikbaar:

Veiligheidsregio's

Nederland is verdeeld in 25 veiligheidsregio's. Samenwerkingsverbanden van gemeenten voor brandweer, GHOR en crisisbeheersing. Binnen MeshCore circuleert het idee om die indeling als extra scope-laag te gebruiken, met codes als vr-vrzhz. Aantrekkelijk is dat een veiligheidsregio provinciegrenzen kan doorsnijden: Zuid-Holland Zuid omvat bijvoorbeeld Dordrecht, maar ook Gorinchem en gemeenten in Noord-Brabant die bestuurlijk bij deze regio horen.

Wat DARES hierover zegt (juli 2026)

Deze pagina koppelde de vr-codes eerder aan DARES (Dutch Amateur Radio Emergency Service). Op navraag laat de secretaris van DARES weten dat dat niet klopt:

  • Er zijn individuele DARES-deelnemers die met MeshCore experimenteren, maar het is geen formele DARES-dienst en het wordt niet ingezet als noodcommunicatiekanaal.
  • DARES ziet vooralsnog geen taak om regiokenmerken op te nemen in de standaard naamgeving. Het voorstel wordt wel binnen de groep gedeeld.

Lees de vr-codes hieronder dus als een community-voorstel, niet als een DARES-standaard en niet als iets waar in een echte noodsituatie op geleund kan worden. Wie noodcommunicatie zoekt, is aangewezen op de kanalen die DARES daar zelf voor inricht.

Naamgeving en parent

Voor wie de codes tóch wil gebruiken: ze beginnen met vr- gevolgd door de Brandbase-afkorting in kleine letters, zie de tabel hieronder. Als parent geldt altijd nl (landniveau), niet de provincie, omdat veiligheidsregio's geen subonderdeel zijn van één provincie.

region put vr-vrzhz nl
region allowf vr-vrzhz

Bedenk wel dat elke extra region rekentijd kost bij ieder binnenkomend floodpakket, en dat een scope die niemand in je omgeving kent geruisloos doodloopt. De repeater in Dordrecht Oost heeft vr-vrzhz om die reden weer uit zijn configuratie gehaald.

Alle 25 veiligheidsregio's

CodeNaamProvincie(s)
vr-hvdgGroningennl-gr
vr-vrfFrieslandnl-fr
vr-vrdDrenthenl-dr
vr-vrijIJssellandnl-ov
vr-vrtTwentenl-ov
vr-vnogNoord- en Oost-Gelderlandnl-ge
vr-vggmGelderland-Middennl-ge
vr-vrgzGelderland-Zuidnl-ge
vr-vruUtrechtnl-ut
vr-vrnhnNoord-Holland Noordnl-nh
vr-vrzwZaanstreek-Waterlandnl-nh
vr-vrkKennemerlandnl-nh
vr-vraaAmsterdam-Amstellandnl-nh
vr-vrgvGooi en Vechtstreeknl-nh / nl-ut
vr-vrhHaaglandennl-zh
vr-vrhmHollands Middennl-zh
vr-vrrRotterdam-Rijnmondnl-zh
vr-vrzhzZuid-Holland Zuidnl-zh
vr-vrzZeelandnl-ze
vr-vrmwbMidden- en West-Brabantnl-nb
vr-vrbnBrabant-Noordnl-nb
vr-vrbzoBrabant-Zuidoostnl-nb
vr-vrlnLimburg-Noordnl-li
vr-vrzlZuid-Limburgnl-li
vr-vrflFlevolandnl-fl

Regio Generator met automatische detectie

De Regio Generator detecteert je veiligheidsregio automatisch op basis van je GPS-locatie of geselecteerde stad, en toont ook de direct aangrenzende regio's gemarkeerd als Aangrenzend. Je kiest zelf welke je wilt opnemen. Zo voeg je in één stap de juiste vr- codes toe aan je repeater-config.

Hardware & Firmware Types

Gebruikers kunnen MeshCore-firmware installeren op compatibele LoRa-hardware, zoals:

De lijst met ondersteunde borden groeit per release. In v1.17.0 kwamen er tien bij, waaronder de Sensecap X1 en MeshTracker X1, de Thinknode M7 en M9, de Heltec RC32, V4 R8 en Tower V2, en de Nibble Zero Connect. Diezelfde release voegde ondersteuning toe voor de LR2021-radiochip, naast de al bekende SX126x, SX128x en LR1110. Kijk voor de actuele lijst in de web-flasher of bij de releases op GitHub. (Bron: release 1.17.0.)

MeshCore biedt vier hoofdfirmware-types:

1. Companion Firmware

Verbindt met een externe client via BLE (standaard), USB Serial of WiFi TCP. Dit is de standaard voor de meeste gebruikers: de node doet alleen de radio-communicatie, terwijl de MeshCore mobiele app (Android/iOS) of web/desktop-app als interface dient. Er bestaan twee firmware-varianten: de gewone BLE+Serial build en een USB-Serial-only variant voor hardware zonder BLE-ondersteuning of bij aansluiting op een vaste computer.

2. Repeater Firmware

Breidt het netwerk uit door berichten automatisch door te sturen op basis van de embedded path-informatie. Werkt volledig autonoom, geen telefoon nodig. Stuurt periodiek flood-adverts (met instelbaar interval) om zichzelf bekend te maken, maar probeert airtime zo laag mogelijk te houden.

3. Room Server Firmware

Fungeert als een soort BBS (Bulletin Board System): slaat berichten op in rooms/kanalen zodat clients ze later kunnen ophalen (store-and-forward). Ondersteunt guest passwords, admin-rechten en QR-code toegang. Beheer op afstand kan via een T-Deck met de remote-adminfunctie ontgrendeld, of via een BLE-companion gekoppeld aan de mobiele app. (Bron: MeshCore FAQ, "How do I administer a room server remotely?")

Sinds v1.17.0 kan de room server zelf een bericht in een room plaatsen met het commando room.post, in plaats van alleen berichten van anderen te bewaren. Handig voor een mededeling of een welkomsttekst die iedereen te zien krijgt die de room later ophaalt. Diezelfde release zette RX boosted gain aan op de room server, wat de gevoeligheid van de ontvanger verhoogt. Let op: room.post staat nog niet in de officiële CLI-documentatie en dus ook niet in onze CLI-referentie. (Bron: release 1.17.0.)

4. T-Deck Direct / Terminal Firmware

Maakt van een T-Deck een volledig standalone apparaat met terminal-achtige interface, directe messaging zonder smartphone-app. Handig voor fixed installaties of als backup. Sommige community-varianten (zoals MeshOS) bieden extra features zoals maps en remote admin, die soms een betaalde unlock-key vereisen.

Praktische opmerkingen:Repeater en Room Server firmware kunnen op dezelfde hardware draaien (je kiest bij het flashen). Companion + Repeater combinaties zijn technisch mogelijk, maar voor betere prestaties worden ze doorgaans op aparte hardware gedraaid. De web-flasher maakt het eenvoudig om het juiste firmwaretype te kiezen en te installeren.

Updaten zonder kabel: een repeater die eenmaal op een dak of mast hangt hoef je er niet af te halen om te updaten. nRF-gebaseerde borden (RAK, T114, Seeed XIAO) werk je over-the-air bij met de DFU-app; ESP32-borden hebben een eigen OTA-procedure. Zorg dat de accu vol is en het signaal stabiel voordat je begint, een afgebroken update laat het apparaat in DFU-modus achter, en dan moet je alsnog de ladder op. Zie FAQ 7.1 t/m 7.3 voor de stappen per platform.

Noteer je instellingen vóór een update naar v1.17.0. Deze release slaat de configuratie in JSON op, op alle firmwaretypes. Of bestaande instellingen bij het updaten meeverhuizen staat niet in de release notes, en dat is precies het soort ding dat je liever niet ontdekt als de repeater al op het dak staat. Draai vooraf get op de waarden die je zelf hebt gezet (regions, dutycycle, flood.advert.interval, path.hash.mode, wachtwoorden) en bewaar de uitvoer. Alles opnieuw invoeren kost sowieso tijd, en hoeveel hangt af van waar de node hangt: op je bureau is het typewerk, bij een repeater op het dak van een flat, in een mast of in een boom komt daar een hele expeditie bij. (Bron: release 1.17.0.)

Gebruikersinterface & Clients

Communicatie met het MeshCore-netwerk verloopt via verschillende clients en platforms:

Mobiele apps: De officiële Android- en iOS-app (gratis). Biedt chat, kanaalbeheer, node-kaart, path-visualisatie en experimentele instellingen. De meest gebruikte manier voor dagelijks gebruik.

Web client: Werkt in Chrome/Edge, ook offline zodra verbonden met een companion via BLE of WiFi. Handig als desktopinterface of als je geen app wil installeren. Beschikbaar via meshcore.io/client.html.

Seriële / Terminal console: Directe CLI-toegang via USB voor gevorderde configuratie van repeaters en room servers, troubleshooting en het instellen van regio's, TX power en firmware-parameters.

Web-configurator: Op config.meshcore.io verbind je een geflashte repeater of room server via USB-serieel met je browser, en stel je naam, frequentie, locatie en wachtwoorden in via een grafische interface. Prettiger dan de CLI voor de eerste inrichting; voor region-configuratie en de fijnere instellingen blijf je bij de commandoregel.

Standalone apparaten: De LilyGo T-Deck (en T-Deck Plus) functioneren als volledig zelfstandige terminals met eigen scherm, toetsenbord en MeshCore-firmware, app-vrij en zonder smartphone.

MQTT & automatisering: Via community-tools zoals LetsMesh of een eigen MQTT-bridge kun je MeshCore koppelen aan Home Assistant, Node-RED of eigen scripts. Hiermee zijn monitoring (repeater-status, signaalwaarden) en integraties mogelijk zonder zelf berichten te sturen over het radionetwerk.

Bekijk de MeshCore Software pagina voor een overzicht van actuele firmware-versies, apps en release-notes.

Bots en Geautomatiseerde Berichten

Waarom bots een probleem zijn

LoRa heeft van nature een extreem beperkte bandbreedte en strenge duty cycle-regels (sub-band P: ≤ 10% zendtijd per uur). Elke zending (ook een geautomatiseerde) kost airtime die anderen niet meer kunnen gebruiken. In een groeiend netwerk zoals het Nederlandse mesh leidt dit direct tot:

Bots die regelmatig berichten sturen (weerstations, quote-bots, ping-bots, periodieke status-updates), zijn om deze reden onwenselijk in gedeelde kanalen.

Wat is soms wél acceptabel?

Niet alle automatisering is per definitie problematisch. Toepassingen die zeer zelden zenden (intervallen van uren, niet minuten) en geen gedeelde kanalen vervuilen kunnen verantwoord zijn:

Region scoping als mitigerende factor

Region scoping biedt een belangrijk middel om de impact van geautomatiseerde berichten te beperken. Door een nauwe scope in te stellen (bijvoorbeeld nl-zh-dor voor Dordrecht of nl-zh voor Zuid-Holland), worden berichten alleen doorgestuurd door repeaters in dat gebied. Het verkeer blijft lokaal en cascadeert niet door het hele netwerk.

Dit maakt sommige toepassingen acceptabeler dan ze zonder scoping zouden zijn: een weerstation dat elk uur een update stuurt op scope nl-zh-dor belast alleen de lokale repeaters, niet het landelijke mesh. Hoe smaller de scope, hoe kleiner de impact.

Scoping is dan ook geen vrijbrief voor hoge zendfrequentie, de lokale duty cycle en airtime zijn net zo eindig als die van het grotere netwerk. Maar het is wél een relevante factor bij de afweging.

Praktische richtlijnen

Doel van MeshCore

Het doel van MeshCore is het bieden van een betrouwbare, veilige en efficiënte communicatieoplossing voor situaties waarin traditionele infrastructuur ontbreekt of onbetrouwbaar is. De missie is om een gedecentraliseerd mesh-radiosysteem te ontwikkelen dat toegankelijk is voor iedereen, met een sterke focus op beveiliging en lage energieconsumptie, ideaal voor batterij- of zonne-energiegevoede apparaten.

Belangrijke Kenmerken

MeshCore onderscheidt zich van andere LoRa-systemen op de volgende punten:

Gedecentraliseerd en robuust

Het MeshCore-protocol heeft geen centrale server of internet nodig; het netwerk is zelfherstellend en blijft functioneren, zelfs als nodes uitvallen. Veel tools rondom het ecosysteem (kaarten, dashboards, node-directories) zijn echter wél centraal gehost en vereisen internetverbinding.

Laag Energieverbruik

Ideaal voor apparaten op batterijen of zonne-energie, dankzij efficiënte LoRa-modulatie met SF7 en BW 62.5 kHz configuratie. Batterijen gaan dagen tot weken mee, ideaal voor noodsituaties.

Eenvoudig te Implementeren

Configureerbare Netwerk Parameters

Beveiliging & Encryptie

MeshCore implementeert een robuust tweelaagsysteem voor beveiliging:

Identiteit & Sleutelbeheer

Message Encryption

Standaardwachtwoorden: wijzig deze direct

De cryptografie hierboven is sterk, maar een vers geflashte repeater of room server is dat niet automatisch. MeshCore levert twee bekende standaardwaarden mee die iedereen kan opzoeken:

WatStandaardwaardeWijzigen met
Admin-wachtwoord repeater / room serverpasswordpassword JOUW-WACHTWOORD
Gast-wachtwoord room serverhelloset guest.password JOUW-WACHTWOORD
Bluetooth-pairingcode123456via de app- of firmware-instellingen

Zolang je het admin-wachtwoord niet wijzigt, kan iedereen binnen radiobereik je repeater op afstand beheren: naam en frequentie aanpassen, regions herschrijven, zendvermogen veranderen of hem simpelweg uitschakelen. Dit is de eerste stap na het flashen, vóór je de repeater ophangt.

password mijn-eigen-wachtwoord

(Bron: MeshCore FAQ 3.3, 3.4 en 6.5.)

Rechten per gebruiker (ACL)

Eén gedeeld admin-wachtwoord is grofmazig: iedereen die het kent kan alles, en intrekken kan alleen door het voor iedereen te wijzigen. Voor repeaters en room servers kun je in plaats daarvan per companion rechten toekennen op basis van diens publieke sleutel:

setperm <publieke-sleutel> <niveau>
NiveauRolBetekenis
0GastBasistoegang
1Alleen-lezenMeekijken, niets wijzigen
2Lezen-schrijvenNormaal gebruik
3AdminVolledig beheer

Laat je het niveau weg, dan wordt de vermelding verwijderd. Met acl bekijk je de huidige lijst. Voor een room server bestaat daarnaast allow.read.only (standaard off), waarmee je de hele server op meelezen-zonder-plaatsen zet.

Dit is de nettere aanpak voor een repeater die je met meerdere mensen beheert: geef ieder een eigen sleutel met het juiste niveau, in plaats van één wachtwoord rond te sturen dat je later niet selectief kunt intrekken. Zie ook de CLI-referentie.

Privacy Features

Wat is er wél zichtbaar?

Twee dingen worden op deze pagina makkelijk over het hoofd gezien, maar bepalen in de praktijk hoe privé je communicatie is.

Het standaard publieke kanaal is niet privé. De sleutel van het publieke kanaal is openbaar gepubliceerd in de officiële documentatie (8b3387e9c5cdea6ac9e5edbaa115cd72). Technisch is het verkeer versleuteld, praktisch heeft iedereen de sleutel: ga ervan uit dat alles wat je op het publieke kanaal stuurt wereldwijd meeleesbaar is. Wil je écht besloten communiceren, maak dan een eigen kanaal met een zelf gegenereerde sleutel (let daarbij wel op het onderscheid hieronder) of gebruik een DM, die is end-to-end versleuteld naar één ontvanger.

Drie soorten kanalen, en twee ervan zijn openbaar

"Een eigen kanaal aanmaken" klinkt als iets besloten, maar dat hangt volledig af van waar de sleutel vandaan komt. Een kanaal ís namelijk niets anders dan een gedeelde AES-sleutel; er is geen server, geen ledenlijst en geen toegangscontrole. Wie de sleutel heeft, hoort erbij. De officiële companion-protocoldocumentatie onderscheidt drie varianten:

SoortWaar komt de sleutel vandaanWie kan meelezen
PublicVaste sleutel, ingebakken in elke installatieIedereen met een MeshCore-apparaat
HashtagAfgeleid uit de kanaalnaam: de eerste 16 bytes van SHA-256("#naam")Iedereen die de naam kent of raadt
PrivateWillekeurig gegenereerde 16 bytes, buiten het mesh om gedeeldAlleen wie de sleutel van je kreeg

De middelste is de valkuil. Een hashtag-kanaal voelt als een eigen kanaal (je typt een naam in en je hebt een eigen chat) maar de sleutel is een rechtstreekse functie van die naam. #dordrecht levert bij iedereen ter wereld exact dezelfde sleutel op. Wie de naam raadt, leest mee; en namen als #test, #dordrecht of #noodnet raadt niemand zich een ongeluk. Het is bedoeld als openbare themachat, niet als beslotenheid.

Wil je werkelijk een besloten groep, dan moet de sleutel willekeurig gegenereerd zijn en via een QR-code of een ander kanaal buiten het mesh gedeeld worden. Dat is het verschil tussen "niemand kent het adres" en "niemand heeft de sleutel".

(Bron: companion_protocol.md, Channel Types; het voorbeeld in die documentatie is #test, met sleutel 9cd8fcf22a47333b591d96a2b848b73f.)

Twee technische details die hierbij horen. De kanaal-hash die in elk pakket meegaat is afgeleid van de sleutel, niet van de naam: SHA-256(secret), waarvan alleen de eerste byte wordt vergeleken (BaseChatMesh.cpp). Een repeater gebruikt die byte om te zien of hij het kanaal zelf kent, hij hoeft de sleutel niet te hebben om het bericht door te sturen. En de versleuteling is AES-128: CIPHER_KEY_SIZE staat op 16 en de encryptieroutine in Utils.cpp roept AES128 aan. Kom je ergens AES-256 tegen in verband met MeshCore, dan klopt dat niet met de broncode.

Je advertentie verklapt waar je staat. Een advert bevat je naam, je publieke sleutel én je positie, ondertekend en over de radio uitgezonden. Vul je set lat en set lon in, dan verschijnt je node met locatie op publieke kaarten zoals map.meshcore.io. Voor een vaste repeater op een dak is dat precies de bedoeling; voor een handheld die je meedraagt is het een bewuste keuze.

Die keuze is een instelling, en de standaardwaarde is delen. Met gps advert bepaal je wat er in je advertenties terechtkomt:

WaardeGedrag
noneGeen locatie in je adverts
shareLocatie uit de GPS-ontvanger
prefsStandaard: zendt de lat/lon uit die je zelf hebt ingesteld
gps advert none

Wil je wél op de kaart maar niet exact op je voordeur, zet dan lat/lon bewust een klein stukje verderop, voor mesh-doeleinden is een globale positie ruim voldoende.

(Bron: MeshCore FAQ 2.4, 3.2 en 5.6 en de CLI-referentie.)

Frequentiegebied en Configuratie (Nederland)

Nederland valt binnen de Europese regelgeving voor licentievrije SRD-banden (Short Range Devices). De band 863–870 MHz is opgedeeld in sub-banden met elk eigen limieten voor vermogen en duty cycle, vastgelegd in ETSI EN 300 220-2 Annex B:

Sub-bandFrequentiebereikMax. ERPMax. Duty CycleOpmerkingen
K863 – 865 MHz25 mW0,1%Zeer beperkt
L865 – 868 MHz25 mW1%Standaard voor veel LoRa
M868 – 868,6 MHz25 mW1%Vaak gebruikt (bijv. 868.1 / 868.3 / 868.5 MHz)
O868,6 – 868,7 MHz25 mW1%Alarm-toepassingen; niet voor general purpose LoRa
N868,7 – 869,2 MHz25 mW0,1%Zeer beperkt
P869,4 – 869,65 MHz500 mW10%Meest gebruikt in NL MeshCore (869.618 MHz), hoogste duty cycle + hoger vermogen
Q869,7 – 870 MHz25 mW1%Beperkt

Duty cycle = percentage van de tijd dat je mag zenden (gemeten over 1 uur).
0,1% ≈ max. 86 sec/dag · 1% ≈ max. 864 sec/dag · 10% ≈ max. 8.640 sec/dag

Sub-band P is de NL-keuze voor MeshCore omdat het zowel het hoogste zendvermogen (500 mW ERP) als de ruimste duty cycle (10%) biedt, wat essentieel is voor een mesh-repeater die regelmatig doorgeeft.

Met een bandbreedte van 62,5 kHz (narrowband) passen er theoretisch 4 kanalen in de 250 kHz brede sub-band P:

KanaalBereikMiddenGebruik
1869,400 – 869,4625 MHz869,4313 MHz,
2869,4625 – 869,525 MHz869,4938 MHz,
3869,525 – 869,5875 MHz869,5563 MHz,
4869,5875 – 869,650 MHz869,6188 MHzNL MeshCore (869,618 MHz)

De Nederlandse community heeft kanaal 4 gekozen. Het zit vrijwel exact op het theoretische midden van dat slot.

Nederlandse MeshCore Instellingen

Op 9 mei 2026 is de Nederlandse MeshCore-community overgestapt op een nieuw radiopreset. De huidige standaardinstellingen zijn:

Deze instellingen zijn de community-preset Netherlands (SF7/CR5) en vallen binnen sub-band P (869.4–869.65 MHz) volgens ETSI EN 300 220-2 V3.3.1 (2025-03) regelgeving. Zie de sectie The Change voor de volledige achtergrond en het verschil met de vorige preset.

Let op: niet alle repeaters zijn al omgeschakeld, en sommige willen dat (voorlopig) ook niet. Controleer altijd welke preset de repeaters in jouw buurt gebruiken voordat je zelf omschakelt. Een node op SF7 en een repeater op SF8 horen elkaar simpelweg niet. Kijk op Cornmeister.nl of MC Radar voor de actuele status van repeaters in jouw regio.

TX Delay

Wanneer meerdere repeaters in de buurt hetzelfde flood-pakket horen, wacht elk van hen een willekeurige tijd voordat hij het opnieuw uitzendt. Dat voorkomt dat ze tegelijk zenden en elkaars signaal onleesbaar maken. TX Delay is geen vaste wachttijd in seconden, maar een factor die de grootte van dat willekeurige venster schaalt: hoe hoger de factor, hoe breder het venster en hoe kleiner de kans op botsingen, ten koste van extra vertraging per hop. De waarde 0 schakelt het venster volledig uit.

MeshCore kent drie afzonderlijke instellingen:

CommandoGeldt voorBereikStandaard
set txdelay <waarde>Flood-verkeer0 – 20.5
set direct.txdelay <waarde>Direct (gerouteerd) verkeer0 – 20.2(zie noot)
set rxdelay <waarde>Verwerkingsvertraging bij ontvangst (experimenteel, zie RX Delay)0 – 200.0

direct.txdelay staat standaard lager omdat een direct pakket aan één specifieke volgende hop is geadresseerd, er concurreren simpelweg veel minder nodes om het door te sturen.

Noot bij de standaardwaarde: de CLI-referentie noemt 0.2, maar de repeater-firmware zet in v1.16.0 _prefs.direct_tx_delay_factor = 0.3f met de opmerking // was 0.2 (simple_repeater/MyMesh.cpp). De documentatie loopt hier dus achter op de code. Controleer je eigen node met get direct.txdelay.

Praktische richtlijnen:

Samenvatting: weinig overlap? → 0 of 0.5 · normale situatie? → 0.5 · veel repeaters die elkaar goed horen? → 1.0 tot 1.5, bij voorkeur verschillend per repeater. Bron: CLI-referentie, txdelay.

Troubleshooting. Repeater wordt 'doof':SX1262-chips (Heltec, RAK) kunnen na verloop van tijd ophouden met ontvangen door AGC-drift. Stel in: set agc.reset.interval 4 (seconden; geldige waarden zijn veelvouden van 4: 4, 8, 12 …) om de AGC periodiek te resetten. Dit lost het meest voorkomende "repeater hoort niets meer"-probleem op.

Listen before talk en hardware-CAD

Het willekeurige venster hierboven is niet het enige dat botsingen tegengaat. De firmware luistert ook vóór het zenden of het kanaal vrij is, en dat luisteren is in v1.17.0 grondig herzien: de preamble-detectie werkt nu zoals bedoeld, vastgelopen interrupt-vlaggen worden opgeruimd en de RX-timeout klopt. MeshCore noemt dit zelf de grootste winst van de release. (Bron: release 1.17.0.)

Daarnaast is er sinds diezelfde versie een aparte schakelaar voor de hardware-CAD van de radiochip, die vóór elke zending een echte kanaalscan doet:

CommandoStandaardOns advies
get cad / set cad <on|off>offLaat uit staan tenzij je het meet

De scan zelf is niet nieuw, de schakelaar wel. Tot v1.17.0 hing hardware-CAD vast aan int.thresh: stond die drempel op nul, dan gebeurde er niets, en stond hij hoger, dan deed de node een hardwarescan of je dat nu wilde of niet. Sinds deze release zijn het twee losse controles. int.thresh vergelijkt alleen nog de signaalsterkte met de ruisvloer, cad doet de scan, en je kunt beide aan hebben, één van de twee, of geen van beide. (Broncode: isChannelActive() in RadioLibWrappers.cpp, losgekoppeld in commit 7c8e092.)

MeshCore laat de standaard op off en licht dat zo toe: de vernieuwde software-variant "performs on par with hardware CAD, but without the 4 second lock-up glitches that CAD still suffers from. So, we are still leaving hardware CAD off by default." Dat is een keuze voor de standaardwaarde, geen advies om het commando niet te gebruiken; de schakelaar is er juist zodat je het in je eigen omgeving kunt uitproberen. Doe je dat, meet dan het verschil in plaats van hem aan te laten staan omdat het beter klinkt. (Bron: release 1.17.0.)

Let op bij het bijwerken. Had je int.thresh ingesteld, dan draaide je vóór v1.17.0 met hardware-CAD aan zonder dat je daarvoor gekozen had. Na de update is dat niet meer zo, tenzij je set cad on geeft. Dit staat niet in de release notes.

Dit is geen gecertificeerde LBT. Zie Regelgeving sub-band P: voor de Nederlandse uitzondering op de duty cycle is Listen Before Talk plus Adaptive Frequency Agility nodig, en die tweede helft heeft MeshCore niet. De duty cycle van 10% blijft dus gewoon gelden.

Diagnose: hoort mijn repeater nog iets?

Voordat je aan instellingen gaat sleutelen is het handig om vast te stellen wát de repeater eigenlijk nog binnenkrijgt. Drie commando's:

CommandoWat het doet
neighborsToont nodes waarvan recent een advert is ontvangen (de 8 meest recente), met tijdstip en signaalsterkte
discover.neighborsZoekt actief naar directe buren op nul hops
neighbor.remove <sleutel>Verwijdert een node uit de burenlijst

Een lege of verouderde neighbors-lijst terwijl er wel repeaters in de buurt staan, wijst op het doofheidsprobleem hierboven of op een verkeerde radio-preset, een node op SF7 en een repeater op SF8 horen elkaar simpelweg niet.

Met stats-core haal je accuspanning, uptime, wachtrijlengte en foutentellers op. Vooral relevant voor solar-repeaters: een oplopende wachtrij of een accu die 's nachts te ver wegzakt zie je hier eerder dan aan de berichten.

Herstart je node uit zichzelf, dan vertelt get pwrmgt.bootreason waaróm: een watchdog, een lege accu of een gewone reset zien er in de berichten hetzelfde uit maar vragen om een ander antwoord. Werkt alleen op borden met power management; nRF52-borden konden dit al, ESP32-borden sinds v1.17.0. Samen met get pwrmgt.bootmv (de accuspanning op het moment van opstarten) is dat meestal genoeg om een nachtelijke herstart te verklaren.

Een extra ontvangstversterker op sommige borden. Zit er een front-end module (FEM) op je bord, dan kun je sinds v1.17.0 de ontvangstkant daarvan apart aan- en uitzetten met set radio.fem.rxgain <on|off>. Dat is niet hetzelfde als radio.rxgain, wat de boosted gain van de radiochip zelf regelt; ze staan los van elkaar. Ondersteunt je bord het niet, dan antwoordt de node met Error: unsupported. Meer versterking betekent niet automatisch betere ontvangst: een LNA tilt ook de ruisvloer op, en in een drukke band kan dat averechts werken. Meet het verschil dus voor je het laat staan. (Broncode: radio.fem.rxgain in CommonCLI.cpp, dat canControlLoRaFemLna() van het bord bevraagt.)

Laatste redmiddel:erase zet de node terug naar fabrieksinstellingen. Dat werkt alleen via de seriële console (niet op afstand, logisch, anders kon iedereen je repeater wissen) en is onomkeerbaar: naam, wachtwoorden, regions en sleutelpaar zijn weg. Noteer je configuratie vóór je dit doet.

RX Delay

Waar txdelay het móment van doorsturen spreidt, grijpt rxdelay een stap eerder in: bij het verwerken van wat er binnenkomt. Repeaters die een flood-pakket met een zwak signaal ontvingen worden in een wachtrij gezet, terwijl repeaters die het sterk binnenkregen het meteen verwerken. Sterke paden krijgen zo voorrang, en tegen de tijd dat de zwakke ontvangers aan de beurt zijn is het pakket vaak al langsgekomen. Dan wordt hun kopie als duplicaat onderdrukt en hoeft er niets meer de lucht in.

CommandoBereikStandaardStatus
set rxdelay <waarde>0 – 200.0 (uit)Experimenteel

Het is bedoeld voor dichte gebieden waar veel repeaters elkaar horen. Hoe je weet of dat bij jou speelt: kijk hoe vaak hetzelfde bericht méér dan één keer binnenkomt. Op de Raw Packet Breakdown telt de kaart dat per bericht, staat daar bij de meeste berichten "opnieuw opgevangen na doorgifte", dan hoort je repeater veel dubbel werk aan. Op de repeater in Dordrecht Oost geldt dat voor ruim de helft van de berichten; die draait daarom set rxdelay 1.

Praktische richtlijnen:

Samenvatting:set rxdelay 0 tenzij je repeater merkbaar veel duplicaten hoort; dan 1 en meten. Bron: CLI-referentie, rxdelay.

Flood Advert Interval

Een repeater kondigt zichzelf periodiek aan via een flood advertisement: een pakket dat door het hele netwerk vloeit en andere nodes vertelt dat deze repeater bestaat en via welk pad hij bereikbaar is. Hoe vaker die advertentie verstuurd wordt, hoe meer airtime er verbruikt wordt, ook door alle repeaters die het pakket doorgeven.

In mei 2026 telt het Nederlandse netwerk meer dan 2.000 actieve repeaters ((bron: LocalMesh, Mesh-netwerk dekking in Nederland; zie ook de live kaart)). Als die allemaal elke 3 uur adverteren, zijn dat ruim 650 flood adverts per uur. Elk pakket reist door tientallen repeaters en wordt bij elke stap opnieuw uitgezonden. De beschikbare airtime is eindig; op drukke momenten is congestie dan geen uitzondering maar het gevolg. De Nederlandse community hanteert daarom een minimumrichtlijn van 50 uur voor het flood advert interval. (Bron: MeshWiki, Repeater via CLI configureren en LocalMesh, MeshCore repeater setup.)

Er zijn twee aparte interval-instellingen:

InstellingBeschrijvingBereikAanbevolen waarde
set flood.advert.interval <uren>Hoe vaak de repeater een flood advert verstuurt, reist door het hele netwerk3 – 168 uur50 uur
set advert.interval <minuten>Hoe vaak een zero-hop (direct) advert wordt verstuurd, alleen voor directe buren, reist niet door het mesh60 – 240 min240 min (4 uur)

Let op de commandonaam: het zero-hop interval stel je in met set advert.interval (in minuten). Een commando zerohop.advert.interval bestaat niet. Dat levert een foutmelding op. Het losstaande advert.zerohop is iets anders: dat verstuurt direct één zero-hop advert. Zie de CLI-referentie.

Sinds firmwarev1.16.0 (6 juni 2026) is de firmware-standaard voor het flood advert interval opgehoogd van 12 naar 47 uur: de upstream-standaard beweegt dus richting het Nederlandse advies. Diezelfde release voegde flood.max.advert toe (standaard 8), dat adverts na een X aantal hops laat vallen.

Let op de exacte commandonaam en de bron. Verschillende community-pagina's noemen dit commando flood.advert.max; dat bestaat niet en levert een foutmelding op. Het is set flood.max.advert, zoals in de officiële CLI-referentie staat en in de broncode (_prefs->flood_max_advert in CommonCLI.cpp). Ook de 47 uur wordt elders nog als 12 uur genoemd. Dat is de verouderde waarde uit docs/cli_commands.md; de broncode zet _prefs.flood_advert_interval = 47 en de wijziging staat in PR #2608.

Zero-hop advertenties zijn minder belastend voor het netwerk omdat ze niet doorgegeven worden, maar ook zij tellen mee voor de lokale airtime. De waarde van 4 uur is een goede balans tussen zichtbaarheid voor directe buren en airtime-verbruik.

Praktische richtlijnen:

Samenvatting: gebruik set flood.advert.interval 50 en set advert.interval 240 als standaard. Lagere waarden belasten het netwerk onnodig, zonder merkbaar voordeel voor de gebruiker.

Airtime Factor

Sinds firmwarev1.15.0 stel je de duty cycle direct in procenten in met set dutycycle. De oudere airtime factor (set af) is daarmee officieel deprecated, gebruik dutycycle op alle nieuwe installaties.

De huidige instelling: dutycycle

set dutycycle <waarde> neemt een percentage van 1 tot 100. De standaardwaarde is 50%, wat véél ruimer is dan de Nederlandse sub-band P toestaat. Zet dit dus bewust:

set dutycycle 10
WaardeEffect
100Geen duty cycle-limiet
50Firmware-standaard: te ruim voor NL
10Wettelijke limiet sub-band P, gebruik dit
1Strengste EU-eis (andere sub-banden)

De oude instelling: af (airtime factor)

Op firmware ouder dan v1.15.0 bestaat alleen set af <waarde>, met waarde 0–9. Let op de richting. Die is tegenovergesteld aan wat je intuïtief zou verwachten: na elke zending houdt de repeater een stilteperiode aan van ongeveer de zendtijd × de factor. De resulterende duty cycle is grofweg 1 / (1 + factor):

Airtime FactorResulterende duty cycle
1 (firmware-standaard)~50%
2~33%
3~25%
9~10%

Praktische richtlijnen:

Samenvatting:set dutycycle 10 op v1.15.0+. Op oudere firmware set af 9. Bron: CLI-referentie, dutycycle.

Loop Detection

In een mesh-netwerk kan een pakket in theorie blijven rondreizen: repeater A stuurt door naar B, B naar C, C stuurt het terug naar A. Loop detection voorkomt dit door te tellen hoe vaak de eigen ID/hash al in het pad van een flood-pakket voorkomt, en het pakket boven een drempel te weigeren.

De functie is toegevoegd in firmwarev1.14 en kent vier niveaus. De drempel hangt af van de pad-hashgrootte van het pakket, bij een grotere hash is herhaling van dezelfde ID veel onwaarschijnlijker, dus wordt er strenger geteld:

NiveauDrempel bij 1-byte2-byte3-byte
off(geen detectie: firmware-standaard)()
minimal≥ 4×≥ 2×≥ 1×
moderate≥ 2×≥ 1×≥ 1×
strict≥ 1×≥ 1×≥ 1×

Een pakket wordt geweigerd zodra de eigen hash het aantal keren uit de tabel in het pad voorkomt. Bij minimal mag een 1-byte pakket dus nog drie keer via dezelfde repeater lopen voordat het gedropt wordt. Dat klinkt ruim, maar 1-byte ID's botsen nu eenmaal vaak, en een lagere drempel zou legitieme pakketten van naamgenoten treffen. Bij strict is één keer al genoeg, ongeacht de hashgrootte.

Let op: de firmware-standaard is off. Loop detection staat dus niet vanzelf aan, je moet dit expliciet instellen.

Praktische richtlijnen:

Samenvatting:set loop.detect minimal voor vrijwel elke installatie. Bron: CLI-referentie, loop.detect.

Multi-byte Path Hash (pad-hashing)

Elk pakket in MeshCore bevat een pad: een lijst van de repeaters die het bericht al gepasseerd heeft. Iedere repeater in dat pad wordt geïdentificeerd door een hash van zijn publieke sleutel. Hoe lang die hash is, bepaalt hoeveel repeaters uniek te onderscheiden zijn én hoeveel hops een pakket maximaal kan maken.

Het probleem met 1 byte (origineel)

In het originele protocol werd slechts 1 byte (8 bits) van de publieke sleutel gebruikt als repeater-ID. Dat levert maximaal 254 unieke ID's op (waarden 00 en FF zijn gereserveerd). In een klein netwerk is dat voldoende, maar naarmate het Nederlandse mesh groeide ontstond er een probleem: meerdere repeaters kunnen dezelfde eerste byte in hun publieke sleutel hebben. Het mesh stuurt pakketten gewoon door (forwarding werkt correct) maar analysetools zoals LetsMesh.net Analyzer en MeshMapper kunnen repeaters niet meer uniek identificeren. Padanalyse wordt onbetrouwbaar; het is puur een diagnostiek-probleem.

Multi-byte hashing (firmware v1.14+)

Vanaf firmwarev1.14 kunnen repeaters en companion-apparaten pakketten versturen met een 2- of 3-byte pad-hash. De path-sectie van een LoRa-pakket heeft een maximale omvang van circa 64 bytes. Een langere hash per repeater betekent dus minder hops mogelijk:

Hash-grootteUnieke IDsMax. hopsCLI-waarde (repeater)
1 byte (origineel)25464 hopsset path.hash.mode 0(standaard)
2 bytes(aanbevolen)~65.00032 hopsset path.hash.mode 1
3 bytes~16,6 miljoen21 hopsset path.hash.mode 2

(De "hash" is geen berekende hash maar simpelweg de eerste 1, 2 of 3 bytes van de publieke sleutel. Omdat de eerste byte nooit 00 of FF mag zijn, zijn er 254 mogelijkheden bij 1 byte en 254 × 256 ≈ 65.000 bij 2 bytes. Bron: FAQ 3.9, multibyte support en Identity.h.)

Belangrijk:path.hash.mode bepaalt uitsluitend de hash-grootte van de eigen advertenties van de repeater. Het heeft geen invloed op welke pakketten de repeater doorstuurt, een repeater met v1.14+ stuurt altijd 1-, 2- én 3-byte pakketten door.

Waarom 2 bytes?

Backward compatibility

Repeaters met firmware ouder dan v1.14 verwerpen 2- en 3-byte pakketten stilzwijgend. Er zijn twee aparte instellingen:

Repeater. Stel path.hash.mode 1 direct in via de CLI. Dit geldt alleen voor eigen advertenties en is altijd veilig:

set path.hash.mode 1

Companion (app): de hash-grootte voor berichten en kanaalberichten stel je in via Instellingen → Experimentele Instellingen → Default Path Hash Size. Schakel dit pas om naar 2 bytes als de overgrote meerderheid van de repeaters in jouw regio op v1.14+ draait, pre-1.14 repeaters laten deze berichten anders stilzwijgend vallen.

De Nederlandse community heeft dit als onderdeel van The Change (9 mei 2026) opgenomen in de voorbereidingsstappen.

Regelgeving Sub-band P

Frequentiebereik: 869.4-869.65 MHz
Maximaal vermogen: 500 mW ERP (*) (+27 dBm)
Duty cycle: ≤ 10%, de regelgeving noemt LBT + AFA als alternatief, maar dat is voor MeshCore geen begaanbare route (zie hieronder)
Regulering: ETSI EN 300.220, RDI

Sub-band P biedt aanzienlijk hogere zendvermogens (500 mW ERP) vergeleken met de standaard sub-banden (25 mW), waardoor grotere dekking mogelijk is. Dit maakt het bijzonder geschikt voor repeater/gateway implementaties. De duty cycle van 10% is ruimer dan de 1% beperking voor andere sub-banden, maar het betekent ook dat je dit vermogen niet continu mag gebruiken. Bij intensief gebruik (hoge packet-frequentie of lange time-on-air) moet je de duty cycle actief bewaken om binnen de regelgeving te blijven.

De Nederlandse H-regels: waar het precies staat

"Sub-band P" is ETSI-taal. De regel waar je in Nederland op wordt afgerekend staat ergens anders: in Bijlage 11, Subcategorie 1 (niet-specifieke korteafstandsapparatuur) van de Regeling gebruik van frequentieruimte zonder vergunning en zonder meldingsplicht 2015. Die bijlage kent de rijen H1 tot en met H7, en dát zijn de getallen waar de RDI naar kijkt.

Hieronder de rijen zoals ze in de geldende tekst staan (versie 1 juli 2025), rechtstreeks uit de Regeling overgenomen:

RijFrequentiebandMax. vermogenDuty cycle
H1863,000 – 865,000 MHz25 mW e.r.p.< 0,1%
H2865,000 – 868,600 MHz25 mW e.r.p.< 1,0%
H3868,700 – 869,200 MHz25 mW e.r.p.< 0,1%
H4869,400 – 869,650 MHz500 mW e.r.p.< 10%
H5869,400 – 869,650 MHz25 mW e.r.p.< 0,1%
H6869,700 – 870,000 MHz5 mW e.r.p.(geen)
H7869,700 – 870,000 MHz25 mW e.r.p.< 1,0%

H4 en H5 dekken exact dezelfde band. Dat is geen fout in de tabel: het zijn twee regimes waaruit je kiest, en die keuze bepaalt waartegen je apparatuur gecertificeerd moet zijn. H4 geeft je twintig keer het vermogen en honderd keer de zendtijd van H5, vandaar dat MeshCore in Nederland op H4 zit. Voor een repeater die andermans verkeer doorgeeft is de 3,6 seconden per uur van H5 simpelweg onwerkbaar.

Twee dingen die je hier moet meenemen:

Je zit waarschijnlijk al in H4, of je het wil of niet. Vrijwel alle MeshCore-hardware draait op een SX1262 die tot +22 dBm (158 mW) gaat. Dat is bij elke antenne al ruim boven de 25 mW van H5. Wie bewust onder H5 wil blijven moet het zendvermogen terugbrengen tot ongeveer +14 dBm, met een dipool kom je dan op 25 mW e.r.p. uit.

De duty cycle geldt per apparaat, niet per netwerk. De Regeling beschrijft één zendend apparaat. Twintig repeaters die elk op 9% zitten overtreden formeel niets, ook al is de band lokaal dichtgeslibd. En doorgegeven verkeer is juridisch jouw uitzending: hoe drukker het mesh, hoe sneller je eigen budget volloopt. Dat is precies de reden waarom set dutycycle 10 en een ruim advert-interval geen etiquette zijn maar noodzaak.

Het LBT+AFA-uitweggetje geldt hier niet. De Regeling staat bij H1 t/m H5 en H7 toe om de duty cycle te vervangen door "technieken om toegang te krijgen tot spectrum en interferentie te onderdrukken", in de praktijk Listen Before Talk plus Adaptive Frequency Agility. Die tweede helft is het probleem: AFA betekent tussen kanalen springen, en MeshCore draait in Nederland op één vaste frequentie. Voor NL-nodes blijft dus alleen de duty-cycle-route over.

Sinds v1.17.0 heeft de firmware wél echte listen-before-talk, met verbeterde preamble-detectie, en kun je met set cad on ook de hardware-kanaalscan van de radiochip inschakelen (zie Listen before talk en hardware-CAD). Dat maakt het netwerk rustiger, maar verandert niets aan de regels: zonder AFA en zonder certificering blijft set dutycycle 10 verplicht. (Bron: release 1.17.0.)

(Terzijde: de tekst van Bijlage 11 verwijst voor die technieken nog naar richtlijn 1999/5/EG, de R&TTE-richtlijn die sinds 13 juni 2016 is ingetrokken en vervangen door de RED 2014/53/EU. De regelingtekst is op dat punt nooit bijgewerkt; lees het als "de opvolger daarvan".)

Juridische Status Nederland

Het gebruik van 869.618 MHz is volledig legaal in Nederland en de EU, zolang wordt voldaan aan:

Nederlandse rechtsgrond

De keten loopt van wet naar concrete band-regel in drie stappen:

DocumentWat het doet
Wet: Telecommunicatiewet, art. 3.9Bepaalt dat bepaald frequentiegebruik zonder vergunning mag
AMvB: Frequentiebesluit 2013, art. 2Delegeert de uitwerking naar een ministeriële regeling
Regeling: zonder vergunning en zonder meldingsplicht 2015Bijlage 11 bevat de concrete rijen H1–H7 met band, vermogen en duty cycle

Die laatste regel is waar je het uiteindelijk van moet hebben: rij H4 in Bijlage 11 geeft 869,400–869,650 MHz vrij tot 500 mW e.r.p. bij een duty cycle onder de 10%. Zie De Nederlandse H-regels voor de volledige tabel.

Voor de eisen aan de apparatuur zelf (zendvermogen, frequentiestabiliteit, ontvangerprestaties) verwijst de regelgeving naar de geharmoniseerde Europese norm ETSI EN 300 220-2 V3.3.1, onder de Radio Equipment Directive 2014/53/EU.

Pas op met de naamgeving. Er wordt online vaak verwezen naar een "Besluit gebruik van frequentieruimte zonder vergunning 2015" als grondslag voor licentievrij zenden. Onder die naam bestaat geen regeling. Wat wél bestaat zijn twee ministeriële regelingen die makkelijk verward worden, en die precies het tegenovergestelde publiek bedienen:

BWBROfficiële titelVoor wie
BWBR0036378Regeling gebruik van frequentieruimte zonder vergunning en zonder meldingsplicht 2015SRD/LPD, hier valt MeshCore onder
BWBR0036375Regeling gebruik van frequentieruimte met meldingsplicht 2015Onder meer radiozendamateurs (registratie vereist)

De tweede is de regeling waarin artikel 10 staat met de amateurvoorschriften. Het versleutelingsverbod, de roepletterplicht. Die is dus juist niet van toepassing als je op 869,618 MHz als SRD-gebruiker zendt. Zie MeshCore op 433 MHz voor waarom dat onderscheid uitmaakt.

Rijksinspectie Digitale Infrastructuur (RDI)

De RDI is de toezichthouder. Zij handhaaft de regels en geeft praktische richtlijnen, maar is niet de rechtsgrond. Het recht om zonder vergunning te zenden ontleen je uitsluitend aan de Telecommunicatiewet, het Frequentiebesluit en de Regeling, niet aan de RDI-richtlijnen.

Voor het gebruik van 869,618 MHz is dus geen vergunning of melding nodig, mits je binnen rij H4 van Bijlage 11 blijft en de apparatuur voldoet aan ETSI EN 300 220.

MeshCore op 433 MHz voor radiozendamateurs?

Een vraag die met enige regelmaat langskomt: je bent radiozendamateur, je mag op 70 cm veel meer vermogen dan de 500 mW van sub-band P, kun je MeshCore dan niet gewoon op 433 MHz zetten en verder komen? Het antwoord is nee, en de reden is fundamenteel genoeg om hier uit te schrijven.

Wat MeshCore zelf ondersteunt

De officiële FAQ is kort: MeshCore ondersteunt het 868 MHz-bereik (UK/EU) en het 915 MHz-bereik (Nieuw-Zeeland, Australië, VS). Voor 433 MHz bestaan geen regio-presets. De firmware draait wel op 433-hardware (T-Deck, RAK4631, Heltec V3 in de 433-uitvoering) en je kunt met set freq of tempradio elke frequentie invoeren, technisch kan het dus. Ondersteund is iets anders.

Twee regelkaders, en je moet kiezen

Het frequentiegebied 433,050–434,790 MHz wordt in Nederland gedeeld door twee heel verschillende groepen, met elk hun eigen regels (RDI):

Vergunningvrij (SRD/LPD)Radiozendamateur
Status in de bandNIB-gebruikerPrimair gebruiker
Zendvermogen10 mW, vaste antenne aan het apparaatVolgens registratie, fors meer
VersleutelingToegestaanNiet toegestaan
RoeplettersNiet van toepassingVerplicht
Verbindingen metAndere LPD-gebruikersAlleen andere amateurs

NIB betekent dat je storing van primaire gebruikers moet accepteren én zelf zoveel mogelijk moet voorkomen. Merk meteen het pijnpunt op: 10 mW is vijftig keer minder dan de 500 mW ERP die je op 869.618 MHz mag gebruiken. Als licentievrije route levert 433 MHz dus fors bereik in, niet meer.

Wat is "SRD-apparatuur" eigenlijk?

Het onderscheid zit niet alleen in de frequentie, maar in het apparaat zelf, en dat verrast veel mensen. De RDI trekt de scheidslijn zo:

SRD- / LPD-apparatuurAmateurapparatuur
Waar komt het vandaanVrij in de handel verkrijgbaarOok zelfbouw toegestaan
Herkenbaar aanCE-markering, bestemd voor LPD-gebruikGeen markteis; bestemd voor radiozendamateurs
ZendvermogenMaximaal 10 mW (in 433 MHz)Volgens je registratie
AntenneVast aan het apparaatVrij te kiezen
Wie mag het gebruikenIedereenAlleen geregistreerde amateurs

Een Heltec- of RAK-bordje dat je als kant-en-klaar product met CE-markering koopt en binnen de gestelde grenzen gebruikt, is SRD-apparatuur. Datzelfde bordje met een zelfgebouwde eindtrap of een externe antenne op het dak, gebruikt onder je registratie op amateurvermogen, is amateurapparatuur. Hetzelfde stukje hardware, twee regelkaders.

En dat heeft een consequentie die zelden genoemd wordt:

Als u geen gelicenseerde radiozendamateur bent, dan mag u geen apparatuur voor zendamateurs gebruiken, aanleggen, of geheel of gedeeltelijk aangelegd aanwezig hebben.

Niet alleen gebruiken dus: ook aanwezig hebben. Wie geen registratie heeft, houdt het bij apparatuur die als SRD op de markt is gebracht.

Waarom de amateurroute dichtzit

Blijft over: het onder je eigen registratie doen, als amateurgebruik. Dan geldt artikel 10, eerste lid, van de Regeling gebruik van frequentieruimte met meldingsplicht 2015, en daar lopen vier bepalingen stuk op hoe MeshCore werkt:

f. informatie wordt niet versleuteld verzonden

Dit is de kern. MeshCore versleutelt altijd: directe berichten met AES-128 en HMAC op basis van een ECDH-sleutel, kanaalberichten met een gedeelde sleutel. Er is geen plaintext-modus en die valt ook niet aan te zetten, encryptie zit in het protocolontwerp, niet in een instelling. Let op dat de Nederlandse bepaling onvoorwaardelijk is; het internationale ITU Radioreglement 25.2A verbiedt versleuteling alleen tussen amateurstations van verschillende landen, maar Nederland kent die beperking niet.

d. de combinatie van letters of cijfers is bij data- en beeldoverdracht aan de ontvangstzijde na demodulatie in leesbaar schrift zichtbaar

Je roepletters moeten na demodulatie leesbaar zijn. Bij MeshCore is de payloadciphertext, dus dat kan per definitie niet.

g. radioverbindingen worden alleen tot stand gebracht met andere gebruikers van frequentieruimte met de bestemming ‘amateur’ of ‘amateursatelliet’

Een mesh waaraan iedereen met dezelfde firmware kan deelnemen, laat zich niet beperken tot geregistreerde amateurs.

a. de radiozendamateur bedient het radioapparaat zelf en, indien hij niet aanwezig is, draagt er zorg voor dat alleen hij zijn radioapparaat op afstand kan bedienen

Een repeater die onbeheerd het verkeer van anderen doorgeeft, verhoudt zich slecht tot deze bepaling.

Daarnaast schrijft c. voor dat je roepletters minstens bij begin en einde van elke uitzending klinken, en minimaal elke vijf minuten.

En andersom: gebruik je roepletters níet op ISM

De RDI is hier expliciet over, en het is een punt dat veel amateurs verrast:

Als een zendamateur SRD apparatuur gebruikt en een verbinding maakt met een andere LPD gebruiker is het niet nodig en ongewenst om amateurroepletters te gebruiken.

Draai je MeshCore op 869.618 MHz, dan doe je dat als SRD-gebruiker, niet als amateur. Je nodenaam mag natuurlijk van alles zijn, maar je zendt daar geen amateurverkeer uit en je roepletters horen er niet thuis. De RDI waarschuwt in hetzelfde document voor het vermengen van beide werelden, omdat daardoor het beeld ontstaat dat een amateurexamen niet meer nodig zou zijn.

Wat wél kan op 70 cm

LoRa-mesh op de amateurband bestaat, alleen niet met MeshCore. De projecten die daarvoor ontworpen zijn werken onversleuteld en op basis van roepletters:

ProjectFrequentieMeer informatie
MeshCom433,175 MHzicssw.org/meshcom · ÖVSV-wiki · firmware op GitHub
LoRa-APRS433,775 MHz uplink · 433,900 MHz downlinkiGate · tracker · live logs

MeshCom is een project van het Institute of Citizen Science (ICSSW), ontwikkeld met de Oostenrijkse ÖVSV, en is expliciet voor radiozendamateurs ontworpen: tekstcommunicatie via LoRa in de 70cm-band, met gateways die via HAMNET aan elkaar geknoopt kunnen worden zodat losstaande mesh-eilanden elkaar toch bereiken. Dat is precies de architectuur die je onder een amateurregistratie wél mag draaien.

LoRa-APRS is geen mesh maar een LoRa-variant op het klassieke APRS: trackers zenden hun positie uit, iGates zetten dat door naar het APRS-IS-netwerk. Let op 433,775 MHz: daar draait dit al jaren, dus daar moet je geen ander mesh overheen leggen.

Samengevat: licentievrij lever je op 433 MHz vijftig keer vermogen in; onder je registratie botst MeshCore op het versleutelingsverbod van artikel 10. Wie MeshCore wil, blijft op 869.618 MHz, en laat de roepletters daar achterwege. Wie LoRa op 70 cm wil, kijkt naar MeshCom.

Antennes en Effectief Uitgestraald Vermogen (ERP)

Het maximaal toegestane vermogen van 500 mW ERP (+27 dBm) op 869.618 MHz is niet hetzelfde als het zendvermogen van je apparaat. Het ERP wordt berekend volgens de formule:

ERP = Zendvermogen − Kabelverliezen + Antennegain in dBd

Let op de eenheid. Dit gaat vaak mis.Effective Radiated Power is per definitie gemeten ten opzichte van een halvegolf-dipool, dus je vult de antennegain in dBd in. Datasheets vermelden tegenwoordig vrijwel altijd dBi (ten opzichte van een isotrope straler), en die waarde is 2,15 dB hoger: dBd = dBi − 2,15. Reken je met dBi door, dan bereken je in feite EIRP en kom je 2,15 dB te hoog uit, je denkt dan dat je over de limiet zit terwijl dat niet zo hoeft te zijn. (Bron: ETSI EN 300 220-1 V3.1.1 §5.2, e.r.p. is gedefinieerd t.o.v. de halvegolf-dipool; de Nederlandse Regeling hanteert diezelfde eenheid mW e.r.p. Voor banden boven 1 GHz gebruikt de regelgeving juist e.i.r.p., vergis je daar niet in.)

De rekenhulp hieronder houdt hier rekening mee: vul je dBi in, dan trekt hij er zelf 2,15 dB af.

Antennetypes in de praktijk

Gain versus openingshoek

Antennegain is geen echte versterking. Het is concentratie. Een antenne met hogere gain "knijpt" het stralingsveld samen in één richting, ten koste van de andere richtingen. Hoe hoger de gain, hoe smaller de bundel:

GainVerticale openingshoek (ca.)Typisch gebruik
0 – 2 dBi75° – 90°Handheld companion, korte afstanden
3 – 5 dBi45° – 60°Standaard repeater, stedelijk gebied
6 – 8 dBi20° – 35°Repeater op hoogte, vlak terrein
9 – 12 dBi10° – 18°Hilltop / lange afstand omni
13+ dBi (Yagi/panel)5° – 12°Punt-naar-punt verbinding

Indicatieve waarden. De relatie tussen gain en openingshoek is geen vaste formule: twee antennes met dezelfde 6 dBi kunnen een merkbaar ander stralingspatroon hebben, afhankelijk van constructie en aantal elementen. Gebruik deze tabel om een antenne te kiezen; gebruik het stralingsdiagram uit het datasheet van jouw specifieke antenne om te rekenen. Datzelfde geldt voor de openingshoeken in de dodezone-tabel verderop.

Een omnidirectionele antenne straalt in de horizontale vlak altijd 360°, maar de verticale openingshoek wordt smaller naarmate de gain toeneemt. Het stralingsveld lijkt op een frisbee: hoge gain = dunnere frisbee.

Wanneer welke antenne?

Lage gain omni (0–5 dBi). Gebruik bij:

Hoge gain omni (6–12 dBi). Gebruik bij:

Let op bij hoge gain omni op hoogte: hoe hoger de gain, hoe groter de kans dat nodes die dichtbij en laag staan buiten de bundel vallen. Een repeater op 30 meter hoogte met een 10 dBi antenne kan moeite hebben om een node op straatniveau op 100 meter afstand te bereiken. Die valt in het "gat" recht onder de antenne.

Richtantenne / Yagi / panel (13+ dBi), gebruik bij:

De dode zone: reken hem uit vóór je de mast in gaat

Dat "gat" onder de antenne is geen vaag verschijnsel, je kunt op een bierviltje uitrekenen of jouw eigen node erin valt. Een verticale omni straalt namelijk niet bolvormig maar in een donutvorm om de mast heen; recht boven en recht onder gaat vrijwel geen energie heen. Hoe hoger de gain, hoe platter die donut en hoe breder het schaduwgebied op de grond.

AntennetypeGainVerticale openingshoek (indicatief)
Kwartgolf groundplane0 dBi~60°
Halvegolf-dipool2,2 dBi~50°
5/8-golf whip3 dBi~45°
2×5/8 collineair6 dBi~15–30°
3×5/8 collineair9 dBi~8–15°

Of jouw node binnen of buiten de bundel valt hangt af van de depressiehoek: de hoek waaronder de repeater naar jou "omlaag kijkt".

depressiehoek = arctan(hoogteverschil / horizontale afstand)

Met een 6 dBi collineair pakt dat zo uit:

HoogteverschilHorizontale afstandDepressiehoekDekking
10 m200 m~3°In de piek van de bundel
15 m100 m~9°Binnen de lob, prima
20 m50 m~22°Randgebied, aanzienlijk verlies
26 m25 m~46°Ver in de dode zone

Praktijkvoorbeeld uit Zwolle. Een repeater op 21 m hoogteverschil en 25 m afstand werkte prima met een 3 dBi antenne (depressiehoek 40°). Toen kwamen er twee wijzigingen tegelijk: de mast ging 5 m omhoog (hoek naar 46°) én de antenne werd een 6 dBi collineair (openingshoek van ~45° naar ~18°). Elk van beide apart was te overleven geweest; de combinatie tilde de thuisnodes precies de dode zone in.

Verwarrend detail: het voelt vaak alsof alleen zenden stuk is en ontvangen nog werkt. Antennepatronen zijn echter reciprook, de bundel is voor zenden en ontvangen identiek. Het lijkt asymmetrisch omdat de repeater op hoger vermogen zendt en in een schonere RF-omgeving staat, terwijl jij thuis in lokale ruis zit. Snelle test: loop een paar honderd meter van huis weg. Werkt zenden daar ineens weer, dan zat je onder de hoofdlob.

Oplossingen, in volgorde van eenvoud:

Vuistregel: reken de depressiehoek uit voor je belangrijkste lokale nodes. Boven ongeveer 20° is een antenne van 6 dBi of meer een risico. En hoger plaatsen is niet gratis: elke meter extra hoogte vergroot de dode zone op de grond.

(Gebaseerd op het hoofdstuk "Dode Zone" uit de MeshCore-handleiding van PE1HVH en de DOMCA-documentatiereeks; de hoekberekeningen zijn nagerekend.)

Keuzehulp: stel jezelf deze vragen

  1. Hoe hoog staat de repeater? Hoog geplaatst + vlak terrein → hogere gain omni is zinvol. Laag of in bebouwing → lage gain omni geeft betere algehele dekking.
  2. Waar bevinden de nodes zich? Rondom in alle richtingen → omni. Voornamelijk in één richting → richtantenne.
  3. Hoe dicht zijn de dichtstbijzijnde nodes? Nodes dicht in de buurt (< 500 m) + hoge gain → risico op "dode zone" onder de antenne. Kies dan lagere gain of kantel de antenne licht.
  4. Wat is het doel? Maximaal bereik in één richting → Yagi/panel. Zo veel mogelijk nodes in de omgeving bedienen → omni.
  5. Wat is het ERP-budget? Een 10 dBi antenne (= 7.85 dBd) op een radio met 22 dBm zendvermogen komt op 29.85 dBm ERP, bijna 3 dB boven de limiet van 27 dBm. Hogere gain dwingt je dus het zendvermogen te verlagen.

Companion devices vs. repeaters

Companion devices (handheld, mobiel):

Repeaters (vast opgesteld):

Technische Parameters

De Nederlandse preset gebruikt BW 62.5 kHz (narrowband), ongewijzigd vóór en na The Change. Wat wél verandert op 9 mei 2026 is de spreading factor en coding rate. Hieronder een directe vergelijking:

ParameterVóór 9 mei (SF8/CR8)Na 9 mei (SF7/CR5)Verschil
Spreading FactorSF8SF71 stap lager
Coding RateCR8 (4/8)CR5 (4/5)Minder redundantie
Bandbreedte62.5 kHz62.5 kHzOngewijzigd
Netto datarate~0.98 kbit/s~2.73 kbit/s2.8× sneller
Time-on-air (50-byte pakket)~510 ms~180 ms2.8× korter
Pakketten/uur (10% duty cycle)~700~2.0002.8× meer capaciteit
Ontvanggevoeligheid−132 dBm−129 dBm~3 dB minder gevoelig
Foutcorrectie overhead50%20%Minder robuust
Maximaal bereik (vrij veld)~100% (referentie)~85%Licht minder bereik

Hoe deze cijfers tot stand komen. Datarate en time-on-air zijn berekend met de standaard LoRa-formules uit de Semtech SX1276 datasheet (§4.1.1): R = SF × BW / 2^SF × 4/(4+CR) en de symbol-formule voor de pakketduur, met BW 62,5 kHz, 8 preamble-symbolen, expliciete header en CRC aan. Voor een pakket van 50 bytes geeft dat ~509 ms op SF8/CR8 en ~195 ms op SF7/CR5. Je komt elders wel hogere waarden tegen (300+ ms voor SF7); die zijn met andere aannames gerekend. Reken het na met een online LoRa airtime-calculator als je twijfelt, de verhouding van 2,8× tussen beide presets blijft in alle varianten overeind, en dát is waar de omschakeling om draaide.

Wat betekent dit in de praktijk?

Spreading Factor: het hart van de wijziging

De spreading factor bepaalt hoeveel symbolen er per bit gebruikt worden. SF8 gebruikt 2⁸ = 256 chips per symbool, SF7 gebruikt 2⁷ = 128 chips. Die factor 2 is direct terug te zien in de time-on-air: een pakket op SF7 is ruwweg half zo lang in de lucht als op SF8. Elk pakket dat korter duurt, maakt meer ruimte voor andere pakketten op hetzelfde kanaal, precies wat een overbelast mesh nodig heeft.

Coding Rate: minder verpakking, meer inhoud

De coding rate bepaalt de verhouding tussen nuttige data en foutcorrectiebits. CR8 (4/8) voegt voor elke 4 databits 4 controlbits toe, 50% overhead, maximale bescherming. CR5 (4/5) voegt slechts 1 controlbit toe per 4 databits, 20% overhead. Dat scheelt 30% aan "verspilde" zendtijd per pakket. In een rustige, goed-opgezette mesh is de lagere foutcorrectie geen probleem: de kans op een bitfout is laag genoeg dat CR5 ruimschoots voldoet.

Gevoeligheid en bereik

Elke SF-stap omlaag kost circa ~3 dB ontvanggevoeligheid (bron: SX1262 datasheet en The Switch, meshwiki.nl). Dit vertaalt zich in een iets kleiner maximaal bereik onder marginale omstandigheden (~15% minder). In de praktijk is dit nauwelijks merkbaar: een goed geplaatste repeater op SF7 bereikt nog altijd dezelfde nodes als op SF8, omdat de meeste verbindingen ruim boven de minimale signaallimiet zitten. Het Nederlandse mesh kiest bewust voor capaciteit boven maximaal bereik.

Het netto effect: 2.8× meer ruimte in het netwerk

Kortere time-on-air + minder foutcorrectiebits samen leveren bijna drie keer zoveel beschikbare pakkettencapaciteit op binnen dezelfde 10% duty cycle. Dat lost het congestieprobleem structureel op.

Typisch bereik (ongewijzigd):, ordegroottes uit de praktijk, geen gemeten waarden; terrein, opstelhoogte en bebouwing wegen zwaarder dan welke instelling ook.

SituatieBereik
Open veld, line-of-sight, hoog geplaatst10+ km
Bebouwde omgeving / handheld1–5 km realistisch
Via repeater-ketenHonderden km (hop voor hop)

Licentie & Ontwikkeling

De MeshCore-firmware is open-source uitgebracht onder de MIT License, vrij te gebruiken, modificeren en distribueren. Niet alle apps en tools rondom het ecosysteem zijn volledig open source, sommige companion-apps en premium features zijn closed source of vereisen een licentie. Het project wordt actief ontwikkeld door de community, met discussies en ondersteuning beschikbaar via:

Sommige premium features (zoals ESP-NOWbridge licentie) zijn beschikbaar om de ontwikkeling van het project te financieren.

Wat is die bridge precies? Een bridge koppelt twee mesh-segmenten die elkaar over de radio niet kunnen bereiken, bijvoorbeeld twee gebouwen, of een repeater binnen en een antenne buiten. Het verkeer loopt dan via ESP-NOW (draadloos, op WiFi-hardware) of RS-232 (kabel) in plaats van via LoRa. De bijbehorende commando's zitten gewoon in de firmware, mits die met bridge-ondersteuning gebouwd is: bridge.enabled, bridge.source, bridge.delay, bridge.baud (RS-232) en bridge.channel plus bridge.secret (ESP-NOW). Zie de CLI-referentie voor de details per commando.

Aan de slag (video)

Volg ook zeker het kanaal van Andy Kirby voor meer informatie over MeshCore.

Achtergrond: Andy Kirby was een prominent lid van het MeshCore-team en maakte populaire instructievideo's. In april 2026 diende hij echter zonder medeweten van de rest van het team een trademark-aanvraag in voor de naam "MeshCore". Daarop besloot het kernteam zelfstandig verder te gaan onder meshcore.io. De technische inhoud van zijn video's is nog steeds bruikbaar, maar zijn site meshcore.co.uk valt niet onder het officiële project. Zie Projectsplit (april 2026) voor de volledige achtergrond.

ERP Calculator

ERP Calculator

of
m
dB
× 0.15 dB/stuk

⚡ Vermogen Calculator van dBm naar (m)W (en vice versa)

dB, dBi en dBm: wat is het verschil?

TermWat het isWanneer gebruik je het
dBDecibel. Een relatieve verhoudingVerlies of versterking: "3 dB verlies = signaal gehalveerd"
dBmdB t.o.v. 1 milliwatt. absoluut vermogenZendvermogen: "20 dBm = 100 mW"
dBidB t.o.v. een isotrope stralerAntennegain: "5 dBi = antenne bundelt 3× meer dan een bolstraler"
dBddB t.o.v. een halve-golf dipoolDe eenheid die de regelgeving voor e.r.p. gebruikt: dBi = dBd + 2,15 (de dipool heeft zelf al 2,15 dBi gain)

Vuistregel voor dB (vermogen): dB is een verhouding, geen vaste hoeveelheid. Elke +3 dB verdubbelt het vermogen (×2) en elke −3 dB halveert het (÷2); +10 dB is 10× zoveel vermogen en −10 dB nog maar een tiende (÷10). Voorbeeld: +6 dB = ×4 (2× verdubbelen), −6 dB = ÷4.

Omdat dB een logaritmische schaal is, tel je dB-waarden op in plaats van te vermenigvuldigen. Dat is precies waarom de ERP-formule werkt met optellen en aftrekken:

ERP (dBm) = Zendvermogen (dBm) − Kabelverliezen (dB) + Antennegain (dBd)

Staat de gain van je antenne in dBi (en dat is meestal zo) reken hem dan eerst om: dBd = dBi − 2,15. Vul je de dBi-waarde rechtstreeks in, dan reken je EIRP uit in plaats van ERP en zit je er 2,15 dB naast.


Het maximaal toegestane vermogen van 500 mW ERP (+27 dBm) op 869.618 MHz is niet hetzelfde als het zendvermogen van je apparaat.

Uitleg van de componenten

Zendvermogen (TX Power)
Het vermogen dat je radio uitzendt, meestal instelbaar in de firmware. De meeste MeshCore-hardware (Heltec, RAK, LilyGO) zendt typisch tot max 22 dBm (158 mW), afhankelijk van het model.

Let op bij versterkte modules, de ingestelde waarde is níet de uitgestraalde waarde. Boards met een ingebouwde eindversterker sturen je instelling door een PA-trap heen. Wat je in de app of met set tx invult is de waarde vóór die versterking:

Bord / moduleInstellingWerkelijke output
Heltec V4: standaard10 dBm22 dBm (~0,15 W)
Heltec V4: high output22 dBm28 dBm (~0,5–0,6 W)
Station G2: EU868, 1 W9 dBm1 W
Ikoka Stick E22-900M30S19 dBm1 W
Ikoka Stick E22-900M33S9 dBm2 W

Twee redenen om dit serieus te nemen. Ten eerste: 1 W of 2 W zit ver boven de 500 mW ERP die sub-band P toestaat, zonder dat je het aan je instelling ziet. Ten tweede waarschuwt de fabrikant expliciet dat een te hoge instelling de eindtrappermanent kan doorbranden. Zoek de juiste waarde voor jouw specifieke bord op vóór je zendt, en reken daarna pas je ERP uit met de calculator hieronder.

(Bron: MeshCore FAQ 7.7, inclusief datasheets per module.)

Kabelverliezen
Verliezen in de coaxkabel tussen radio en antenne. Deze zijn afhankelijk van:

Antenne Gain

De "versterking" van de antenne ten opzichte van een isotrope antenne (dBi). Let op:

Praktijkvoorbeelden

Voorbeeld 1: Companion device met korte kabel

Voorbeeld 2: Repeater met richtantenne

Voorbeeld 3: Repeater met lange kabellengte

Belangrijke tips

  1. Minimaliseer kabelverliezen: Gebruik zo kort mogelijke kabel van goede kwaliteit
  2. Berekentools: Gebruik online dBm/mW calculators voor nauwkeurige berekeningen
  3. Meetapparatuur: Bij twijfel kun je het daadwerkelijke ERP laten meten door een specialist
  4. Veiligheidsmarge: Blijf liever onder de 27 dBm limiet om zeker binnen de wet te blijven
  5. Documentatie: Noteer je configuratie (zendvermogen, kabeltype/lengte, antenne) voor controles

Verantwoordelijkheid

Het is de verantwoordelijkheid van de gebruiker om ervoor te zorgen dat het totale uitgestraalde vermogen binnen de wettelijke limieten blijft. Bij controle door het RDI wordt het daadwerkelijk uitgestraalde vermogen gemeten, niet alleen het zendvermogen van het apparaat.


RSSI, SNR en Noise Floor

In MeshCore (en LoRa in het algemeen) zie je drie belangrijke waarden in logs, de app of de analyzer: RSSI, SNR en (soms impliciet) de noise floor. Hieronder een uitleg van wat ze betekenen, hoe je ze interpreteert en wat typische goede/slechte waarden zijn, gebaseerd op LoRa SX1262 chips met de Nederlandse narrow preset (BW 62.5 kHz / SF7).

De grenswaarden hieronder zijn vuistregels, geen specificatie. Ze komen uit praktijkervaring en zijn bedoeld om een meting te kunnen duiden, niet om een harde grens te trekken. De enige waarde die echt vastligt is de demodulatiedrempel van de chip zelf; alles daarboven hangt af van je ruisomgeving, antenne en opstelling. Twee locaties met dezelfde RSSI kunnen zich compleet anders gedragen.

RSSI (Received Signal Strength Indicator)

De absolute sterkte van het ontvangen signaal in dBm. Hoe dichter bij 0, hoe sterker; hoe meer negatief, hoe zwakker.

RSSISituatie
-50 tot -90 dBmSterk, lokaal, line-of-sight
-90 tot -110 dBmRedelijk, typisch op enkele kilometers
-110 tot -130 dBmZwak, grens van bereik, vaak nog decodeerbaar
onder -130 dBmTe zwak, packet loss, afhankelijk van SF

RSSI alleen zegt niet alles. Een signaal van -100 dBm kan prima werken bij weinig ruis, maar falen bij veel interferentie. Kijk altijd samen met SNR.

Noise Floor (ruisvloer)

Het niveau van achtergrondruis in dBm, thermische ruis plus interferentie van andere radios, WiFi, etc. MeshCore toont dit zelden direct, maar je ziet het indirect via RSSI en SNR.

OmgevingNoise floor
Buiten, rustig platteland-110 tot -125 dBm of lager
Stedelijk / met interferentie-95 tot -105 dBm

Narrow presets (BW 62.5 kHz) geven een lagere noise floor dan brede bandwidths. Dit is een van de redenen waarom Nederland bewust voor 62.5 kHz heeft gekozen. LoRa kan signalen onder de noise floor nog decoderen (dat is het principe achter spread spectrum), maar hoe lager de ruis, hoe beter je zwakke signalen oppikt.

SNR (Signal-to-Noise Ratio)

Het verschil tussen het ontvangen signaal en de noise floor in dB. Positief = signaal sterker dan ruis (makkelijk decoderen). Negatief = signaal zwakker dan ruis, LoRa kan dit nog steeds aan, tot een limiet.

Formule:SNR ≈ RSSI − noise floor

SNRKwaliteit
+5 tot +12 dBUitstekend, dichtbij of heel schone band
-5 tot +5 dBGoed, betrouwbaar, normaal mesh gebruik
-10 tot -5 dBRedelijk, 90-100% packet delivery
-15 tot -10 dBZwak, packet loss begint, maar werkt vaak nog
-18 tot -20 dBZeer zwak, alleen haalbaar bij hoge SF (SF11/12)
onder -20 dBOnbruikbaar, SF7/SF8 haalt dit niet meer

Snelle vuistregels (Nederlandse narrow preset)

SituatieRSSISNRVerwachting
Zeer sterk / lokaal-60 .. -85 dBm+5 .. +12 dBPerfect, geen drops
Goed bereik-85 .. -105 dBm-5 .. +5 dBBetrouwbaar normaal gebruik
Matig / op limiet-105 .. -120 dBm-10 .. -5 dBNog oké, gevoelig bij beweging
Ver / fringe-115 .. -130 dBm-15 .. -10 dBWerkt, maar onbetrouwbaar
Extreem / noise floor+-125 .. -140 dBm-18 .. -22 dBVeel drops, alleen hoge SF
Ruis overheerstelke RSSI< -20 dBDecodering faalt

Praktische tips


Veelgestelde vragen (FAQ)

Wat is MeshCore?
MeshCore is een open-source LoRamesh-netwerk voor tekstcommunicatie zonder internet of simkaart. Kleine radionodes geven berichten aan elkaar door via een zelf-organiserend netwerk.

Wat is het verschil tussen MeshCore en Meshtastic?
Beide gebruiken LoRa hardware, maar MeshCore kiest voor pad-gebaseerd routeren: nodes leren routes en sturen berichten direct door naar de bestemming. Meshtastic gebruikt flooding, elk bericht wordt door elke node doorgestuurd. MeshCore verbruikt daardoor minder zendtijd en veroorzaakt minder collisions in dichte netwerken. Zie Multi-Hop Packet Routing met Path Learning voor een gedetailleerde uitleg.

Hoe ver reikt een MeshCore node?
In open veld met line-of-sight en een hoog geplaatste node: 10+ km. In bebouwd gebied of handheld: realistisch 1–5 km. Via een keten van repeaters kunnen berichten honderden kilometers reizen. Zie Technische Parameters voor een bereiktabel per situatie.

Welke hardware heb ik nodig?
Populaire keuzes zijn de Heltec LoRa32 V3, LilyGo T-Deck (met scherm en toetsenbord), RAK Wireless (RAK4631) en Seeed Studio T1000-E. Voor de meeste gebruikers volstaat een companion node (~€20–50) in combinatie met de gratis mobiele app. Zie Hardware & Firmware Types voor een beschrijving van alle firmwaretypes.

Werkt MeshCore zonder internet?
Het protocol zelf werkt volledig offline, geen wifi, geen simkaart, geen server nodig. Aanvullende diensten zoals kaarten, node-directories en firmware-updates vereisen wel internet.

Heb ik een vergunning nodig?
Nee. In Nederland gebruik je 869.618 MHz (sub-band P), een licentievrije ISM-band. Je moet wel voldoen aan de ETSI-regels: maximaal 500 mW ERP en een duty cycle van ≤ 10%. Zie Juridische Status Nederland voor verdere details.

Werkt MeshCore samen met Meshtastic nodes?
Nee. MeshCore en Meshtastic gebruiken een ander packet-formaat en zijn niet onderling compatibel.

Hoe stel ik een repeater in?
Flash de repeater-firmware via de web flasher, verbind via USB serieel of BLE, en configureer via de CLI (set name, set tx.power, region put, etc.). Zie de MeshCore FAQ voor volledige instructies. Voor de NL-specifieke voorbereiding: The Change en de Regio Generator.

Mijn repeater ontvangt plotseling niets meer, wat nu?
Dit is een bekend probleem met SX1262-chips (Heltec, RAK). Stel in: set agc.reset.interval 4 (geldige waarden: veelvouden van 4) om de AGC periodiek te resetten. Herstart daarna de repeater. Zie ook TX Delay voor verdere troubleshooting-tips.

Hoe zit het met encryptie en privacy?
Direct Messages en private rooms zijn end-to-end versleuteld met AES-128 op basis van ECDH-sleuteluitwisseling, alleen de beoogde ontvanger kan het bericht lezen. Berichten in publieke kanalen zijn versleuteld met een gedeelde kanaalsleutel; iedereen met die sleutel kan meelezen. Je publieke sleutel is zichtbaar in het netwerk (de eerste bytes zijn je node-ID), maar de inhoud van berichten is altijd beschermd. Zie Beveiliging & Encryptie voor een volledig technisch overzicht.

Kan ik een eigen kanaal of room aanmaken?
Ja. Kanalen en rooms werken via een gedeelde sleutel (PSK, Pre-Shared Key). Je maakt een kanaal aan in de app, stelt een naam en sleutel in, en deelt die (via QR-code of handmatig) met de mensen die mee mogen doen. Je kunt een publiek kanaal (bekende sleutel voor iedereen) of een volledig privé kanaal maken. Room Servers slaan berichtgeschiedenis op zodat deelnemers berichten kunnen ophalen als ze offline waren. Zie Hardware & Firmware Types voor meer over Room Server firmware.

Wat kost het ongeveer?
Richtprijzen bij Nederlandse en Europese hobbywinkels, peildatum juli 2026, losse aanbiedingen en directe import uit China vallen hier makkelijk onder:

Zie Hardware & Firmware Types voor een beschrijving van alle hardwarecategorieën.

Hoeveel repeaters zijn er in Nederland?
Het netwerk groeit snel. Begin 2026 waren er honderden actieve repeaters; in mei 2026 zijn dat er ruim 2.000 verspreid over Nederland, met de meeste dekking in de Randstad en stedelijke gebieden (bron: LocalMesh, Mesh-netwerk dekking in Nederland). Zie de live kaart op localmesh.nl of cornmeister.nl voor actuele dekking in jouw regio. Meer tools en community-links in Bronnen en community.


Projectsplit (april 2026)

MeshCore is mede geboren uit de nasleep van Cycloon Gabrielle (Nieuw-Zeeland, februari 2023). De orkaan verwoestte grote delen van het Noordereiland en legde veel communicatie-infrastructuur plat. Scott Powell (grondlegger, firmware en protocol) en Liam Cottle (Nieuw-Zeeland, web- en mobiele clients) werkten vanuit die noodcommunicatiebehoefte samen aan een robuust, volledig offline mesh-netwerk dat zonder simkaart of internet toch berichten kon doorsturen. Dat experiment groeide uit tot MeshCore. (Bronnen: Wikipedia, MeshCore en het NZ Herald-portret van de ontwikkelaar.)

In april 2026 vond een openbare scheiding plaats binnen het MeshCore-project. Het kernteam. Scott Powell (grondlegger, firmware), Liam Cottle (clients/app), Recrof (kaart en flasher), FDLamotte (Python-tooling en STM32) en Oltaco (bootloader), maakte bekend dat teamlid Andy Kirby op 29 maart 2026 zonder medeweten van de rest van het team een trademark-aanvraag had ingediend voor de naam "MeshCore". Andy beheerde ook de domeinnaam meshcore.co.uk, die hij bij de split onder zijn eigen beheer hield. (Bron: The Split, blog.meshcore.io.)

Het kernteam besloot zelfstandig verder te gaan en startte opnieuw onder meshcore.io als officieel thuis van het project. Het project telde op dat moment meer dan 38.000 nodes op de wereldkaart en ruim 100.000 actieve app-gebruikers op Android en iOS. (Beide cijfers komen uit de blogpost The Split van 23 april 2026 en zijn sindsdien niet opnieuw gepubliceerd.)

Wat is meshcore.co.uk?
meshcore.co.uk is de voormalige projectsite, nu in beheer van Andy Kirby. Deze site valt niet onder het officiële project en wordt niet onderhouden door het kernteam.

De officiële kanalen zijn:

Lees de volledige achtergrond in de officiële blogpost: The Split, blog.meshcore.io


The Change: 9 mei 2026

Op 9 mei 2026 schakelt de Nederlandse MeshCore-community gezamenlijk over naar een nieuw radiopreset: SF7 / CR5. Deze gemeenschappelijke omschakeling staat bekend als The Change. (Bron: The Switch, meshwiki.nl; het testweekend was 6–8 maart 2026.)

Waarom is deze overstap nodig?

Het Dutch MeshCore mesh is in 2025–2026 explosief gegroeid en daardoor zwaar overbelast geraakt. Netwerkcongesti zorgt voor pakketverlies, vertraagde berichten en onbetrouwbare communicatie voor iedereen. Community-tests tijdens het testweekend van 6–8 maart 2026 bevestigden dat overstappen naar SF7 de netwerkcapaciteit significant vergroot: een kortere time-on-air per pakket betekent meer ruimte voor alle deelnemers op dezelfde frequentie.

Lees de achtergrond en testresultaten in de officiële documenten:

Wat verandert er?

Alleen de spreading factor en coding rate wijzigen, frequentie en bandbreedte blijven gelijk:

ParameterVóór 9 meiVanaf 9 mei
Spreading FactorSF8SF7
Coding RateCR8 (4/8)CR5 (4/5)
Frequentie869.618 MHz869.618 MHz
Bandbreedte62.5 kHz62.5 kHz
Vereiste firmware:v1.15+

Belangrijk: Op de schakeldag moet iedereen tegelijk overschakelen. Nodes die na 9 mei nog op SF8 draaien zijn niet meer compatibel met het netwerk.

Voor repeater beheerders

Stappen 1–6 kunnen voor de schakeldag worden uitgevoerd op je eigen tempo. Stap 7 voer je uit op 9 mei zelf.

Vóór 9 mei. Voorbereiding:

  1. Firmware updaten naar v1.15+: vereist voor correcte regioscoping en betrouwbaar werken van region denyf * (Fase 8, 18 juli). Update zowel de repeater-firmware als je companion app. (Basis-regiofiltering bestaat sinds repeater v1.10.0, maar is pas vanaf v1.15.0 betrouwbaar bruikbaar, zie region filtering en default scope.)

  2. Advert interval aanpassen. Stel het flood advert interval in op minimaal 50 uur. Zero-hop advertenties: 240 minuten (4 uur). Te frequente advertenties zijn een van de hoofdoorzaken van congestie. Controleer via mc-radar.woodwar.com/mesh-health of je node in de probleemlijst staat.

  3. Bots en scripts stoppen: controleer en stop geautomatiseerde integraties zoals Home Assistant, eigen scripts of auto-reply bots in gedeelde kanalen zoals #test.

  4. Regioscoping configureren: voeg regiocodes toe aan je repeater. Gebruik de Regio Generator op TechSpeeltuin of een andere community-tool. Stel ook de standaard regio in op je companion app. Voeg region denyf * hier nog niet toe: dat is Fase 8 op 18 juli.

  5. Multi-byte pad inschakelen. Schakel 2-byte pad-hashing in voor betere netwerkzichtbaarheid:

    set path.hash.mode 1
    
  6. Lusdetectie en duty cycle instellen:

    set loop.detect minimal
    set dutycycle 10
    

    loop.detect minimal weert flood-pakketten die door het mesh lussen. dutycycle 10 handhaaft de wettelijk verplichte 10% zendtijdlimiet.

Op 9 mei. Schakeldag:

  1. Netherlands radio preset toepassen: open de repeater-instellingen in de MeshCore app en selecteer de preset Netherlands. Dit configureert SF7 / CR5 / 869.618 MHz / 62.5 kHz automatisch. Controleer daarna of je je buren kunt horen op de nieuwe instellingen.

Vangnet voor repeaters die je niet even kunt pakken: een radio-instelling die niet blijkt te werken maakt een repeater onbereikbaar, en als hij op een mast of dak hangt, betekent dat de ladder op. Gebruik daarom tempradio om nieuwe parameters eerst met een tijdslimiet te proberen:

tempradio 869.618,62.5,7,5,15

Dat zet frequentie, bandbreedte, spreading factor en coding rate voor 15 minuten. De instelling wordt niet opgeslagen en verdwijnt bij een reboot, dus hoor je niets meer, dan komt de repeater vanzelf terug op zijn oude configuratie. Werkt het wel, dan leg je het daarna pas definitief vast. Zie de CLI-referentie.

Voor clients (companion gebruikers)

Als gebruiker zonder repeater is je voorbereiding eenvoudiger, maar ook jij moet omschakelen op 9 mei, anders ben je na die dag niet meer compatibel met het netwerk.

Vóór 9 mei:

Op 9 mei. Schakeldag:


Regio Doorsturing: 18 juli 2026

Ruim twee maanden na de SF7-omschakeling volgde Fase 8: strikte regio-doorsturing. Sinds 18 juli 2026 zetten repeater-beheerders hun repeater zo in dat pakketten zonder regiotag geweigerd worden. (Bron: The Switch, meshwiki.nl.)

Deze datum is inmiddels verstreken. Draait jouw repeater nog zonder region denyf *, dan loop je achter op de rest van het netwerk; heb je als gebruiker geen scope op je kanalen ingesteld, dan worden je berichten door correct geconfigureerde repeaters al niet meer doorgestuurd. De stappen hieronder blijven dus onverkort gelden, alleen de wachttijd is voorbij.

Wat verandert er?

Tot en met 17 juli stuurt elke repeater alle pakketten door, ook pakketten zonder regio, die zo potentieel door heel Europa reizen en congestie veroorzaken. Vanaf 18 juli geldt: een pakket zonder regiotag wordt door correct geconfigureerde repeaters stilletjes weggegooid.

Dit wordt ingesteld met één commando op je repeater:

region denyf *
region save

Via de UI: ga naar Regio's Beheren → optie Pakketten zonder regio → stel in op Flood weigeren.

Alternatief sinds v1.16.0: in plaats van ongescopete floods volledig te weigeren kun je ze in reikwijdte beperken met set flood.max.unscoped <hops>. De officiële CLI-documentatie noemt dit expliciet een alternatief voor region denyf *: een waarde van bijvoorbeeld 3 laat lokale ongescopete berichten nog gewoon rondgaan, maar houdt floods van verder weg buiten de deur. De standaardwaarde is 64, wat neerkomt op "geen beperking". Dit is een zachtere variant die minder snel legitiem verkeer breekt.

Waarom?

Door strikte doorsturing ontstaan logisch gescheiden regionale zones. Congestie of problemen in Noord-Holland cascaderen niet meer naar Zeeland of Limburg. Advertenties blijven beperkt tot hun eigen regio. Het resultaat is een stabieler en betrouwbaarder netwerk voor de hele community.

Strikte doorsturing blokkeert uitsluitend pakketten zonder regiotag. Het voorkomt geen communicatie met naburige provincies, heel Nederland of andere EU-landen. Zolang scope correct is ingesteld, werkt communicatie over regiogrenzen gewoon door.

Belangrijk: Voer region denyf *niet vóór 18 juli uit. Een te vroeg geconfigureerde repeater weigert berichten van nodes die regioscoping nog niet hebben ingesteld, wat onnodige communicatiestoringen veroorzaakt.

Voor repeater beheerders

Controleer vóór 18 juli:

Op 18 juli. Één commando:

region denyf *
region save

Voor clients (companion gebruikers)

Als client hoef je op 18 juli niets te wijzigen aan je radio-instellingen. Maar let op: als je kanalen geen scope hebben, worden jouw pakketten na 18 juli niet meer doorgestuurd door correct geconfigureerde repeaters.

Controleer vóór 18 juli:

Zo niet: stel dit in via Experimentele Instellingen in de app. Zie de referentielijst van publieke kanalen voor aanbevolen scopes per kanaal.

Regio Generator al klaar

De Regio Generator op TechSpeeltuin is al voorbereid op Fase 8. De gegenereerde CLI-commando's bevatten de volledige regioconfiguratie inclusief de region denyf * opdracht die je op 18 juli kunt toepassen. Genereer je configuratie alvast, zodat je op 18 juli direct klaar bent.


DTIS: Distributed Text Infrastructure System

DTIS (Distributed Text Infrastructure System) is een publiek maatschappelijk samenwerkingsverband (van overheden, kennisinstellingen, partners en sponsoren) dat zich richt op de ontwikkeling, uitbreiding en duurzame borging van autonome communicatie-infrastructuur op basis van MeshCore. De technische uitvoering ligt bij SkyLab en SkyNet IoT. Waar de meeste MeshCore-gebruikers zelf een node of repeater beheren, bouwt DTIS aan een professionele, vaste infrastructuur van autonome solar-repeater stations die onafhankelijk van internet en mobiele netwerken opereren.

Waarom DTIS?

Nederland (en Europa breder), is kwetsbaar voor communicatiestoringen door geopolitieke spanningen, cyberaanvallen, netwerkoverlast en stroomstoringen. DTIS positioneert MeshCore als aanvullende infrastructuur voor korte tekstcommunicatie die operationeel blijft wanneer reguliere netwerken uitvallen. De nadruk ligt op vaste, betrouwbare stations in plaats van mobiele gebruikers-devices, wat een stabielere en beter voorspelbare communicatielaag oplevert.

Aanpak en partners

Het samenwerkingsverband brengt overheden, kennisinstellingen, maatschappelijke organisaties en technische partners samen. Technische uitvoering en operationele ondersteuning liggen bij SkyLab en SkyNet IoT. Deelname is mogelijk via het beschikbaar stellen van locaties voor repeater-stations, technische ontwikkeling of sponsoring.

De infrastructuur is publiek toegankelijk (geen abonnementen, geen kosten) en biedt end-to-end versleutelde tekstcommunicatie (AES-128) op dezelfde LoRa-frequenties als het Nederlandse MeshCore-netwerk.

Wie het bouwt, en waar het staat

De abstracte omschrijving hierboven komt van DTIS zelf. Het locatie-overzicht maakt concreet wat dat in de praktijk betekent, en dat beeld is specifieker dan "overheden en kennisinstellingen" doet vermoeden. Stand van zaken bij het laatste nazien van deze pagina, 27 juli 2026:

KenmerkStand van zaken
Stations26 actief
Activatie21 januari – 15 juli 2026
BouwSkyLab, alle 26
FinancieringSURF (19) · SkyLab (6)
HardwareSEEED P1 Pro Solar MeshCore Repeater (MOD)
AntenneLongAP omni, 3 of 6 dBi
Opstelhoogte10 – 102 meter

Waar ze staan is het meest tekenend. Het overgrote deel hangt op daken van universiteiten en hogescholen: TU Eindhoven, Universiteit Twente, Radboud, Wageningen, Tilburg, Hogeschool Utrecht, NHL Stenden, Hanze, HZ, Naturalis, MindLabs en het Summa College. Daarnaast Eindhoven Airport, Rotterdam Airport en de gemeente Rotterdam.

Dat SURF (de ICT-coöperatie van het Nederlandse onderwijs en onderzoek) de grootste financier is, verklaart die concentratie op onderwijsinstellingen. Het is dus in de kern een onderzoeks- en onderwijsnetwerk dat als publieke voorziening wordt neergezet, en niet zozeer een overheidsproject; van echte overheden staat er tot nu toe één gemeente op de lijst. Elk station publiceert zijn publieke sleutel, activatiedatum, antenne en opstelhoogte: die transparantie maakt het een van de best gedocumenteerde delen van het Nederlandse mesh.

Waar het om gaat is het verschil in ontwerpfilosofie: waar het community-netwerk uit duizenden losse nodes bestaat die komen en gaan, zet DTIS in op een klein aantal vaste, solar-gevoede stations op grote hoogte die er over vijf jaar nog staan. Beide vullen elkaar aan: DTIS levert de ruggengraat, de community (LocalMesh.nl en het vrijwilligersnetwerk) de dekking in de haarvaten. De actuele kaart staat op dtis.io/map.


Bronnen en community

TechSpeeltuin:

Officiële bronnen:

Nederlandse community sites:

Community chat en forums:


Klopt er iets niet?

Deze pagina is met zorg samengesteld en waar mogelijk gecontroleerd tegen de broncode van MeshCore, de officiële documentatie en de Nederlandse regelgeving. Toch verandert er in dit project veel, en soms snel: firmware-instellingen krijgen andere standaardwaarden, commando's verdwijnen, en afspraken binnen de community schuiven op.

Denk je dat iets hier niet klopt? Laat het me weten: graag met een korte uitleg en een bron waaruit het tegendeel blijkt, bijvoorbeeld een link naar de officiële documentatie, een release-notitie, een regel uit de wet of een discussie in de community. Dan pas ik het aan en vermeld ik de correcte bron erbij.

Via het contactformulier · of in de Nederlandstalige Telegram-groep

Aan de informatie op deze pagina kunnen geen rechten worden ontleend. Voor de exacte voorwaarden van vergunningvrij zenden geldt altijd Bijlage 11 van de Regeling zonder vergunning en zonder meldingsplicht, en voor amateurgebruik de Regeling met meldingsplicht plus je eigen registratie.