واٹر میٹر کو سمارٹ ہوم سے جوڑنا

ایک زمانے میں، ہوم آٹومیشن سسٹم، یا "سمارٹ ہوم" جیسا کہ انہیں اکثر کہا جاتا تھا، بہت مہنگے تھے اور صرف امیر ہی انہیں برداشت کر سکتے تھے۔ آج مارکیٹ میں آپ کو روشنی، ساکٹ، وینٹیلیشن، پانی کی فراہمی اور دیگر صارفین کو کنٹرول کرنے کے لیے سینسر، بٹن/سوئچز اور ایکچیوٹرز کے ساتھ کافی سستی کٹس مل سکتی ہیں۔ اور یہاں تک کہ سب سے زیادہ ٹیڑھا DIY شخص بھی خوبصورتی میں شامل ہو سکتا ہے اور سستی قیمت پر سمارٹ گھر کے لیے ڈیوائسز اسمبل کر سکتا ہے۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

عام طور پر، مجوزہ آلات یا تو سینسر ہیں یا ایکچیوٹرز۔ وہ منظرناموں کو نافذ کرنا آسان بناتے ہیں جیسے کہ "جب موشن سینسر ٹرگر ہوتا ہے تو لائٹس آن کریں" یا "ایگزٹ کے قریب سوئچ پورے اپارٹمنٹ کی لائٹس کو آف کر دیتا ہے۔" لیکن کسی نہ کسی طرح ٹیلی میٹری کے ساتھ چیزیں کام نہیں کرتی تھیں۔ بہترین طور پر، یہ درجہ حرارت اور نمی کا گراف ہے، یا کسی مخصوص آؤٹ لیٹ پر فوری طاقت۔

میں نے حال ہی میں پلس آؤٹ پٹ کے ساتھ پانی کے میٹر نصب کیے ہیں۔ ہر لیٹر کے لیے جو میٹر سے گزرتا ہے، ریڈ سوئچ چالو ہو جاتا ہے اور رابطہ بند کر دیتا ہے۔ صرف تاروں سے چمٹنا اور اس سے فائدہ اٹھانے کی کوشش کرنا باقی رہ جاتا ہے۔ مثال کے طور پر، ہفتے کے گھنٹے اور دن کے حساب سے پانی کی کھپت کا تجزیہ کریں۔ ٹھیک ہے، اگر اپارٹمنٹ میں پانی کے کئی ریزر موجود ہیں، تو پھر ٹارچ کے ساتھ مشکل سے پہنچنے والے طاقوں میں چڑھنے کے بجائے تمام موجودہ اشارے ایک اسکرین پر دیکھنا زیادہ آسان ہے۔

کٹ کے نیچے ESP8266 پر مبنی ایک ڈیوائس کا میرا ورژن ہے، جو پانی کے میٹر سے دالیں گنتا ہے اور MQTT کے ذریعے سمارٹ ہوم سرور کو ریڈنگ بھیجتا ہے۔ ہم uasyncio لائبریری کا استعمال کرتے ہوئے micropython میں پروگرام کریں گے۔ فرم ویئر بناتے وقت، مجھے کئی دلچسپ مشکلات کا سامنا کرنا پڑا، جن پر میں اس مضمون میں بھی بات کروں گا۔ جاؤ!

ڈرائیونگ

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

پورے سرکٹ کا دل ESP8266 مائکروکنٹرولر پر ایک ماڈیول ہے۔ ESP-12 اصل میں منصوبہ بندی کی گئی تھی، لیکن میرا ناقص نکلا۔ ہمیں ESP-07 ماڈیول سے مطمئن ہونا پڑا، جو دستیاب تھا۔ خوش قسمتی سے، وہ پن اور فعالیت دونوں کے لحاظ سے ایک جیسے ہیں، فرق صرف اینٹینا میں ہے - ESP-12 میں ایک بلٹ ان ہے، جبکہ ESP-07 میں ایک بیرونی ہے۔ تاہم، WiFi اینٹینا کے بغیر بھی، میرے باتھ روم میں سگنل عام طور پر موصول ہوتا ہے۔

معیاری ماڈیول وائرنگ:

  • پل اپ اور کپیسیٹر کے ساتھ بٹن کو ری سیٹ کریں (حالانکہ دونوں پہلے ہی ماڈیول کے اندر ہیں)
  • فعال سگنل (CH_PD) کو پاور تک کھینچ لیا جاتا ہے۔
  • GPIO15 زمین پر کھینچا جاتا ہے۔ یہ صرف شروع میں ہی درکار ہے، لیکن میرے پاس اب بھی اس ٹانگ سے جوڑنے کے لیے کچھ نہیں ہے؛ مجھے اب اس کی ضرورت نہیں ہے۔

ماڈیول کو فرم ویئر موڈ میں ڈالنے کے لیے، آپ کو GPIO2 کو زمین پر شارٹ سرکٹ کرنے کی ضرورت ہے، اور اسے مزید آسان بنانے کے لیے، میں نے بوٹ بٹن فراہم کیا ہے۔ عام حالت میں، اس پن کو طاقت میں کھینچ لیا جاتا ہے۔

GPIO2 لائن کی حالت صرف آپریشن کے آغاز میں چیک کی جاتی ہے - جب پاور لگائی جاتی ہے یا دوبارہ سیٹ ہونے کے فوراً بعد۔ لہذا ماڈیول یا تو معمول کے مطابق بوٹ ہوجاتا ہے یا فرم ویئر موڈ میں چلا جاتا ہے۔ ایک بار لوڈ ہونے کے بعد، اس پن کو باقاعدہ GPIO کے طور پر استعمال کیا جا سکتا ہے۔ ٹھیک ہے، چونکہ وہاں پہلے سے ہی ایک بٹن موجود ہے، آپ اس کے ساتھ کچھ مفید فنکشن منسلک کر سکتے ہیں۔

پروگرامنگ اور ڈیبگنگ کے لیے میں UART استعمال کروں گا، جو کنگھی میں آؤٹ پٹ ہے۔ جب ضروری ہو، میں وہاں صرف USB-UART اڈاپٹر کو جوڑتا ہوں۔ آپ کو صرف یہ یاد رکھنے کی ضرورت ہے کہ ماڈیول 3.3V سے چلتا ہے۔ اگر آپ اڈاپٹر کو اس وولٹیج میں تبدیل کرنا اور 5V فراہم کرنا بھول جاتے ہیں، تو امکان ہے کہ ماڈیول جل جائے گا۔

مجھے باتھ روم میں بجلی کے ساتھ کوئی مسئلہ نہیں ہے - آؤٹ لیٹ میٹر سے تقریبا ایک میٹر کے فاصلے پر واقع ہے، لہذا مجھے 220V سے طاقت ملے گی۔ طاقت کے منبع کے طور پر میرے پاس ایک چھوٹا سا ہوگا۔ بلاک HLK-PM03 Tenstar روبوٹ کی طرف سے. ذاتی طور پر، مجھے ینالاگ اور پاور الیکٹرانکس کے ساتھ مشکل وقت ہے، لیکن یہاں ایک چھوٹی سی صورت میں ایک ریڈی میڈ پاور سپلائی ہے۔

