2 पॉइंट द्वारा GN⁺ 2024-10-25 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • सैन फ्रांसिस्को में बिना कार के आने-जाने वाली जीवनशैली में, घर से निकलने से पहले पास के स्टॉप पर अगली arrival time तुरंत दिखाने वाला डिवाइस ज़्यादा उपयोगी है
  • एक पुराने Kindle को jailbreak करके दीवार पर लगने वाला e-ink डिस्प्ले बनाया गया, और शुरुआत में BART वेबपेज के screenshot इमेज समय-समय पर दिखाए जाते थे
  • MUNI जोड़ने पर कई browser tabs, Raspberry Pi की memory पर दबाव, और HTTP 429 जैसी समस्याओं के कारण screenshot-आधारित संरचना की विश्वसनीयता घट गई
  • Rust में दोबारा लिखे गए संस्करण में 511.org Stop Monitoring API से डेटा लाया जाता है, और skia-safe से Kindle resolution और 8-bit color depth के अनुरूप PNG सीधे बनाया जाता है
  • browser engine हटाकर caching, error display, और layout adjustment जोड़ने के बाद यह एक व्यावहारिक Kindle public transit display बन गया

घर से निकलते समय ज़रूरी जानकारी सरल होती है

  • सैन फ्रांसिस्को में बिना कार के यात्रा करते हुए बस, ट्रेन, ट्राम, ट्रॉलीबस, केबल कार और फेरी जैसे public transit का अक्सर उपयोग किया जाता है
  • CityMapper जैसे ऐप गंतव्य तक पहुँचने के लिए उपयोगी हैं, लेकिन घर के सामने “कहाँ जाना है” से ज़्यादा हर route की अगली arrival time महत्वपूर्ण होती है
  • अगर उपयोगकर्ता पहले से जानता है कि कौन-सा स्टॉप और route लेना है, तो सामान्य navigation ऐप का current location और destination मॉडल ज़रूरत से ज़्यादा जटिल हो जाता है
  • पुराने Kindle को smart home display की तरह इस्तेमाल करने पर Matt Healy की पोस्ट और पुराने Nook को iCloud photo frame की तरह इस्तेमाल करने पर Ben Borgers की पोस्ट से यह विचार मिला

Kindle पर इमेज दिखाने तक का सफर

  • पहला कदम Kindle को jailbreak करके USBNet चालू करना और SSH access सक्षम बनाना था
    • इसके बाद cron job के जरिए डिस्प्ले को समय-समय पर refresh किया गया
    • mobileread wiki और forum की Kindle hacking सामग्री संदर्भ के रूप में इस्तेमाल हुई
  • BART का Real Time Departure पेज चुने गए स्टेशन की अगली ट्रेनें और auto-refresh देता था, इसलिए शुरुआती data source के रूप में उपयुक्त था
  • Kindle CLI के eips से PNG दिखाने की कोशिश की गई, लेकिन शुरुआत में इमेज बहुत खिंच जाती थी या कट जाती थी, इसलिए उपयोग योग्य नहीं थी
  • समस्या यह थी कि Kindle display tool 24-bit RGB PNG को सही तरह से प्रोसेस नहीं करता था और उसे 8-bit इमेज की तरह पढ़ता था
    • ImageMagick convert में -colorspace gray -depth 8 लगाने पर इमेज सही दिखने लगी
    • Kindle screen size के अनुरूप इमेज और 8-bit color depth मुख्य शर्तें निकलीं

पहला implementation: Node.js, Puppeteer, Raspberry Pi

  • शुरुआती server में Node.js और Puppeteer से BART वेबपेज के आवश्यक हिस्से का capture लिया जाता था
  • capture की गई इमेज को Kindle screen size और 8-bit grayscale के अनुसार बदलकर HTTP endpoint से लौटाया जाता था
  • server Raspberry Pi पर चलता था, और Kindle cron के जरिए हर मिनट इमेज लाकर eips से दिखाता था
  • चूँकि BART पेज खुद auto-refresh सपोर्ट करता था, इसलिए server start पर पेज को एक बार खोलकर रखा जाता था और हर request पर उसे दोबारा load नहीं किया जाता था
  • यह संस्करण कुछ समय तक ठीक चला, लेकिन refresh कभी-कभी रुक जाता था या server memory की कमी के कारण restart माँगता था

