Ambient TV'lere aşina olmayanlar için bu, daha sürükleyici bir deneyim sağlamak amacıyla TV ekranının kenarından ve yakın çevresinden atlamayı yumuşatmanın bir yoludur. Ortalıkta bazı LED ışıklar vardı ve ışıkları kodla kontrol etmenin mümkün olup olmadığını görmeye ve bilgisayar ekranımı bir ortam monitörü haline getirmeye karar verdim. Monitörüm için kullanmak istesem de, ışıklarınızın sahip olabileceği ses reaksiyonları veya rastgele desenler gibi diğer özellikler de dahil olmak üzere, gönderebileceğiniz her yerde ve hangi renklerle kullanılabilir. Daha önceki bir monitörde kullandığım için bu yazıyı bir süredir yazmayı planlıyordum, ancak yeni monitörüme eklemeyi bir türlü başaramadım, bu yüzden bu yazıyı bulabilecek herkes için ilerledikçe belgeledim. faydalıdır. O halde hadi konuya geçelim! (LED ışıkların muhtemelen Bluetooth Düşük Enerji (BLE) olacağını, dolayısıyla onlarla etkileşim kurabilmek için bilgisayarınızın BLE'yi desteklemesi gerektiğini lütfen unutmayın). Kodun tamamı GitHub'da .
Yapmamız gereken ilk adım, ışıklarla birlikte gelen uygulamanın beklendiği gibi çalıştığından emin olmaktır. Bu, ışığın orijinal uygulamasını çalıştırarak ve uygulamanızda bastığınız açma/kapama/aydınlatma düğmelerine bağlı olarak ışıkların buna göre tepki vermesini sağlayarak kolayca test edilebilir. Bunu yapıyoruz çünkü kısa bir süre sonra ışıkların üzerindeki Bluetooth alıcısına gönderilen belirli kodlara basıp tespit edeceğiz.
Benim uygulayabileceğim iki yaklaşım var. Bunlardan biri, uygulamanın JAR dosyasını kaynak koda dönüştürmek ve gönderilen kodları bulmaktı, ancak Bluetooth protokolü hakkında daha fazla bilgi edinmek istediğimden, tüm Bluetooth etkinliğini Android cihazıma kaydetmeyi ve oradan çıkarmayı seçtim. İşte nasıl:
Android cihazınızda Geliştirici Seçeneklerini etkinleştirin.
Bluetooth HCI gözetleme günlüğünü etkinleştirin (HCI, Ana Bilgisayar Denetleyici Arayüzü anlamına gelir). Bu seçeneği Ayarlar > Sistem > Geliştirici bölümünde bulabilir veya aşağıdaki görüntüdeki gibi ayarlarda arayabilirsiniz.
Artık her eylemin ışığın Bluetooth alıcısına ne gönderdiğini tanımlayabilmemiz için belirli eylemler gerçekleştirmemiz gerekiyor. Bu sırayla Açık/Kırmızı/Yeşil/Mavi/Kapalı olarak basit tutacağım, ancak ışıklarınız diğer özellikleri destekliyorsa, bunlarla da oynayabilirsiniz.
Uygulamayı çalıştırın ve Açık, Kırmızı, Yeşil, Mavi ve Kapalı tuşlarına basın. Cihazınızda çok fazla Bluetooth etkinliği varsa filtrelemeyi kolaylaştırmak için yaklaşık süreye dikkat etmeniz de yararlı olabilir.
Daha fazla gürültü duymamak için Bluetooth'u kapatın. Sonraki adımlarda Bluetooth komutlarını analiz edeceğiz ve bastığımız sırayı bildiğimiz için hangi tuşa bastığımıza hangi değerlerin karşılık geldiğini bulabiliriz.
Artık telefondaki Bluetooth kayıtlarına erişmemiz gerekiyor. Bunu yapmanın birkaç yolu var, ancak bir hata raporu oluşturup dışa aktaracağım. Bunu yapmak için telefonun Ayarlar bölümünde USB Hata Ayıklamayı etkinleştirin, telefonu bilgisayara bağlayın ve adb.exe komut satırı aracını kullanın.
adb bugreport led_bluetooth_report
Bu, bilgisayarınızın yerel dizininde “ led_bluetooth_report.zip ” dosya adına sahip bir zip dosyası oluşturacaktır. İsterseniz bir yol belirleyebilirsiniz (örn. C:\MyPath\led_bluetooth_report")
Bu zip'in içinde ihtiyacımız olan günlükler var. Bu, cihazdan cihaza değişiklik gösterebilir (cihazınızda başka bir yerde bulduysanız lütfen yorum yapın). Google Pixel telefonumda FS\data\misc\bluetooth\logs\btsnoop_hci.log konumundaydı
Artık günlük dosyalarımız var, onları analiz edelim! Bunu yapmak için Wireshark kullanmaya karar verdim, bu yüzden Wireshark'ı başlatın ve Dosya...Aç... seçeneğine gidin ve btsnoop_hci günlük dosyasını seçin.
Her ne kadar göz korkutucu görünse de, Wireshark kaynak kodundaki Öznitelik Protokolü olan 0x0004 üzerindeki BTL2CAP'yi filtreleyerek aradığımız şeyi bulmamızı kolaylaştıralım. Öznitelik protokolü, iki BLE cihazının birbiriyle konuşma şeklini tanımlar; dolayısıyla uygulamanın ışıklarla nasıl konuştuğunu bulmamıza yardımcı olmak için ihtiyacımız olan şey budur. Wireshark'ta üst kısımdaki “ Ekran filtresi uygula ” çubuğuna btl2cap.cid == 0x0004 yazıp Enter tuşuna basarak logları filtreleyebilirsiniz.
Artık günlüğü filtreledik; komutların aranmasını kolaylaştırmalıdır. Zaman damgalarına bakabiliriz (Yanlış formattaysa saati dönüştürmek için Görünüm…Saat Görüntüleme Formatı…Günün Saati seçeneğine gidin). Işıklara bir değer gönderdiğimiz kayıtlar olduğu için Gönderilen Yazma Komutu kayıtlarına bakmak istiyoruz. En son zamanınızın en altta olduğunu varsayarak son beş etkinliğe doğru ilerleyin. Bunlar sırasıyla Açık, Kırmızı, Yeşil, Mavi ve Kapalı olmalıdır; Kapalı sonuncu olmalıdır.
Hedef BD_ADDR'yi not edin, çünkü buna kısa süre sonra ihtiyacımız olacak ve Sherlock Holmes şapkanızı takın, çünkü burası, renklerin ve açma/kapama komutlarının mesaj içinde nasıl kodlandığına ilişkin desenin kilidini açmamız gereken yerdir. Bu, ışık üreticisine bağlı olarak değişecektir ancak cihazım için aldığım değerlerin listesi:
Bunlar açıkça onaltılık değerlerdir ve dikkatli bakarsanız bazı sabit kalıpların olduğunu görürsünüz. Desenleri bölelim, çünkü bu işleri daha net hale getirecektir.
Saf kırmızı, yeşil ve mavinin onaltılık değerlerine aşina olanlar için değerlerin sırasıyla #FF000, #00FF00 ve #0000FF olduğunu bileceksiniz; bu da tam olarak yukarıda görebildiğimiz gibi. Bu, artık renkleri istediğimiz şekilde değiştirecek formatı bildiğimiz anlamına geliyor! (veya en azından ışıkların kendilerinin neler yapabileceğine göre). Açık ve Kapalı'nın renklerden farklı bir formata sahip olduğunu ve birbirine benzer olduğunu da görebiliriz; Açık'ta f00001 ve Kapalı'da 00000 bulunur.
Bu kadar! Artık kodlamaya ve ışıklarla etkileşime geçmeye başlamak için yeterli bilgiye sahibiz.
İhtiyacımız olan üç temel şey var:
Cihazın adresi (yukarıdaki Hedef BD_ADDR'dir)
Cihaza gönderilecek değerler (yukarıda elde edilen onaltılık değerler)
Değiştirmek istediğimiz özellik. Bluetooth LE özelliği, esas olarak bir ana bilgisayar ile istemci Bluetooth aygıtları arasında gönderilebilecek verileri tanımlayan bir veri yapısıdır. Işıkları ifade eden karakteristiği (16 bit veya 128 bit UUID) bulmamız gerekiyor. Burada bulunabilecek bazı yaygın olarak kullanılan atanmış numaralar vardır ancak cihaz bunlara uymuyorsa özel bir UUID kullanıyor olabilirler. Işıklarım atanan numaralar listesinde olmadığından kodla bulalım.
Python 3.10 ve Kasvetli 0.20.1 kullanıyorum. Bilgisayarınızdaki Bluetooth'un açık olduğundan emin olun (cihazla eşleştirmenize gerek yoktur, kod aracılığıyla ona bağlanacağız).
# 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)
Kod hakkında yorum yaptım, bu yüzden kendini açıklayıcı olmalı ama esasen ışıklara bağlanıyoruz ve ortaya çıkardığı tüm özellikleri buluyoruz. Çıktım şuydu:
Karakteristik: 00002a00-0000-1000-8000-00805f9b34fb Karakteristik: 00002a01-0000-1000-8000-00805f9b34fb Karakteristik: 0000fff3-0000-1000-8000-00805f9b34fb Karakteristik: 0000fff4-0000-1000-8000-00805f9b34fb
İlk iki UUID'nin hızlı bir Google'ı, bunun bizim için alakasız olan hizmetin adı ve görünümüne atıfta bulunduğunu gösterir. Bununla birlikte, bu sayfaya göre üçüncü ( 0000fff3-0000-1000-8000-00805f9b34fb ) yazma özelliği olduğundan üçüncü ve dördüncü en uygunu gibi görünmektedir . Mükemmel, artık bu özel cihazın bir değerle (onaltılık renk) yazması için ihtiyacımız olan özelliğe sahibiz.
Sonunda ihtiyacımız olan tüm parçalara sahibiz. Bu aşamada hangi renk girişini kullanmak istediğiniz konusunda yaratıcı olabilirsiniz. Örneğin, portföyünüzün performansına göre renkleri değiştirmek için ışıkları bir ticaret piyasası API'sine bağlayabilirsiniz. Bu durumda, monitörlerimizi ortama duyarlı hale getirmek istiyoruz, bu nedenle ekranın baskın rengini elde edip bunu göndermemiz gerekiyor.
Bunu yapmanın birçok yolu vardır, bu nedenle istediğiniz algoritmaları denemekten çekinmeyin. En basit yaklaşımlardan biri, ekrandaki her X piksel sayısını yinelemek ve ortalamayı almak olacaktır; daha karmaşık çözümler ise insan gözünün algıladığı renkleri daha baskın olarak arar. Paylaşmak istediğiniz bulgular hakkında yorum yapmaktan çekinmeyin!
Bu blog yazısının hatırı için, fast_colorthief kütüphanesinin get_dominant_color yöntemini kullanarak konuyu basit tutacağım.
''' 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)
Kod yorumlanmıştır, dolayısıyla ne olduğu açık olmalıdır, ancak ekranın ortasından daha küçük bir bölgeyi alıyoruz ve ardından o bölgeden baskın rengi alıyoruz. Daha küçük bir bölgeyi almamın nedeni performanstır; daha az pikselin analiz edilmesi gerekir.
Neredeyse geldik! Artık ne göndereceğimizi, nereye göndereceğimizi biliyoruz. Bu mücadelenin son büyük kısmı olan onu gerçekten göndermek olan bitirelim. Neyse ki, Bleak kütüphanesinde bu oldukça basittir.
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")
Günlüklerden öğrendiğimiz gibi, her rengin sabit bir şablonu vardır, bu nedenle ortak kısmı sabit kodlamak için f dizelerini kullanabiliriz ve ortadaki değer için basitçe bir rengin onaltılı sayısını iletebiliriz. Bu bizim döngümüzden çağrılabilir. Açık ve Kapalı'nın benzersiz onaltılık değerleri vardı, bu yüzden ayrı ayrı işlevler oluşturdum ve ilgili onaltılığı içeren sabit bir değer aktardım.
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)
Ve işte elimizde; Bluetooth LED ışıklarımız artık ekrandaki renklerle kontrol ediliyor ve kendi Ortam Monitörümüzü oluşturuyor.
Bu yazıya özel olmayan az miktarda altyapı kodu içeren kodun tamamını GitHub'da görebilirsiniz. Kodu kendi kendini açıklayıcı olacak şekilde yorumlamaya çalıştım ancak herhangi bir soru sormaktan veya öneride bulunmaktan çekinmeyin.
Umarız bu size LED ışıklarınızla nasıl yaratıcı olmaya başlayabileceğiniz konusunda bir fikir verir.
Herhangi bir geri bildiriminiz veya sorunuz varsa aşağıya yorum yapmaktan çekinmeyin.
Burada Ayrıca Yayınlandı