آپریٹنگ طریقوں کو سگنل کرنے کے لیے، میں نے GPIO2 سے منسلک ایک LED فراہم کی۔ تاہم، میں نے اسے فروخت نہیں کیا، کیونکہ... ESP-07 ماڈیول میں پہلے سے ہی ایک LED ہے، اور یہ GPIO2 سے بھی منسلک ہے۔ لیکن اسے بورڈ پر رہنے دو، اگر میں اس ایل ای ڈی کو کیس میں آؤٹ پٹ کرنا چاہتا ہوں۔

آئیے سب سے دلچسپ حصے کی طرف چلتے ہیں۔ پانی کے میٹر کی کوئی منطق نہیں ہے؛ آپ ان سے کرنٹ ریڈنگ کے لیے نہیں پوچھ سکتے۔ ہمارے لیے صرف ایک چیز دستیاب ہے وہ ہے تسلسل - ہر لیٹر پر ریڈ سوئچ کے رابطوں کو بند کرنا۔ میرے ریڈ سوئچ آؤٹ پٹ GPIO12/GPIO13 سے جڑے ہوئے ہیں۔ میں ماڈیول کے اندر پروگرامی طور پر پل اپ ریزسٹر کو فعال کروں گا۔

ابتدائی طور پر، میں R8 اور R9 ریزسٹر فراہم کرنا بھول گیا تھا اور بورڈ کے میرے ورژن میں وہ نہیں ہیں۔ لیکن چونکہ میں پہلے ہی ہر کسی کے دیکھنے کے لیے خاکہ پوسٹ کر رہا ہوں، اس لیے اس نگرانی کو درست کرنا ضروری ہے۔ ریزسٹرز کی ضرورت ہوتی ہے تاکہ اگر فرم ویئر خراب ہو جائے اور پن کو ایک پر سیٹ کر دے تو بندرگاہ کو جلا نہ دے، اور ریڈ سوئچ اس لائن کو زمین پر شارٹ کر دیتا ہے (ریزسٹر کے ساتھ زیادہ سے زیادہ 3.3V/1000Ohm = 3.3mA بہے گا)۔

یہ سوچنے کا وقت ہے کہ اگر بجلی چلی جائے تو کیا کریں۔ پہلا آپشن یہ ہے کہ شروع میں سرور سے ابتدائی کاؤنٹر ویلیوز کی درخواست کی جائے۔ لیکن اس کے لیے ایکسچینج پروٹوکول کی ایک اہم پیچیدگی درکار ہوگی۔ مزید یہ کہ اس معاملے میں ڈیوائس کی کارکردگی کا انحصار سرور کی حالت پر ہے۔ اگر سرور پاور آف ہونے کے بعد شروع نہیں ہوا (یا بعد میں شروع ہوا)، تو واٹر میٹر ابتدائی اقدار کی درخواست نہیں کر سکے گا اور صحیح طریقے سے کام نہیں کرے گا۔

لہذا، میں نے I2C کے ذریعے منسلک میموری چپ میں سیونگ کاؤنٹر ویلیوز کو لاگو کرنے کا فیصلہ کیا۔ میرے پاس فلیش میموری کے سائز کے لیے کوئی خاص تقاضے نہیں ہیں - آپ کو صرف 2 نمبر (گرم اور ٹھنڈے پانی کے میٹر کے مطابق لیٹر کی تعداد) بچانے کی ضرورت ہے۔ یہاں تک کہ سب سے چھوٹا ماڈیول بھی کرے گا۔ لیکن آپ کو ریکارڈنگ سائیکلوں کی تعداد پر توجہ دینے کی ضرورت ہے۔ زیادہ تر ماڈیولز کے لیے یہ 100 ہزار سائیکل ہے، کچھ کے لیے ایک ملین تک۔

ایسا لگتا ہے کہ ایک ملین بہت ہے۔ لیکن اپنے اپارٹمنٹ میں رہنے کے 4 سال کے دوران، میں نے 500 کیوبک میٹر سے تھوڑا زیادہ پانی استعمال کیا، یعنی 500 ہزار لیٹر! اور فلیش میں 500 ہزار ریکارڈ۔ اور یہ صرف ٹھنڈا پانی ہے۔ آپ یقیناً ہر دو سال میں چپ کو دوبارہ بیچ سکتے ہیں، لیکن یہ پتہ چلتا ہے کہ وہاں FRAM چپس موجود ہیں۔ پروگرامنگ کے نقطہ نظر سے، یہ وہی I2C EEPROM ہے، صرف ایک بہت بڑی تعداد میں دوبارہ لکھنے والے سائیکلوں (سیکڑوں ملین) کے ساتھ۔ یہ صرف اتنا ہے کہ میں اب بھی اس طرح کے مائیکرو سرکٹس کے ساتھ اسٹور پر نہیں جا سکتا، اس لیے فی الحال معمول کے مطابق 24LC512 کھڑا رہے گا۔

چھپی ہوئی سرکٹ بورڈ

شروع میں، میں نے گھر پر بورڈ بنانے کا ارادہ کیا۔ لہذا، بورڈ کو یک طرفہ کے طور پر ڈیزائن کیا گیا تھا. لیکن لیزر آئرن اور سولڈر ماسک کے ساتھ ایک گھنٹہ گزارنے کے بعد (اس کے بغیر یہ کسی بھی طرح سے کام نہیں ہے)، میں نے پھر بھی چینیوں سے بورڈ منگوانے کا فیصلہ کیا۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

بورڈ کو آرڈر کرنے سے تقریباً پہلے، میں نے محسوس کیا کہ فلیش میموری چپ کے علاوہ، میں I2C بس سے کسی اور مفید چیز کو جوڑ سکتا ہوں، جیسے کہ ڈسپلے۔ اس میں بالکل کیا آؤٹ پٹ کرنا ہے اب بھی ایک سوال ہے، لیکن اسے بورڈ پر روٹ کرنے کی ضرورت ہے۔ ٹھیک ہے، چونکہ میں فیکٹری سے بورڈ آرڈر کرنے جا رہا تھا، اس لیے خود کو ایک طرفہ بورڈ تک محدود رکھنے کا کوئی فائدہ نہیں تھا، اس لیے I2C لائنیں صرف بورڈ کے پچھلے حصے پر ہوتی ہیں۔

ایک طرفہ وائرنگ کے ساتھ ایک بڑا مسئلہ بھی تھا۔ کیونکہ بورڈ کو یک طرفہ بنایا گیا تھا، اس لیے پٹریوں اور SMD اجزاء کو ایک طرف رکھنے کا منصوبہ بنایا گیا تھا، اور دوسری طرف آؤٹ پٹ کے اجزاء، کنیکٹر اور بجلی کی فراہمی۔ جب مجھے ایک ماہ بعد بورڈز موصول ہوئے تو میں اصل منصوبے کو بھول گیا اور سامنے کی طرف تمام اجزاء کو سولڈر کر دیا۔ اور جب پاور سپلائی سولڈرنگ کی بات کی گئی تو پتہ چلا کہ پلس اور مائنس ریورس میں وائرڈ تھے۔ مجھے جمپر کے ساتھ کھیتی کرنی تھی۔ اوپر کی تصویر میں، میں نے پہلے ہی وائرنگ تبدیل کر دی ہے، لیکن زمین کو بوٹ بٹن کے پنوں کے ذریعے بورڈ کے ایک حصے سے دوسرے حصے میں منتقل کیا جاتا ہے (حالانکہ دوسری تہہ پر ٹریک بنانا ممکن ہو گا)۔

