ইন্টারনেট অফ থিংস আজকাল সকলের ঠোঁটে রয়েছে এবং এটি আমার মতো টিঙ্কার এবং প্রোগ্রামারদের খুব উত্তেজিত করে তোলে। আপনার নিজের উদ্ভাবনগুলিকে জীবনে আনা এবং তাদের সাথে কথা বলতে সক্ষম হওয়ার চেয়ে আর কিছুই শীতল নয়!
কিন্তু IoT ডিভাইসগুলি যে অ্যাপগুলি ইনস্টল করে যেগুলি আপনি খুব কমই ব্যবহার করেন সেগুলি বিরক্তিকর হতে পারে, তাই আমরা IoT ডিভাইসগুলিকে আরও স্বজ্ঞাত এবং কম অনুপ্রবেশকারী করে তুলতে ফিজিক্যাল ওয়েব এবং ওয়েব ব্লুটুথের মতো আসন্ন ওয়েব প্রযুক্তিগুলির সুবিধা গ্রহণ করি৷
ওয়েব এবং IoT, একটি মিল হতে হবে
ইন্টারনেট অফ থিংস একটি বিশাল সাফল্য হতে পারে তার আগে এখনও অনেক বাধা অতিক্রম করতে হবে। একটি প্রতিবন্ধকতা হল কোম্পানি এবং পণ্য যেগুলির জন্য লোকেদের তাদের কেনা প্রতিটি ডিভাইসের জন্য অ্যাপ ইনস্টল করতে হবে, ব্যবহারকারীদের ফোনে এমন অনেক অ্যাপ রয়েছে যা তারা খুব কমই ব্যবহার করে।
এই কারণে, আমরা ফিজিক্যাল ওয়েব প্রজেক্টের ব্যাপারে খুবই উচ্ছ্বসিত, যা ডিভাইসগুলিকে একটি অনলাইন ওয়েবসাইটে একটি URL সম্প্রচার করতে দেয়, অ-অনুপ্রবেশকারী উপায়ে ৷ ওয়েব ব্লুটুথ , ওয়েব ইউএসবি এবং ওয়েব এনএফসি-র মতো উদীয়মান ওয়েব প্রযুক্তিগুলির সংমিশ্রণে, সাইটগুলি সরাসরি ডিভাইসের সাথে সংযোগ করতে পারে বা অন্তত এটি করার সঠিক উপায় ব্যাখ্যা করতে পারে।
যদিও আমরা এই নিবন্ধে প্রাথমিকভাবে ওয়েব ব্লুটুথের উপর ফোকাস করি, কিছু ব্যবহারের ক্ষেত্রে ওয়েব NFC বা ওয়েব USB-এর জন্য আরও উপযুক্ত হতে পারে। উদাহরণস্বরূপ, যদি নিরাপত্তার কারণে আপনার একটি শারীরিক সংযোগের প্রয়োজন হয় তবে ওয়েব USB পছন্দ করা হয়৷
ওয়েবসাইটটি একটি প্রগতিশীল ওয়েব অ্যাপ (PWA) হিসেবেও কাজ করতে পারে। আমরা পাঠকদের পিডব্লিউএ -র Google-এর ব্যাখ্যা চেক করার জন্য উৎসাহিত করি। PWA হল এমন সাইট যেগুলির একটি প্রতিক্রিয়াশীল, অ্যাপের মতো ব্যবহারকারীর অভিজ্ঞতা আছে, অফলাইনে কাজ করতে পারে এবং ডিভাইসের হোম স্ক্রিনে যোগ করা যেতে পারে।
ধারণার প্রমাণ হিসেবে, আমি Intel® Edison Arduino ব্রেকআউট বোর্ড ব্যবহার করে একটি ছোট ডিভাইস তৈরি করছি। ডিভাইসটিতে একটি তাপমাত্রা সেন্সর (TMP36) পাশাপাশি একটি অ্যাকচুয়েটর (রঙিন LED ক্যাথোড) রয়েছে। এই ডিভাইসের স্কিম্যাটিক্স এই নিবন্ধের শেষে পাওয়া যাবে।
ইন্টেল এডিসন একটি আকর্ষণীয় পণ্য কারণ এটি একটি সম্পূর্ণ লিনাক্স* ডিস্ট্রিবিউশন চালাতে পারে। তাই আমি সহজেই Node.js ব্যবহার করে এটি প্রোগ্রাম করতে পারি। ইনস্টলার আপনাকে Intel* XDK ইনস্টল করতে দেয় যা শুরু করা সহজ করে তোলে, যদিও আপনি নিজে নিজে প্রোগ্রাম এবং আপলোড করতে পারেন আপনার ডিভাইসে।
আমার Node.js অ্যাপের জন্য, আমার তিনটি নোড মডিউল, সেইসাথে তাদের নির্ভরতা প্রয়োজন:
-
eddystone-beacon
-
parse-color
-
johnny-five
প্রাক্তন স্বয়ংক্রিয়ভাবে noble
ইনস্টল করে, যা নোড মডিউল যা আমি Bluetooth Low Energy এর মাধ্যমে কথা বলতে ব্যবহার করি।
প্রকল্পের জন্য package.json
ফাইলটি এইরকম দেখাচ্ছে:
{
"name": "edison-webbluetooth-demo-server",
"version": "1.0.0",
"main": "main.js",
"engines": {
"node": ">=0.10.0"
},
"dependencies": {
"eddystone-beacon": "^1.0.5",
"johnny-five": "^0.9.30",
"parse-color": "^1.0.0"
}
}
ওয়েবসাইট ঘোষণা
সংস্করণ 49 থেকে শুরু করে, অ্যান্ড্রয়েডে ক্রোম ফিজিক্যাল ওয়েবকে সমর্থন করে, যা Chrome এর চারপাশের ডিভাইসগুলির দ্বারা সম্প্রচারিত URL দেখতে দেয়৷ কিছু প্রয়োজনীয়তা রয়েছে যা ডেভেলপারকে অবশ্যই সচেতন হতে হবে, যেমন সাইটগুলির প্রয়োজন সর্বজনীনভাবে অ্যাক্সেসযোগ্য হওয়া এবং HTTPS ব্যবহার করা।
এডিস্টোন প্রোটোকলের URL-এ 18 বাইট আকারের সীমা রয়েছে। তাই আমার ডেমো অ্যাপের জন্য ইউআরএল তৈরি করতে ( https://webbt-sensor-hub.appspot.com/ ), আমাকে একটি ইউআরএল শর্টনার ব্যবহার করতে হবে।
URL সম্প্রচার করা বেশ সহজ। আপনাকে যা করতে হবে তা প্রয়োজনীয় লাইব্রেরি আমদানি করতে হবে এবং কয়েকটি ফাংশন কল করতে হবে। এটি করার একটি উপায় হল advertiseUrl
কল করা যখন BLE চিপ চালু থাকে:
var beacon = require("eddystone-beacon");
var bleno = require('eddystone-beacon/node_modules/bleno');
bleno.on('stateChange', function(state) {
if (state === 'poweredOn') {
beacon.advertiseUrl("https://goo.gl/9FomQC", {name: 'Edison'});
}
}
যে সত্যিই সহজ হতে পারে না. আপনি নীচের ছবিতে দেখতে পাচ্ছেন যে Chrome ডিভাইসটিকে সুন্দরভাবে খুঁজে পেয়েছে।
সেন্সর/অ্যাকচুয়েটরের সাথে যোগাযোগ করা
আমরা আমাদের বোর্ডের উন্নতির সাথে কথা বলতে জনি-ফাইভ * ব্যবহার করি। TMP36 সেন্সরের সাথে কথা বলার জন্য জনি-ফাইভের একটি চমৎকার বিমূর্ততা রয়েছে।
নীচে আপনি তাপমাত্রা পরিবর্তনের সাথে সাথে প্রাথমিক LED রঙ সেট করার জন্য বিজ্ঞপ্তি পাওয়ার জন্য সহজ কোডটি খুঁজে পেতে পারেন।
var five = require("johnny-five");
var Edison = require("edison-io");
var board = new five.Board({
io: new Edison()
});
board.on("ready", function() {
// Johnny-Five's Led.RGB class can be initialized with
// an array of pin numbers in R, G, B order.
// Reference: http://johnny-five.io/api/led.rgb/#parameters
var led = new five.Led.RGB([ 3, 5, 6 ]);
// Johnny-Five's Thermometer class provides a built-in
// controller definition for the TMP36 sensor. The controller
// handles computing a Celsius (also Fahrenheit & Kelvin) from
// a raw analog input value.
// Reference: http://johnny-five.io/api/thermometer/
var temp = new five.Thermometer({
controller: "TMP36",
pin: "A0",
});
temp.on("change", function() {
temperatureCharacteristic.valueChange(this.celsius);
});
colorCharacteristic._led = led;
led.color(colorCharacteristic._value);
led.intensity(30);
});
আপনি উপরের *Characteristic
ভেরিয়েবলগুলিকে আপাতত উপেক্ষা করতে পারেন; এগুলি ব্লুটুথের সাথে ইন্টারফেসিং সম্পর্কে পরবর্তী বিভাগে সংজ্ঞায়িত করা হবে।
আপনি থার্মোমিটার অবজেক্টের ইনস্ট্যান্টেশনে লক্ষ্য করতে পারেন, আমি এনালগ A0
পোর্টের মাধ্যমে TMP36 এর সাথে কথা বলি। রঙিন এলইডি ক্যাথোডের ভোল্টেজ লেগগুলি ডিজিটাল পিন 3, 5 এবং 6 এর সাথে সংযুক্ত থাকে, যা এডিসন আরডুইনো ব্রেকআউট বোর্ডের পালস-উইডথ মড্যুলেশন (PWM) পিন হতে পারে।
ব্লুটুথের সাথে কথা বলছি
ব্লুটুথের সাথে কথা বলা noble
এর চেয়ে বেশি সহজ হতে পারে না।
নিম্নলিখিত উদাহরণে, আমরা দুটি ব্লুটুথ লো এনার্জি বৈশিষ্ট্য তৈরি করি: একটি LED এর জন্য এবং একটি তাপমাত্রা সেন্সরের জন্য৷ প্রাক্তন আমাদের বর্তমান LED রঙ পড়তে এবং একটি নতুন রঙ সেট করার অনুমতি দেয়। পরেরটি আমাদের তাপমাত্রা পরিবর্তন ইভেন্টগুলিতে সদস্যতা নিতে দেয়।
noble
সঙ্গে, একটি বৈশিষ্ট্য তৈরি করা বেশ সহজ. আপনাকে যা করতে হবে তা হল কীভাবে বৈশিষ্ট্যটি যোগাযোগ করে এবং একটি UUID সংজ্ঞায়িত করে। যোগাযোগের বিকল্পগুলি পঠন, লিখুন, অবহিত করুন বা এর কোনো সমন্বয়। এটি করার সবচেয়ে সহজ উপায় হল একটি নতুন অবজেক্ট তৈরি করা এবং bleno.Characteristic
থেকে ইনহেরিট করা।
ফলস্বরূপ বৈশিষ্ট্যযুক্ত বস্তু নিম্নলিখিত মত দেখায়:
var TemperatureCharacteristic = function() {
bleno.Characteristic.call(this, {
uuid: 'fc0a',
properties: ['read', 'notify'],
value: null
});
this._lastValue = 0;
this._total = 0;
this._samples = 0;
this._onChange = null;
};
util.inherits(TemperatureCharacteristic, bleno.Characteristic);
আমরা this._lastValue
ভেরিয়েবলে বর্তমান তাপমাত্রার মান সংরক্ষণ করছি। কাজ করার জন্য আমাদের একটি onReadRequest
পদ্ধতি যোগ করতে হবে এবং একটি "রিড" এর মান এনকোড করতে হবে।
TemperatureCharacteristic.prototype.onReadRequest = function(offset, callback) {
var data = new Buffer(8);
data.writeDoubleLE(this._lastValue, 0);
callback(this.RESULT_SUCCESS, data);
};
"বিজ্ঞপ্তি" এর জন্য আমাদের সাবস্ক্রিপশন এবং আনসাবস্ক্রিপশন পরিচালনা করার জন্য একটি পদ্ধতি যোগ করতে হবে। মূলত, আমরা কেবল একটি কলব্যাক সঞ্চয় করি। যখন আমাদের কাছে একটি নতুন তাপমাত্রার কারণ আমরা পাঠাতে চাই, তখন আমরা সেই কলব্যাকটিকে নতুন মান দিয়ে কল করি (উপরের মতো এনকোড করা)।
TemperatureCharacteristic.prototype.onSubscribe = function(maxValueSize, updateValueCallback) {
console.log("Subscribed to temperature change.");
this._onChange = updateValueCallback;
this._lastValue = undefined;
};
TemperatureCharacteristic.prototype.onUnsubscribe = function() {
console.log("Unsubscribed to temperature change.");
this._onChange = null;
};
যেহেতু মানগুলি কিছুটা ওঠানামা করতে পারে, তাই আমাদের TMP36 সেন্সর থেকে পাওয়া মানগুলিকে মসৃণ করতে হবে। আমি কেবল গড়ে 100টি নমুনা নিতে বেছে নিয়েছি এবং তাপমাত্রা কমপক্ষে 1 ডিগ্রি পরিবর্তিত হলেই কেবলমাত্র আপডেট পাঠাতে পারি।
TemperatureCharacteristic.prototype.valueChange = function(value) {
this._total += value;
this._samples++;
if (this._samples < NO_SAMPLES) {
return;
}
var newValue = Math.round(this._total / NO_SAMPLES);
this._total = 0;
this._samples = 0;
if (this._lastValue && Math.abs(this._lastValue - newValue) < 1) {
return;
}
this._lastValue = newValue;
console.log(newValue);
var data = new Buffer(8);
data.writeDoubleLE(newValue, 0);
if (this._onChange) {
this._onChange(data);
}
};
এটি ছিল তাপমাত্রা সেন্সর। রঙ LED সহজ. বস্তুর পাশাপাশি "পড়ুন" পদ্ধতিটি নীচে দেখানো হয়েছে। বৈশিষ্ট্যটি "পড়া" এবং "লিখতে" ক্রিয়াকলাপের অনুমতি দেওয়ার জন্য কনফিগার করা হয়েছে এবং তাপমাত্রা বৈশিষ্ট্যের চেয়ে আলাদা UUID রয়েছে।
var ColorCharacteristic = function() {
bleno.Characteristic.call(this, {
uuid: 'fc0b',
properties: ['read', 'write'],
value: null
});
this._value = 'ffffff';
this._led = null;
};
util.inherits(ColorCharacteristic, bleno.Characteristic);
ColorCharacteristic.prototype.onReadRequest = function(offset, callback) {
var data = new Buffer(this._value);
callback(this.RESULT_SUCCESS, data);
};
অবজেক্ট থেকে এলইডি নিয়ন্ত্রণ করতে, আমি একটি this._led
সদস্য যোগ করি যা আমি জনি-ফাইভ এলইডি অবজেক্ট সংরক্ষণ করতে ব্যবহার করি। আমি LED এর রঙকে এর ডিফল্ট মান (সাদা, ওরফে #ffffff
) সেট করেছি।
board.on("ready", function() {
...
colorCharacteristic._led = led;
led.color(colorCharacteristic._value);
led.intensity(30);
...
}
"লিখুন" পদ্ধতিটি একটি স্ট্রিং পায় (যেমন "পড়ুন" একটি স্ট্রিং পাঠায়), এতে একটি CSS রঙের কোড থাকতে পারে (উদাহরণস্বরূপ: CSS নাম যেমন rebeccapurple
বা হেক্স কোড যেমন #ff00bb
)। আমি সর্বদা হেক্স মান পেতে পার্স-কালার নামক একটি নোড মডিউল ব্যবহার করি যা জনি-ফাইভ আশা করে।
ColorCharacteristic.prototype.onWriteRequest = function(data, offset, withoutResponse, callback) {
var value = parse(data.toString('utf8')).hex;
if (!value) {
callback(this.RESULT_SUCCESS);
return;
}
this._value = value;
console.log(value);
if (this._led) {
this._led.color(this._value);
}
callback(this.RESULT_SUCCESS);
};
উপরের সবগুলো কাজ করবে না যদি আমরা ব্লেনো মডিউল অন্তর্ভুক্ত না করি। eddystone-beacon
bleno এর সাথে কাজ করবে না যদি না আপনি এটির সাথে বিতরণ করা noble
সংস্করণটি ব্যবহার করেন। ভাগ্যক্রমে এটি করা বেশ সহজ:
var bleno = require('eddystone-beacon/node_modules/bleno');
var util = require('util');
এখন আমাদের যা দরকার তা হল আমাদের ডিভাইস (UUID) এবং এর বৈশিষ্ট্যগুলি (অন্যান্য UUID) বিজ্ঞাপন দেওয়ার জন্য।
bleno.on('advertisingStart', function(error) {
...
bleno.setServices([
new bleno.PrimaryService({
uuid: 'fc00',
characteristics: [
temperatureCharacteristic, colorCharacteristic
]
})
]);
});
ক্লায়েন্ট ওয়েব অ্যাপ তৈরি করা
ক্লায়েন্ট অ্যাপের নন-ব্লুটুথ অংশগুলি কীভাবে কাজ করে সে সম্পর্কে অনেকগুলি ত্রুটির মধ্যে না গিয়ে, আমরা উদাহরণ হিসাবে পলিমার * এ তৈরি একটি প্রতিক্রিয়াশীল ব্যবহারকারী ইন্টারফেস প্রদর্শন করতে পারি। ফলস্বরূপ অ্যাপটি নীচে দেখানো হয়েছে:
ডানদিকে একটি পূর্ববর্তী সংস্করণ দেখায়, যা একটি সাধারণ ত্রুটি লগ দেখায় যা আমি উন্নয়ন সহজ করতে যোগ করেছি।
ওয়েব ব্লুটুথ ব্লুটুথ লো এনার্জি ডিভাইসগুলির সাথে যোগাযোগ করা সহজ করে তোলে, তাই আসুন আমার সংযোগ কোডের একটি সরলীকৃত সংস্করণ দেখি৷ প্রতিশ্রুতিগুলি কীভাবে কাজ করে তা আপনি যদি না জানেন তবে আরও পড়ার আগে এই সংস্থানটি দেখুন।
একটি ব্লুটুথ ডিভাইসের সাথে সংযোগ করা প্রতিশ্রুতির একটি শৃঙ্খল জড়িত। প্রথমে আমরা ডিভাইসের জন্য ফিল্টার করি (UUID: FC00
, নাম: Edison
)। এটি ব্যবহারকারীকে ফিল্টার দেওয়া ডিভাইস নির্বাচন করার অনুমতি দেওয়ার জন্য একটি ডায়ালগ প্রদর্শন করে। তারপরে আমরা GATT পরিষেবার সাথে সংযোগ করি এবং প্রাথমিক পরিষেবা এবং সংশ্লিষ্ট বৈশিষ্ট্যগুলি পাই এবং তারপরে আমরা মানগুলি পড়ি এবং বিজ্ঞপ্তি কলব্যাক সেট আপ করি।
নীচের আমাদের কোডের সরলীকৃত সংস্করণটি শুধুমাত্র সর্বশেষ ওয়েব ব্লুটুথ API-এর সাথে কাজ করে এবং তাই Android এ Chrome Dev (M49) প্রয়োজন৷
navigator.bluetooth.requestDevice({
filters: [{ name: 'Edison' }],
optionalServices: [0xFC00]
})
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService(0xFC00))
.then(service => {
let p1 = () => service.getCharacteristic(0xFC0B)
.then(characteristic => {
this.colorLedCharacteristic = characteristic;
return this.readLedColor();
});
let p2 = () => service.getCharacteristic(0xFC0A)
.then(characteristic => {
characteristic.addEventListener(
'characteristicvaluechanged', this.onTemperatureChange);
return characteristic.startNotifications();
});
return p1().then(p2);
})
.catch(err => {
// Catch any error.
})
.then(() => {
// Connection fully established, unless there was an error above.
});
একটি DataView
/ ArrayBuffer
থেকে একটি স্ট্রিং পড়া এবং লেখা (WebBluetooth API যা ব্যবহার করে) Node.js সাইডে Buffer
ব্যবহার করার মতোই সহজ। আমাদের যা ব্যবহার করতে হবে তা হল TextEncoder
এবং TextDecoder
:
readLedColor: function() {
return this.colorLedCharacteristic.readValue()
.then(data => {
// In Chrome 50+, a DataView is returned instead of an ArrayBuffer.
data = data.buffer ? data : new DataView(data);
let decoder = new TextDecoder("utf-8");
let decodedString = decoder.decode(data);
document.querySelector('#color').value = decodedString;
});
},
writeLedColor: function() {
let encoder = new TextEncoder("utf-8");
let value = document.querySelector('#color').value;
let encodedString = encoder.encode(value.toLowerCase());
return this.colorLedCharacteristic.writeValue(encodedString);
},
তাপমাত্রা সেন্সরের জন্য characteristicvaluechanged
ইভেন্ট পরিচালনা করাও বেশ সহজ:
onTemperatureChange: function(event) {
let data = event.target.value;
// In Chrome 50+, a DataView is returned instead of an ArrayBuffer.
data = data.buffer ? data : new DataView(data);
let temperature = data.getFloat64(0, /*littleEndian=*/ true);
document.querySelector('#temp').innerHTML = temperature.toFixed(0);
},
সারাংশ
এটা মানুষ ছিল! আপনি দেখতে পাচ্ছেন, ক্লায়েন্ট সাইডে ওয়েব ব্লুটুথ এবং এডিসনে Node.js ব্যবহার করে ব্লুটুথ লো এনার্জির সাথে যোগাযোগ করা বেশ সহজ এবং খুব শক্তিশালী।
ফিজিক্যাল ওয়েব এবং ওয়েব ব্লুটুথ ব্যবহার করে, ক্রোম ডিভাইসটি খুঁজে পায় এবং ব্যবহারকারীকে কদাচিৎ-ব্যবহৃত অ্যাপ্লিকেশন ইনস্টল না করে সহজেই এর সাথে সংযোগ করার অনুমতি দেয় যা ব্যবহারকারী নাও চাইতে পারে এবং যা সময়ে সময়ে আপডেট হতে পারে।
ডেমো
আপনার কাস্টম ইন্টারনেট অফ থিংস ডিভাইসের সাথে সংযোগ করতে আপনি কীভাবে আপনার নিজস্ব ওয়েব অ্যাপ তৈরি করতে পারেন সে সম্পর্কে অনুপ্রাণিত হওয়ার জন্য আপনি ক্লায়েন্টকে চেষ্টা করতে পারেন।
সোর্স কোড
সোর্স কোড এখানে পাওয়া যায়। সমস্যা রিপোর্ট বা প্যাচ পাঠাতে নির্দ্বিধায়.
স্কেচ
আপনি যদি সত্যিই দুঃসাহসিক হন এবং আমি যা করেছি তা পুনরুত্পাদন করতে চান, নীচের এডিসন এবং ব্রেডবোর্ড স্কেচটি পড়ুন: