از Generic Sensor API برای دسترسی به حسگرهای روی دستگاه مانند شتاب سنج، ژیروسکوپ و مغناطیس سنج استفاده کنید.
امروزه، دادههای حسگر در بسیاری از برنامههای کاربردی خاص پلتفرم برای فعال کردن موارد استفاده مانند بازی همهجانبه، ردیابی تناسب اندام، و واقعیت افزوده یا مجازی استفاده میشود. آیا پر کردن شکاف بین برنامه های کاربردی مخصوص پلتفرم و وب جالب نیست؟ Generic Sensor API را برای وب وارد کنید!
Generic Sensor API چیست؟
Generic Sensor API مجموعهای از رابطها است که دستگاههای حسگر را در معرض پلتفرم وب قرار میدهند. API از رابط Sensor
پایه و مجموعه ای از کلاس های حسگر بتن ساخته شده در بالا تشکیل شده است. داشتن یک رابط پایه، فرآیند اجرا و مشخصات را برای کلاس های حسگر بتن ساده می کند. به عنوان مثال، نگاهی به کلاس Gyroscope
بیندازید. فوق العاده کوچک است! عملکرد اصلی توسط رابط پایه مشخص می شود و Gyroscope
صرفاً آن را با سه ویژگی نشان دهنده سرعت زاویه ای گسترش می دهد.
برخی از کلاسهای حسگر با حسگرهای سختافزاری واقعی مانند کلاسهای شتابسنج یا ژیروسکوپ ارتباط دارند. اینها به عنوان سنسورهای سطح پایین شناخته می شوند. سنسورهای دیگر، که به آنها حسگرهای همجوشی گفته می شود، داده های چندین حسگر سطح پایین را با هم ادغام می کنند تا اطلاعاتی را که یک اسکریپت در غیر این صورت باید محاسبه کند، در معرض دید قرار می دهد. به عنوان مثال، سنسور AbsoluteOrientation
یک ماتریس چرخشی آماده برای استفاده چهار در چهار را بر اساس داده های به دست آمده از شتاب سنج، ژیروسکوپ و مغناطیس سنج ارائه می دهد.
ممکن است فکر کنید که پلتفرم وب قبلاً داده های حسگر را ارائه می دهد و کاملاً حق با شماست! برای مثال، رویدادهای DeviceMotion
و DeviceOrientation
دادههای حسگر حرکت را نشان میدهند. پس چرا به یک API جدید نیاز داریم؟
در مقایسه با رابط های موجود، Generic Sensor API مزایای زیادی را ارائه می دهد:
- Generic Sensor API یک چارچوب حسگر است که به راحتی با کلاس های حسگر جدید قابل توسعه است و هر یک از این کلاس ها رابط عمومی را حفظ می کنند. کد مشتری نوشته شده برای یک نوع سنسور را می توان با تغییرات بسیار کمی برای دیگری استفاده کرد!
- می توانید سنسور را پیکربندی کنید. به عنوان مثال، می توانید فرکانس نمونه برداری را متناسب با نیازهای برنامه خود تنظیم کنید.
- می توانید تشخیص دهید که آیا سنسوری در پلتفرم موجود است یا خیر.
- خوانش سنسور دارای مهر زمانی با دقت بالایی است که امکان همگام سازی بهتر با سایر فعالیت های برنامه شما را فراهم می کند.
- مدلهای دادههای حسگر و سیستمهای مختصات به وضوح تعریف شدهاند و به فروشندگان مرورگر اجازه میدهند راهحلهای قابل همکاری را پیادهسازی کنند.
- رابطهای مبتنی بر حسگر عمومی به DOM محدود نمیشوند (به این معنی که آنها نه
navigator
هستند و نه اشیاءwindow
)، و این فرصتهای آینده را برای استفاده از API در سرویسکاران یا پیادهسازی آن در زمانهای اجرا بدون سر جاوا اسکریپت، مانند دستگاههای جاسازی شده، باز میکند. - جنبه های امنیت و حریم خصوصی اولویت اصلی Generic Sensor API است و امنیت بسیار بهتری را در مقایسه با API های سنسور قدیمی ارائه می دهد. یکپارچگی با Permissions API وجود دارد.
- همگام سازی خودکار با مختصات صفحه نمایش برای
Accelerometer
،Gyroscope
،LinearAccelerationSensor
، سنسورAbsoluteOrientationSensor
، حسگرRelativeOrientationSensor
وMagnetometer
در دسترس است.
APIهای سنسور عمومی موجود
در زمان نوشتن، چندین حسگر وجود دارد که می توانید با آنها آزمایش کنید.
سنسورهای حرکتی:
-
Accelerometer
-
Gyroscope
-
LinearAccelerationSensor
-
AbsoluteOrientationSensor
-
RelativeOrientationSensor
-
GravitySensor
حسگرهای محیطی:
-
AmbientLightSensor
(در پشت پرچم#enable-generic-sensor-extra-classes
در Chromium.) -
Magnetometer
(در پشت پرچم#enable-generic-sensor-extra-classes
در Chromium.)
تشخیص ویژگی
تشخیص ویژگی های API های سخت افزاری مشکل است، زیرا شما باید هم تشخیص دهید که آیا مرورگر از رابط مورد نظر پشتیبانی می کند یا خیر و اینکه آیا دستگاه دارای حسگر مربوطه است یا خیر. بررسی اینکه آیا مرورگر از یک رابط پشتیبانی می کند یا نه، ساده است. ( 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 m/s 2 خواهد بود و هنگامی که دستگاهی صاف روی میز قرار می گیرد، شتاب در جهت رو به بالا (محور Z) خواهد بود. برابر گرانش زمین باشد، یعنی g ≈ +9.8 m/s 2 در حال اندازه گیری نیروی میز که دستگاه را به سمت بالا می راند. اگر دستگاه را به سمت راست فشار دهید، شتاب در محور X مثبت یا اگر دستگاه از راست به چپ شتاب داده شود منفی خواهد بود.
شتابسنجها را میتوان برای مواردی مانند: شمارش گام، سنجش حرکت یا جهتگیری ساده دستگاه استفاده کرد. اغلب، اندازهگیریهای شتابسنج با دادههای منابع دیگر ترکیب میشوند تا حسگرهای همجوشی مانند حسگرهای جهتیابی ایجاد کنند.
LinearAccelerationSensor
شتابی را که به دستگاه میزبان حسگر اعمال میشود، بدون در نظر گرفتن سهم گرانش، اندازهگیری میکند. هنگامی که یک دستگاه در حالت استراحت است، به عنوان مثال صاف روی میز دراز کشیده، سنسور شتاب ≈ 0 m/s 2 را در سه محور اندازه گیری می کند.
سنسور جاذبه
در حال حاضر این امکان برای کاربران وجود دارد که با بازرسی دستی خوانشهای Accelerometer
و LinearAccelerometer
، قرائتهای نزدیک به سنسورهای گرانشی را بدست آورند، اما این میتواند دشوار باشد و به دقت مقادیر ارائهشده توسط آن سنسورها بستگی دارد. پلتفرم هایی مانند Android می توانند خوانش های جاذبه را به عنوان بخشی از سیستم عامل ارائه دهند که باید از نظر محاسباتی ارزان تر باشد، بسته به سخت افزار کاربر مقادیر دقیق تری ارائه دهد و از نظر ارگونومی API استفاده آسان تر باشد. GravitySensor
اثر شتاب را در امتداد محور X، Y و Z دستگاه به دلیل گرانش برمی گرداند.
ژیروسکوپ
سنسور Gyroscope
سرعت زاویه ای را بر حسب رادیان در ثانیه حول محور محلی X، Y و Z دستگاه اندازه گیری می کند. اکثر دستگاه های مصرف کننده دارای ژیروسکوپ های مکانیکی ( MEMS ) هستند که حسگرهای اینرسی هستند که نرخ چرخش را بر اساس نیروی کوریولیس اینرسی اندازه گیری می کنند. ژیروسکوپ های MEMS مستعد رانش هستند که ناشی از حساسیت گرانشی حسگر است که سیستم مکانیکی داخلی سنسور را تغییر شکل می دهد. ژیروسکوپ ها در فرکانس های نسبی بالا، به عنوان مثال، 10 ثانیه کیلوهرتز، نوسان می کنند، و بنابراین، ممکن است در مقایسه با سنسورهای دیگر، انرژی بیشتری مصرف کنند.
سنسورهای جهت یابی
AbsoluteOrientationSensor
یک حسگر همجوشی است که چرخش یک دستگاه را در رابطه با سیستم مختصات زمین اندازه گیری می کند، در حالی که RelativeOrientationSensor
داده هایی را ارائه می دهد که نشان دهنده چرخش دستگاه میزبان حسگرهای حرکتی در رابطه با یک سیستم مختصات مرجع ثابت است.
تمام چارچوبهای جاوا اسکریپت سهبعدی مدرن از ماتریسهای چرخشی و کواترنیونها برای نمایش چرخش پشتیبانی میکنند. با این حال، اگر مستقیماً از WebGL استفاده می کنید، OrientationSensor
به راحتی دارای یک ویژگی quaternion
و یک متد populateMatrix()
است. در اینجا چند قطعه وجود دارد:
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();
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();
// 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);
حسگرهای جهت یابی، موارد استفاده مختلفی مانند بازی همه جانبه، واقعیت افزوده و مجازی را امکان پذیر می کنند.
برای اطلاعات بیشتر در مورد سنسورهای حرکت، موارد استفاده پیشرفته و الزامات، سند توضیح سنسورهای حرکت را بررسی کنید.
همگام سازی با مختصات صفحه نمایش
به طور پیش فرض، خوانش حسگرهای فضایی در یک سیستم مختصات محلی که به دستگاه متصل است و جهت صفحه نمایش را در نظر نمی گیرد، حل می شود.
با این حال، بسیاری از موارد استفاده مانند بازیها یا واقعیت افزوده و مجازی نیاز به خوانش حسگر در یک سیستم مختصاتی دارند که در عوض به جهت صفحه نمایش محدود میشود.
قبلاً، نقشهبرداری مجدد قرائتهای حسگر به مختصات صفحه باید در جاوا اسکریپت پیادهسازی میشد. این رویکرد ناکارآمد است و همچنین پیچیدگی کد برنامه وب را به طور قابل توجهی افزایش می دهد. برنامه وب باید تغییرات جهت صفحه نمایش را مشاهده کند و مختصات را برای خوانش حسگرها انجام دهد، که برای زوایای اویلر یا کواترنیون ها کار بی اهمیتی نیست.
Generic Sensor API راه حل بسیار ساده تر و قابل اعتمادتری را ارائه می دهد! سیستم مختصات محلی برای همه کلاسهای حسگر فضایی تعریفشده قابل تنظیم است: 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' });
بیا کد بزنیم!
Generic Sensor API بسیار ساده و آسان برای استفاده است! رابط سنسور دارای روشهای start()
و stop()
برای کنترل وضعیت حسگر و چندین کنترل کننده رویداد برای دریافت اعلانها در مورد فعالسازی حسگر، خطاها و خوانشهای جدید در دسترس است. کلاس های حسگر بتن معمولاً ویژگی های خواندن خاص خود را به کلاس پایه اضافه می کنند.
محیط توسعه
در طول توسعه، میتوانید از حسگرها از طریق localhost
استفاده کنید. اگر برای دستگاههای تلفن همراه توسعه میدهید، برای سرور محلی خود، پورت فورواردینگ را راهاندازی کنید، و آماده هستید!
وقتی کد شما آماده شد، آن را روی سروری که از HTTPS پشتیبانی می کند، مستقر کنید. صفحات GitHub از طریق HTTPS ارائه می شوند و آن را به مکانی عالی برای اشتراک گذاری دموهای خود تبدیل می کنند.
چرخش مدل سه بعدی
در این مثال ساده، ما از دادههای یک حسگر جهتگیری مطلق برای اصلاح چهارتایی چرخش یک مدل سه بعدی استفاده میکنیم. این model
یک نمونه کلاس سه.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;
};
سرعت جریان به صورت تقریبی به انتگرال تابع شتاب محاسبه می شود.
اشکال زدایی و لغو حسگر با ابزار توسعه دهنده کروم
در برخی موارد برای بازی با Generic Sensor API نیازی به دستگاه فیزیکی ندارید. Chrome DevTools پشتیبانی بسیار خوبی برای شبیه سازی جهت گیری دستگاه دارد.
حریم خصوصی و امنیت
خوانش حسگرها داده های حساسی هستند که می توانند در معرض حملات مختلفی از صفحات وب مخرب قرار گیرند. پیاده سازی Generic Sensor APIs محدودیت هایی را برای کاهش خطرات احتمالی امنیتی و حفظ حریم خصوصی اعمال می کند. این محدودیت ها باید توسط توسعه دهندگانی که قصد استفاده از API را دارند در نظر گرفته شوند، بنابراین اجازه دهید به طور خلاصه آنها را فهرست کنیم.
فقط HTTPS
از آنجایی که Generic Sensor API یک ویژگی قدرتمند است، مرورگر آن را فقط در زمینه های امن اجازه می دهد. در عمل به این معنی است که برای استفاده از Generic Sensor API باید از طریق HTTPS به صفحه خود دسترسی داشته باشید. در طول توسعه می توانید این کار را از طریق http://localhost انجام دهید اما برای تولید باید HTTPS را روی سرور خود داشته باشید. برای بهترین شیوه ها و دستورالعمل ها به مجموعه ایمن و ایمن مراجعه کنید.
یکپارچه سازی خط مشی مجوزها
ادغام خط مشی مجوزها در Generic Sensor API دسترسی به داده های حسگرها را برای یک قاب کنترل می کند.
بهطور پیشفرض، اشیاء Sensor
را میتوان فقط در یک فریم اصلی یا فریمهای فرعی با منشاء ایجاد کرد، بنابراین از خواندن غیرقانونی دادههای حسگر در فریمهای متقاطع جلوگیری میکند. این رفتار پیشفرض را میتوان با فعال کردن یا غیرفعال کردن صریح ویژگیهای کنترلشده توسط خطمشی مربوطه اصلاح کرد.
قطعه زیر اعطای دسترسی به دادههای شتابسنج به یک iframe متقاطع را نشان میدهد، به این معنی که اکنون میتوان اشیاء Accelerometer
یا LinearAccelerationSensor
را در آنجا ایجاد کرد.
<iframe src="https://third-party.com" allow="accelerometer" />
تحویل قرائت سنسور را می توان به حالت تعلیق درآورد
خواندن حسگر فقط توسط یک صفحه وب قابل مشاهده قابل دسترسی است، یعنی زمانی که کاربر واقعاً با آن تعامل دارد. علاوه بر این، اگر فوکوس کاربر به یک زیرفریم با مبدا متقابل تغییر کند، دادههای حسگر به قاب والد ارائه نمیشود. این از استنتاج ورودی کاربر توسط قاب والد جلوگیری می کند.
بعدش چی؟
مجموعه ای از کلاس های حسگر از قبل مشخص شده وجود دارد که در آینده نزدیک اجرا می شوند مانند سنسور نور محیطی یا حسگر مجاورت . با این حال، به لطف توسعه پذیری زیاد چارچوب سنسور عمومی، میتوانیم ظاهر کلاسهای جدید بیشتری را که انواع مختلف حسگر را نشان میدهند، پیشبینی کنیم.
یکی دیگر از زمینه های مهم برای کار آینده، بهبود خود Generic Sensor API است، مشخصات سنسور عمومی در حال حاضر یک توصیه نامزد است، به این معنی که هنوز زمان برای اصلاحات و ارائه عملکردهای جدید مورد نیاز توسعه دهندگان وجود دارد.
شما می توانید کمک کنید!
مشخصات سنسور به سطح بلوغ توصیه نامزد رسیده است، از این رو، بازخورد توسعه دهندگان وب و مرورگر بسیار قدردانی می شود. به ما اطلاع دهید که افزودن چه ویژگیهایی عالی است یا چیزی وجود دارد که میخواهید در API فعلی تغییر دهید.
لطفاً مشکلات مربوط به مشخصات و همچنین باگهای پیادهسازی Chrome را با خیال راحت پرونده کنید.
منابع
- پروژه های آزمایشی: https://intel.github.io/generic-sensor-demos/
- مشخصات API سنسور عمومی: https://w3c.github.io/sensors/
- مشکلات مشخصات: https://github.com/w3c/sensors/issues
- لیست پستی گروه کاری W3C: public-device-apis@w3.org
- وضعیت ویژگی کروم: https://www.chromestatus.com/feature/5698781827825664
- اشکالات پیاده سازی: http://crbug.com?q=component:Blink>Sensor
قدردانی
این مقاله توسط Joe Medley و Kayce Basques بررسی شده است. تصویر قهرمان توسط Misko از طریق Wikimedia Commons .