یہ اس طرح نکلا۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

ہاؤسنگ

اگلا مرحلہ جسم ہے۔ اگر آپ کے پاس 3D پرنٹر ہے تو یہ کوئی مسئلہ نہیں ہے۔ میں نے زیادہ پریشان نہیں کیا - میں نے صرف صحیح سائز کا ایک باکس کھینچا اور صحیح جگہوں پر کٹ آؤٹ بنائے۔ کور چھوٹے سیلف ٹیپنگ پیچ کے ساتھ جسم سے منسلک ہوتا ہے۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

میں نے پہلے ہی ذکر کیا ہے کہ بوٹ بٹن کو عام مقصد کے بٹن کے طور پر استعمال کیا جا سکتا ہے - لہذا ہم اسے فرنٹ پینل پر ڈسپلے کریں گے۔ ایسا کرنے کے لیے، میں نے ایک خاص "کنواں" کھینچا جہاں بٹن رہتا ہے۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

کیس کے اندر ایسے اسٹڈز بھی ہیں جن پر بورڈ نصب ہے اور ایک M3 سکرو سے محفوظ ہے (بورڈ پر مزید جگہ نہیں تھی)

جب میں نے کیس کا پہلا نمونہ ورژن پرنٹ کیا تو میں نے پہلے ہی ڈسپلے کا انتخاب کیا تھا۔ ایک معیاری دو لائن ریڈر اس معاملے میں فٹ نہیں تھا، لیکن نیچے ایک OLED ڈسپلے SSD1306 128×32 تھا۔ یہ تھوڑا سا چھوٹا ہے، لیکن مجھے ہر روز اسے گھورنے کی ضرورت نہیں ہے — یہ میرے لیے بہت زیادہ ہے۔

اس طرح کا پتہ لگاتے ہوئے اور یہ کہ تاروں کو اس سے کیسے روٹ کیا جائے گا، میں نے کیس کے بیچ میں ڈسپلے کو چپکانے کا فیصلہ کیا۔ ایرگونومکس، یقینا، برابر کے نیچے ہیں - بٹن اوپر ہے، ڈسپلے نیچے ہے۔ لیکن میں نے پہلے ہی کہا تھا کہ ڈسپلے کو منسلک کرنے کا خیال بہت دیر سے آیا اور میں بٹن کو منتقل کرنے کے لیے بورڈ کو دوبارہ وائر کرنے میں بہت سست تھا۔

ڈیوائس کو جمع کیا جاتا ہے۔ ڈسپلے ماڈیول گرم گلو کے ساتھ سنوٹ پر چپکا ہوا ہے۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

حتمی نتیجہ KDPV پر دیکھا جا سکتا ہے۔

فرم ویئر۔

آئیے سافٹ ویئر کے حصے کی طرف چلتے ہیں۔ اس طرح کے چھوٹے دستکاری کے لیے، میں واقعی میں ازگر کا استعمال کرنا پسند کرتا ہوں (مائکروپیتھون) - کوڈ بہت کمپیکٹ اور قابل فہم نکلا۔ خوش قسمتی سے، مائیکرو سیکنڈز کو نچوڑنے کے لیے رجسٹر کی سطح پر جانے کی ضرورت نہیں ہے - سب کچھ ازگر سے کیا جا سکتا ہے۔

ایسا لگتا ہے کہ سب کچھ آسان ہے، لیکن بہت آسان نہیں ہے - ڈیوائس میں کئی آزاد افعال ہیں:

  • صارف بٹن دباتا ہے اور ڈسپلے کو دیکھتا ہے۔
  • لیٹر فلیش میموری میں اقدار کو ٹک اور اپ ڈیٹ کرتے ہیں۔
  • ماڈیول وائی فائی سگنل کی نگرانی کرتا ہے اور اگر ضروری ہو تو دوبارہ جڑ جاتا ہے۔
  • ٹھیک ہے، ٹمٹماتی روشنی کے بلب کے بغیر یہ ناممکن ہے۔

آپ یہ فرض نہیں کر سکتے کہ ایک فنکشن کام نہیں کرتا ہے اگر دوسرا کسی وجہ سے پھنس گیا ہو۔ میں نے پہلے ہی دوسرے پروجیکٹس میں کیکٹی بھر لی ہے اور اب بھی مجھے "ایک اور لیٹر چھوٹ گیا کیونکہ ڈسپلے اس وقت اپ ڈیٹ ہو رہا تھا" یا "ماڈیول کے منسلک ہونے کے دوران صارف کچھ نہیں کر سکتا" کے انداز میں خرابیاں دیکھ رہا ہوں۔ وائی ​​فائی." بلاشبہ، کچھ چیزیں رکاوٹوں کے ذریعے کی جا سکتی ہیں، لیکن آپ مدت، کالوں کے گھوںسلا، یا متغیرات میں غیر جوہری تبدیلیوں کی حدود میں چل سکتے ہیں۔ ٹھیک ہے، وہ کوڈ جو سب کچھ کرتا ہے جلدی سے مشک میں بدل جاتا ہے۔

В زیادہ سنجیدہ منصوبہ میں نے کلاسک پریمپٹیو ملٹی ٹاسکنگ اور فری آر ٹی او ایس کا استعمال کیا، لیکن اس معاملے میں ماڈل زیادہ موزوں نکلا۔ کوروٹائنز اور uasync لائبریریاں . مزید یہ کہ، کوروٹینز کا ازگر کا نفاذ محض حیرت انگیز ہے - پروگرامر کے لیے سب کچھ آسان اور آسانی سے کیا جاتا ہے۔ بس اپنی منطق لکھیں، بس مجھے بتائیں کہ آپ کن جگہوں پر اسٹریمز کے درمیان سوئچ کر سکتے ہیں۔

میں تجویز کرتا ہوں کہ ایک اختیاری مضمون کے طور پر پیشگی اور مسابقتی ملٹی ٹاسکنگ کے درمیان فرق کا مطالعہ کریں۔ اب آخر میں کوڈ کی طرف چلتے ہیں۔

#####################################
# Counter class - implements a single water counter on specified pin
#####################################
class Counter():
    debounce_ms = const(25)
    
    def __init__(self, pin_num, value_storage):
        self._value_storage = value_storage
        
        self._value = self._value_storage.read()
        self._value_changed = False

        self._pin = Pin(pin_num, Pin.IN, Pin.PULL_UP)

        loop = asyncio.get_event_loop()
        loop.create_task(self._switchcheck())  # Thread runs forever

ہر کاؤنٹر کو کاؤنٹر کلاس کی مثال کے ذریعے سنبھالا جاتا ہے۔ سب سے پہلے، ابتدائی کاؤنٹر ویلیو کو EEPROM (value_storage) سے منہا کیا جاتا ہے - اس طرح بجلی کی ناکامی کے بعد ریکوری کا احساس ہوتا ہے۔

پن کو پاور سپلائی کے لیے بلٹ ان پل اپ کے ساتھ شروع کیا جاتا ہے: اگر ریڈ سوئچ بند ہے، لائن صفر ہے، اگر لائن کھلی ہے، تو اسے پاور سپلائی تک کھینچ لیا جاتا ہے اور کنٹرولر ایک کو پڑھتا ہے۔

