+++ /dev/null
-#!/usr/bin/env python3
-
-import dbus
-import json
-import os
-import subprocess
-import sys
-import tempfile
-import time
-
-"""
-Instructions!
-1. Pair your bluetooth device, use bluetoothctl
-2. Use 'sdptool search DUN' to find the bluetooth channel
-3. Save your configuration to ~/.config/bt-dun-connect.json
-4. Run bt-dun-connect
-
-
-Example configuration:
-{
- "apn": "internet",
- "bluetooth_addr": "DE:AD:BE:EE:EE:EF",
- "bluetooth_channel": "22"
-}
-
-"""
-
-
-class DiallerException(Exception):
- pass
-
-class BluetoothDialler(object):
- def __init__(self, rfcomm_id, bt_addr, bt_channel, apn):
- self.rfcomm_id = rfcomm_id
- self.bt_addr = bt_addr
- self.bt_channel = bt_channel
- self.apn = apn
-
- self.rfcomm = None
- self.wvdial = None
- self.wvdial_conf_name = None
- self.dbus_system = None
-
- def release(self):
- if self.wvdial:
- try:
- self.wvdial.terminate()
- self.wvdial.wait()
- except Exception as e:
- print(e)
-
- if self.rfcomm:
- try:
- self.rfcomm.terminate()
- self.rfcomm.wait()
- except Exception as e:
- print(e)
-
- if self.wvdial_conf_name:
- try:
- os.unlink(self.wvdial_conf_name)
- except Exception as e:
- print(e)
-
- try:
- reset_rfcomm(self.rfcomm_id)
- except Exception as e:
- print(e)
-
- if self.dbus_system:
- try:
- self.disconnect_bluetooth()
- except Exception as e:
- print(e)
-
-
- def setup_dbus(self):
- self.dbus_system = dbus.SystemBus()
-
- def enable_bluetooth(self):
- bluez = self.dbus_system.get_object("org.bluez", "/org/bluez/hci0")
- iprops = dbus.Interface(bluez, "org.freedesktop.DBus.Properties")
- iprops.Set("org.bluez.Adapter1", "Powered", True)
-
- def disconnect_bluetooth(self):
- path = self.bt_addr.upper().replace(":", "_")
- bluez_dev = self.dbus_system.get_object("org.bluez", "/org/bluez/hci0/dev_" + path)
- idev = dbus.Interface(bluez_dev, "org.bluez.Device1")
- idev.Disconnect()
-
- def connect_rfcomm(self):
- self.rfcomm = subprocess.Popen([
- "rfcomm",
- "connect",
- self.rfcomm_id,
- self.bt_addr,
- self.bt_channel,
- ])
-
- # poll until connected
- start = time.time()
- while time.time() - start < 10:
- if self.is_rfcomm_connected():
- return
- time.sleep(0.1)
- raise DiallerException("Timeout connecting rfcomm")
-
- def is_rfcomm_connected(self):
- output = subprocess.check_output(["rfcomm", "-a"])
- for line in output.decode("ascii").split("\n"):
- if not line.startswith("rfcomm%s:" % self.rfcomm_id):
- continue
- if line.find(" connected ") >= 0:
- return True
- return False
-
- def write_wvdial_conf(self):
- fd, self.wvdial_conf_name = tempfile.mkstemp()
- f = os.fdopen(fd, "w")
- f.write("""
-[Dialer Defaults]
-Modem = /dev/rfcomm0
-Baud = 115200
-Init = ATZ
-Init2 = AT+CGDCONT=1,"IP","%s"
-Phone = *99#
-Username = dummy
-Password = dummy
-""" % self.apn)
- f.close()
-
- def connect_wvdial(self):
- self.wvdial = subprocess.Popen([
- "wvdial", "-C", self.wvdial_conf_name
- ])
- self.wvdial.wait()
-
-
- def run(self):
- try:
- self.setup_dbus()
-
- print("Enabling bluetooth...")
- self.enable_bluetooth()
-
- print("Connecting rfcomm...")
- self.connect_rfcomm()
- self.write_wvdial_conf()
-
- print("Dialling...")
- self.connect_wvdial()
-
- except KeyboardInterrupt as e:
- print("Exiting...")
- except DiallerException as e:
- print(e)
- finally:
- self.release()
-
-
-def get_next_rfcomm_id():
- # for now always use rfcomm0
- reset_rfcomm("all")
- return "0"
-
-def reset_rfcomm(rfcomm_id):
- subprocess.call(["rfcomm", "release", rfcomm_id], stderr=open("/dev/null"))
-
-def read_config(filename):
- try:
- config = open(os.path.expanduser(filename))
- except OSError as e:
- print("Failed to open config file: %s" % e)
- sys.exit(1)
-
- try:
- return json.load(config)
- except ValueError as e:
- print("Failed to parse config file %s: %s" % (filename, e))
- sys.exit(1)
-
-
-def main():
- rfcomm_id = get_next_rfcomm_id()
- config = read_config("~/.config/bt-dun-connect.json")
- dialler = BluetoothDialler(
- rfcomm_id=rfcomm_id,
- bt_addr=config["bluetooth_addr"],
- bt_channel=config["bluetooth_channel"],
- apn=config["apn"],
- )
- dialler.run()
-
-
-if __name__ == "__main__":
- main()
-
-
-