logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak przesyłać strumieniowo dane OpenBeken MQTT do uPlot Dashboard przy użyciu JavaScript i HTML

Zogdan 28 Lip 2025 10:24 813 0
Treść została przetłumaczona angielski » polski Zobacz oryginalną wersję tematu
  • #1 21619093
    Zogdan
    Poziom 10  
    Posty: 25
    Pomógł: 6
    Ocena: 13
    Po normalnym flashowaniu Openbekena chcę szybko sprawdzić, czy wszystko działa.

    I szczerze mówiąc jestem leniwy i po prostu zrzucam wszystkie zmienne do brokera test.mosquitto.org MQTT i używam doskonałego https://mqtt-explorer.com/, aby sprawdzić, czy dane wychodzą poprawnie.

    Teraz miałem problem, że ktoś powiedział hej, chcę również miernik mocy z pulpitem nawigacyjnym.

    Więc najpierw pomyślałem, że użyję "startDriver Charts", ale proszę bardzo, tego nie ma w domyślnym pliku binarnym.

    Dlaczego więc nie zasubskrybować tematu mqtt i nie przesłać go do uPlot, aby użyć go jako dashboardu?
    Oczywiście ma to ograniczenia (takie jak trwałość), ale przynajmniej nie muszę dbać o konfigurowanie serwera / logowania itp.

    Oto prosty JS/HTML, który subskrybuje temat na brokerze i przesyła go jako strumień danych do uPlot ( https://github.com/leeoniya/uPlot ).

    Wykres danych czujników z MQTT pokazujący dwie serie temperatury

    Wziąłem jakiś losowy temat mqtt, który publikuje temperaturę My_Home_1/Temp/temperature3

    Wystarczy zapisać poniższy plik jako HTML i uruchomić go. Możesz wypróbować go również w JsFiddle: https://jsfiddle.net/0yazw571/

    
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>MQTT uPlot</title>
      <link href="https://cdn.jsdelivr.net/npm/uplot@1.6.20/dist/uPlot.min.css" rel="stylesheet">
      <script src="https://cdn.jsdelivr.net/npm/uplot@1.6.20/dist/uPlot.iife.min.js"></script>
      <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
      <style>
        #chart {
          width: 800px;
          height: 400px;
        }
      </style>
    </head>
    <body>
      <div id="chart"></div>
    
      <script>
     function uPlotMQTTPlugin(config) {
          const {
            brokerUrl,
            brokerOptions = {},
            topics,
            maxPoints = 100,
            redrawEvery = 10
          } = config;
    
          const timeStamps = [];
          const seriesDataArray = [timeStamps];
    
          topics.forEach(() => seriesDataArray.push([]));
    
          let uPlotInstance = null;
          let updateCounter = 0;
    
          const mqttClient = mqtt.connect(brokerUrl, brokerOptions);
    
          mqttClient.on("connect", () => {
            topics.forEach(({ topic }) => {
              mqttClient.subscribe(topic, err => {
                if (err) console.error("Subscribe failed:", topic, err);
              });
            });
          });
    
          mqttClient.on("message", (topic, message) => {
            const value = parseFloat(message.toString());
            const currentTime = Date.now() / 1000;
    
            const topicIndex = topics.findIndex(t => t.topic === topic);
            if (topicIndex === -1) return;
    
            const isNewTime = timeStamps.length === 0 || currentTime - timeStamps[timeStamps.length - 1] >= 0.5;
    
            if (isNewTime) {
              timeStamps.push(currentTime);
              for (let i = 1; i < seriesDataArray.length; i++) {
                seriesDataArray[i].push(null);
              }
            }
    
            seriesDataArray[topicIndex + 1][seriesDataArray[0].length - 1] = value;
    
            if (timeStamps.length > maxPoints) {
              timeStamps.shift();
              for (let i = 1; i < seriesDataArray.length; i++) {
                seriesDataArray[i].shift();
              }
            }
    
            updateCounter++;
            if (updateCounter % redrawEvery === 0) {
              uPlotInstance.setData(seriesDataArray);
            }
          });
    
          return {
            hooks: {
              ready: [
                (u) => {
                  uPlotInstance = u;
                  u.setData(seriesDataArray);
                }
              ]
            }
          };
        }
    
        // Configuration for broker and topics
        const sensorTopics = [
          { topic: "My_Home_1/Temp/temperature3", name: "Temperature 3 (°C)", color: "red" },
          { topic: "My_Home_1/Temp/temperature2", name: "Temperature 2 (°C)", color: "blue" }
        ];
    
        const uPlotChart = new uPlot({
          title: "Sensor Data",
          width: 800,
          height: 400,
          series: [
            {}, // timestamp axis
            ...sensorTopics.map(t => ({
              label: t.name,
              stroke: t.color,
              spanGaps: true
            }))
          ],
          axes: [
            {},
            {}
          ],
          plugins: [
            uPlotMQTTPlugin({
              brokerUrl: "wss://test.mosquitto.org:8081",
              brokerOptions: {},
              topics: sensorTopics,
              maxPoints: 100,
              redrawEvery: 10
            })
          ]
        }, [[], ...sensorTopics.map(() => [])], document.getElementById("chart"));
      </script>
    </body>
    </html>
    


    Dodano po 38 [minutach]:

    >>21619093
    Ulepszenia do zrobienia: dodanie mnożników w sensorTopics, ponieważ OpenBeken potrzebuje tego czasami dla surowych wartości, oraz flagi "domyślnie pokaż/ukryj", np. chcesz mieć częstotliwość miernika mocy, ale nie zawsze widoczną.
REKLAMA