MUNI विस्तार से सामने आई सीमाएँ

  • सैन फ्रांसिस्को बे एरिया में 27 public transit operators हैं, और पहला implementation केवल क्षेत्रीय rapid transit BART को संभालता था
  • बाद में MUNI की बस और light rail स्टॉप की arrival times भी साथ में देखना चाहा गया
  • MUNI वेबपेज भी स्टॉप-वार arrival times देता था, इसलिए शुरुआत में कई स्टॉप पेजों को Puppeteer से capture करके ImageMagick से जोड़ने की कोशिश की गई
  • स्क्रीन के 7 sections में से हर एक, Puppeteer द्वारा बनाए रखे जाने वाले browser tab के बराबर था
    • Raspberry Pi में पर्याप्त memory नहीं थी और Chrome हल्का नहीं था
    • MUNI पेज पर बार-बार request भेजने पर HTTP 429 मिलता था
  • BART और MUNI को साथ दिखाने वाली स्क्रीन, BART-only स्क्रीन की तुलना में कहीं अधिक अस्थिर थी, और एक नज़र में देखने योग्य डिस्प्ले के लिए अधिक विश्वसनीय संरचना चाहिए थी

Rust में दोबारा डिजाइन की गई संरचना

  • rewritten version में Puppeteer हटा दिया गया और Rust HTTP server सीधे PNG generate करने लगा
  • public interface को Node.js server जैसा ही रखा गया, लेकिन internal implementation पूरी तरह बदल गया
  • इसके तीन मुख्य हिस्से थे
    • 511.org से अगली arrival times लाना
    • arrival times को 8-bit PNG इमेज में render करना
    • तैयार PNG को HTTP server से लौटाना
  • HTTP server के लिए Axum इस्तेमाल किया गया
  • PNG rendering के लिए rust-skia इस्तेमाल हुआ
    • Skia, Chrome की आधारभूत graphics library भी है, इसलिए Puppeteer की तुलना में कम overhead के साथ rendering तकनीक का उपयोग संभव हुआ
  • अंतिम server code लगभग 1,200 lines का था, और उसमें से केवल महत्वपूर्ण हिस्से संक्षेप में बताए गए

511.org Stop Monitoring API से डेटा लाना

  • 511.org का Stop Monitoring API बे एरिया स्टॉप्स के expected arrival और departure times को XML और JSON में देता है
  • इस्तेमाल किया गया endpoint इस रूप में था: http://api.511.org/transit/StopMonitoring/…]
  • agency 27 बे एरिया public transit operators में से एक को चुनता है, और SF MUNI का code SF है
  • API एक बार में केवल एक operator का data ला सकता है
    • यह किसी एक खास स्टॉप की arrival times या उस operator के सभी स्टॉप्स का data लौटाता है
    • कई स्टॉप्स के किसी subset को एक साथ लाने का तरीका नहीं मिला
  • 511.org API की limit प्रति घंटे 60 requests है, इसलिए हर स्टॉप के लिए कई requests वाला तरीका real-time display के लिए उपयुक्त नहीं था
  • SF MUNI का पूरा data माँगने पर HTTP request में लगभग 5 seconds लगे और लगभग 27 MiB data मिला, जबकि formatted JSON 10 लाख lines से अधिक था
  • पूरे response में लगभग 26k MonitoredStopVisit items थे, लेकिन वास्तविक स्क्रीन के लिए केवल चुने गए स्टॉप और route के LineRef, DirectionRef, DestinationName, StopPointRef, ExpectedArrivalTime, DestinationDisplay की ज़रूरत थी

Rust data processing में मिली बारीक समस्याएँ

  • reqwest, serde, serde_json, chrono, tokio, eyre का उपयोग HTTP requests, JSON parsing, time calculation, async execution, और error handling के लिए किया गया
  • MUNI stop ID, SF MUNI वेबसाइट के stop page पर देखे जा सकते हैं
    • उदाहरण के लिए Persia Ave & Paris St के लिए inbound 15918 और outbound 15919 अलग-अलग हैं
    • MUNI stops दिशा के हिसाब से अलग ID रखते हैं
  • 511.org response, JSON के आगे UTF-8 Byte Order Mark जोड़कर लौटाता था, और सीधे .json() से parse करने पर expected value at line 1 column 1 error मिलता था
  • .text() से response को UTF-8 string की तरह पढ़ने पर BOM हट जाता था, और फिर उसे serde_json::from_str से parse किया जा सकता था
  • filtering के बाद केवल रुचि वाले स्टॉप्स की लगभग 20 arrival entries बचीं, जो शुरुआती 26k entries की तुलना में कहीं अधिक manageable थीं
  • LineRef और DirectionRef के आधार पर group करके, ExpectedArrivalTime के अनुसार sort किया गया और UTC timestamps को “कितने मिनट बाद” के रूप में बदला गया