یہاں ایک الگ ٹاسک بھی شروع کیا گیا ہے جو پن کو پول کرے گا۔ ہر کاؤنٹر اپنا کام خود چلائے گا۔ یہاں اس کا کوڈ ہے۔

    """ Poll pin and advance value when another litre passed """
    async def _switchcheck(self):
        last_checked_pin_state = self._pin.value()  # Get initial state

        # Poll for a pin change
        while True:
            state = self._pin.value()
            if state != last_checked_pin_state:
                # State has changed: act on it now.
                last_checked_pin_state = state
                if state == 0:
                    self._another_litre_passed()

            # Ignore further state changes until switch has settled
            await asyncio.sleep_ms(Counter.debounce_ms)

رابطہ باؤنس کو فلٹر کرنے کے لیے 25ms کی تاخیر کی ضرورت ہوتی ہے، اور ساتھ ہی یہ ریگولیٹ کرتا ہے کہ ٹاسک کتنی بار جاگتا ہے (جب کہ یہ ٹاسک سو رہا ہے، دوسرے کام چل رہے ہیں)۔ ہر 25 منٹ پر فنکشن اٹھتا ہے، پن کو چیک کرتا ہے اور اگر ریڈ سوئچ کے رابطے بند ہیں، تو ایک اور لیٹر میٹر سے گزر چکا ہے اور اس پر کارروائی کی ضرورت ہے۔

    def _another_litre_passed(self):
        self._value += 1
        self._value_changed = True

        self._value_storage.write(self._value)

اگلے لیٹر پر کارروائی کرنا معمولی بات ہے - کاؤنٹر صرف بڑھ جاتا ہے۔ ٹھیک ہے، فلیش ڈرائیو پر نئی قدر لکھنا اچھا ہوگا۔

استعمال میں آسانی کے لیے، "ایکسیسرز" فراہم کیے گئے ہیں۔

    def value(self):
        self._value_changed = False
        return self._value

    def set_value(self, value):
        self._value = value
        self._value_changed = False

ٹھیک ہے، اب آئیے Python اور uasync لائبریری کی خوشیوں سے فائدہ اٹھاتے ہیں اور ایک قابل انتظار کاؤنٹر آبجیکٹ بناتے ہیں (ہم اس کا روسی میں ترجمہ کیسے کر سکتے ہیں؟ جس کی آپ توقع کر سکتے ہیں؟)

    def __await__(self):
        while not self._value_changed:
            yield from asyncio.sleep(0)

        return self.value()

    __iter__ = __await__  

یہ اتنا آسان فنکشن ہے جو کاؤنٹر ویلیو کے اپ ڈیٹ ہونے تک انتظار کرتا ہے - فنکشن وقتاً فوقتاً جاگتا ہے اور _value_changed پرچم کو چیک کرتا ہے۔ اس فنکشن کے بارے میں اچھی بات یہ ہے کہ کالنگ کوڈ اس فنکشن کو کال کرتے وقت سو سکتا ہے اور اس وقت تک سو سکتا ہے جب تک کہ کوئی نئی ویلیو موصول نہ ہو جائے۔

رکاوٹوں کے بارے میں کیا خیال ہے؟جی ہاں، اس مقام پر آپ مجھے یہ کہہ کر ٹرول کر سکتے ہیں کہ آپ نے خود ہی رکاوٹوں کے بارے میں کہا تھا، لیکن حقیقت میں آپ نے ایک احمقانہ پن پول کیا۔ درحقیقت مداخلت پہلی چیز ہے جس کی میں نے کوشش کی۔ ESP8266 میں آپ edge interrupt کو ترتیب دے سکتے ہیں، اور Python میں اس مداخلت کے لیے ایک ہینڈلر بھی لکھ سکتے ہیں۔ اس مداخلت میں، متغیر کی قدر کو اپ ڈیٹ کیا جا سکتا ہے۔ شاید، یہ کافی ہو گا اگر کاؤنٹر ایک غلام آلہ ہوتا - ایک جو انتظار کرتا ہے جب تک کہ اس قیمت کے بارے میں پوچھا نہ جائے۔

بدقسمتی سے (یا خوش قسمتی سے؟) میرا آلہ فعال ہے، اسے خود MQTT پروٹوکول کے ذریعے پیغامات بھیجنا ہوں گے اور EEPROM کو ڈیٹا لکھنا ہوگا۔ اور یہاں پابندیاں عمل میں آتی ہیں - آپ انٹرپٹس میں میموری مختص نہیں کرسکتے اور ایک بڑا اسٹیک استعمال نہیں کرسکتے ہیں، جس کا مطلب ہے کہ آپ نیٹ ورک پر پیغامات بھیجنا بھول سکتے ہیں۔ micropython.schedule() جیسے بنس موجود ہیں جو آپ کو "جلد سے جلد" کچھ فنکشن چلانے کی اجازت دیتے ہیں، لیکن سوال یہ پیدا ہوتا ہے، "کیا بات ہے؟" کیا ہوگا اگر ہم ابھی کسی قسم کا پیغام بھیج رہے ہیں، اور پھر ایک مداخلت آتی ہے اور متغیرات کی قدروں کو خراب کر دیتی ہے۔ یا، مثال کے طور پر، سرور سے ایک نئی کاؤنٹر ویلیو آئی جبکہ ہم نے ابھی تک پرانی قیمت نہیں لکھی تھی۔ عام طور پر، آپ کو مطابقت پذیری کو مسدود کرنے یا کسی طرح مختلف طریقے سے اس سے باہر نکلنے کی ضرورت ہے۔

اور وقتا فوقتا RuntimeError: شیڈول اسٹیک مکمل کریش اور کون جانتا ہے کیوں؟

واضح پولنگ اور uasync کے ساتھ، اس معاملے میں یہ کسی نہ کسی طرح زیادہ خوبصورت اور قابل اعتماد نکلتا ہے

میں ایک چھوٹی کلاس میں EEPROM کے ساتھ کام لایا

class EEPROM():
    i2c_addr = const(80)

    def __init__(self, i2c):
        self.i2c = i2c
        self.i2c_buf = bytearray(4) # Avoid creation/destruction of the buffer on each call


    def read(self, eeprom_addr):
        self.i2c.readfrom_mem_into(self.i2c_addr, eeprom_addr, self.i2c_buf, addrsize=16)
        return ustruct.unpack_from("<I", self.i2c_buf)[0]    
        
    
    def write(self, eeprom_addr, value):
        ustruct.pack_into("<I", self.i2c_buf, 0, value)
        self.i2c.writeto_mem(self.i2c_addr, eeprom_addr, self.i2c_buf, addrsize=16)

ازگر میں، بائٹس کے ساتھ براہ راست کام کرنا مشکل ہے، لیکن یہ بائٹس ہیں جو میموری پر لکھی جاتی ہیں۔ مجھے ustruct لائبریری کا استعمال کرتے ہوئے انٹیجر اور بائٹس کے درمیان تبادلوں کو باڑنا پڑا۔

ہر بار I2C آبجیکٹ اور میموری سیل کا پتہ منتقل نہ کرنے کے لیے، میں نے یہ سب ایک چھوٹے اور آسان کلاسک میں لپیٹ دیا۔

class EEPROMValue():
    def __init__(self, i2c, eeprom_addr):
        self._eeprom = EEPROM(i2c)
        self._eeprom_addr = eeprom_addr
        

    def read(self):
        return self._eeprom.read(self._eeprom_addr)


    def write(self, value):
        self._eeprom.write(self._eeprom_addr, value)

