سیستم ردیابی ناوگان چیست؟ (مبتدی)
تصور کنید ۵ UGV یا AGV در یک محوطه دارید و میخواهید همیشه بدانید هر کدام کجاست. این یک سیستم ردیابی ناوگان است. هر UGV یک گره LoRa دارد که موقعیت GPS را هر ۳۰ ثانیه ارسال میکند.
یک Gateway LoRa (Raspberry Pi + SX1278) تمام این پکتها را دریافت میکند و به یک سرور Node.js میفرستد. سرور داده را در حافظه نگه میدارد و از طریق WebSocket به مرورگر میفرستد. Leaflet.js نقشه OpenStreetMap را در مرورگر نشان میدهد و موقعیت هر UGV را با یک آیکون بهروز میکند — بدون نیاز به Refresh!
محصولی که میسازید
داشبورد نقشه زنده چند UGV با LoRa و Leaflet.js.
- تعداد UGV: تا ۲۵۵ گره (با ID یک بایتی)
- بهروزرسانی: هر ۳۰ ثانیه
- نقشه: Leaflet.js رایگان با OSM
کد Node.js — سرور Gateway
const express = require('express');
const { SerialPort } = require('serialport');
const WebSocket = require('ws');
const { ReadlineParser } = require('@serialport/parser-readline');
const app = express();
const wss = new WebSocket.Server({ port: 8080 });
const fleet = {}; // { ugvId: { lat, lon, timestamp } }
// سریال Gateway LoRa (RPi + SX1278):
const port = new SerialPort({ path: '/dev/ttyUSB0', baudRate: 9600 });
const parser = port.pipe(new ReadlineParser({ delimiter: '\n' }));
// فرمت پکت LoRa از UGV: "ID:01,35.744800,51.375300"
parser.on('data', (line) => {
const parts = line.trim().split(',');
if(parts.length === 3 && parts[0].startsWith('ID:')) {
const id = parts[0].split(':')[1];
const lat = parseFloat(parts[1]);
const lon = parseFloat(parts[2]);
if(!isNaN(lat) && !isNaN(lon)) {
fleet[id] = { lat, lon, ts: Date.now() };
// ارسال به همه مرورگرها:
wss.clients.forEach(c => {
if(c.readyState === WebSocket.OPEN)
c.send(JSON.stringify({ id, lat, lon }));
});
}
}
});
// صفحه نقشه:
app.get('/', (req, res) => res.sendFile(__dirname + '/map.html'));
app.get('/api/fleet', (req, res) => res.json(fleet));
app.listen(3000, () => console.log('Fleet tracker: http://localhost:3000'));
کد Leaflet HTML — نقشه زنده
<!-- map.html -->
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<div id="map" style="height:100vh"></div>
<script>
const map = L.map('map').setView([35.7448, 51.3753], 15);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
const colors = ['red','blue','green','orange','purple'];
const markers = {};
const ws = new WebSocket('ws://localhost:8080');
ws.onmessage = (e) => {
const d = JSON.parse(e.data);
if(!markers[d.id]) {
const ci = Object.keys(markers).length % colors.length;
markers[d.id] = L.marker([d.lat, d.lon], {
title: 'UGV ' + d.id
}).addTo(map).bindPopup('UGV ' + d.id);
} else {
markers[d.id].setLatLng([d.lat, d.lon]);
}
};
</script>
چکلیست سیستم
| بررسی | توضیح |
|---|---|
| Gateway پکت UGV را میگیرد؟ | Serial Monitor RPi |
| Node.js پارس میکند؟ | console.log fleet |
| نقشه روی مرورگر باز میشود؟ | http://localhost:3000 |
| مکانها بهروز میشوند؟ | WebSocket test |