diff options
| author | Po-Hsu Lin <po-hsu.lin@canonical.com> | 2016-03-17 18:36:06 +0800 |
|---|---|---|
| committer | Po-Hsu Lin <po-hsu.lin@canonical.com> | 2016-03-17 18:36:06 +0800 |
| commit | c12ded134f8fe2546721f5658bd4508a88602986 (patch) | |
| tree | 0635277dfaebba1391da882a904674c923754c02 | |
| parent | 56b25733f084bbfef3bca9f18829dbc94b5b44a2 (diff) | |
Add scanning feature and improve the keyboard test case.
Add scanning feature and class code dictionary to determine which device to connect. Improve the keyboard test case.
| -rwxr-xr-x | bin/bt_connect | 105 | ||||
| -rw-r--r-- | jobs/bluetooth.txt.in | 24 |
2 files changed, 77 insertions, 52 deletions
diff --git a/bin/bt_connect b/bin/bt_connect index 51373b0..d70462b 100755 --- a/bin/bt_connect +++ b/bin/bt_connect @@ -1,28 +1,46 @@ #!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# This file is part of Checkbox. +# +# Copyright 2016 Canonical Ltd. +# +# Authors: +# Po-Hsu Lin <po-hsu.lin@canonical.com> +# Yung Shen <yung.shen@canonical.com> +# +# Checkbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, +# as published by the Free Software Foundation. +# +# Checkbox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Checkbox. If not, see <http://www.gnu.org/licenses/>. + # possibility to lockup, if it times out -# TODO: 1. OK - python -> python3 -# 2. OK - asychronous run with GLib (gobject not supported with python3) -# 3. mouse/kb class code -# 4. INPROGRESS - scan feature -# 5. better exception handling (wrong PIN, authentication rejected) +# TODO: 5. better exception handling (wrong PIN, authentication rejected) # 6. different PIN selection # 7. MAC address validator +# 8. Use logging for information +# 9. PEP8 try: from gi.repository import GObject except ImportError: import gobject as GObject import time -import pdb import dbus import dbus.service from dbus.mainloop.glib import DBusGMainLoop -#from gi.repository import GLib from argparse import ArgumentParser PIN = '0000' +CLASS_CODE = {'mouse': [0x580, 0x2580], 'keyboard': [0x540, 0x2540]} mainloop = GObject.MainLoop() -#mainloop = GLib.MainLoop() class Rejected(dbus.DBusException): @@ -53,8 +71,9 @@ class Agent(dbus.service.Object): @dbus.service.method("org.bluez.Agent", in_signature="o", out_signature="s") def RequestPinCode(self, device): - print("RequestPinCode {}".format(device)) - print("Sending {}".format(PIN)) + print("Sending PIN: {} to your device.".format(PIN)) + if TARGET is not 'mouse': + print("For keyboard, please type this PIN on it and hit Enter.") # need to figure out how to send 0000 / 1111 / 1234 return PIN # return raw_input("Enter PIN Code: ") @@ -69,7 +88,7 @@ class Agent(dbus.service.Object): @dbus.service.method("org.bluez.Agent", in_signature="ou", out_signature="") def DisplayPasskey(self, device, passkey): - print("DisplayPasskey {}, {}".format(device, passkey)) + print("Please enter the passkey: {} on your device".format(passkey)) @dbus.service.method("org.bluez.Agent", in_signature="ou", out_signature="") @@ -101,38 +120,45 @@ def create_device_reply(device): def create_device_error(error): - print("Creating device failed: {}".format(error)) + if error._dbus_error_name == 'org.bluez.Error.AuthenticationFailed': + print("ERROR: Passcode Authentication Failed, wrong passcode?") + else: + print("Creating device failed: {}".format(error)) mainloop.quit() def property_changed(name, value): - '''handler function for "PropertyChanged" signal''' + """handler function for "PropertyChanged" signal.""" if (name == "Discovering" and not value): mainloop.quit() def device_found(address, properties): - '''handler function for "DeviceFound" signal''' -# print("Name: {}".format(properties['Name'])) - print("MAC: {}\tClass: {}".format(properties['Address'], hex(properties['Class']))) + global DEVICE_MAC + """handler function for "DeviceFound" signal.""" + if properties['Class'] in CLASS_CODE[TARGET]: + print("Device found: {}".format(properties['Name'])) + print("MAC address: {}".format(properties['Address'])) + DEVICE_MAC = properties['Address'] -#def device_found(sender=None): -# print("got signal from {}".format(sender)) def main(): """Add argument parser here and do most of the job.""" - parser = ArgumentParser(description="Bluetooth auto paring and connect. You must select one option.") + global TARGET + global DEVICE_MAC + DEVICE_MAC = None + parser = ArgumentParser(description="Bluetooth auto paring and connect. Please select one option.") group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--mac", type=str, - help="Connect to an assigned MAC, not using auto scan result") - group.add_argument("--mouse", action="store_true", - help="Pair with any mouse found from scan result") - group.add_argument("--keyboard", action="store_true", - help="Pair with any keyboard found from scan result") - + help="Pair with a given MAC, not using scan result,") + group.add_argument("--mouse", action="store_const", + const="mouse", dest='target', + help="Pair with the last mouse found from scan result.") + group.add_argument("--keyboard", action="store_const", + const="keyboard", dest='target', + help="Pair with the last keyboard found from scan result.") parser.add_argument("-i", "--interface", type=str, help="Device interface, e.g. hci0") - # from the original code parser.add_argument("-c", "--capability", type=str, default="DisplayYesNo") args = parser.parse_args() @@ -140,7 +166,6 @@ def main(): bus = dbus.SystemBus() manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager") - if args.interface: path = manager.FindAdapter(args.interface) else: @@ -153,33 +178,33 @@ def main(): agent = Agent(bus, path) if not args.mac: # Activate scan and auto pairing + TARGET = args.target + print("Trying to scan and pair with a {}.".format(TARGET)) bus.add_signal_receiver(device_found, signal_name="DeviceFound", dbus_interface="org.bluez.Adapter") bus.add_signal_receiver(property_changed, - signal_name = "PropertyChanged", - dbus_interface= "org.bluez.Adapter") + signal_name="PropertyChanged", + dbus_interface="org.bluez.Adapter") adapter.StartDiscovery() mainloop.run() -# device_mac = + adapter.StopDiscovery() + if not DEVICE_MAC: + print("ERROR: No pairable device found, terminating") + return 1 else: - device_mac = args.mac + DEVICE_MAC = args.mac # Try to remove the Device entry if exist try: - device = adapter.FindDevice(device_mac) + device = adapter.FindDevice(DEVICE_MAC) print("Device already exist, remove it first") adapter.RemoveDevice(device) except dbus.exceptions.DBusException: print("Creating device entry") -# for item in adapter.ListDevices(): -# if args[1].replace(':','_') in item: -# print("Device Already Exist, remove it first") -# device = adapter.FindDevice(args[1]) -# adapter.RemoveDevice(device) agent.set_exit_on_release(False) print("Paring device") - adapter.CreatePairedDevice(device_mac, path, args.capability, + adapter.CreatePairedDevice(DEVICE_MAC, path, args.capability, reply_handler=create_device_reply, error_handler=create_device_error) @@ -187,12 +212,10 @@ def main(): time.sleep(3) print("Connecting device...") - device = adapter.FindDevice(device_mac) + device = adapter.FindDevice(DEVICE_MAC) hid = dbus.Interface(bus.get_object("org.bluez", device), "org.bluez.Input") hid.Connect() -# adapter.UnregisterAgent(path) -# print("Agent unregistered") if __name__ == "__main__": main() diff --git a/jobs/bluetooth.txt.in b/jobs/bluetooth.txt.in index 76f60d0..82e925d 100644 --- a/jobs/bluetooth.txt.in +++ b/jobs/bluetooth.txt.in @@ -168,9 +168,11 @@ plugin: user-interact-verify category_id: 2013.com.canonical.plainbox::bluetooth id: bluetooth4/HOGP-mouse depends: bluetooth/detect-output -requires: manifest.has_bt_smart == 'True' +requires: + manifest.has_bt_smart == 'True' + package.name == 'zenity' estimated_duration: 30.0 -command: bt_connect --mac `zenity --entry` +command: bt_connect --mac `zenity --entry --title="device MAC" --text="Please enter the MAC address for testing"` _description: PURPOSE: This test will check that you can use a HID Over GATT Profile (HOGP) with your Bluetooth Smart mouse. @@ -186,18 +188,18 @@ plugin: user-interact-verify category_id: 2013.com.canonical.plainbox::bluetooth id: bluetooth4/HOGP-keyboard depends: bluetooth/detect-output -requires: manifest.has_bt_smart == 'True' +requires: + manifest.has_bt_smart == 'True' + package.name == 'zenity' estimated_duration: 30.0 -command: keyboard_test +command: bt_connect --mac `zenity --entry --title="device MAC" --text="Please enter the MAC address for testing"` && keyboard_test _description: PURPOSE: This test will check that you can use a HID Over GATT Profile (HOGP) with your Bluetooth Smart keyboard. STEPS: - 1. Enable either a Bluetooth Smart keyboard. - 2. Click on the bluetooth icon in the menu bar - 3. Select 'Setup new device' - 4. Look for the device in the list and select it - 5. For mice, perform actions such as moving the pointer, right and left button clicks and double clicks - 6. For keyboards, commence the test to launch a small tool. Enter some text into the tool and close it. + 1. Enable a Bluetooth Smart keyboard, and put it into paring mode. + 2. Use "hcitool scan" command in another terminal to get the MAC address of it. + 3. Commence the test to do the auto-pairing, you will be asked to enter the MAC address and PIN code. + 4. After it's paired and connected, enter some text with your keyboard and close the small input test tool. VERIFICATION: - Did the device work as expected? + Did the Bluetooth Smart keyboard work as expected? |
