Bỏ qua

Tích hợp lập tuyến giao hàng

Tài liệu này mô tả cách kết hợp Geocode v4, Place v4, VRP và Route v4 để lập tuyến giao hàng cho đội xe, từ danh sách đơn hàng tới tuyến đường của từng xe.

Thứ tự gọi API:

Bước Việc API
1 Đổi địa chỉ ra toạ độ Geocode v4 rồi Place v4
2 Chia điểm cho các xe và sắp thứ tự VRP; chỉ một xe thì TSP v4
3 Đường đi từng chặng, phí cầu đường Route v4
4 Xác nhận xe đã tới điểm giao Geofencing
5 Đối soát quãng đường đã chạy Map Matching

Bước 1–2: từ địa chỉ tới tuyến của từng xe

Geocode v4 và Place v4 chuyển địa chỉ thành toạ độ. VRP nhận danh sách xe và điểm giao, trả về tuyến của từng xe. Đoạn mã dưới đây phân ba đơn hàng cho hai xe xuất phát và quay về cùng một kho.

// Node.js 18+. Gọi từ server để không lộ API key.
const KEY = process.env.VIETMAP_API_KEY;
const API = "https://maps.vietmap.vn/api";

async function getJson(url, init) {
  const res = await fetch(url, init);
  if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
  return res.json();
}

// Địa chỉ -> [kinh độ, vĩ độ] (Geocode v4 rồi Place v4)
async function toLngLat(address) {
  const q = new URLSearchParams({ apikey: KEY, text: address });
  const [best] = await getJson(`${API}/search/v4?${q}`);
  if (!best) throw new Error(`Không tìm thấy địa chỉ: ${address}`);
  const p = new URLSearchParams({ apikey: KEY, refid: best.ref_id });
  const place = await getJson(`${API}/place/v4?${p}`);
  return [place.lng, place.lat]; // VRP nhận [kinh độ, vĩ độ]
}

async function planRoutes(depot, addresses, vehicleCount) {
  const depotLngLat = await toLngLat(depot);
  const jobs = [];
  for (const [i, address] of addresses.entries()) {
    jobs.push({ id: i + 1, location: await toLngLat(address), service: 300 });
  }
  const vehicles = Array.from({ length: vehicleCount }, (_, i) => ({
    id: i + 1, profile: "car", start: depotLngLat, end: depotLngLat,
  }));
  const plan = await getJson(`${API}/vrp?api-version=1.1&apikey=${KEY}`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ vehicles, jobs }),
  });
  if (plan.code !== 0) throw new Error(`VRP: code ${plan.code}`);
  return plan;
}

const plan = await planRoutes("197 Trần Phú, Phường 4, Quận 5, TP. Hồ Chí Minh", [
  "10 Trần Huy Liệu, Phường 11, Phú Nhuận, TP. Hồ Chí Minh",
  "56 Cô Giang, Phường 2, Phú Nhuận, TP. Hồ Chí Minh",
  "1 Nguyễn Huệ, Quận 1, TP. Hồ Chí Minh",
], 2);
for (const route of plan.routes) {
  const stops = route.steps.filter((s) => s.type === "job").map((s) => s.id);
  console.log(`Xe ${route.vehicle}: đơn ${stops.join(" → ")}, ${route.distance} m`);
}
console.log("Không xếp được:", plan.unassigned.map((j) => j.id));
import os

import requests

KEY = os.environ["VIETMAP_API_KEY"]
API = "https://maps.vietmap.vn/api"


def to_lng_lat(address):
    """Địa chỉ -> [kinh độ, vĩ độ] (Geocode v4 rồi Place v4)."""
    resp = requests.get(f"{API}/search/v4", params={"apikey": KEY, "text": address}, timeout=10)
    resp.raise_for_status()
    results = resp.json()
    if not results:
        raise ValueError(f"Không tìm thấy địa chỉ: {address}")
    resp = requests.get(f"{API}/place/v4", params={"apikey": KEY, "refid": results[0]["ref_id"]}, timeout=10)
    resp.raise_for_status()
    place = resp.json()
    return [place["lng"], place["lat"]]  # VRP nhận [kinh độ, vĩ độ]


def plan_routes(depot, addresses, vehicle_count):
    depot_lng_lat = to_lng_lat(depot)
    jobs = [{"id": i + 1, "location": to_lng_lat(a), "service": 300} for i, a in enumerate(addresses)]
    vehicles = [
        {"id": i + 1, "profile": "car", "start": depot_lng_lat, "end": depot_lng_lat}
        for i in range(vehicle_count)
    ]
    resp = requests.post(
        f"{API}/vrp",
        params={"api-version": "1.1", "apikey": KEY},
        json={"vehicles": vehicles, "jobs": jobs},
        timeout=60,
    )
    resp.raise_for_status()
    plan = resp.json()
    if plan["code"] != 0:
        raise RuntimeError(f"VRP: code {plan['code']}")
    return plan


