GNSS Technologia 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 Mistrz, 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 wysyłasz na port COM wtyczki XBee wiadomości, które chcesz wysłać na serwer. Zwykle chcesz wysłać co najmniej: 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