發表文章

目前顯示的是 10月, 2013的文章

Bluez的藍牙配對工具程式

圖片
藍牙配對時常會困擾使用者,特別是一般的使用者。其實藍牙組織(Bluetooth SIG)也知道這個情況,所以配對的方式也有改善,以前的方式(legacy pairing, 藍牙2.0+EDR及之前)使用PIN Code,配對雙方的設備都要輸入相同的PIN Code,通常是4碼數字(規格書定義可到16位數數字)。兩個設備檢查所持有PIN Code是否相同,相同才會配對成功。但是一般使用者可能會按錯鍵,所以常常都要試很多次才會成功,對一般使用者來說經驗是不太好的。近來新的藍牙設備都已改用新的配對方式(secure simple pairing),兩個設備會先溝通一個passkey,通常是6位數的數字,然後兩個設備都會顯示這個數字,接著只要求使用者確認雙方數字是否相同即可。這樣使用者原本必須按10個鍵(4個PIN Code X 2 + 2次確認),現在只要按兩個鍵(確認鍵)就可以了。不但大量降低按錯的機會,也加快了配對的速度。 不過對於Linux的使用者來說,許多藍牙設備因為市場考量的關係,並不見得原生會支援Linux作業系統。例如,Logitech K810的鍵盤要和ubuntu配對時,就要自己費一點功夫 [1]  。這是因為設備廠商只會支援熱門的作業系統,這是很自然的事情;只是Linux系統近年來其實都有整合BlueZ這套藍牙管理程式,所以只要有依循藍牙規格書的設備,Linux就可以透過BlueZ來與之相連運作。反之,設備廠商也不需太費心專門為Linux系統做驅動,其設備就可以連上Linux系統。當然,專門做個驅動還是比較好的,會有助於使用經驗的提升。 BlueZ原生的配對工具,在Ubuntu中就是 [1] 提到的bluez-simple-agent這支程式,其實這是一支Python寫成的script,所以我們可以用more, cat, vi, gedit等指令直接看到它的內容。沒錯,它是命令列的指令用法,對大多數的使用者來說都是不易使用的。所以,其實在大部份的Linux套件中都會使用gnome-bluetooth [2] 之類的圖形界面工具。這樣一來,使用者只要點選按就可以了,自然接受度會好很多。不過,這些工具都只是界面改善(當然有些有加入其他功能),其實主要的配對工作,還是丟給BlueZ去做的。就像我在 [3] 那篇文章中提到一樣,其實只...

QtDBus Proxy 訪問遠端物件與回傳值 demarshall

在之前的文章 [1] 裡,我提到QtDBus在叫用DBus上的方法時,對輸入參數和輸出參數的資料型態必須做marshall和demarshall,而且有點不太容易。有些人會説,你只使用QDBusMessage來叫用方法以及接收回傳值,這不是Qt建議的作法!用QDBusMessage來做太低階了,所以參數的型態才要轉換的那麼辛苦。 因此,我要使用Qt建議的Proxy類别 [2] 做法來試試看,是不是比較容易一些。首先,之前討讑提到的輸入參數資料型態為object path時,必須自己使用QVariant::fromValue(object_path)將資料填入參數列中。使用Proxy類别做法,在使用qdbusxml2cpp工具産生需要的proxy類别後,我們可以很直觀的使用以下語法,將資料型態為QDBusObjectPath的變數,直接送入輸入參數資料型態為object path的方法中。 proxy.Method(object_path); 真是太好了,這様大家都輕鬆許多。 看一下qdbusxml2cpp工具産生的類别proxy程式,可以看到如下一段程式,原來是這個proxy類别幫我自動做了同様的轉換工作。 inline QDBusPendingReply<> Method(const QDBusObjectPath &device) { QList<QVariant> argumentList; argumentList << QVariant::fromValue(device) ; return asyncCallWithArgumentList(QLatin1String("Method"), argumentList); } 其實不管Qt是如何做到的,只要能減輕我們的工作就好了。 那麼複雜的參數型態呢?是不是也可以幫我們一點忙呢? 我們來看一下之前討讑的字典中有矩陣的問題,許多的DBus方法中,特别是取得屬性的方法,通常是叫做GetProperties(),它的回傳值都是一個字典(a{sv}),而且其中有一些值,其實是個矩陣。一様的問題,用Proxy類别的作法可以取得字典的回傳值。但我要取得其中一...

QtDBus marshall and demarshall

最近在寫Qt存取DBus服務的程式,才發現要對應DBus的資料型態到Qt的資料型態,必須花點功夫,所以在此筆記一下,以免日後忘記。 首先,若要叫用DBus服務上的一個方法,基本上最簡單的方式: // 建立一個要在D-Bus上傳遞的Message QDBusMessage m = QDBusMessage::createMethodCall("org.bluez", path, interface, method); //send message QDBusConnection::systemBus().send(m); 一開始,如果很幸運地,要叫用的方法沒有輸入參數也沒有回傳值,那只要使用以上方法就可以很容易地完成。但是如果需要輸入參數的話呢?在KDE TechBase有一篇文章 [1] 提到兩個寫法: 《寫法一》 // 建立一個要在D-Bus上傳遞的Message QDBusMessage m = QDBusMessage::createMethodCall("org.bluez", path, interface, method); QList args; args.append("kde.org"); m.setArguments(args); //send message QDBusConnection::systemBus().send(m);  《寫法二》 // 建立一個要在D-Bus上傳遞的Message QDBusMessage m = QDBusMessage::createMethodCall("org.bluez", path, interface, method); m << "kde.org"; //send message QDBusConnection::systemBus().send(m); Ok, 輸入參數的資料型態是字串的時候,這様也就够了。但是如果不是字串的話呢?那就很可能會讓人找半天也不知道如何寫。例如,輸入參數的資料型態為Object Path的話,就不是...