طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 251 · برمجة الأجهزة الذكية
الدرس 20 · الوحدة 9: تكامل التفاعل مع المستشعرات في تطبيقات الأجهزة الذكية

تطبيق لياقة يدمج عدّة مستشعرات

تطبيقٌ حقيقيّ يجمع الحركة والطاقة والإضاءة. ⏱ نحو 45 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تدمج عدّة مستشعراتٍ في تطبيقٍ واحد.
  • تبني عدّاد خطواتٍ مبسّطًا مع منع التكرار.
  • تعرض تنبيهاتٍ شرطيّة من قراءات المستشعرات.

١دمج عدّة مستشعرات

التطبيقات الحقيقيّة تدمج مستشعراتٍ عدّة. تطبيق لياقةٍ مثلًا: الحركة (خطوات من الإمالة)، البطارية (تنبيه عند الانخفاض)، والضوء (وضع ليليّ للتمارين المسائيّة). ندير ذلك بمكوّنٍ رئيسٍ يجمع القراءات.

٢عدّاد خطوات من الحركة

نشترك في الإمالة؛ عند تجاوز المقدار عتبةً نعدّ خطوة (مع منع العدّ المزدوج):

import { useState, useEffect, useRef } from 'react';import { View, Text, StyleSheet } from 'react-native';import SmartDevice from 'smartdevice'; export default function App() {  const [steps, setSteps] = useState(0);  const armed = useRef(true);   useEffect(() => {    return SmartDevice.onTilt(({ x, y }) => {      const mag = Math.abs(x) + Math.abs(y);      if (mag > 30 && armed.current) { armed.current = false; setSteps((s) => s + 1); }      if (mag < 10) armed.current = true;          // أعد التسليح عند الهدوء    });  }, []);   const goal = 20;  const pct = Math.min(100, Math.round((steps / goal) * 100));  return (    <View style={styles.box}>      <Text testID="steps" style={styles.n}>{steps}</Text>      <Text style={styles.lbl}>خطوة من {goal}</Text>      <View style={styles.barBg}><View style={[styles.barFill, { width: pct + '%' }]} /></View>    </View>  );} const styles = StyleSheet.create({  box: { padding: 24, alignItems: 'center' },  n: { fontSize: 52, fontWeight: 'bold', color: '#E8820C' },  lbl: { color: '#666' },  barBg: { width: 200, height: 12, backgroundColor: '#eee', borderRadius: 6, marginTop: 12, overflow: 'hidden' },  barFill: { height: 12, backgroundColor: '#2E7D32' },});

useRef يحمل علَم «مسلّح» دون إعادة رسم. اضغط «هزّ» عدّة مرّات ليرتفع العدّاد.

٣لوحة اللياقة الكاملة

نجمع الخطوات مع البطارية والإضاءة في لوحةٍ واحدة. حرّك المستشعرات الثلاثة:

import { View, Text, StyleSheet } from 'react-native';import { useBattery, useLight } from 'smartdevice'; function Stat({ icon, label, value, color }) {  return (    <View style={styles.stat}>      <Text style={styles.ic}>{icon}</Text>      <Text style={[styles.val, { color }]}>{value}</Text>      <Text style={styles.lbl}>{label}</Text>    </View>  );} export default function App() {  const bat = useBattery();  const lux = useLight();  const night = lux < 50;  return (    <View style={[styles.box, { backgroundColor: night ? '#1a2330' : '#F7FAFC' }]}>      <Text style={[styles.h, { color: night ? '#fff' : '#333' }]}>        {night ? '🌙 تمرين مسائيّ' : '☀️ تمرين نهاريّ'}      </Text>      <View style={styles.row}>        <Stat icon="🚶" label="خطوات" value="12" color="#E8820C" />        <Stat icon="🔋" label="البطارية" value={bat.level + '%'} color={bat.level < 20 ? '#C62828' : '#2E7D32'} />        <Stat icon="💡" label="الإضاءة" value={lux} color="#1565C0" />      </View>      {bat.level < 20 && <Text style={styles.warn}>⚠ البطارية منخفضة — قد يتوقّف التتبّع</Text>}    </View>  );} const styles = StyleSheet.create({  box: { padding: 18, borderRadius: 14, margin: 10 },  h: { fontSize: 18, fontWeight: 'bold', marginBottom: 14, textAlign: 'center' },  row: { flexDirection: 'row', justifyContent: 'space-around' },  stat: { alignItems: 'center' },  ic: { fontSize: 26 },  val: { fontSize: 20, fontWeight: 'bold', marginTop: 4 },  lbl: { color: '#888', fontSize: 12 },  warn: { color: '#C62828', textAlign: 'center', marginTop: 14 },});

ثلاث قراءاتٍ في لوحةٍ واحدة، وتنبيهٌ شرطيّ عند انخفاض البطارية. هذا دمج المستشعرات الحقيقيّ.

توقّع وتحقّق

لماذا useRef لعلَم التسليح؟

لمنع العدّ المزدوج للخطوة:

دمج المستشعرات يعني:

التنبيه عند انخفاض البطارية:

الخلاصة

تحدٍّ برمجي: عدّاد نشاط

متقدم

ادمج الخطوات (ثابتة) مع تنبيه البطارية.

المطلوب:
  • استورد useBattery.
  • <Text testID="steps"> يعرض عدد خطواتٍ ثابت (مثلًا 8).
  • <Text testID="bat">: إن كانت البطارية أقلّ من 20 «منخفضة» وإلا «جيدة».
👀 اعرض الناتج المطلوب (وجرّبه)
✓ التحقق الآلي من حلّك:
  • الكود يعمل بلا أخطاء في Console
  • الخطوات 8
  • البطارية «جيدة» ابتداءً
  • استُخدم useBattery

💡 تلميح 1
البطارية الابتدائيّة 80% ≥ 20 فالحالة «جيدة».
💡 تلميح 2
ادمج قراءتين: ثابتة (خطوات) وحيّة (بطارية).

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

import { View, Text, StyleSheet } from 'react-native';import { useBattery } from 'smartdevice'; export default function App() {  const bat = useBattery();  const steps = 8;  const low = bat.level < 20;  return (    <View style={{ padding: 20, gap: 8 }}>      <Text testID="steps" style={styles.s}>الخطوات: {steps}</Text>      <Text testID="bat" style={{ color: low ? '#C62828' : '#2E7D32' }}>        {low ? 'منخفضة' : 'جيدة'}      </Text>    </View>  );} const styles = StyleSheet.create({ s: { fontSize: 22, fontWeight: 'bold', color: '#E8820C' } });
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس