forked from ctmesh/web
205 lines
6.4 KiB
HTML
205 lines
6.4 KiB
HTML
<!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>CT Mesh MeshCore Resources</title>
|
|
<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, body {
|
|
margin: 0;
|
|
padding: 0;
|
|
width: 100%;
|
|
min-height: 100%;
|
|
}
|
|
body {
|
|
font-family: "Roboto", sans-serif;
|
|
background: url('background.svg') no-repeat center center fixed;
|
|
background-size: cover;
|
|
background-color: #EBEBEB;
|
|
color: #2C2D3C;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: center;
|
|
padding: 2em 0;
|
|
}
|
|
.overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(87, 87, 87, 0.4);
|
|
pointer-events: none;
|
|
}
|
|
.content-box {
|
|
background-color: #EBEBEB;
|
|
border-radius: 30px;
|
|
padding: 2.5em 3em;
|
|
margin: 1em;
|
|
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 #67EA94;
|
|
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: #67EA94;
|
|
color: #000000;
|
|
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: #67EA94;
|
|
color: #000000;
|
|
border: none;
|
|
padding: 0.75em 1.5em;
|
|
border-radius: 15px;
|
|
cursor: pointer;
|
|
font-weight: bold;
|
|
font-size: 15px;
|
|
text-decoration: none;
|
|
}
|
|
.back-link {
|
|
margin-top: 1.5em;
|
|
}
|
|
@media (max-width: 800px) {
|
|
body {
|
|
padding-top: calc(env(safe-area-inset-top, 1em));
|
|
}
|
|
.content-box {
|
|
padding: 2em;
|
|
}
|
|
}
|
|
@media (max-width: 480px) {
|
|
.content-box {
|
|
padding: 1.5em;
|
|
}
|
|
h1 {
|
|
font-size: 22px;
|
|
}
|
|
h2 {
|
|
font-size: 18px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="overlay"></div>
|
|
<div class="content-box">
|
|
<h1>MeshCore Resources</h1>
|
|
|
|
<h2>Community-run Web Tools</h2>
|
|
<div class="community-tools">
|
|
<p><em>These tools use data reported to our MQTT server by nodes across the state.</em></p>
|
|
<ul>
|
|
<li><a href="https://meshcore-map.ctmesh.org/" target="_blank">MeshCore Map</a> <strong>NEW!</strong> - live map showing MeshCore nodes</li>
|
|
<li><a href="https://meshcore-wardrive.ctmesh.org/" target="_blank">MeshCore Wardriving Map</a> <strong>NEW!</strong> - coverage maps for MeshCore (you can also contribute!). <em>Note: a new app is in testing and may supersede this.</em></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<h2>Official Links</h2>
|
|
<p><a href="https://meshcore.co.uk/" target="_blank">meshcore.co.uk</a></p>
|
|
<p><a href="https://flasher.meshcore.co.uk/" target="_blank">flasher.meshcore.co.uk</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. This configuration stanza goes in your <code>.env.local</code> file after the first two MQTT servers that upload to analyzer.letsmesh.net. <strong>This also requires a 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"># MQTT Broker 3 - CT Mesh
|
|
MCTOMQTT_MQTT3_ENABLED=true
|
|
MCTOMQTT_MQTT3_SERVER=mqtt.ctmesh.org
|
|
MCTOMQTT_MQTT3_PORT=1883
|
|
MCTOMQTT_MQTT3_USE_TLS=false
|
|
MCTOMQTT_MQTT3_USERNAME=meshdev
|
|
MCTOMQTT_MQTT3_PASSWORD=large4cats</pre>
|
|
</div>
|
|
|
|
<a class="btn back-link" href="index.html">Back to CT Mesh</a>
|
|
</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>
|