I2C آبجیکٹ خود ان پیرامیٹرز کے ساتھ بنایا گیا ہے۔

i2c = I2C(freq=400000, scl=Pin(5), sda=Pin(4))

ہم سب سے دلچسپ حصے پر آتے ہیں - MQTT کے ذریعے سرور کے ساتھ مواصلات کا نفاذ۔ ٹھیک ہے، پروٹوکول کو خود نافذ کرنے کی ضرورت نہیں ہے - میں نے اسے انٹرنیٹ پر پایا ریڈی میڈ غیر مطابقت پذیر عمل درآمد. یہ وہی ہے جو ہم استعمال کریں گے۔

تمام دلچسپ چیزیں CounterMQTTClient کلاس میں جمع کی جاتی ہیں، جو MQTTClient لائبریری پر مبنی ہے۔ آئیے دائرہ سے شروع کرتے ہیں۔

#####################################
# Class handles both counters and sends their status to MQTT
#####################################
class CounterMQTTClient(MQTTClient):

    blue_led = Pin(2, Pin.OUT, value = 1)
    button = Pin(0, Pin.IN)

    hot_counter = Counter(12, EEPROMValue(i2c, EEPROM_ADDR_HOT_VALUE))
    cold_counter = Counter(13, EEPROMValue(i2c, EEPROM_ADDR_COLD_VALUE))

یہاں آپ لائٹ بلب پن اور بٹن کے ساتھ ساتھ ٹھنڈے اور گرم پانی کے میٹر کی اشیاء بنا اور ترتیب دے سکتے ہیں۔

ابتدا کے ساتھ، ہر چیز اتنی معمولی نہیں ہے۔

    def __init__(self):
        self.internet_outage = True
        self.internet_outages = 0
        self.internet_outage_start = ticks_ms()

        with open("config.txt") as config_file:
            config['ssid'] = config_file.readline().rstrip()
            config['wifi_pw'] = config_file.readline().rstrip()
            config['server'] = config_file.readline().rstrip()
            config['client_id'] = config_file.readline().rstrip()
            self._mqtt_cold_water_theme = config_file.readline().rstrip()
            self._mqtt_hot_water_theme = config_file.readline().rstrip()
            self._mqtt_debug_water_theme = config_file.readline().rstrip()

        config['subs_cb'] = self.mqtt_msg_handler
        config['wifi_coro'] = self.wifi_connection_handler
        config['connect_coro'] = self.mqtt_connection_handler
        config['clean'] = False
        config['clean_init'] = False
        super().__init__(config)

        loop = asyncio.get_event_loop()
        loop.create_task(self._heartbeat())
        loop.create_task(self._counter_coro(self.cold_counter, self._mqtt_cold_water_theme))
        loop.create_task(self._counter_coro(self.hot_counter, self._mqtt_hot_water_theme))
        loop.create_task(self._display_coro())

mqtt_as لائبریری کے آپریٹنگ پیرامیٹرز کو سیٹ کرنے کے لیے، مختلف سیٹنگز کی ایک بڑی لغت کا استعمال کیا جاتا ہے - config۔ ہمارے لیے زیادہ تر ڈیفالٹ سیٹنگز ٹھیک ہیں، لیکن بہت سی سیٹنگز کو واضح طور پر سیٹ کرنے کی ضرورت ہے۔ کوڈ میں سیٹنگز کو براہ راست نہ لکھنے کے لیے، میں انہیں ٹیکسٹ فائل config.txt میں اسٹور کرتا ہوں۔ یہ آپ کو ترتیبات سے قطع نظر کوڈ کو تبدیل کرنے کے ساتھ ساتھ مختلف پیرامیٹرز کے ساتھ کئی ایک جیسی ڈیوائسز کو تبدیل کرنے کی اجازت دیتا ہے۔

کوڈ کا آخری بلاک سسٹم کے مختلف کاموں کو انجام دینے کے لیے کئی کورٹینز شروع کرتا ہے۔ مثال کے طور پر، یہاں ایک کوروٹین ہے جو خدمات کا شمار کرتی ہے۔

    async def _counter_coro(self, counter, topic):
        # Publish initial value
        value = counter.value()
        await self.publish(topic, str(value))

        # Publish each new value
        while True:
            value = await counter
            await self.publish_msg(topic, str(value))

کوروٹین ایک نئی کاؤنٹر ویلیو کا انتظار کرتی ہے اور، جیسے ہی یہ ظاہر ہوتی ہے، MQTT پروٹوکول کے ذریعے ایک پیغام بھیجتی ہے۔ کوڈ کا پہلا ٹکڑا ابتدائی قدر بھیجتا ہے یہاں تک کہ اگر کاؤنٹر سے پانی نہ بہہ رہا ہو۔

بیس کلاس MQTTClient اپنے آپ کو سروس دیتا ہے، ایک وائی فائی کنکشن شروع کرتا ہے اور کنکشن کھو جانے پر دوبارہ جڑ جاتا ہے۔ جب وائی فائی کنکشن کی حالت میں تبدیلیاں آتی ہیں، تو لائبریری ہمیں wifi_connection_handler پر کال کرکے مطلع کرتی ہے۔

    async def wifi_connection_handler(self, state):
        self.internet_outage = not state
        if state:
            self.dprint('WiFi is up.')
            duration = ticks_diff(ticks_ms(), self.internet_outage_start) // 1000
            await self.publish_debug_msg('ReconnectedAfter', duration)
        else:
            self.internet_outages += 1
            self.internet_outage_start = ticks_ms()
            self.dprint('WiFi is down.')
            
        await asyncio.sleep(0)

فنکشن کو ایمانداری سے مثالوں سے کاپی کیا گیا ہے۔ اس صورت میں، یہ بندش کی تعداد (انٹرنیٹ_آوٹیجز) اور ان کی مدت کو شمار کرتا ہے۔ جب کنکشن بحال ہوجاتا ہے، سرور کو ایک بیکار وقت بھیجا جاتا ہے۔

ویسے، آخری نیند کی ضرورت صرف فنکشن کو غیر مطابقت پذیر بنانے کے لیے ہوتی ہے - لائبریری میں اسے via await کہا جاتا ہے، اور صرف ان فنکشنز کو کہا جا سکتا ہے جن کے جسم میں دوسرا await ہوتا ہے۔

وائی ​​فائی سے منسلک ہونے کے علاوہ، آپ کو MQTT بروکر (سرور) سے بھی کنکشن قائم کرنے کی ضرورت ہے۔ لائبریری بھی ایسا کرتی ہے، اور رابطہ قائم ہونے پر ہمیں کچھ مفید کام کرنے کا موقع ملتا ہے۔

    async def mqtt_connection_handler(self, client):
        await client.subscribe(self._mqtt_cold_water_theme)
        await client.subscribe(self._mqtt_hot_water_theme)

یہاں ہم کئی پیغامات کو سبسکرائب کرتے ہیں - سرور اب متعلقہ پیغام بھیج کر موجودہ جوابی اقدار کو سیٹ کرنے کی صلاحیت رکھتا ہے۔

    def mqtt_msg_handler(self, topic, msg):
        topicstr = str(topic, 'utf8')
        self.dprint("Received MQTT message topic={}, msg={}".format(topicstr, msg))

        if topicstr == self._mqtt_cold_water_theme:
            self.cold_counter.set_value(int(msg))

        if topicstr == self._mqtt_hot_water_theme:
            self.hot_counter.set_value(int(msg))