Skia से Kindle के लिए PNG बनाना

  • PNG rendering को skia-safe से बनाया गया
  • Kindle screen size 1024x758 के अनुरूप Gray8 bitmap बनाया गया, बैकग्राउंड सफेद भरा गया, फिर text और lines draw की गईं
  • पहले “Hello World” दिखाने वाला PNG8 इमेज बनाकर rendering pipeline की जाँच की गई
  • उसके बाद fake arrival time data से inbound और outbound दो columns वाली table-जैसी इमेज बनाई गई
  • जब इसे असली API data से जोड़ा गया, तो test data की तुलना में destination और arrival time अधिक विविध निकले, और fixed layout में text overlap होने लगा
  • तेज़ iteration और API limits से बचने के लिए response को data.json में cache करने वाला अस्थायी code जोड़ा गया

display layout को निखारना

  • शुरुआती वास्तविक data स्क्रीन में हर row में अलग मात्रा में information होने के कारण readability कम थी
  • किए गए सुधार इस प्रकार थे
    • arrival times को right-align किया गया ताकि table के अंत की खाली जगह कम हो
    • हर time के बाद का min हटाकर केवल सूची के अंत में min रखा गया
    • केवल अगली 3 गाड़ियाँ दिखाई गईं
    • लंबे route नामों को ध्यान में रखकर destination name को दाईं ओर खिसकाया गया
  • इसके बाद route ID को गोल कोनों वाले gray bubble की तरह दिखाने के लिए measure_str से text boundary निकाली गई
  • destination string को route ID bubble के दाएँ किनारे से 15 pixels दूर रखा गया
  • ऊपर हल्का gray header जोड़ा गया और Muni Inbound, Muni Outbound को center-align करके दिखाया गया

Axum से PNG serve करना

  • HTTP server Axum 0.7 से बनाया गया और /stops.png route पर PNG लौटाया गया
  • response header को Content-Type: image/png पर सेट किया गया
  • शुरुआत में खाली body के साथ HTTP 200 की पुष्टि की गई, फिर image generation function को जोड़कर PNG bytes को सीधे memory से लौटाया गया
  • Kindle पर wget से इमेज लाकर eips से दिखाने पर शुरुआत में इमेज rotate होकर कट जाती थी
  • Kindle डिफ़ॉल्ट रूप से portrait orientation में काम करता है, इसलिए landscape की तरह दिखाने के लिए render करने से पहले rotation matrix लगानी पड़ी
    • इमेज size को (758, 1024) में उलट दिया गया
    • canvas को 90.0 degree घुमाया गया

production version में जोड़ी गई अतिरिक्त सुविधाएँ

  • वास्तविक उपयोग वाले version में ये सुविधाएँ और जोड़ी गईं
    • API data को background में लगातार लाकर HTTP server को तेज़ response देने वाली caching system
    • नीचे बाएँ current time और नीचे दाएँ data cache status
    • anti-aliasing
    • arrival time area से overlap न हो, इसके लिए destination names को truncate करना
    • route के अनुसार अलग-अलग gray tones देकर उन्हें जल्दी पहचानने योग्य बनाना
    • config file आधारित configuration
    • error होने पर error और .source() chain को PNG पर render करके Kindle पर सीधे दिखाना
  • साथ में बनाया गया simplified server code transit-kindle-simplified में उपलब्ध है
  • वास्तविक wall-mounted Kindle चलाने वाला server code transit-kindle में है
  • BART screenshot-आधारित version लगभग फ़रवरी 2023 में काम कर रहा था, और Rust rewrite के अंतिम UI सुधार जनवरी 2024 में पूरे हुए

