أدوات استشعار الويب

استخدِم Generic Sensor API للوصول إلى أدوات الاستشعار على الجهاز، مثل مقاييس التسارع والجيروسكوب ومقياسات المغناطيسية.

في الوقت الحالي، يتم استخدام بيانات أجهزة الاستشعار في العديد من التطبيقات المخصّصة للنظام الأساسي لتفعيل حالات الاستخدام، مثل الألعاب الغامرة وتتبُّع مستوى اللياقة البدنية والواقع المعزّز أو الافتراضي. ألا يكون من الرائع سدّ الفجوة بين تطبيقات الويب وتطبيقات المنصات؟ أدخِل Generic Sensor API للويب.

ما هي Generic Sensor API؟

Generic Sensor API هي مجموعة من الواجهات التي توفّر أجهزة الاستشعار لمنصّة الويب. تتكوّن واجهة برمجة التطبيقات من واجهة برمجة التطبيقات الأساسية Sensor ومجموعة من فئات الأجهزة الاستشعارية المحددة التي تم إنشاؤها على أساسها. إنّ توفُّر واجهة أساسية يسهّل عملية تنفيذ فئات أجهزة الاستشعار المحدّدة وتحديد مواصفاتها. على سبيل المثال، ألقِ نظرة على صف واحد (Gyroscope). إنه صغير جدًا. يتم تحديد الوظائف الأساسية من خلال الواجهة الأساسية، ولا تفعل سوى Gyroscope توسيع نطاقها باستخدام ثلاث سمات تمثّل السرعة الزاوية.

تتفاعل بعض فئات أدوات الاستشعار مع أدوات استشعار الأجهزة الفعلية، مثل فئات مقياس التسارع أو الجيروسكوب. ويُشار إلى هذه باسم أجهزة الاستشعار ذات المستوى المنخفض. أدوات استشعار أخرى يُشار إليها باسم مستشعرات الدمج، ندمج البيانات من عدة أجهزة استشعار منخفضة المستوى أجهزة الاستشعار للكشف عن المعلومات التي قد يحتاج النص البرمجي إلى حسابها. على سبيل المثال، جهاز استشعار AbsoluteOrientation توفر مصفوفة تدوير من أربعة في أربعة جاهزة للاستخدام استنادًا إلى البيانات التي تم الحصول عليها من مثل مقياس التسارع والجيروسكوب ومقياس المغناطيسية.

قد تعتقد أنّ منصة الويب توفّر بيانات حول أجهزة الاستشعار، وأنت على صواب. على سبيل المثال، يعرض حدثا DeviceMotion و DeviceOrientation بيانات جهاز استشعار الحركة. لماذا نحتاج إلى واجهة برمجة تطبيقات جديدة؟

مقارنةً بالواجهات الحالية، توفّر Generic Sensor API عددًا كبيرًا من المزايا:

  • Generic Sensor API هي إطار عمل لأجهزة الاستشعار يمكن توسيعه بسهولة باستخدام فئات أجهزة استشعار جديدة، وستحتفظ كل فئة من هذه الفئات بالواجهة العامة. يمكن إعادة استخدام رمز العميل المكتوب لنوع واحد من أجهزة الاستشعار لنوع آخر من أجهزة الاستشعار بعد إجراء تعديلات قليلة جدًا.
  • يمكنك ضبط جهاز الاستشعار. على سبيل المثال، يمكنك ضبط معدّل أخذ العينات المناسب لاحتياجات تطبيقك.
  • يمكنك معرفة ما إذا كان هناك جهاز استشعار متاح على المنصة.
  • تحتوي قراءات أجهزة الاستشعار على طوابع زمنية عالية الدقة، ما يتيح مزامنة أفضل مع أنشطة أخرى في تطبيقك.
  • يتم تحديد نماذج بيانات أجهزة الاستشعار وأنظمة التنسيق بوضوح، ما يسمح لمورّدي المتصفّحات بما يلي: وتنفيذ حلول قابلة للتشغيل التفاعلي.
  • الواجهات المستندة إلى أداة الاستشعار العامة غير مرتبطة بنموذج DOM (أي أنّ الواجهات ليست navigator) أو window)، وهذا يفتح فرصًا مستقبلية لاستخدام واجهة برمجة التطبيقات ضمن الخدمة العاملين أو تنفيذها في بيئات تشغيل JavaScript بلا واجهة مستخدم رسومية، مثل الأجهزة.
  • تُعدّ جوانب الأمان والخصوصية من أهم الأولويات في واجهة برمجة التطبيقات Generic Sensor API، كما أنّها توفّر مستوى أمان أفضل بكثير مقارنةً بواجهات برمجة تطبيقات أجهزة الاستشعار القديمة. هناك عملية دمج مع واجهة برمجة التطبيقات Permissions API.
  • تتوفّر ميزة المزامنة التلقائية مع إحداثيات الشاشة لأجهزة Accelerometer وGyroscope وLinearAccelerationSensor وAbsoluteOrientationSensor وRelativeOrientationSensor وMagnetometer.