plan = plan_routes("197 Trần Phú, Phường 4, Quận 5, TP. Hồ Chí Minh", [
    "10 Trần Huy Liệu, Phường 11, Phú Nhuận, TP. Hồ Chí Minh",
    "56 Cô Giang, Phường 2, Phú Nhuận, TP. Hồ Chí Minh",
    "1 Nguyễn Huệ, Quận 1, TP. Hồ Chí Minh",
], 2)
for route in plan["routes"]:
    stops = [s["id"] for s in route["steps"] if s["type"] == "job"]
    print(f"Xe {route['vehicle']}: đơn {stops}, {route['distance']} m")
print("Không xếp được:", [j["id"] for j in plan["unassigned"]])
Xây chức năng lập tuyến giao hàng cho đội xe bằng API của VIETMAP.

1. Mỗi địa chỉ đơn hàng: GET https://maps.vietmap.vn/api/search/v4 (text=địa chỉ) lấy ref_id,
   rồi GET https://maps.vietmap.vn/api/place/v4 (refid=ref_id) lấy lat, lng. Lưu lại toạ độ để lần sau khỏi gọi.
2. POST https://maps.vietmap.vn/api/vrp?api-version=1.1 với body {vehicles, jobs}.
   Toạ độ trong VRP là [kinh độ, vĩ độ]. Kho là start và end của mỗi xe.
   code = 0 là giải xong; routes là tuyến từng xe, unassigned là đơn không xếp được.
3. Với tuyến của từng xe, gọi Route v4 để có chỉ dẫn từng chặng và phí cầu đường.

Yêu cầu:
- Gọi API từ server. Đọc API key từ biến môi trường VIETMAP_API_KEY và truyền qua `apikey`, không ghi cứng trong code.
- Kiểm tra mã HTTP của mọi lần gọi (401: sai key, 423: hết hạn mức hoặc API chưa bật).
- Đọc tài liệu bên dưới trước. Chỉ dùng tham số và trường dữ liệu có trong tài liệu.

Tài liệu:
- https://maps.vietmap.vn/docs/vi/map-api/use-cases/delivery-routing-guide/index.txt
- https://maps.vietmap.vn/docs/vi/map-api/vrp/index.txt
- https://maps.vietmap.vn/docs/vi/map-api/route-version/route-v4/index.txt
- https://maps.vietmap.vn/docs/assets/agents/logistics.txt

VRP hỗ trợ tải trọng xe, khung giờ giao, giờ làm của tài xế, xe chuyên dụng và đơn ưu tiên. Chi tiết ở trang VRP.

Bước 3: chỉ đường và phí cầu đường

VRP trả về thứ tự ghé và hình học của từng tuyến. Route v4 bổ sung chỉ dẫn từng chặng và phí cầu đường theo loại xe, với các điểm theo đúng thứ tự VRP đã xếp. Phí cầu đường được tính theo từng chặng, xem Tính phí cầu đường cho xe tải, container.

Bước 4–5: trong và sau chuyến

  • Xác nhận tới điểm giao: gửi vị trí từ ứng dụng tài xế cùng toạ độ các điểm giao và bán kính (mét) tới Geofencing. API trả inside cho từng điểm.
  • Đối soát sau chuyến: Map Matching nhận vệt GPS của cả chuyến, trả tuyến đã chạy và quãng đường thực tế.

Định dạng toạ độ và đơn vị

Định dạng toạ độ theo từng API:

Ở đâu Định dạng
focus của Autocomplete, Geocode; point của Route v4, Matrix v4, TSP v4 Chuỗi lat,lng, vĩ độ trước
Kết quả Place v4, Reverse v4 Hai trường lat, lng
location, start, end của VRP; body của Map Matching Mảng [lng, lat], kinh độ trước
Geofencing Hai trường lat, long
VietMap GL JS (center, setLngLat) Mảng [lng, lat]

Đơn vị: Route v4 trả distance theo mét và time theo mili giây; VRP dùng giây cho service, duration, time_windows và mét cho distance; Map Matching trả distance theo km.

Ước tính chi phí

Ví dụ một ngày có 3 xe và 20 điểm giao:

  • Geocode v4 và Place v4 cho 20 địa chỉ: 20 × 2 = 40 transaction. Toạ độ đã lưu dùng lại được cho khách hàng cũ.
  • VRP: 3 xe × 20 điểm = 60 transaction.
  • Route v4: ⌊số điểm / 5⌋ + 1 transaction cho mỗi request.

Quy ra tiền bằng công cụ quy đổi.

API liên quan

  • Matrix v4 — thời gian, quãng đường giữa mọi cặp điểm, khi bạn tự lập kế hoạch.
  • Isochrone — vùng xe đi tới được trong một khoảng thời gian, để chia vùng giao cho từng kho.
  • Mã lỗi — xử lý 401, 423, 429 và code trong phản hồi.
Hotline
Tổng đài hỗ trợ
089.616.4567
Messenger Chat Facebook zalo Chat Zalo