forked from ctmesh/web
Refine MeshCore repeater setup guidance
* Add a dedicated CT Mesh MQTT upload configuration page * Link the resources page to the MQTT upload guide and MeshCore CLI command reference * Add common repeater commands, MeshMapper, neighbor discovery, and Discord #test validation guidance * Update the recommended flood advert interval to 47 hours
This commit is contained in:
@@ -0,0 +1,313 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<title>Configure MeshCore MQTT Upload | CT Mesh</title>
|
||||
<meta name="description" content="How to configure a MeshCore repeater to upload traffic to the CT Mesh MQTT system.">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.png?3">
|
||||
<link rel="icon" type="image/png" href="favicon.png?3">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
background-color: #272727;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background-color: transparent;
|
||||
color: #2C2D3C;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding: 2em 0;
|
||||
}
|
||||
body::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('background.svg') no-repeat center center;
|
||||
background-size: cover;
|
||||
filter: invert(1) brightness(0.85);
|
||||
z-index: 0;
|
||||
}
|
||||
a,
|
||||
a:visited {
|
||||
color: #000000;
|
||||
}
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(80, 80, 80, 0.35);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
.content-box {
|
||||
background-color: #EBEBEB;
|
||||
border-radius: 30px;
|
||||
padding: 2.5em 3em;
|
||||
margin: 2.5em;
|
||||
max-width: 820px;
|
||||
width: 90%;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
font-size: 28px;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
font-size: 20px;
|
||||
}
|
||||
p {
|
||||
margin: 0.5em 0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
ul {
|
||||
margin: 0.5em 0 0.5em 1.25em;
|
||||
padding: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.community-tools li {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.note {
|
||||
background: #F5F5F5;
|
||||
border-left: 4px solid #2B3A4E;
|
||||
border-radius: 8px;
|
||||
padding: 0.75em 1em;
|
||||
margin: 0.75em 0 0.5em;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
.code-block {
|
||||
background: #F5F5F5;
|
||||
border-radius: 12px;
|
||||
padding: 1em;
|
||||
border: 1px solid #D0D0D0;
|
||||
margin: 0.75em 0;
|
||||
position: relative;
|
||||
}
|
||||
.code-block pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
.copy-btn {
|
||||
position: absolute;
|
||||
top: 0.75em;
|
||||
right: 0.75em;
|
||||
background-color: #2B3A4E;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 0.4em 0.75em;
|
||||
font-size: 0.75em;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
background-color: #2B3A4E;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
padding: 0.75em 1.5em;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.page-header-bg {
|
||||
background-color: #272727;
|
||||
border-radius: 20px 20px 0 0;
|
||||
margin: -2.5em -3em 1.5em -3em;
|
||||
padding: 2em 3em;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
text-decoration: none;
|
||||
}
|
||||
.page-header img {
|
||||
width: 300px;
|
||||
height: auto;
|
||||
}
|
||||
.page-header span {
|
||||
font-weight: bold;
|
||||
font-size: 19px;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
.back-link,
|
||||
.back-link:visited {
|
||||
margin-top: 1.5em;
|
||||
color: #ffffff;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.back-link::before {
|
||||
content: "";
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2.5L3.5 6L8 9.5'/%3E%3C/svg%3E") no-repeat center;
|
||||
background-size: contain;
|
||||
flex-shrink: 0;
|
||||
opacity: 0.4;
|
||||
filter: invert(1);
|
||||
}
|
||||
a[target="_blank"]::after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
vertical-align: middle;
|
||||
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5L8.5 3.5M5 3.5h3.5V7'/%3E%3C/svg%3E") no-repeat center;
|
||||
background-size: contain;
|
||||
opacity: 0.4;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.btn[target="_blank"]::after,
|
||||
.copy-btn::after,
|
||||
.site-footer a::after {
|
||||
display: none;
|
||||
}
|
||||
.site-footer {
|
||||
margin-top: 2em;
|
||||
padding-top: 2em;
|
||||
text-align: center;
|
||||
font-size: 0.875rem;
|
||||
color: #2C2D3C;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
.site-footer a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.site-footer a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
@media (max-width: 800px) {
|
||||
body {
|
||||
padding-top: calc(env(safe-area-inset-top, 1em));
|
||||
}
|
||||
.content-box {
|
||||
padding: 2em;
|
||||
}
|
||||
.page-header-bg {
|
||||
margin: -2em -2em 1.5em -2em;
|
||||
padding: 2em;
|
||||
}
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.content-box {
|
||||
padding: 1.5em;
|
||||
}
|
||||
.page-header-bg {
|
||||
margin: -1.5em -1.5em 1.5em -1.5em;
|
||||
padding: 1.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="overlay"></div>
|
||||
<div class="content-box">
|
||||
<div class="page-header-bg">
|
||||
<a href="index.html" class="page-header">
|
||||
<img src="logo_sm.png" alt="CT Mesh" />
|
||||
</a>
|
||||
</div>
|
||||
<h1>How to Configure Your Repeater to Upload to the CT Mesh MQTT System</h1>
|
||||
<p>Our MQTT broker is <em>uplink-only</em> and designed for fixed nodes across the state to serve as gateway nodes. Its purpose is not to bridge gaps or extend mesh coverage, but to report local traffic to our own web-based tools for analytical data and metrics to assess the mesh's performance. <strong>This role is best suited for stable, well-placed nodes with reliable coverage.</strong></p>
|
||||
<p>MeshCore MQTT uplink uses <a href="https://github.com/Cisien/meshcoretomqtt" target="_blank">meshcoretomqtt</a> on a Raspberry Pi or similar Linux computer with the service installed. This also requires custom observer firmware on the radio. See <a href="https://analyzer.letsmesh.net/observer/onboard" target="_blank">custom repeater firmware setup</a> before configuring the broker.</p>
|
||||
|
||||
<h2>Configuration</h2>
|
||||
<p>Configure meshcoretomqtt with a <a href="https://github.com/Cisien/meshcoretomqtt" target="_blank">Toml file</a> at <code>/etc/mctomqtt/config.d/00-user.toml</code>. In your existing <code>[general]</code> section, set the region to <code>iata = "BDL"</code>. Then add the custom broker block below at the end of the config file. Fill in your own broker credentials if you were issued dedicated credentials.</p>
|
||||
|
||||
<div class="code-block">
|
||||
<button class="copy-btn" type="button" data-copy-target="meshcore-mqtt">Copy all</button>
|
||||
<pre id="meshcore-mqtt">[[broker]]
|
||||
name = "ctmesh"
|
||||
enabled = true
|
||||
server = "mqtt.ctmesh.org"
|
||||
port = 1883
|
||||
transport = "tcp"
|
||||
keepalive = 60
|
||||
qos = 0
|
||||
retain = true
|
||||
|
||||
[broker.auth]
|
||||
method = "password"
|
||||
username = "meshdev"
|
||||
password = "large4cats"</pre>
|
||||
</div>
|
||||
<p class="note"><strong>Note:</strong> The <code>meshdev</code>/<code>large4cats</code> credentials are intentionally shared secrets for this broker. We recognize the security implications. Specific credentials to this broker can be requested.</p>
|
||||
|
||||
<h2>Testing</h2>
|
||||
<p>After the service is running, check the <a href="https://meshcore-map.ctmesh.org/" target="_blank">MeshCore Map</a>, <a href="https://bdl.meshmapper.net/" target="_blank">MeshMapper</a>, and <a href="https://analyzer.letsmesh.net/packets?region=BDL" target="_blank">MeshCore Analyzer</a> to confirm that traffic from the repeater is being reported.</p>
|
||||
<p>MQTT messages sent to channels such as <code>#test</code> are also mirrored into the <a href="https://discord.com/channels/1359317424301801512/1484659122988126339" target="_blank">Discord #test channel</a> by a bot. This gives you a quick way to test whether the main areas of the mesh can hear your new repeater, and whether companion nodes behind the repeater are making it through.</p>
|
||||
|
||||
<h2>Related Guides</h2>
|
||||
<p><a href="repeater-setup.html">CT Mesh repeater setup guide</a></p>
|
||||
<p><a href="meshcore-resources.html">MeshCore resources</a></p>
|
||||
|
||||
<a class="btn back-link" href="index.html">Back to CT Mesh</a>
|
||||
<footer class="site-footer">
|
||||
<p><a href="https://ctmesh.org/">CT Mesh</a> is a volunteer-run user group for mesh technology enthusiasts in Connecticut.</p>
|
||||
<p><a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener">Content licensed CC BY-SA 4.0</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
<script>
|
||||
const copyButtons = document.querySelectorAll("[data-copy-target]");
|
||||
copyButtons.forEach((button) => {
|
||||
button.addEventListener("click", async () => {
|
||||
const targetId = button.getAttribute("data-copy-target");
|
||||
const target = document.getElementById(targetId);
|
||||
if (!target) return;
|
||||
try {
|
||||
await navigator.clipboard.writeText(target.textContent);
|
||||
button.textContent = "Copied";
|
||||
setTimeout(() => {
|
||||
button.textContent = "Copy all";
|
||||
}, 1500);
|
||||
} catch (err) {
|
||||
button.textContent = "Copy failed";
|
||||
setTimeout(() => {
|
||||
button.textContent = "Copy all";
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+3
-20
@@ -261,31 +261,14 @@
|
||||
<h2>Official Links</h2>
|
||||
<p><a href="https://meshcore.io/" target="_blank">meshcore.io</a></p>
|
||||
<p><a href="https://flasher.meshcore.io/" target="_blank">flasher.meshcore.io</a></p>
|
||||
<p><a href="https://docs.meshcore.io/cli_commands/" target="_blank">MeshCore CLI commands reference</a></p>
|
||||
<p><a href="repeater-setup.html">CT Mesh repeater setup guide</a></p>
|
||||
<div class="note"><strong>Note:</strong> the flasher requires WebSerial or Web Bluetooth support in your browser</div>
|
||||
|
||||
<h2>MQTT</h2>
|
||||
<p>Our MQTT broker is <em>uplink-only</em> and designed for fixed nodes across the state to serve as gateway nodes. Its purpose is not to bridge gaps or extend mesh coverage, but to report local traffic to our own web-based tools for analytical data and metrics to assess the mesh's performance. <strong>This role is best suited for stable, well-placed nodes with reliable coverage.</strong></p>
|
||||
<p>MeshCore MQTT uplink uses <a href="https://github.com/Cisien/meshcoretomqtt" target="_blank">meshcoretomqtt</a> on a Raspberry Pi or similar Linux computer with the service installed. Configure it with a <a href="https://github.com/Cisien/meshcoretomqtt" target="_blank">Toml file</a> at <code>/etc/mctomqtt/config.d/00-user.toml</code>, with region set in your existing <code>[general]</code> section as <code>iata = "BDL"</code>, and a custom broker named <code>ctmesh</code>. The block below should be added at the end of the config file. Fill in your own broker credentials. <strong>This also requires custom firmware.</strong> See <a href="https://analyzer.letsmesh.net/observer/onboard" target="_blank">custom repeater firmware setup</a>.</p>
|
||||
|
||||
<div class="code-block">
|
||||
<button class="copy-btn" type="button" data-copy-target="meshcore-mqtt">Copy all</button>
|
||||
<pre id="meshcore-mqtt">[[broker]]
|
||||
name = "ctmesh"
|
||||
enabled = true
|
||||
server = "mqtt.ctmesh.org"
|
||||
port = 1883
|
||||
transport = "tcp"
|
||||
keepalive = 60
|
||||
qos = 0
|
||||
retain = true
|
||||
|
||||
[broker.auth]
|
||||
method = "password"
|
||||
username = "meshdev"
|
||||
password = "large4cats"</pre>
|
||||
</div>
|
||||
<p class="note"><strong>Note:</strong> The <code>meshdev</code>/<code>large4cats</code> credentials are intentionally shared secrets for this broker. We recognize the security implications. Specific credentials to this broker can be requested.</p>
|
||||
<p>For setup steps, see <a href="meshcore-mqtt-upload.html">How to configure your repeater to upload to the CT Mesh MQTT system</a>.</p>
|
||||
<p class="note"><strong>Testing note:</strong> MQTT messages sent to channels such as <code>#test</code> are mirrored into the <a href="https://discord.com/channels/1359317424301801512/1484659122988126339" target="_blank">Discord #test channel</a> by a bot. This is useful for checking whether the main mesh can hear a new repeater, or whether companion nodes behind that repeater are making it back to the wider mesh.</p>
|
||||
|
||||
<a class="btn back-link" href="index.html">Back to CT Mesh</a>
|
||||
<footer class="site-footer">
|
||||
|
||||
+24
-2
@@ -323,6 +323,7 @@
|
||||
<li><a href="#program-path">Programming with a Companion</a></li>
|
||||
<li class="toc-sub"><a href="#program-needs">Programming Requirements</a></li>
|
||||
<li class="toc-sub"><a href="#program-repeater">Program the Repeater</a></li>
|
||||
<li class="toc-sub"><a href="#repeater-commands">Common Repeater Commands</a></li>
|
||||
<li><a href="#deploy-path">Deploy the Node</a></li>
|
||||
<li class="toc-sub"><a href="#choose-site">Choose a Good Site</a></li>
|
||||
<li class="toc-sub"><a href="#tree-mounting">Tree Mounting</a></li>
|
||||
@@ -441,7 +442,7 @@
|
||||
<ul>
|
||||
<li>You can leave location blank for privacy reasons.</li>
|
||||
<li>If you change the frequency, bandwidth, or spreading factor, the repeater will no longer communicate with nodes on the public mesh, which is usually not what you want.</li>
|
||||
<li>For the public mesh, set <strong>Flood advert interval (hours)</strong> to <strong>48</strong>. The UI may default lower, such as <strong>12</strong>, so change it before saving.</li>
|
||||
<li>For the public mesh, set <strong>Flood advert interval (hours)</strong> to <strong>47</strong>. The UI may default lower, such as <strong>12</strong>, so change it before saving.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -463,7 +464,7 @@
|
||||
<li>This opens the repeater admin status page. Tap <strong>Request status</strong> if you want to refresh and view the repeater status.</li>
|
||||
<li>At the bottom of that screen, open <strong>Command Line</strong> and run <code>set path.hash.mode 1</code> to set <strong>2 byte mode</strong>. <a href="repeater-hash-mode-entry-iphone.png" class="inline-shot" data-modal-image="repeater-hash-mode-entry-iphone.png">View screenshot</a> <a href="repeater-hash-mode-confirm-iphone.png" class="inline-shot" data-modal-image="repeater-hash-mode-confirm-iphone.png">View result</a></li>
|
||||
<li>Tap the <strong>Settings</strong> icon in the bottom right next to <strong>Command Line</strong> to change other node settings such as advert intervals, owner info, position, syncing the device clock, and other access control or telemetry settings.</li>
|
||||
<li>Set <strong>Flood advert interval (hours)</strong> to <strong>48</strong> for best public mesh performance if you have not already set it during USB configuration.</li>
|
||||
<li>Set <strong>Flood advert interval (hours)</strong> to <strong>47</strong> for best public mesh performance if you have not already set it during USB configuration.</li>
|
||||
</ol>
|
||||
<div class="note"><strong>Notes:</strong>
|
||||
<ul>
|
||||
@@ -474,11 +475,32 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3 id="repeater-commands">Common Repeater Commands</h3>
|
||||
<p>These are the commands CT Mesh operators most commonly use while setting up or checking a repeater from the MeshCore command line. The full upstream reference is available in the <a href="https://docs.meshcore.io/cli_commands/" target="_blank">MeshCore CLI commands documentation</a>.</p>
|
||||
<div class="note notes-list">
|
||||
<ul>
|
||||
<li><code>set path.hash.mode 1</code> - set 2 byte path hash mode for public mesh use.</li>
|
||||
<li><code>get path.hash.mode</code> - confirm the current path hash mode.</li>
|
||||
<li><code>set flood.advert.interval 47</code> - set the flood advert interval to 47 hours.</li>
|
||||
<li><code>get flood.advert.interval</code> - confirm the current flood advert interval.</li>
|
||||
<li><code>neighbors</code> - list recently heard nearby repeaters.</li>
|
||||
<li><code>discover.neighbors</code> - actively discover zero-hop neighbors from a repeater.</li>
|
||||
<li><code>clock sync</code> - sync the repeater clock with the remote device.</li>
|
||||
<li><code>advert</code> - send a flood advert after setup or after moving the node.</li>
|
||||
<li><code>powersaving on</code> / <code>powersaving off</code> - enable or disable repeater power saving.</li>
|
||||
<li><code>reboot</code> - reboot the node after configuration changes that require it.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 id="deploy-path">Deploy the Node</h2>
|
||||
<h3 id="choose-site">Choose a Good Site</h3>
|
||||
<ul>
|
||||
<li>Choose a stable location with useful height, clear exposure, and enough sun to keep the battery healthy.</li>
|
||||
<li>If your radio site and panel site differ, remote panel placement is fine if it improves sun exposure.</li>
|
||||
<li>Use <a href="https://bdl.meshmapper.net/" target="_blank">MeshMapper</a> to look for coverage gaps, likely line-of-sight paths, and candidate sites that would help the existing mesh.</li>
|
||||
<li>Use MeshCore's neighbor discovery tools, including <strong>Discover Nearby Nodes</strong> in the app and the <code>neighbors</code> / <code>discover.neighbors</code> commands, to compare candidate locations before final mounting.</li>
|
||||
<li>Before sealing the install, test the repeater at the planned location and confirm it can hear useful neighbors and can be heard by the main mesh.</li>
|
||||
<li>If MQTT/Discord test monitoring is available, send a test message on a channel such as <code>#test</code> from the new repeater area. A Discord bot mirrors received mesh messages into the <a href="https://discord.com/channels/1359317424301801512/1484659122988126339" target="_blank">Discord #test channel</a>, which helps confirm whether the wider mesh can hear the repeater or companion nodes behind it.</li>
|
||||
</ul>
|
||||
<h3 id="tree-mounting">Tree Mounting</h3>
|
||||
<p>For tree installs, a common approach is to use a slingshot to place a lightweight mason line over a suitable branch, then use that line to pull up a stronger rope for hoisting and securing the node. Choose a healthy branch, avoid power lines, and make sure the enclosure and antenna can hang clear without rubbing through on bark or hardware.</p>
|
||||
|
||||
Reference in New Issue
Block a user