یہ فنکشن آنے والے پیغامات پر کارروائی کرتا ہے، اور موضوع (پیغام کے عنوان) پر منحصر ہے، کاؤنٹر میں سے ایک کی قدروں کو اپ ڈیٹ کیا جاتا ہے

مددگار افعال کے ایک جوڑے

    # Publish a message if WiFi and broker is up, else discard
    async def publish_msg(self, topic, msg):
        self.dprint("Publishing message on topic {}: {}".format(topic, msg))
        if not self.internet_outage:
            await self.publish(topic, msg)
        else:
            self.dprint("Message was not published - no internet connection")

کنکشن قائم ہونے پر یہ فنکشن پیغام بھیجتا ہے۔ اگر کوئی کنکشن نہیں ہے، تو پیغام کو نظر انداز کر دیا جاتا ہے۔

اور یہ صرف ایک آسان فنکشن ہے جو ڈیبگنگ پیغامات تیار اور بھیجتا ہے۔

    async def publish_debug_msg(self, subtopic, msg):
        await self.publish_msg("{}/{}".format(self._mqtt_debug_water_theme, subtopic), str(msg))

اتنا متن، اور ہم نے ابھی تک ایل ای ڈی کو نہیں جھپکا۔ یہاں

    # Blink flash LED if WiFi down
    async def _heartbeat(self):
        while True:
            if self.internet_outage:
                self.blue_led(not self.blue_led()) # Fast blinking if no connection
                await asyncio.sleep_ms(200) 
            else:
                self.blue_led(0) # Rare blinking when connected
                await asyncio.sleep_ms(50)
                self.blue_led(1)
                await asyncio.sleep_ms(5000)

میں نے 2 پلک جھپکنے کے طریقے فراہم کیے ہیں۔ اگر کنکشن منقطع ہو جائے (یا یہ ابھی قائم ہو رہا ہے)، تو آلہ تیزی سے پلک جھپکائے گا۔ اگر کنکشن قائم ہو جائے تو آلہ ہر 5 سیکنڈ میں ایک بار پلک جھپکتا ہے۔ اگر ضروری ہو تو، دوسرے ٹمٹمانے کے طریقوں کو یہاں لاگو کیا جا سکتا ہے۔

لیکن ایل ای ڈی صرف لاڈ ہے۔ ہم نے ڈسپلے کا بھی مقصد کیا۔

    async def _display_coro(self):
        display = SSD1306_I2C(128,32, i2c)
    
        while True:
            display.poweron()
            display.fill(0)
            display.text("COLD: {:.3f}".format(self.cold_counter.value() / 1000), 16, 4)
            display.text("HOT:  {:.3f}".format(self.hot_counter.value() / 1000), 16, 20)
            display.show()
            await asyncio.sleep(3)
            display.poweroff()

            while self.button():
                await asyncio.sleep_ms(20)

یہ وہی ہے جس کے بارے میں میں بات کر رہا تھا - یہ کوروٹین کے ساتھ کتنا آسان اور آسان ہے۔ یہ چھوٹا سا فنکشن صارف کے پورے تجربے کو بیان کرتا ہے۔ کوروٹین صرف بٹن کے دبانے کا انتظار کرتا ہے اور 3 سیکنڈ کے لیے ڈسپلے کو آن کر دیتا ہے۔ ڈسپلے موجودہ میٹر ریڈنگ کو دکھاتا ہے۔

ابھی ایک دو چھوٹی چیزیں باقی ہیں۔ یہ وہ فنکشن ہے جو (دوبارہ) اس پورے انٹرپرائز کو شروع کرتا ہے۔ مین لوپ صرف ایک منٹ میں ایک بار مختلف ڈیبگنگ معلومات بھیجتا ہے۔ عام طور پر، میں اسے ویسا ہی نقل کرتا ہوں - مجھے نہیں لگتا کہ بہت زیادہ تبصرہ کرنے کی ضرورت ہے۔

   async def main(self):
        while True:
            try:
                await self._connect_to_WiFi()
                await self._run_main_loop()
                    
            except Exception as e:
                self.dprint('Global communication failure: ', e)
                await asyncio.sleep(20)

    async def _connect_to_WiFi(self):
        self.dprint('Connecting to WiFi and MQTT')
        sta_if = network.WLAN(network.STA_IF)
        sta_if.connect(config['ssid'], config['wifi_pw'])
        
        conn = False
        while not conn:
            await self.connect()
            conn = True

        self.dprint('Connected!')
        self.internet_outage = False

    async def _run_main_loop(self):
        # Loop forever
        mins = 0
        while True:
            gc.collect()  # For RAM stats.
            mem_free = gc.mem_free()
            mem_alloc = gc.mem_alloc()

            try:
                await self.publish_debug_msg("Uptime", mins)
                await self.publish_debug_msg("Repubs", self.REPUB_COUNT)
                await self.publish_debug_msg("Outages", self.internet_outages)
                await self.publish_debug_msg("MemFree", mem_free)
                await self.publish_debug_msg("MemAlloc", mem_alloc)
            except Exception as e:
                self.dprint("Exception occurred: ", e)
            mins += 1

            await asyncio.sleep(60)

ٹھیک ہے، تفصیل کو مکمل کرنے کے لیے کچھ مزید ترتیبات اور مستقل

#####################################
# Constants and configuration
#####################################


config['keepalive'] = 60
config['clean'] = False
config['will'] = ('/ESP/Wemos/Water/LastWill', 'Goodbye cruel world!', False, 0)

MQTTClient.DEBUG = True

EEPROM_ADDR_HOT_VALUE = const(0)
EEPROM_ADDR_COLD_VALUE = const(4)

یہ سب کچھ اس طرح شروع ہوتا ہے۔

client = CounterMQTTClient()
loop = asyncio.get_event_loop()
loop.run_until_complete(client.main())

میری یادداشت کو کچھ ہوا۔

تو، تمام کوڈ وہاں ہے. میں نے فائلوں کو ampy یوٹیلیٹی کا استعمال کرتے ہوئے اپ لوڈ کیا ہے - یہ آپ کو ان کو اندرونی (ESP-07 میں ہی) فلیش ڈرائیو پر اپ لوڈ کرنے کی اجازت دیتا ہے اور پھر پروگرام سے عام فائلوں کی طرح اس تک رسائی حاصل کرتا ہے۔ وہاں میں نے mqtt_as, uasyncio, ssd1306 اور مجموعہ لائبریریوں کو بھی اپ لوڈ کیا جو میں نے استعمال کیا (mqtt_as کے اندر استعمال کیا گیا)۔

ہم لانچ کرتے ہیں اور... ہمیں ایک MemoryError ملتا ہے۔ مزید یہ کہ میں نے جتنا زیادہ یہ سمجھنے کی کوشش کی کہ میموری کہاں سے لیک ہو رہی ہے، میں نے جتنے زیادہ ڈیبگ پرنٹس رکھے، اتنی ہی پہلے یہ خرابی ظاہر ہوئی۔ گوگل کی ایک مختصر تلاش نے مجھے یہ سمجھا کہ مائیکرو کنٹرولر کے پاس اصولی طور پر صرف 30 kB میموری ہے، جس میں 65 kB کا کوڈ (بشمول لائبریریاں) بس فٹ نہیں ہو سکتا۔

لیکن ایک راستہ ہے. اس سے پتہ چلتا ہے کہ micropython براہ راست .py فائل سے کوڈ نہیں چلاتا ہے - یہ فائل پہلے مرتب کی جاتی ہے۔ مزید برآں، یہ براہ راست مائیکرو کنٹرولر پر مرتب کیا جاتا ہے، بائٹ کوڈ میں تبدیل ہوتا ہے، جسے پھر میموری میں محفوظ کیا جاتا ہے۔ ٹھیک ہے، کمپائلر کے کام کرنے کے لیے، آپ کو ایک خاص مقدار میں ریم کی بھی ضرورت ہے۔

چال یہ ہے کہ مائیکرو کنٹرولر کو وسائل سے بھرپور تالیف سے بچایا جائے۔ آپ فائلوں کو ایک بڑے کمپیوٹر پر مرتب کر سکتے ہیں اور ریڈی میڈ بائی کوڈ کو مائیکرو کنٹرولر میں اپ لوڈ کر سکتے ہیں۔ ایسا کرنے کے لیے، آپ کو مائیکرو پیتھون فرم ویئر ڈاؤن لوڈ کرنے اور بنانے کی ضرورت ہے۔ mpy-کراس کی افادیت.

میں نے میک فائل نہیں لکھی، لیکن دستی طور پر تمام ضروری فائلوں (بشمول لائبریریوں) کو کچھ اس طرح مرتب کیا

mpy-cross water_counter.py

بس جو باقی ہے وہ ہے .mpy ایکسٹینشن کے ساتھ فائلیں اپ لوڈ کرنا، پہلے ڈیوائس کے فائل سسٹم سے متعلقہ .py کو حذف کرنا نہ بھولیں۔

میں نے پروگرام (IDE؟) ESPlorer میں تمام ترقی کی۔ یہ آپ کو مائیکرو کنٹرولر پر اسکرپٹس اپ لوڈ کرنے اور فوری طور پر ان پر عمل کرنے کی اجازت دیتا ہے۔ میرے معاملے میں، تمام اشیاء کی تمام منطق اور تخلیق water_counter.py (.mpy) فائل میں موجود ہے۔ لیکن یہ سب خود بخود شروع ہونے کے لیے، شروع میں main.py نامی ایک فائل بھی ہونی چاہیے۔ مزید یہ کہ، یہ بالکل .py ہونا چاہیے، نہ کہ پہلے سے مرتب کردہ .mpy۔ یہاں اس کے معمولی مشمولات ہیں۔

import water_counter

ہم اسے لانچ کرتے ہیں - سب کچھ کام کرتا ہے۔ لیکن مفت میموری خطرناک حد تک چھوٹی ہے - تقریبا 1kb۔ میرے پاس ابھی بھی ڈیوائس کی فعالیت کو بڑھانے کا منصوبہ ہے، اور یہ کلو بائٹ واضح طور پر میرے لیے کافی نہیں ہے۔ لیکن معلوم ہوا کہ اس کیس کے لیے بھی ایک راستہ ہے۔

یہ رہی بات۔ اگرچہ فائلیں بائیک کوڈ میں مرتب کی جاتی ہیں اور اندرونی فائل سسٹم پر رہتی ہیں، حقیقت میں وہ اب بھی رام میں لوڈ ہوتی ہیں اور وہاں سے عمل میں لائی جاتی ہیں۔ لیکن یہ پتہ چلتا ہے کہ مائیکرو پیتھون فلیش میموری سے بائٹ کوڈ کو براہ راست چلا سکتا ہے، لیکن اس کے لیے آپ کو اسے براہ راست فرم ویئر میں بنانا ہوگا۔ یہ مشکل نہیں ہے، حالانکہ اس میں میری نیٹ بک پر کافی وقت لگا (صرف وہاں میرے پاس لینکس ہوا)۔

الگورتھم اس طرح ہے:

  • ڈاؤن لوڈ اور انسٹال کریں۔ ESP اوپن SDK. یہ چیز ESP8266 کے پروگراموں کے لیے ایک کمپائلر اور لائبریریوں کو جمع کرتی ہے۔ پروجیکٹ کے مرکزی صفحہ پر دی گئی ہدایات کے مطابق جمع کیا گیا (میں نے اسٹینڈالون = ہاں سیٹنگ کا انتخاب کیا)
  • ڈاؤن لوڈ، اتارنا micropython کی قسمیں
  • مائیکرو پیتھون ٹری کے اندر مطلوبہ لائبریریوں کو بندرگاہوں/esp8266/ماڈیولز میں رکھیں
  • ہم فائل میں دی گئی ہدایات کے مطابق فرم ویئر کو جمع کرتے ہیں۔ ports/esp8266/README.md
  • ہم فرم ویئر کو مائیکرو کنٹرولر پر اپ لوڈ کرتے ہیں (میں یہ ESP8266Flasher پروگرام یا Python esptool استعمال کرکے ونڈوز پر کرتا ہوں)

بس، اب 'import ssd1306' کوڈ کو براہ راست فرم ویئر سے اٹھا لے گا اور اس کے لیے RAM استعمال نہیں کی جائے گی۔ اس چال کے ساتھ، میں نے فرم ویئر میں صرف لائبریری کوڈ اپ لوڈ کیا، جبکہ مرکزی پروگرام کوڈ فائل سسٹم سے عمل میں آتا ہے۔ یہ آپ کو فرم ویئر کو دوبارہ مرتب کیے بغیر آسانی سے پروگرام میں ترمیم کرنے کی اجازت دیتا ہے۔ اس وقت میرے پاس تقریباً 8.5kb مفت RAM ہے۔ یہ ہمیں مستقبل میں کافی مختلف مفید فعالیتوں کو لاگو کرنے کی اجازت دے گا۔ ٹھیک ہے، اگر کافی میموری نہیں ہے، تو آپ فرم ویئر میں مرکزی پروگرام کو دھکا سکتے ہیں.

تو اب ہمیں اس کے بارے میں کیا کرنا چاہیے؟

ٹھیک ہے، ہارڈ ویئر کو سولڈر کیا جاتا ہے، فرم ویئر لکھا جاتا ہے، باکس پرنٹ ہوتا ہے، آلہ دیوار پر پھنس جاتا ہے اور خوشی سے ایک روشنی کا بلب جھپکتا ہے۔ لیکن ابھی کے لیے یہ سب ایک بلیک باکس ہے (لفظی اور علامتی طور پر) اور اس کا اب بھی بہت کم فائدہ ہے۔ یہ MQTT پیغامات کے ساتھ کچھ کرنے کا وقت ہے جو سرور کو بھیجے جاتے ہیں۔

میرا "سمارٹ ہوم" گھوم رہا ہے۔ میجرڈومو سسٹم. MQTT ماڈیول یا تو باکس سے باہر آتا ہے، یا آسانی سے ایڈ آن مارکیٹ سے انسٹال ہوتا ہے - مجھے یاد نہیں کہ میں نے اسے کہاں سے حاصل کیا ہے۔ MQTT کوئی خود کفیل چیز نہیں ہے - آپ کو ایک نام نہاد کی ضرورت ہے۔ بروکر - ایک سرور جو کلائنٹس کو MQTT پیغامات وصول کرتا، ترتیب دیتا اور آگے بھیجتا ہے۔ میں مچھر استعمال کرتا ہوں، جو (میجرڈومو کی طرح) اسی نیٹ بک پر چلتا ہے۔

