Technologia GNSS RTK może być wykorzystywana w wielu zastosowaniach. Zazwyczaj wykonuje się pomiary, a następnie eksportuje je do komputera w celu analizy. To najczęstszy przypadek.
Jednak w przypadku niektórych zastosowań może zaistnieć konieczność przesłania danych GNSS RTK do komputera/serwera w czasie rzeczywistym, dzięki czemu można podjąć działania natychmiast, bez konieczności czekania kilku godzin na przetworzenie danych.
Do popularnych aplikacji wymagających przesyłania danych o położeniu w czasie rzeczywistym na serwer należą: zarządzanie flotą i logistyka, przewozy osób i transport publiczny, śledzenie zasobów, monitorowanie dzikiej przyrody, …
W tym samouczku pokażemy, jak skonfigurować serwer z Node-RED, popularnym narzędziem do programowania wizualnego, dzięki któremu możesz rozpocząć własny projekt. Pokażemy również, jak skonfigurować odbiornik GNSS i wtyczkę do wysyłania danych na ten serwer.
Wymagany sprzęt
- Zdalny serwer Linux
Chociaż w naszym przykładzie wykorzystamy powyższe informacje, możesz także uruchomić Node-RED lokalnie na komputerze z systemem Windows/Linux, na RaspberryPi, Dockerze, Androidzie, w chmurze itd. - Android smartphone
- RTK Portable Bluetooth Kit
- Alternatywnie, każdy inny odbiornik GNSS z 4G NTRIP Master, WiFi NTRIP Master or Ethernet NTRIP Master wtyczki
Wymagane oprogramowanie
- GNSS Master aplikacja na Androida
Instalacja Node-RED
Zdalny serwer Linux
W naszym przypadku wykorzystujemy dystrybucję AlmaLinux.
Otwórz terminal na swoim serwerze i uruchom następujące polecenia:
sudo dnf module reset -y nodejs
sudo dnf module enable -y nodejs:20
sudo dnf install -y nodejs npm gcc-c++ make
# then:
sudo npm i -g --unsafe-perm node-red
Możesz sprawdzić czy instalacja przebiegła pomyślnie wpisując:/usr/local/bin/node-red --version
Jeśli wszystko jest w porządku, zobaczysz wersję wyświetlaną na terminalu.
Inne urządzenia/system operacyjny
Instrukcje znajdziesz na oficjalnej stronie projektu Node-RED różne systemy.
Otwórz port TCP na swoim serwerze
Nie zawsze jest to konieczne, ale może zaistnieć konieczność otwarcia portu TCP, aby umożliwić połączenia przychodzące.
W tym przykładzie będziemy używać portu TCP 2222. Powinieneś wpisać na terminalu serwera:iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
Uruchom Node-RED
Wpisz to polecenie: /usr/local/bin/node-red &
Przejdź do przeglądarki i wpisz:
172.123.123.123:1880
Gdzie 172.123.123.123 musi być adresem IP Twojego serwera.
Jeśli wszystko jest w porządku, powinieneś zobaczyć coś takiego:
Przygotuj swój pierwszy przepływ
W Node-RED projekty nazywane są przepływami.
Przygotujemy nowy przepływ, który będzie nasłuchiwał przychodzących połączeń TCP i drukował wszystkie otrzymane dane w oknie debugowania.
Wyszukaj na lewym panelu, węzeł o nazwie wejście tcp, przeciągnij i upuść na płótno przepływu.
Szukaj także debug węzeł i połącz je ze sobą w ten sposób:
W Node-RED projekty nazywane są przepływami.
Przygotujemy nowy przepływ, który będzie nasłuchiwał przychodzących połączeń TCP i drukował wszystkie otrzymane dane w oknie debugowania.
Wyszukaj na lewym panelu, węzeł o nazwie wejście tcp, przeciągnij i upuść na płótno przepływu.
Szukaj także debug węzeł i połącz je ze sobą w ten sposób:
Kliknij dwukrotnie na węźle TCP i ustaw port TCP, na którym chcesz nasłuchiwać, w tym przykładzie: 2222.
Ustaw również strumienie ciągów ograniczone znakiem \r\n.
Po zrobieniu tego kliknij przycisk Wdróż w prawym górnym rogu ekranu.
Ten przycisk uruchomi bloki po każdej modyfikacji.
Podłącz odbiornik GNSS do Node-RED
RTK Portable Bluetooth Kit z urządzeniem z Androidem
- Podłącz swój przenośny zestaw Bluetooth przez BT do urządzenia z systemem Android.
- Otwarte GNSS Master aplikacji, połącz się z modułem BT w Połączeniu odbiornika GNSS.
- W razie potrzeby ustaw korektę wejściową
- W sekcji „Dane wyjściowe odbiornika” wybierz opcję „Klient TCP” i wpisz adres IP swojego serwera w polu „Adres TCP” oraz 2222 w polu „Port TCP”. Kliknij „Połącz”.
- To wszystko. Jeśli klikniesz dwukrotnie na okno debugowania w Node-RED, powinieneś zobaczyć coś takiego ze wszystkimi odebranymi danymi:
Inne odbiorniki GNSS z wtyczkami 4G, WiFi lub Ethernet
Jeśli posiadasz inny odbiornik GNSS, możesz osiągnąć te same rezultaty, nawet bez urządzenia z systemem Android.
Upewnij się, że na porcie COM wtyczki XBee wyprowadzasz wiadomości, które chcesz wysłać do serwera. Zazwyczaj należy wysyłać co najmniej wiadomości NMEA GGA.
Następnie skonfiguruj 4G, WiFi lub Ethernet NTRIP Master wtyczki z funkcjonalnością klienta TCP o takich samych parametrach jak robiliśmy to wcześniej, serwer TCP to adres IP Twojego serwera, a port TCP to 2222.
Tak po prostu 🙂
Zrób coś z danymi
No cóż, jak dotąd nic ekscytującego, prawda?
Można oglądać transmisje strumieniowe NMEA na żywo na swoim serwerze, ale chcielibyśmy zobaczyć niektóre możliwości Node-RED.
W następnym przykładzie pokażemy, jak analizować strumień wejściowy, aby uzyskać szerokość i długość geograficzną, a następnie naniesiemy aktualną lokalizację na mapę ze śladem pokazującym stare lokalizacje.
Przede wszystkim usuń obecny przepływ.
Kliknij w menu w prawym górnym rogu > Zarządzaj paletą > Zainstaluj > wyszukaj node-red-contrib-web-worldmap i zainstalować go.
Wróć do menu > Importuj > Schowek i wklej następujący kod:
[
{
"id": "tab1",
"type": "tab",
"label": "GNSS Live Map + Track",
"disabled": false,
"info": ""
},
{
"id": "tcpInNmea2222",
"type": "tcp in",
"z": "tab1",
"name": "NMEA TCP 2222",
"server": "server",
"host": "",
"port": "2222",
"datamode": "stream",
"datatype": "utf8",
"newline": "\\r\\n",
"topic": "",
"base64": false,
"x": 150,
"y": 140,
"wires": [
[
"fnGGA"
]
]
},
{
"id": "fnGGA",
"type": "function",
"z": "tab1",
"name": "Filter GGA → {lat,lon}",
"func": "// Allman style\nfunction nmeaToDecimal(raw, hemi)\n{\n if (!raw || !hemi)\n {\n return null;\n }\n const isLat = (hemi === 'N' || hemi === 'S');\n const degDigits = isLat ? 2 : 3;\n const deg = parseInt(raw.slice(0, degDigits), 10);\n const min = parseFloat(raw.slice(degDigits));\n if (Number.isNaN(deg) || Number.isNaN(min))\n {\n return null;\n }\n let dec = deg + (min / 60.0);\n if (hemi === 'S' || hemi === 'W')\n {\n dec = -dec;\n }\n return dec;\n}\n\nif (typeof msg.payload !== 'string')\n{\n return null;\n}\n\nconst line = msg.payload.trim();\nif (!line.startsWith('$') || line.indexOf('GGA,') === -1)\n{\n return null;\n}\n\nconst f = line.split(',');\nconst lat = nmeaToDecimal(f[2], f[3]);\nconst lon = nmeaToDecimal(f[4], f[5]);\nif (lat == null || lon == null)\n{\n return null;\n}\n\nmsg.payload = { lat, lon };\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 410,
"y": 140,
"wires": [
[
"fnToWorldmap"
]
]
},
{
"id": "fnToWorldmap",
"type": "function",
"z": "tab1",
"name": "Marker + Track",
"func": "// Input: msg.payload={lat,lon}\n// Output1 → worldmap marker\n// Output2 → worldmap-tracks polyline (then wired into worldmap)\n\nif (!msg.payload || msg.payload.lat == null || msg.payload.lon == null)\n{\n return null;\n}\n\nconst lat = Number(msg.payload.lat);\nconst lon = Number(msg.payload.lon);\nconst name = \"GPS-1\"; // keep constant per device\nconst now = Date.now();\n\nconst base =\n{\n name: name,\n lat: lat,\n lon: lon,\n layer: \"GNSS\",\n time: now, // helps pruning\n icon: \"fa-location-arrow\",\n popup: `Lat: ${lat.toFixed(6)}
Lon: ${lon.toFixed(6)}
UTC: ${new Date(now).toISOString()}`\n};\n\nreturn [ { payload: base }, { payload: base } ];",
"outputs": 2,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 650,
"y": 140,
"wires": [
[
"worldmap",
"dbgMarker"
],
[
"tracks"
]
]
},
{
"id": "tracks",
"type": "worldmap-tracks",
"z": "tab1",
"name": "Track GNSS (layer GNSS)",
"depth": "1000",
"layer": "GNSS",
"doors": "",
"x": 930,
"y": 180,
"wires": [
[
"worldmap"
]
]
},
{
"id": "worldmap",
"type": "worldmap",
"z": "tab1",
"name": "Live Map (/worldmap)",
"lat": "0",
"lon": "0",
"zoom": "2",
"layer": "OSM",
"cluster": "",
"maxage": "",
"usermenu": "show",
"layers": "show",
"panit": "false",
"panlock": "false",
"zoomlock": "false",
"hiderightclick": "false",
"coords": "none",
"showgrid": "false",
"showruler": "false",
"showlayer": "true",
"showmenu": "true",
"path": "/worldmap",
"overlist": "DR,CO,RA,DN,HM",
"maplist": "OSM,Esri Terrain,Esri Satellite",
"mapname": "",
"mapurl": "",
"mapopt": "",
"kmlurl": "",
"devicelabel": "name",
"layercontrol": "false",
"x": 930,
"y": 120,
"wires": []
},
{
"id": "dbgMarker",
"type": "debug",
"z": "tab1",
"name": "Marker payload",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"statusVal": "",
"statusType": "auto",
"x": 930,
"y": 220,
"wires": []
},
{
"id": "hint",
"type": "comment",
"z": "tab1",
"name": "Send NMEA (\\r\\n delimited) to TCP 2222. Open http://:1880/worldmap",
"info": "",
"x": 330,
"y": 90,
"wires": []
}
]
Powinieneś zobaczyć coś takiego:
Kliknij dwukrotnie węzeł mapy świata.
Na liście rozwijanej Map wybierz OpenStreetMap lub inną warstwę i kliknij Gotowe:
Naciśnij Rozmieścić przycisk.
Dostęp do mapy na żywo możesz uzyskać z poziomu przeglądarki tutaj:
172.123.123.123:1880/mapa świata/
gdzie adres IP musi być taki sam jak adres Twojego serwera.
Zobaczysz mapę z markerem pokazującym lokalizację Twojego odbiornika GNSS, aktualizowaną w czasie rzeczywistym. Możesz powiększać i pomniejszać mapę według własnego uznania.
Zalecamy przyjrzenie się każdemu z węzłów w przepływie, aby lepiej zrozumieć, co robią, zmodyfikować je i zobaczyć, co się zmieni.
Znajdziesz tu mnóstwo samouczków i narzędzi AI, które pomogą Ci, jeśli chcesz zrobić coś bardziej zaawansowanego.
Miłej zabawy!
Jeśli chcesz wyłączyć Node-RED, wykonaj następujące czynności:iptables -A INPUT -p tcp --dport 2222 -j REJECT
rodzaj ps aux | grep node , znajdź proces węzła, jeśli i zabij proces poprzez:kill NODE_PROCESS_ID