واجهات برمجة التطبيقات المتاحة للأجهزة الاستشعارية العامة

في وقت كتابة هذه المقالة، تتوفّر عدة أدوات استشعار يمكنك تجربتها.

أجهزة استشعار الحركة:

  • Accelerometer
  • Gyroscope
  • LinearAccelerationSensor
  • AbsoluteOrientationSensor
  • RelativeOrientationSensor
  • GravitySensor

أجهزة الاستشعار البيئية:

  • AmbientLightSensor (خلف الميزة التجريبية #enable-generic-sensor-extra-classes في Chromium)
  • Magnetometer (خلف الميزة التجريبية #enable-generic-sensor-extra-classes في Chromium)

رصد الميزات

يُعد اكتشاف الميزات لواجهات برمجة تطبيقات الأجهزة أمرًا معقدًا، نظرًا لأنك تحتاج إلى اكتشاف كلٍ من ما إذا كان المستعرض يتوافق مع الواجهة المعنيّة وما إذا كان الجهاز يحتوي على أداة الاستشعار المقابلة. جارٍ التحقّق ما إذا كان المتصفح يدعم الواجهة أمرًا سهلاً أم لا. (استبدِل Accelerometer بأي من الواجهات الأخرى المذكورة أعلاه).

if ('Accelerometer' in window) {
  // The `Accelerometer` interface is supported by the browser.
  // Does the device have an accelerometer, though?
}

للحصول على نتيجة فعّالة لميزة رصد الأجسام، عليك محاولة الاتصال بجهاز الاستشعار أيضًا. يوضّح هذا المثال كيفية إجراء ذلك.

let accelerometer = null;
try {
  accelerometer = new Accelerometer({ frequency: 10 });
  accelerometer.onerror = (event) => {
    // Handle runtime errors.
    if (event.error.name === 'NotAllowedError') {
      console.log('Permission to access sensor was denied.');
    } else if (event.error.name === 'NotReadableError') {
      console.log('Cannot connect to the sensor.');
    }
  };
  accelerometer.onreading = (e) => {
    console.log(e);
  };
  accelerometer.start();
} catch (error) {
  // Handle construction errors.
  if (error.name === 'SecurityError') {
    console.log('Sensor construction was blocked by the Permissions Policy.');
  } else if (error.name === 'ReferenceError') {
    console.log('Sensor is not supported by the User Agent.');
  } else {
    throw error;
  }
}

حشو بوليستر

بالنسبة إلى المتصفحات التي لا تتيح استخدام Generic Sensor API، يتوفّر polyfill. يتيح لك polyfill تحميل أجهزة الاستشعار ذات الصلة فقط وعمليات التنفيذ.

// Import the objects you need.
import { Gyroscope, AbsoluteOrientationSensor } from './src/motion-sensors.js';

// And they're ready for use!
const gyroscope = new Gyroscope({ frequency: 15 });
const orientation = new AbsoluteOrientationSensor({ frequency: 60 });

ما هي كل أدوات الاستشعار هذه؟ كيف يمكنني استخدامها؟

أدوات الاستشعار هي مجال قد يحتاج إلى مقدمة موجزة. إذا كنت على دراية بأجهزة الاستشعار، يمكنك انتقِل مباشرةً إلى قسم الترميز العملي. بخلاف ذلك، لنلقِ نظرة على كل جهاز استشعار متوافق بالتفصيل.

مقياس التسارع وجهاز استشعار التسارع الخطّي

قياسات جهاز استشعار التسارع

جهاز استشعار Accelerometer يقيس تسارع الجهاز الذي يستضيف أداة الاستشعار على ثلاثة محاور (X وY وZ). أداة الاستشعار هذه هي وهو ما يعني أنه عندما يكون الجهاز في وضع السقوط الحر الخطي، فإن إجمالي سيكون التسارع 0 م/ث2، وعندما يرقد الجهاز بشكل مستوٍ على الطاولة، فإن التسارع في الاتجاه لأعلى (المحور Z) يساوي جاذبية الأرض، أي g ≈ +9.8 م/ث2 يقيس قوة الطاولة التي تدفع الجهاز إلى الأعلى. إذا دفعت الجهاز ناحية اليمين، سيكون التسارع على محور X موجبًا، أو سالبًا إذا تم تسريع الجهاز من اليمين باتجاه اليسار.

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

يقيس LinearAccelerationSensor التسارع الذي يتم تطبيقه على الجهاز الذي يستضيف أداة الاستشعار، باستثناء المساهمة للجاذبية. عندما يكون الجهاز غير نشط، على سبيل المثال، في وضع مستوٍ على الطاولة، ستقيس أداة الاستشعار ≈ 0 م/ث2 تسارع على ثلاثة محاور.

أداة استشعار الجاذبية

بإمكان المستخدمين الحصول يدويًا على قراءات قريبة من أجهزة استشعار الجاذبية عن طريق فحص قراءات Accelerometer وLinearAccelerometer يدويًا، ولكن قد يكون هذا مرهقًا وتعتمد على دقة القيم التي تقدمها أجهزة الاستشعار هذه. يمكن للمنصّات، مثل Android، تقديم قراءات الجاذبية كجزء من نظام التشغيل، ما يُفترض أن يكون أرخص من حيث الحساب، ويقدّم قيمًا أكثر دقة استنادًا إلى أجهزة المستخدم، ويسهل استخدامه من حيث سهولة استخدام واجهة برمجة التطبيقات. تعرِض دالة GravitySensor تأثير التسارع على طول محورَي X وY وZ للجهاز بسبب الجاذبية.

الجيروسكوب

قياسات أجهزة استشعار الجيروسكوب

تقيس أداة استشعار Gyroscope السرعة الزاويّة بوحدات الراديان في الثانية حول المحور المحلي "س" و"ص" و"ع" للجهاز. معظم المستهلكين تحتوي الأجهزة على ميكانيكية (MEMS) الجيروسكوب، وهي أدوات استشعار بالقصور الذاتي تقيس معدل الدوران بناءً على قوة كوريوليس غير المنتظمة الجيروسكوب (MEMS) عرضة الانحراف الناتج عن حساسية الجاذبية لجهاز الاستشعار التي تتشوّه نظام ميكانيكي داخلي. تهتز أجهزة الجيرسكوب بمعدّلات تكرار عالية نسبيًا، على سبيل المثال: 10 كيلوهرتز وبالتالي، قد تستهلك المزيد من الطاقة مقارنةً بالمستشعرات الأخرى.

أجهزة استشعار الاتجاه

القياسات التي يرصدها جهاز استشعار التوجيه المطلق

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

جميع أطر عمل JavaScript الثلاثية الأبعاد الحديثة توفّر الأرقام الرباعية. ومصفوفات التدوير لتمثيل الدوران؛ ومع ذلك، إذا كنت تستخدم WebGL بشكل مباشر، فإن OrientationSensor تحتوي على كلٍ من موقع واحد (quaternion) و طريقة واحدة (populateMatrix()) في ما يلي بعض المقتطفات:

three.js

let torusGeometry = new THREE.TorusGeometry(7, 1.6, 4, 3, 6.3);
let material = new THREE.MeshBasicMaterial({ color: 0x0071c5 });
let torus = new THREE.Mesh(torusGeometry, material);
scene.add(torus);

// Update mesh rotation using quaternion.
const sensorAbs = new AbsoluteOrientationSensor();
sensorAbs.onreading = () => torus.quaternion.fromArray(sensorAbs.quaternion);
sensorAbs.start();

// Update mesh rotation using rotation matrix.
const sensorRel = new RelativeOrientationSensor();
let rotationMatrix = new Float32Array(16);
sensor_rel.onreading = () => {
  sensorRel.populateMatrix(rotationMatrix);
  torus.matrix.fromArray(rotationMatrix);
};
sensorRel.start();

BABYLON

const mesh = new BABYLON.Mesh.CreateCylinder('mesh', 0.9, 0.3, 0.6, 9, 1, scene);
const sensorRel = new RelativeOrientationSensor({ frequency: 30 });
sensorRel.onreading = () => mesh.rotationQuaternion.FromArray(sensorRel.quaternion);
sensorRel.start();

WebGL

// Initialize sensor and update model matrix when new reading is available.
let modMatrix = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
const sensorAbs = new AbsoluteOrientationSensor({ frequency: 60 });
sensorAbs.onreading = () => sensorAbs.populateMatrix(modMatrix);
sensorAbs.start();

// Somewhere in rendering code, update vertex shader attribute for the model
gl.uniformMatrix4fv(modMatrixAttr, false, modMatrix);

تتيح أدوات استشعار الاتجاه حالات استخدام متنوعة، مثل الألعاب الغامرة، والألعاب المعززة والافتراضية. الواقع.

للحصول على مزيد من المعلومات حول أجهزة استشعار الحركة وحالات الاستخدام المتقدّمة والمتطلبات، يمكنك الاطّلاع على مستند توضيحي حول أجهزة استشعار الحركة.

المزامنة مع إحداثيات الشاشة

يتم تلقائيًا حل قراءات أجهزة الاستشعار المكانية في نظام إحداثيات محلي مرتبط بالجهاز ولا يأخذ اتجاه الشاشة في الاعتبار.

نظام إحداثيات الجهاز
نظام الإحداثيات للجهاز

ومع ذلك، تتطلب العديد من حالات الاستخدام مثل الألعاب أو الواقع المعزز والواقع الافتراضي أن تكون قراءات جهاز الاستشعار في نظام إحداثي مرتبط باتجاه الشاشة بدلاً من ذلك.

نظام إحداثيات الشاشة
نظام إحداثيات الشاشة

في السابق، كان يجب تنفيذ إعادة ربط قراءات المستشعرات بتنسيقات الإحداثيات على الشاشة باستخدام JavaScript. هذه الطريقة غير فعالة كما أنها تزيد إلى حد كبير من تعقيد الويب رمز التطبيق يجب على تطبيق الويب مشاهدة التغييرات في اتجاه الشاشة وإجراء الإحداثيات التحويلات في قراءات المستشعر، وهو أمر ليس تافهًا ينبغي القيام به بالنسبة إلى زوايا أولر الرباعية.

توفّر واجهة برمجة تطبيقات أداة الاستشعار العامة حلاً أبسط وموثوقًا به! يمكن تعديل نظام الإحداثيات المحلي لجميع فئات أجهزة الاستشعار المكانية المحدّدة: Accelerometer وGyroscope وLinearAccelerationSensor وAbsoluteOrientationSensor وRelativeOrientationSensor و Magnetometer. من خلال تمرير الخيار referenceFrame إلى أداة إنشاء عنصر أداة الاستشعار، يحدِّد المستخدم ما إذا كان سيتم حلّ القراءات المعروضة في إحداثيات الجهاز أو الشاشة.

// Sensor readings are resolved in the Device coordinate system by default.
// Alternatively, could be RelativeOrientationSensor({referenceFrame: "device"}).
const sensorRelDevice = new RelativeOrientationSensor();

// Sensor readings are resolved in the Screen coordinate system. No manual remapping is required!
const sensorRelScreen = new RelativeOrientationSensor({ referenceFrame: 'screen' });

لنقم بالترميز!

واجهة برمجة تطبيقات أداة الاستشعار العامة بسيطة جدًا وسهلة الاستخدام. تحتوي واجهة Sensor على أسلوبَي start() و stop() للتحكّم في حالة أداة الاستشعار والعديد من معالجي الأحداث لتلقّي إشعارات بشأن تفعيل أداة الاستشعار والأخطاء والقياسات المتاحة حديثًا. تضيف فئات المستشعرات الخرسانية عادةً سمات القراءة الخاصة بها إلى القاعدة الصف.

بيئة التطوير

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

عندما يكون الرمز جاهزًا، انشره على خادم يتوافق مع HTTPS. يتم عرض صفحات GitHub عبر HTTPS، مما يجعلها مكانًا رائعًا لمشاركة عروضك التوضيحية.

تدوير التصميم الثلاثي الأبعاد

في هذا المثال البسيط، نستخدم البيانات الواردة من أداة استشعار التوجيه المطلق لتعديل كمية الدوران للرباعي لنموذج ثلاثي الأبعاد. عنصر model هو three.js مثيل الفئة Object3D الذي يحتوي على الموقع quaternion يوضّح المقتطف التالي من رمز الاختبار المرجعي لميزة اتجاه الهاتف كيفية استخدام أداة استشعار الاتجاه المطلق لتدوير تصميم ثلاثي الأبعاد.

function initSensor() {
  sensor = new AbsoluteOrientationSensor({ frequency: 60 });
  sensor.onreading = () => model.quaternion.fromArray(sensor.quaternion);
  sensor.onerror = (event) => {
    if (event.error.name == 'NotReadableError') {
      console.log('Sensor is not available.');
    }
  };
  sensor.start();
}

سيظهر اتجاه الجهاز من خلال دوران model ثلاثي الأبعاد في مشهد WebGL.

أداة الاستشعار تعدِّل اتجاه التصميم الثلاثي الأبعاد
يعدّل جهاز الاستشعار اتجاه التصميم الثلاثي الأبعاد

أداة قياس عدد اللقطات

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

this.maxSpeed = 0;
this.vx = 0;
this.ax = 0;
this.t = 0;

/* … */

this.accel.onreading = () => {
  let dt = (this.accel.timestamp - this.t) * 0.001; // In seconds.
  this.vx += ((this.accel.x + this.ax) / 2) * dt;

  let speed = Math.abs(this.vx);

  if (this.maxSpeed < speed) {
    this.maxSpeed = speed;
  }

  this.t = this.accel.timestamp;
  this.ax = this.accel.x;
};

ويتم حساب السرعة الحالية كتقريب إلى التكامل مع دالة التسارع.

عرض توضيحي لتطبيق الويب لقياس السرعة المثقوبة
قياس سرعة اللكمة

تصحيح الأخطاء وتجاوز بيانات المستشعر باستخدام "أدوات مطوّري البرامج في Chrome"

في بعض الحالات، لا تحتاج إلى جهاز فعلي للاستفادة من Generic Sensor API. أدوات مطوري البرامج في Chrome دعم كبير محاكاة اتجاه الجهاز.

استخدام &quot;أدوات مطوّري البرامج في Chrome&quot; لتجاوز بيانات الاتجاه المخصّصة لهاتف افتراضي
محاكاة اتجاه الجهاز باستخدام "أدوات مطوّري البرامج في Chrome"

الخصوصية والأمان

قراءات أجهزة الاستشعار هي بيانات حساسة يمكن أن تتعرض لهجمات متنوعة من صفحات الويب الضارة. يؤدي تنفيذ واجهات برمجة التطبيقات لأداة الاستشعار العامة إلى فرض بعض القيود للحدّ من مستوى الأمان المحتمل. مخاطر الخصوصية. يجب أن يأخذ المطوّرون الذين يريدون استخدام واجهة برمجة التطبيقات هذه القيود في الاعتبار، لذا لنلقِ نظرة سريعة عليها.

HTTPS فقط

بما أنّ واجهة برمجة التطبيقات General Sensor API هي ميزة فعّالة، لا يتيح المتصفِّح استخدامها إلا في السياقات الآمنة. ضِمن والممارسة تعني أنّه لاستخدام واجهة برمجة التطبيقات العامة الخاصة بجهاز الاستشعار، عليك الوصول إلى صفحتك من خلال بروتوكول HTTPS. أثناء التطوير، يمكنك إجراء ذلك عبر http://localhost، ولكن عليك إجراء ذلك تحتاج إلى بروتوكول HTTPS على خادمك. اطّلِع على مجموعة آمن وسليم للاطّلاع على أفضل الممارسات والإرشادات.

دمج سياسة الأذونات

يتحكّم دمج سياسة الأذونات في Generic Sensor API في الوصول إلى بيانات أجهزة الاستشعار لإطار معيّن.

لا يمكن إنشاء عناصر Sensor تلقائيًا إلا ضمن إطار رئيسي أو إطارات فرعية من المصدر نفسه، وبالتالي يمنع ذلك إطارات iframe من مصادر مختلفة من قراءة بيانات الاستشعار بدون إذن. يمكن تعديل هذا السلوك التلقائي من خلال تفعيل الميزات التي تتحكّم فيها السياسة أو إيقافها بشكل صريح.

يوضِّح المقتطف أدناه منح إذن الوصول إلى بيانات مقياس التسارع إلى إطار iframe من مصادر متعددة، ما يعني أصبح بالإمكان الآن إنشاء عناصر Accelerometer أو LinearAccelerationSensor هناك.

<iframe src="https://third-party.com" allow="accelerometer" />

يمكن تعليق تسليم قراءات أجهزة الاستشعار

لا يمكن الوصول إلى قراءات أدوات الاستشعار إلا من خلال صفحة ويب مرئية، أي عندما يكون المستخدم مبتدئًا للتفاعل معه. بالإضافة إلى ذلك، لن يتم تقديم بيانات أداة الاستشعار إلى الإطار الرئيسي إذا تغيّر تركيز المستخدِم إلى إطار فرعي من مصدر مختلف. ويؤدي ذلك إلى منع الإطار الرئيسي من استنتاج البيانات التي أدخلها المستخدم.

ما هي الخطوات التالية؟

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

من المجالات المهمة الأخرى التي يجب العمل عليها في المستقبل تحسين Generic Sensor API نفسها، علمًا بأنّ مواصفات Generic Sensor هي حاليًا اقتراح مرشح، ما يعني أنّه لا يزال هناك وقت لإجراء إصلاحات وتقديم وظائف جديدة يحتاجها المطوّرون.

يمكنك المساعدة

وصلت مواصفات أداة الاستشعار إلى مستوى النضج في مرحلة الاقتراح المُرشح، وبالتالي، نُقدّر بشدة الملاحظات الواردة من مطوّري الويب والمتصفّحات. اسمح لنا معرفة الميزات التي سيكون من الرائع إضافتها أو ما إذا كان هناك شيء تريد تعديله في واجهة برمجة التطبيقات الحالية.

يُرجى عدم التردد في تقديم المشاكل المتعلقة بالمواصفات أيضًا. كأخطاء في تنفيذ Chrome.

الموارد

شكر وتقدير

تمت مراجعة هذه المقالة من قِبل جو ميدلي و كايسى باسكيز. صورة رئيسية بواسطة Misko عبر ويكيميديا كومنز