Skip to content
كل المقالات

بناء خريطة أسطول مباشرة على Navixy GPS API

تحديث بيقف لما محدش باصص، علامات بتتزحلق بدل ما تنط، والفخاخ الصغيرة في بيانات الـ GPS: نوعين من الحالة، وأجهزة تتبّع بتقول إنها في 0,0.

أحمد عبد المجيد

قراءة دقيقتين

شارك:WhatsAppLinkedIn

Sima Track منصة تتبّع أساطيل: كل مركبة مباشرة على الخريطة، على الويب وفي تطبيق آيفون وأندرويد. الأماكن جاية من Navixy، منصة تتبّع GPS ليها HTTP API. Navixy بيدّيك إحداثيات. إنها تحسّسك بخريطة مباشرة دي شغلة التطبيق، ودي الحتت اللي احتاجت تفكير.

١. خلّي مفتاح الحساب على السيرفر#

Navixy بيقبل نوعين من بيانات الدخول: مفتاح API للحساب كله، و session hash المستخدم بياخده لما يسجّل دخول. لوحة التحكم على الويب مش بتشوف ولا واحد فيهم. المتصفح بيكلّم باك إند Express بتسجيل دخول خاص بيه، والباك إند هو اللي بيضيف المفتاح ويكلّم Navixy.

this.http = axios.create({
  baseURL,
  headers: { Authorization: `NVX ${apiKey}` },
  timeout: 15_000,
});

تطبيق الموبايل بيشتغل بطريقة تانية. كل مستخدم بيدخل بحساب Navixy بتاعه، والتطبيق بيحتفظ بالـ session hash بتاع المستخدم ده بس، في التخزين الآمن بتاع الموبايل. مفتاح الحساب عمره ما بيتحط جوه التطبيق، عشان أي حد يقدر يطلّعه من هناك.

٢. حدّث، بس طول ما حد باصص#

الأماكن بتتجاب بسؤال كل خمس ثواني. الـ setInterval العادي ليه تمن على الموبايل: التبويب بيفضل شغال بعد ما تسيبه، فالتايمر بيفضل يجيب كل المركبات ويعيد رسم كل العلامات تحت أي شاشة مفتوحة. الـ hook بتاع التحديث في التطبيق بيشتغل بس طول ما شاشته هي اللي قدامك، وبيعدّي الدور لما التطبيق يبقى في الخلفية.

export function usePoll(fn: () => void | Promise<unknown>, ms: number) {
  const saved = useRef(fn);
  useEffect(() => {
    saved.current = fn;
  }, [fn]);

  useFocusEffect(
    useCallback(() => {
      const tick = () => {
        if (AppState.currentState !== 'active') return;
        Promise.resolve(saved.current()).catch(() => {});
      };
      tick();
      const id = setInterval(tick, ms);
      return () => clearInterval(id);
    }, [ms]),
  );
}

فخ كمان: أول طلب بعد ما الموبايل يصحى غالباً بيفشل، عشان النظام قفل الاتصال والتطبيق واقف. الكود بيبعت الطلب اللي فشل مرة كمان بعد 600 مللي ثانية، وده لطلبات القراءة بس. طلب الكتابة اللي ما جالوش رد ممكن يكون اتنفّذ فعلاً، فعمره ما بيتكرر.

const READ = /\/(list|list_\w+|get_\w+|count|search|search_\w+)$/;

export function isReplayable(url: string): boolean {
  return READ.test(url);
}

٣. نوعين من الحالة، وجهاز تتبّع في 0,0#

Navixy بيقول حاجتين منفصلتين عن جهاز التتبّع: متصل ولا لأ، وبيتحرك ولا لأ. الخريطة محتاجة لون واحد لكل مركبة، فالتطبيق بيدمجهم في حالة واحدة، والاتصال الأول.

function mapStatus(s: NavixyState): VehicleStatus {
  const conn = s.connection_status;
  if (!conn || conn === 'offline' || conn === 'signal_lost' || conn === 'just_registered') {
    return 'OFFLINE';
  }
  if (s.movement_status === 'moving') return 'MOVING';
  if (s.movement_status === 'parked' || s.movement_status === 'stopped') return 'STOPPED';
  return 'IDLE';
}
العربية الواقفة اللي فصلت تبقى غير متصلة، مش واقفة.

المفاجأة التانية جهاز تتبّع عمره ما جاله إشارة GPS. بيقول إن مكانه 0,0 ومن غير وقت، ولو اترسم زي ما هو المركبة هتظهر في المحيط قدام غرب أفريقيا. التطبيق بيعتبره من غير مكان وما بيحطهوش على الخريطة.

const loc = s.gps?.location;
// A tracker with no fix (e.g. just_registered) returns location {0,0} with a
// null `updated` — treat that as no position, not a marker off West Africa.
if (!loc || !s.gps?.updated) return null;

٤. خلّي تحديث كل خمس ثواني يبان حركة#

لما مكان جديد ييجي كل خمس ثواني، العلامة اللي بتنط شكلها بايظ. على الموبايل إحداثيات كل علامة متحرّكة، فالمكان الجديد بيزحلق المركبة لمكانها في 900 مللي ثانية.

const coord = useRef(
  new AnimatedRegion({
    latitude: pos.lat,
    longitude: pos.lng,
    latitudeDelta: 0,
    longitudeDelta: 0,
  }),
).current;

useEffect(() => {
  coord
    .timing({
      latitude: pos.lat,
      longitude: pos.lng,
      latitudeDelta: 0,
      longitudeDelta: 0,
      duration: 900,
      useNativeDriver: false,
    } as any)
    .start();
  // ...

فيه مشكلة مع العلامات المخصصة في react-native-maps: شكل العلامة بيتحوّل لصورة مرة واحدة، فتغيير الاتجاه أو الحالة ما بيظهرش. الحل إن العلامة تتسمح لها تترسم من جديد لمدة ثانية بعد كل تحديث وبعدين تتثبّت تاني، وده بيخلّي خريطة مليانة علامات خفيفة. ولما الكاميرا تمشي ورا مركبة مختارة، بتحرّك المركز بس، فالزوم اللي المستخدم اختاره بيفضل زي ما هو.

نصيحتي لأي حد بيبني حاجة زي كده#

  • خلّي مفتاح الحساب على سيرفر، وادّي كل موبايل جلسة خاصة بالمستخدم.
  • حدّث بس طول ما الشاشة قدام المستخدم والتطبيق شغال.
  • أعد طلبات القراءة مرة واحدة. وعمرك ما تعيد طلبات الكتابة.
  • قرّر "الحالة" معناها إيه قبل ما تختار الألوان، واحمي نفسك من 0,0.
  • حرّك العلامة بين كل مكان والتاني؛ الخريطة اللي بتنط شكلها غلطة.
شارك:WhatsAppLinkedIn

Keyboard shortcuts