diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f58d255
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Daniel Pupius
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/main.go b/main.go
index 53f2737..2a7321c 100644
--- a/main.go
+++ b/main.go
@@ -226,10 +226,12 @@ func main() {
// Start the web server
webServer := server.New(server.Config{
- Host: config.ServerHost,
- Port: config.ServerPort,
- Broker: broker,
- Logger: logger,
+ Host: config.ServerHost,
+ Port: config.ServerPort,
+ Broker: broker,
+ Logger: logger,
+ MQTTServer: config.MQTTBroker,
+ MQTTTopicPath: config.MQTTTopicPrefix + "/#",
})
// Start the server in a goroutine
diff --git a/server/server.go b/server/server.go
index 7fddad8..0586ee9 100644
--- a/server/server.go
+++ b/server/server.go
@@ -17,10 +17,21 @@ import (
// Config holds server configuration
type Config struct {
- Host string
- Port string
- Logger logging.Logger
- Broker *mqtt.Broker // The MQTT message broker
+ Host string
+ Port string
+ Logger logging.Logger
+ Broker *mqtt.Broker // The MQTT message broker
+ MQTTServer string // MQTT server hostname
+ MQTTTopicPath string // MQTT topic path being subscribed to
+}
+
+// Create connection info JSON to send to the client
+type ConnectionInfo struct {
+ Message string `json:"message"`
+ MQTTServer string `json:"mqttServer"`
+ MQTTTopic string `json:"mqttTopic"`
+ Connected bool `json:"connected"`
+ ServerTime int64 `json:"serverTime"`
}
// Server encapsulates the HTTP server functionality
@@ -144,19 +155,34 @@ func (s *Server) handleStream(w http.ResponseWriter, r *http.Request) {
heartbeatTicker := time.NewTicker(30 * time.Second)
defer heartbeatTicker.Stop()
- // Send an initial message with an additional 1.5k payload. This force buffer
- // flush so the client knows the connection is open.
+ // Send an initial message with connection information and an additional padding payload.
+ // This forces buffer flush so the client knows the connection is open.
w.WriteHeader(http.StatusOK)
- initialMessage := "Connected to stream"
+ connectionInfo := ConnectionInfo{
+ Message: "Connected to stream",
+ MQTTServer: s.config.MQTTServer,
+ MQTTTopic: s.config.MQTTTopicPath,
+ Connected: true,
+ ServerTime: time.Now().Unix(),
+ }
+
+ // Convert to JSON
+ infoJson, err := json.Marshal(connectionInfo)
+ if err != nil {
+ logger.Errorw("Failed to marshal connection info", "error", err)
+ infoJson = []byte(`{"message":"Connected to stream"}`)
+ }
+
+ // Create padding for buffer flush
paddingSize := 1500
padding := make([]byte, paddingSize)
for i := 0; i < paddingSize; i++ {
padding[i] = byte('A' + (i % 26))
}
- // Send the event with the padded data
- fmt.Fprintf(w, "event: info\ndata: %s\n\n", initialMessage)
+ // Send the event with connection info and padded data
+ fmt.Fprintf(w, "event: connection_info\ndata: %s\n\n", infoJson)
fmt.Fprintf(w, "event: padding\ndata: %s\n\n", padding)
flusher.Flush()
diff --git a/web/src/components/MqttConnectionInfo.tsx b/web/src/components/MqttConnectionInfo.tsx
new file mode 100644
index 0000000..e6e675b
--- /dev/null
+++ b/web/src/components/MqttConnectionInfo.tsx
@@ -0,0 +1,47 @@
+import React from "react";
+import { useAppSelector } from "../hooks";
+
+/**
+ * Component that displays MQTT connection details
+ */
+export const MqttConnectionInfo: React.FC = () => {
+ const connectionInfo = useAppSelector(state => state.connection.info);
+
+ if (!connectionInfo) {
+ return (
+
+ This site provides real-time visualization and monitoring of the Meshtastic network via MQTT.
+ It allows you to view node positions, track message traffic, and monitor the status of devices in the mesh.
+
+ Meshtastic is an open source, off-grid, decentralized mesh networking platform that allows
+ for text messaging, GPS location sharing, and data transmission without the need for cellular
+ service or internet access. It uses affordable, low-power radio devices based on LoRa technology.
+
+
+
+
+
+
+
+
+
+ Position data shown on this dashboard may have reduced precision for privacy reasons,
+ depending on the configuration of the Meshtastic network and MQTT server.
+
+
+ This dashboard only displays information that has been explicitly shared via the
+ Meshtastic mesh network and relayed through an MQTT gateway.
+
+ Meshstream is open source software licensed under the MIT License. You are free to use,
+ modify, and distribute this software according to the terms of the license.
+