1 टिप्पणियां

 
GN⁺ 2024-10-25
Hacker News टिप्पणियाँ
  • मैं OneBusAway के पीछे वाली non-profit संस्था में काम करता/करती हूँ। OneBusAway एक open source प्रोजेक्ट है, जिसे रोज़ लाखों लोग बसों, ट्रेनों, ट्रामों और फनिक्युलर की लोकेशन और arrival times देखने के लिए इस्तेमाल करते हैं
    अगर आपके शहर में पहले से OneBusAway server है, तो नए SDK से custom app बना सकते हैं: https://github.com/onebusAway/?q=sdk&type=all&language=&sort...
    अगर server नहीं है, तो इस साल बनाए गए Docker image और OpenTofu configuration से GTFS/GTFS-RT feed को REST API में बदला जा सकता है
    BART भी GTFS और GTFS-RT उपलब्ध कराता है: https://mobilitydatabase.org/feeds/mdb-53
    अमेरिका की दूसरी public transit agencies को भी नए federal rules की वजह से कम-से-कम static timetable data GTFS में सार्वजनिक करना होगा
    संबंधित software में योगदान देने वाले developers की हमेशा ज़रूरत है, और खास तौर पर रोज़ 2.5 लाख users के अनुभव को बेहतर बनाने में मदद करने वाले iOS developers की बहुत ज़रूरत है। संपर्क: aaron@onebusaway.org
    Docker: https://github.com/OneBusAway/onebusaway-docker / OpenTofu: https://github.com/OneBusAway/onebusaway-deployment

    • अभी दुनिया भर में समर्थित शहर सिर्फ़ 9 हैं, और उनमें से 2 beta में हैं, इसलिए लगता है कि इसे ज़्यादा व्यापक रूप से फैलना होगा तभी open source योगदान भी आसान होगा
      अगर प्रक्रिया सरल हो तो मैं अपना शहर भी जोड़ना चाहूँगा/चाहूँगी। लगता है हाल में libraries और SDK support पर काफी engineering time लगाया गया है, लेकिन नए contributors के लिए समय लगाना आसान हो, इसके लिए developer experience का आसान रास्ता बनाने में निवेश करना बेहतर दिखता है
      उदाहरण के लिए यह document काफी जटिल है: https://github.com/OneBusAway/onebusaway/wiki/Multi-Region
    • OneBusAway deployed वाले शहरों की list कहाँ मिलेगी, यह जानना चाहता/चाहती हूँ। “onebusaway cities” खोजने पर https://onebusaway.org/onebusaway-deployments/ आता है, लेकिन उसमें आपके बताए Adelaide जैसे शहर नहीं थे
    • अगर यह open source है, तो इसे सिर्फ़ Play Store पर ही क्यों डाला गया है और F-Droid पर distribute क्यों नहीं किया जाता, यह सोचने वाली बात है
    • OneBusAway ही नहीं, Google Maps जैसे bus tracking apps इतने inaccurate क्यों होते हैं, यह भी समझ नहीं आता
      “4 मिनट बाद आएगी” दिखता है, लेकिन बस सामने से निकल जाती है; या “5 मिनट late” कहता है, पर असल में 2 मिनट पहले आ जाती है। कभी-कभी बस आती ही नहीं
      शायद source data की समस्या हो, लेकिन अंदरूनी तौर पर ऐसा क्या होता है जिससे reliability इतनी कम हो जाती है, यह जानना चाहूँगा/चाहूँगी। संदर्भ के लिए, यह Seattle की बात है
  • BART और MUNI दोनों General Transit Feed Specification support करते हैं, और यह data पाने का standard तरीका है
    https://gtfs.org/documentation/overview/#gtfs-realtime

    • real-time information कितनी भरोसेमंद होती है, यह जानना चाहता/चाहती हूँ। Google Maps कहता है “bus 4 मिनट बाद आएगी”, लेकिन मैं bus को जाते हुए देख रहा/रही होता/होती हूँ; या “5 मिनट late” कहता है, जबकि असल में वह 2 मिनट पहले आ जाती है—ऐसा अक्सर होता है
  • बहुत पसंद आया। पहले जब मैं Boston में बिना car के रहता/रहती था/थी, तब A से B तक जाने के कई तरीके होते थे और “best” क्या है यह समय या बीच में कहाँ रुकना है, इस पर निर्भर करता था—इसे handle करने के लिए मैंने खुद इससे कहीं ज़्यादा कच्ची चीज़ जोड़-तोड़ कर बनाई थी
    उदाहरण के लिए office जाने से पहले बेटे को school छोड़ता/छोड़ती था/थी, और कभी-कभी drop-off के बाद breakfast करता/करती था/थी। अगला departure time देखना अगर होता, तो किसी दिलचस्प जगह पर 4 साल के बच्चे के साथ चलते हुए unpredictable स्थिति में, या ऐसी train पकड़ने के लिए जल्दी करनी चाहिए या नहीं जिसे miss करने पर frequency gap आ जाएगा—ऐसे फैसले कहीं ज़्यादा flexible तरीके से लिए जा सकते थे

  • हैरानी है कि अभी तक https://oeffi.schildbach.de/index.html का ज़िक्र नहीं हुआ। यह ठीक वही करता है जो यहाँ चाहिए

  • अगर UK में हैं, तो स्टेशन के departure board की नकल करने वाला departure board device खरीद सकते हैं
    https://ukdepartureboards.co.uk/store/product/desktop-depart...

    • कुछ स्टेशनों में इस्तेमाल होने वाले departure board की नकल करने वाला https://departureboards.mobi/departures/BTH भी है
    • अच्छा तो है, लेकिन impulse purchase को justify करने के लिए काफ़ी महंगा है
    • Switzerland में tram information board की नकल करने वाला मिलता-जुलता product भी है
      https://tramli.ch/en
  • मैं भी SF में रहता हूँ, और इसी समस्या को हल करने के लिए A Better Ride नाम का iOS app बनाया है
    यह सिर्फ़ आसपास के stops के public transit departure times दिखाता है। लक्ष्य public transit को predictable और explore करने में आसान बनाकर stress कम करना है। यह बिना monetization के खाली समय में बनाया जा रहा personal project है

    • यह app सच में शानदार है। यह आसपास के routes और वे routes कहाँ जाते हैं, बस यही दिखाता है—इसी वजह से यह दूसरे public transit apps से अलग है
      यह आपको transfers की चिंता किए बिना उन जगहों को explore करने देता है जहाँ आप जा सकते हैं
    • app सच में बहुत बढ़िया है। real-time map खास तौर पर अच्छा है
      मैं भी इसी क्षेत्र में hardware बना रहा हूँ और हाल में GTFS के साथ काफ़ी काम किया है, इसलिए तुरंत दिखता है कि transit data parse करने और दिखाने में कितना काम लगा होगा
      अगर ठीक हो, तो हर stop से उपलब्ध trips को summarize और group करने से जुड़े UX decisions, और backend के बारे में बात करना चाहूँगा
    • बहुत अच्छा है। सड़क के किस तरफ़ है, कुल travel direction किस ओर है—ऐसे कई thoughtful details हैं
  • Kindle को jailbreak करने या images render करने की ज़रूरत नहीं है
    अपनी बनाई हुई webpage को Kindle browser में खोलें, और debug command से Kindle के “screensaver” ads या sleep screen को बंद कर दें
    browser bar Kindle के एक किनारे पर रह तो जाती है, लेकिन device orientation घुमाकर उसे नीचे या दाईं तरफ़ रखा जा सकता है। इसके बदले weather, transit और news screen को आसान HTML/CSS/JS और अपनी पसंद की backend language से बना सकते हैं, और सस्ते DigitalOcean के 4 डॉलर वाले instance जैसी जगह पर चला सकते हैं
    https://blog.notfaqs.com/2018/06/kindle-e-reader-disable-scr...
    https://www.mobileread.com/forums/showthread.php?t=198334

    • अगर Amazon ऐसे display hacking के लिए Kindle browser में kiosk mode को encourage करे और बना दे, तो और भी cool होगा
    • Android चलाने वाले inkBOOK पर मैंने ऐसा किया था। Chrome APK sideload किया और अपनी बनाई webpage खोली
      document.documentElement.requestFullscreen() से सच में fullscreen में चला गया, status bar भी नहीं दिखता। local public transit API webpage से सीधे accessible थी, इसलिए backend की भी ज़रूरत नहीं पड़ी
    • 4th generation Kindle पर देखा, लेकिन certificates valid नहीं हैं, इसलिए लगता है HTTPS sites लगभग इस्तेमाल नहीं कर सकते
      फिर भी अगर local network के server से communicate करवाएँ, तो ठीक लग रहा है
    • बाद के Kindle में screensaver disable करने वाला feature हटाया गया हो, इसकी संभावना लगभग पक्की है
  • शायद मैं इस use case को ठीक से समझ नहीं पाया। बात “train लेने” की नहीं है, बल्कि A से B तक जाने की है
    अगर train खराब है, strike चल रही है, दोपहर 1–4 बजे line बंद है, या service hours नहीं हैं, तो मुझे alternatives चाहिए। इसलिए मुझे वही चाहिए जो Google Maps देता है, या देने की कोशिश करता है
    Ferry Building से Oakland जाना हो और BART खराब हो, तो ferry बेहतर हो सकती है; देर रात हो तो taxi या Uber के अलावा कुछ न हो
    Tokyo में Shibuya से Azabujuban जाना हो, तो Ginza Line→Namboku Line, Hanzomon Line→Oedo Line, Yamanote Line→Namboku Line, bus no. 6, taxi जैसे options हैं
    हर line के stations और bus stops के बीच भी 3–8 मिनट पैदल चलना पड़ता है, इसलिए अभी आप किसके करीब हैं, यह choice को प्रभावित करता है। आप late हैं या नहीं, luggage बड़ा या भारी है या नहीं, यह भी मायने रखता है

    • Google Maps शायद बहुत strongly assume करता है कि पैदल चलना बहुत खराब चीज़ है और कोई नहीं चाहता
      उदाहरण के लिए, किसी जगह जाने के लिए 39 नंबर bus लेकर 15 मिनट पैदल चलना काफी है, लेकिन Google से पूछें तो वह 2 transfers वाला route देता है। किस्मत अच्छी हो तो bus एक बार + walking वाले route जितना ही time लगता है
      इसलिए अगर जानना हो कि 39 नंबर bus कब आ रही है, तो मुझे destination जानबूझकर कुछ और बताना पड़ता है
      और जहाँ मैं रहता हूँ, वहाँ Google का real-time data संदिग्ध लगता है; operator या कुछ third-party data ज़्यादा भरोसेमंद है
    • use case daily commuting है। बहुत से लोग ज़्यादातर समय सचमुच “train लेना” ही चाहते हैं
      कभी-कभी real time में जबरदस्त planning करनी पड़ती है और ऐसा tool हो तो अच्छा है, लेकिन daily commuting को कहीं ज़्यादा simple tool से भी पर्याप्त रूप से cover किया जा सकता है
      आपका Tokyo example भी दिलचस्प है, लेकिन Google के हिसाब से ज़्यादातर public transit options 30–40 मिनट के हैं, इसलिए rough planning में लगभग equivalent हैं। taxi तेज़ है और bicycle भी लगभग वैसी ही है
    • रोज़ commute करते समय सचमुच बस “train लेना” ही चाहता हूँ
      train खराब हो या strike हो, तो real-time train list में unexpected gap के रूप में दिख जाएगा
      शहर में घूमते समय Google Maps खोलकर destination डालता हूँ, लेकिन जिस जगह 500 बार जा चुका हूँ वहाँ घर से निकलते समय उसे खोलने की ज़रूरत नहीं समझता
    • central Tokyo का public transit experience पूरी दुनिया पर generalize नहीं किया जा सकता
      यह उतना ही meaningful है जितना Disneyland के अंदर के store shopping या dining experience के आधार पर बात करना। Suica tap करना ही दूसरी जगहों से कई गुना तेज़ है, और कई जगह तो support ही नहीं है
    • https://citymapper.com आपको पसंद आ सकता है
      इसमें बहुत features हैं, लेकिन Tokyo में कितना support है, पता नहीं। London में अगर home जाने को कहें तो cost, walking distance, speed, transfers, accessibility वगैरह के आधार पर optimized कई तरीके दिखाता है
  • रीसायकल किए गए Lenovo ThinkSmart View टैबलेट/मीटिंग रूम डिवाइस पर Home Assistant और स्थानीय ट्रांसपोर्ट एजेंसी का इंटीग्रेशन जोड़कर कुछ ऐसा ही इस्तेमाल कर रहा हूँ
    फायदा यह है कि यह कहीं ज़्यादा तुरंत इस्तेमाल करने लायक है। बेशक Lenovo पर custom Android ROM डाला है, लेकिन जो चाहें वह दिखा सकते हैं और लाइटिंग या robot vacuum जैसी चीज़ें भी कंट्रोल कर सकते हैं

  • BART मैप को फिजिकल LED साइनबोर्ड के रूप में बनाया गया एक खूबसूरत प्रोडक्ट भी है: https://www.designrules.co/