ڈیوائس کے کم از کم ایک بار پیغام بھیجنے کے بعد، قیمت فوری طور پر فہرست میں ظاہر ہو جائے گی۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

ان اقدار کو اب سسٹم آبجیکٹ کے ساتھ منسلک کیا جا سکتا ہے، انہیں آٹومیشن اسکرپٹس میں استعمال کیا جا سکتا ہے اور مختلف تجزیوں کا نشانہ بنایا جا سکتا ہے - یہ سب اس مضمون کے دائرہ کار سے باہر ہیں۔ میں دلچسپی رکھنے والے کسی کو میجرڈومو سسٹم کی سفارش کرسکتا ہوں۔ لینس میں چینل الیکٹرانکس — ایک دوست بھی ایک سمارٹ ہوم بنا رہا ہے اور سسٹم کو ترتیب دینے کے بارے میں واضح طور پر بات کر رہا ہے۔

میں آپ کو صرف چند گراف دکھاؤں گا۔ یہ روزانہ کی اقدار کا ایک سادہ گراف ہے۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا
یہ دیکھا جا سکتا ہے کہ رات کو تقریباً کوئی بھی پانی استعمال نہیں کرتا تھا۔ ایک دو بار کوئی بیت الخلا گیا، اور ایسا لگتا ہے کہ ریورس اوسموسس فلٹر فی رات چند لیٹر چوستا ہے۔ صبح میں، کھپت میں نمایاں اضافہ ہوتا ہے. میں عام طور پر بوائلر سے پانی استعمال کرتا ہوں، لیکن پھر میں نے نہانا چاہا اور عارضی طور پر شہر کے گرم پانی میں تبدیل ہو گیا - یہ نیچے کے گراف میں بھی واضح طور پر نظر آتا ہے۔

اس گراف سے میں نے سیکھا کہ بیت الخلا جانے کے لیے 6-7 لیٹر پانی درکار ہوتا ہے، نہانے کے لیے 20-30 لیٹر، برتن دھونے کے لیے تقریباً 20 لیٹر اور نہانے کے لیے 160 لیٹر کی ضرورت ہوتی ہے۔ میرا خاندان روزانہ تقریباً 500-600 لیٹر استعمال کرتا ہے۔

ان لوگوں کے لیے جو خاص طور پر متجسس ہیں، آپ ہر انفرادی قدر کے ریکارڈز کو دیکھ سکتے ہیں۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

یہاں سے میں نے سیکھا کہ جب نل کھلتا ہے تو پانی تقریباً 1 لیٹر فی 5 سیکنڈ کی رفتار سے بہتا ہے۔

لیکن اس شکل میں اعدادوشمار کو دیکھنے کے لئے شاید بہت آسان نہیں ہے۔ میجرڈومو میں دن، ہفتے اور مہینے کے حساب سے کھپت کے چارٹ دیکھنے کی صلاحیت بھی ہے۔ یہاں، مثال کے طور پر، سلاخوں میں کھپت کا گراف ہے۔

واٹر میٹر کو سمارٹ ہوم سے جوڑنا

اب تک میرے پاس صرف ایک ہفتے کا ڈیٹا ہے۔ ایک مہینے میں، یہ گراف زیادہ اشارے والا ہوگا - ہر دن کا الگ کالم ہوگا۔ تصویر ان اقدار میں ایڈجسٹمنٹ سے تھوڑی خراب ہو گئی ہے جو میں دستی طور پر داخل کرتا ہوں (سب سے بڑا کالم)۔ اور یہ ابھی تک واضح نہیں ہے کہ آیا میں نے پہلی ہی اقدار کو غلط طریقے سے سیٹ کیا، تقریباً ایک مکعب کم، یا یہ فرم ویئر میں ایک بگ ہے اور تمام لیٹر شمار نہیں کیے گئے۔ مزید وقت درکار ہے۔

خود گراف کو ابھی بھی کچھ جادو، سفید دھونے، پینٹنگ کی ضرورت ہے۔ شاید میں ڈیبگنگ کے مقاصد کے لیے میموری کی کھپت کا گراف بھی بناؤں گا - اگر وہاں کچھ لیک ہو رہا ہو۔ شاید میں کسی طرح ان ادوار کو ظاہر کروں گا جب انٹرنیٹ نہیں تھا۔ فی الحال یہ سب خیالات کی سطح پر ہے۔

حاصل يہ ہوا

آج میرا اپارٹمنٹ تھوڑا ہوشیار ہو گیا ہے۔ اتنے چھوٹے آلے کے ساتھ، میرے لیے گھر میں پانی کی کھپت کی نگرانی کرنا زیادہ آسان ہوگا۔ اگر پہلے میں "دوبارہ، ہم نے ایک مہینے میں بہت زیادہ پانی پیا" پر ناراض تھا، اب میں اس استعمال کا ذریعہ تلاش کر سکتا ہوں۔

کچھ لوگوں کو اسکرین پر ریڈنگز کو دیکھنا عجیب لگ سکتا ہے اگر یہ میٹر سے ہی ایک میٹر دور ہے۔ لیکن بہت دور نہیں مستقبل میں، میں ایک اور اپارٹمنٹ میں جانے کا ارادہ رکھتا ہوں، جہاں پانی کے کئی ریزر ہوں گے، اور میٹر خود ہی لینڈنگ پر واقع ہوں گے۔ اس لیے ریموٹ ریڈنگ ڈیوائس بہت کارآمد ثابت ہوگی۔

میں ڈیوائس کی فعالیت کو بڑھانے کا بھی ارادہ رکھتا ہوں۔ میں پہلے ہی موٹر والے والوز کو دیکھ رہا ہوں۔ اب، بوائلر کو شہر کے پانی میں تبدیل کرنے کے لیے، مجھے ایک مشکل جگہ میں 3 نلکوں کو موڑنے کی ضرورت ہے۔ متعلقہ اشارے کے ساتھ ایک بٹن کے ساتھ ایسا کرنا زیادہ آسان ہوگا۔ ٹھیک ہے، یقینا، یہ لیک کے خلاف تحفظ کو لاگو کرنے کے قابل ہے.

مضمون میں میں نے ESP8266 پر مبنی ڈیوائس کا اپنا ورژن بیان کیا۔ میری رائے میں، میں کوروٹینز کا استعمال کرتے ہوئے مائیکرو پیتھون فرم ویئر کا ایک بہت ہی دلچسپ ورژن لے کر آیا ہوں - سادہ اور عمدہ۔ میں نے مہم کے دوران پیش آنے والی بہت سی باریکیوں اور خامیوں کو بیان کرنے کی کوشش کی۔ شاید میں نے ہر چیز کو بہت زیادہ تفصیل سے بیان کیا ہے؛ ذاتی طور پر، ایک قاری کے طور پر، میرے لیے غیر ضروری چیزوں کو چھوڑنا آسان ہے بعد میں یہ سوچنے کے کہ کہ کیا چھوڑا گیا تھا۔

ہمیشہ کی طرح، میں تعمیری تنقید کے لیے کھلا ہوں۔

ماخذ کوڈ
سرکٹ اور بورڈ
کیس ماڈل

ماخذ: www.habr.com

نیا تبصرہ شامل کریں