उन लोगों के लिए जो एम्बिएंट टीवी से परिचित नहीं हैं, यह टीवी स्क्रीन के किनारे और उसके आस-पास के परिवेश से छलांग को नरम करने का एक तरीका है ताकि अधिक इमर्सिव अनुभव प्रदान किया जा सके। मेरे पास कुछ एलईडी लाइटें पड़ी थीं और यह देखने का फैसला किया कि क्या कोड के माध्यम से रोशनी को नियंत्रित करना संभव है और बदले में, मेरे कंप्यूटर स्क्रीन को एक परिवेशी मॉनिटर बना दें। जबकि मैं इसे अपने मॉनिटर के लिए उपयोग करना चाहता था, इसे कहीं भी इस्तेमाल किया जा सकता है और जो भी रंग आप इसे भेज सकते हैं, जिसमें अन्य विशेषताएं शामिल हैं, जैसे कि ऑडियो प्रतिक्रियाएं या यादृच्छिक पैटर्न। मैं इस पोस्ट को कुछ समय के लिए लिखने का अर्थ कर रहा हूं क्योंकि मैं इसे पहले के मॉनिटर पर उपयोग कर रहा हूं, लेकिन मुझे इसे अपने नए मॉनिटर में जोड़ने के लिए कभी नहीं मिला, इसलिए मैंने इसे प्रलेखित किया क्योंकि मैं किसी के लिए भी गया था जो मिल सकता है यह उपयोगी है। तो चलिए इसे प्राप्त करते हैं! (कृपया ध्यान दें, एलईडी रोशनी ब्लूटूथ कम ऊर्जा (बीएलई) होने की संभावना है, इसलिए उनके साथ बातचीत करने के लिए आपके कंप्यूटर को बीएलई का समर्थन करने की आवश्यकता होगी)। पूरा कोड GitHub पर है।
हमें जो पहला कदम उठाने की जरूरत है, वह यह सुनिश्चित करना है कि रोशनी के साथ आने वाला ऐप उम्मीद के मुताबिक काम कर रहा है। प्रकाश के मूल ऐप को चलाकर और यह सुनिश्चित करके आसानी से इसका परीक्षण किया जा सकता है कि आपके द्वारा अपने ऐप पर दबाए जा रहे ऑन/ऑफ/लाइटिंग बटन के आधार पर रोशनी तदनुसार प्रतिक्रिया करती है। हम ऐसा इसलिए करते हैं क्योंकि हम जल्द ही रोशनी पर ब्लूटूथ रिसीवर को भेजे गए विशिष्ट कोड को दबाएंगे और उसका पता लगाएंगे।
दो दृष्टिकोण हैं जो मैं ले सकता था। एक था ऐप की JAR फ़ाइल को डीकंपाइल करना और भेजे जा रहे कोड को ढूंढना, लेकिन मैं ब्लूटूथ प्रोटोकॉल के बारे में अधिक जानना चाहता था, इसलिए मैंने अपने एंड्रॉइड पर सभी ब्लूटूथ गतिविधि को लॉग करने और इसे वहां से निकालने का विकल्प चुना। ऐसे:
अपने Android डिवाइस पर डेवलपर विकल्प सक्षम करें।
ब्लूटूथ एचसीआई स्नूप लॉग सक्षम करें (एचसीआई होस्ट-कंट्रोलर इंटरफेस के लिए खड़ा है)। आप इस विकल्प को सेटिंग्स > सिस्टम > डेवलपर में पा सकते हैं या इसे सेटिंग में खोज सकते हैं जैसा कि नीचे दी गई छवि में है।
अब हमें विशिष्ट क्रियाएं करने की आवश्यकता है ताकि हम यह पहचान सकें कि प्रत्येक क्रिया प्रकाश के ब्लूटूथ रिसीवर को क्या भेजती है। मैं उस क्रम में चालू/लाल/हरा/नीला/बंद करने के लिए इसे सरल रखने जा रहा हूं, लेकिन यदि आपकी रोशनी अन्य सुविधाओं का समर्थन करती है, तो आप उनके साथ खिलवाड़ भी कर सकते हैं।
ऐप चलाएं और ऑन, रेड, ग्रीन, ब्लू और ऑफ दबाएं। यदि आपके डिवाइस पर बहुत अधिक ब्लूटूथ गतिविधि है, तो इसे फ़िल्टर करना आसान बनाने के लिए अनुमानित समय पर नज़र रखना भी उपयोगी हो सकता है।
ब्लूटूथ बंद कर दें ताकि हमें और शोर न हो। निम्नलिखित चरणों में, हम ब्लूटूथ कमांड का विश्लेषण करेंगे और, जैसा कि हम जानते हैं कि हमने क्या दबाया है, हम यह पता लगा सकते हैं कि कौन से मान किस बटन को दबाने के अनुरूप हैं।
अब हमें फ़ोन पर ब्लूटूथ लॉग एक्सेस करने की आवश्यकता है। ऐसा करने के कई तरीके हैं, लेकिन मैं एक बग रिपोर्ट तैयार और निर्यात करूंगा। ऐसा करने के लिए, फ़ोन की सेटिंग में USB डीबगिंग सक्षम करें, फ़ोन को कंप्यूटर से कनेक्ट करें और adb.exe कमांड लाइन टूल का उपयोग करें।
adb bugreport led_bluetooth_report
यह आपके कंप्यूटर की स्थानीय निर्देशिका पर " led_bluetooth_report.zip " फ़ाइल नाम के साथ एक ज़िप फ़ाइल उत्पन्न करेगा। यदि आप चाहें तो आप पथ निर्दिष्ट कर सकते हैं (उदा. C:\MyPath\led_bluetooth_report")
इस ज़िप के भीतर वे लॉग हैं जिनकी हमें आवश्यकता है। यह डिवाइस से डिवाइस में भिन्न हो सकता है (कृपया टिप्पणी करें यदि आपने इसे अपने डिवाइस पर कहीं और पाया है)। मेरे Google पिक्सेल फोन पर, यह FS\data\misc\ब्लूटूथ\logs\btsnoop_hci.log में था
अब हमारे पास लॉग फाइलें हैं, आइए उनका विश्लेषण करें! ऐसा करने के लिए, मैंने Wireshark का उपयोग करने का निर्णय लिया इसलिए Wireshark प्रारंभ करें और File...Open... पर जाएं और btsnoop_hci लॉग फ़ाइल चुनें।
हालांकि यह चुनौतीपूर्ण लग सकता है, आइए 0x0004 पर BTL2CAP को फ़िल्टर करके जो हम ढूंढ रहे हैं उसे ढूंढना आसान बनाएं, जो कि Wireshark स्रोत कोड में विशेषता प्रोटोकॉल है। विशेषता प्रोटोकॉल परिभाषित करता है कि दो बीएलई डिवाइस एक दूसरे से कैसे बात करते हैं, इसलिए हमें यह पता लगाने में मदद करने की आवश्यकता है कि ऐप रोशनी से कैसे बात करता है। आप शीर्ष के पास " प्रदर्शन फ़िल्टर लागू करें " बार में btl2cap.cid == 0x0004 टाइप करके Wireshark में लॉग फ़िल्टर कर सकते हैं और Enter दबाएं
अब हमने लॉग को फ़िल्टर कर दिया है; इसे कमांड्स की तलाश को आसान बनाना चाहिए। हम टाइमस्टैम्प देख सकते हैं (देखने के लिए जाएं...समय प्रदर्शन प्रारूप...दिन का समय समय बदलने के लिए यदि यह गलत प्रारूप है)। हम भेजे गए राइट कमांड लॉग को देखना चाहते हैं क्योंकि वे वही हैं जहां हमने रोशनी को एक मूल्य भेजा था। यह मानते हुए कि आपका सबसे हाल का समय सबसे नीचे है, पिछले पांच ईवेंट तक नीचे स्क्रॉल करें। ये उस क्रम में ऑन, रेड, ग्रीन, ब्लू और ऑफ होने चाहिए, जिसमें ऑफ आखिरी हो।
गंतव्य BD_ADDR पर ध्यान दें, क्योंकि हमें शीघ्र ही इसकी आवश्यकता होगी, और अपनी शर्लक होम्स टोपी पहन लें, क्योंकि यही वह जगह है जहां हमें पैटर्न को अनलॉक करने की आवश्यकता होती है कि संदेश के भीतर रंग और ऑन/ऑफ कमांड कैसे एन्कोड किए जाते हैं। यह प्रकाश निर्माता के आधार पर अलग-अलग होगा लेकिन यहां मेरे डिवाइस के लिए प्राप्त मूल्यों की सूची है:
ये स्पष्ट रूप से हेक्साडेसिमल मान हैं और यदि आप ध्यान से देखें, तो आप देखेंगे कि कुछ निश्चित पैटर्न हैं। आइए पैटर्न को विभाजित करें क्योंकि इससे चीजों को और अधिक स्पष्ट होना चाहिए।
शुद्ध लाल, हरे और नीले रंग के हेक्साडेसिमल मानों से परिचित लोगों के लिए, आप जानेंगे कि मान क्रमशः #FF000, #00FF00, और #0000FF हैं, जो कि हम ऊपर देख सकते हैं। इसका मतलब है कि अब हम जो चाहते हैं उसमें रंग बदलने का प्रारूप जानते हैं! (या कम से कम रोशनी खुद क्या करने में सक्षम हैं)। हम यह भी देख सकते हैं कि ऑन और ऑफ का रंग से भिन्न प्रारूप है और एक दूसरे के समान हैं, ऑन होने पर f00001 और ऑफ होने पर 00000।
इतना ही! अब हमारे पास रोशनी के साथ कोडिंग और इंटरैक्ट करने के लिए पर्याप्त जानकारी है।
हमें तीन प्रमुख चीजों की आवश्यकता है:
डिवाइस का पता (यह ऊपर से गंतव्य BD_ADDR है)
डिवाइस को भेजे जाने वाले मान (ऊपर प्राप्त हेक्साडेसिमल मान)
जिस विशेषता को हम बदलना चाहते हैं। एक ब्लूटूथ LE विशेषता एक डेटा संरचना है जो अनिवार्य रूप से उस डेटा को परिभाषित करती है जिसे होस्ट और क्लाइंट ब्लूटूथ डिवाइस के बीच भेजा जा सकता है। हमें उस विशेषता (16-बिट या 128-बिट UUID) को खोजने की आवश्यकता है जो रोशनी को संदर्भित करती है। कुछ सामान्य रूप से उपयोग किए जाने वाले असाइन किए गए नंबर हैं जो यहां पाए जा सकते हैं लेकिन जब तक कि डिवाइस उनके अनुरूप न हो, वे एक कस्टम यूयूआईडी का उपयोग कर सकते हैं। जैसा कि मेरी रोशनी निर्दिष्ट संख्या सूची में नहीं है, आइए इसे कोड के माध्यम से खोजें।
मैं पायथन 3.10 और ब्लेक 0.20.1 का उपयोग कर रहा हूं। सुनिश्चित करें कि आपके कंप्यूटर पर ब्लूटूथ चालू है (उपकरण के साथ युग्मित करने की आवश्यकता नहीं है, हम इसे कोड के माध्यम से कनेक्ट करेंगे)।
# Function to create a BleakClient and connect it to the address of the light's Bluetooth reciever async def init_client(address: str) -> BleakClient: client = BleakClient(address) print("Connecting") await client.connect() print(f"Connected to {address}") return client # Function we can call to make sure we disconnect properly otherwise there could be caching and other issues if you disconnect and reconnect quickly async def disconnect_client(client: Optional[BleakClient] = None) -> None: if client is not None : print("Disconnecting") if characteristic_uuid is not None: print(f"charUUID: {characteristic_uuid}") await toggle_off(client, characteristic_uuid) await client.disconnect() print("Client Disconnected") print("Exited") # Get the characteristic UUID of the lights. You don't need to run this every time async def get_characteristics(client: BleakClient) -> None: # Get all the services the device (lights in this case) services = await client.get_services() # Iterate the services. Each service will have characteristics for service in services: # Iterate and subsequently print the characteristic UUID for characteristic in service.characteristics: print(f"Characteristic: {characteristic.uuid}") print("Please test these characteristics to identify the correct one") await disconnect_client(client)
मैंने कोड पर टिप्पणी की है, इसलिए यह स्व-व्याख्यात्मक होना चाहिए लेकिन अनिवार्य रूप से, हम रोशनी से जुड़ते हैं और उन सभी विशेषताओं को खोजते हैं जो इसे उजागर करती हैं। मेरा आउटपुट था:
विशेषता: 00002A00-0000-1000-8000-00805F9B34FB विशेषता: 00002A01-0000-1000-8000-00805F9B34FB विशेषता: 0000FFF3-0000-1000-8000-00805F9B34FB CHARTARISTIC
पहले दो यूयूआईडी का एक त्वरित Google दिखाता है कि यह सेवा के नाम और उपस्थिति को संदर्भित करता है, जो हमारे लिए अप्रासंगिक है। हालांकि, तीसरा और चौथा तीसरा ( 0000fff3-0000-1000-8000-00805f9b34fb ) इस पृष्ठ के अनुसार लेखन विशेषता होने के साथ सबसे उपयुक्त लगता है। बहुत बढ़िया, अब हमारे पास इस विशेष उपकरण के लिए मूल्य (रंग हेक्साडेसिमल) के साथ लिखने के लिए आवश्यक विशेषता है।
हमारे पास आखिरकार वे सभी टुकड़े हैं जिनकी हमें आवश्यकता है। इस स्तर पर, आप रचनात्मक हो सकते हैं कि आप किस रंग के इनपुट का उपयोग करना चाहते हैं। उदाहरण के लिए, आप अपने पोर्टफोलियो के प्रदर्शन के अनुसार रंग बदलने के लिए लाइट्स को ट्रेडिंग मार्केट एपीआई से जोड़ सकते हैं। इस मामले में, हम अपने मॉनिटर को परिवेश से अवगत कराना चाहते हैं, इसलिए हमें स्क्रीन के प्रमुख रंग को प्राप्त करने और उसे भेजने की आवश्यकता है।
ऐसा करने के कई तरीके हैं, इसलिए बेझिझक प्रयोग करें जो आप एल्गोरिदम चाहते हैं। सबसे सरल तरीकों में से एक यह होगा कि स्क्रीन पर प्रत्येक X संख्या के पिक्सेल को पुनरावृत्त किया जाए और औसत लिया जाए जबकि अधिक जटिल समाधान ऐसे रंगों की तलाश करेंगे जिन्हें मानव आंखें अधिक प्रभावी मानती हैं। किसी भी निष्कर्ष पर बेझिझक टिप्पणी करें जिसे आप साझा करना चाहते हैं!
इस ब्लॉग पोस्ट के लिए, मैं इसे fast_colorthief लाइब्रेरी के get_dominant_color मेथड का उपयोग करके सरल रखने जा रहा हूँ।
''' Instead of taking the whole screensize into account, I'm going to take a 640x480 resolution from the middle. This should make it faster but you can toy around depending on what works for you. You may, for example, want to take the outer edge colours instead so it the ambience blends to the outer edges and not the main screen colour ''' screen_width, screen_height = ImageGrab.grab().size #get the overall resolution size region_width = 640 region_height = 480 region_left = (screen_width - region_width) // 2 region_top = (screen_height - region_height) // 2 screen_region = (region_left, region_top, region_left + region_width, region_top + region_height) screenshot_memory = io.BytesIO(b"") # Method to get the dominant colour on screen. You can change this method to return whatever colour you like def get_dominant_colour() -> str: # Take a screenshot of the region specified earlier screenshot = ImageGrab.grab(screen_region) ''' The fast_colorthief library doesn't work directly with PIL images but we can use an in memory buffer (BytesIO) to store the picture This saves us writing then reading from the disk which is costly ''' # Save screenshot region to in-memory bytes buffer (instead of to disk) # Seeking and truncating fo performance rather than using "with" and creating/closing BytesIO object screenshot_memory.seek(0) screenshot_memory.truncate(0) screenshot.save(screenshot_memory, "PNG") # Get the dominant colour dominant_color = fast_colorthief.get_dominant_color(screenshot_memory, quality=1) # Return the colour in the form of hex (without the # prefix as our Bluetooth device doesn't use it) return '{:02x}{:02x}{:02x}'.format(*dominant_color)
कोड पर टिप्पणी की गई है, इसलिए उम्मीद है, यह स्पष्ट होना चाहिए कि क्या हो रहा है, लेकिन हम बीच से स्क्रीन का एक छोटा क्षेत्र ले रहे हैं और फिर उस क्षेत्र से प्रमुख रंग प्राप्त कर रहे हैं। मैं प्रदर्शन के लिए एक छोटा क्षेत्र ले रहा हूँ; कम पिक्सेल का विश्लेषण करने की आवश्यकता होगी।
हम बस पहुँच गए! अब हम जानते हैं कि इसे क्या भेजना है और कहां भेजना है। आइए इस चुनौती के अंतिम प्रमुख भाग को समाप्त करते हैं जो वास्तव में इसे भेजना है। सौभाग्य से, ब्लेक लाइब्रेरी के साथ, यह काफी सीधा है।
async def send_colour_to_device(client: BleakClient, uuid: str, value: str) -> None: #write to the characteristic we found, in the format that was obtained from the Bluetooth logs await client.write_gatt_char(uuid, bytes.fromhex(f"7e070503{value}10ef")) async def toggle_on(client: BleakClient, uuid: str) -> None: await client.write_gatt_char(uuid, bytes.fromhex(ON_HEX)) print("Turned on") async def toggle_off(client: BleakClient, uuid: str) -> None: await client.write_gatt_char(uuid, bytes.fromhex(OFF_HEX)) print("Turned off")
जैसा कि हमने लॉग से पता लगाया है, प्रत्येक रंग का एक निश्चित टेम्पलेट होता है, इसलिए हम सामान्य भाग को हार्डकोड करने के लिए एफ-स्ट्रिंग्स का उपयोग कर सकते हैं और बीच में मूल्य के लिए रंग का हेक्साडेसिमल पास कर सकते हैं। इसे हमारे पाश से बुलाया जा सकता है। ऑन और ऑफ में अद्वितीय हेक्साडेमिकल थे इसलिए मैंने अलग-अलग फ़ंक्शन बनाए और एक स्थिर मूल्य में पारित किया जिसमें प्रासंगिक हेक्स शामिल था।
while True: # send the dominant colour to the device await send_colour_to_device(client, characteristic_uuid, get_dominant_colour()) # allow a small amount of time before update time.sleep(0.1)
एंड देयर वी हैव इट; हमारी ब्लूटूथ एलईडी लाइट्स अब स्क्रीन पर रंगों द्वारा नियंत्रित होती हैं, जिससे हमारा अपना एम्बिएंट मॉनिटर बन जाता है।
आप गिटहब पर पूरा कोड देख सकते हैं, जिसमें थोड़ी मात्रा में इंफ्रास्ट्रक्चर कोड है जो इस पोस्ट के लिए विशिष्ट नहीं था। मैंने कोड को आत्म-व्याख्यात्मक होने के लिए टिप्पणी करने की कोशिश की है, लेकिन बेझिझक कोई प्रश्न पूछ सकता हूं या सुझाव दे सकता हूं।
उम्मीद है, यह आपको एक विचार देता है कि आप अपनी एलईडी लाइट्स के साथ रचनात्मक कैसे बनना शुरू कर सकते हैं।
यदि आपके पास कोई प्रतिक्रिया या प्रश्न हैं, तो नीचे टिप्पणी करने के लिए स्वतंत्र महसूस करें।
यहाँ भी प्रकाशित