Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Siglo service #30

Merged
merged 25 commits into from
May 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python.formatting.provider": "black"
}
3 changes: 3 additions & 0 deletions data/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ install_data(join_paths('icons', 'org.gnome.siglo.svg'),
install_dir: join_paths(get_option('datadir'), 'icons')
)

install_data('siglo.service', install_dir: '/etc/systemd/user/')

appstream_file = i18n.merge_file(
input: 'org.gnome.siglo.appdata.xml.in',
output: 'org.gnome.siglo.appdata.xml',
Expand All @@ -43,3 +45,4 @@ if compile_schemas.found()
args: ['--strict', '--dry-run', meson.current_source_dir()]
)
endif

5 changes: 5 additions & 0 deletions data/siglo.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[Unit]
Description=siglo service
[Service]
ExecStart=siglo --daemon
Environment=PYTHONUNBUFFERED=1
2 changes: 1 addition & 1 deletion src/ble_dfu.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,4 @@ def step_nine(self):
def get_init_bin_array(self):
# Open the DAT file and create array of its contents
init_bin_array = array("B", open(self.datfile_path, "rb").read())
return init_bin_array
return init_bin_array
77 changes: 64 additions & 13 deletions src/bluetooth.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from os import sync
import gatt
import datetime
import struct
Expand Down Expand Up @@ -26,39 +27,60 @@ def get_current_time():


def get_default_adapter():
""" https://stackoverflow.com/a/49017827 """
"""https://stackoverflow.com/a/49017827"""
import dbus

bus = dbus.SystemBus()
try:
manager = dbus.Interface(bus.get_object('org.bluez', '/'),
'org.freedesktop.DBus.ObjectManager')
manager = dbus.Interface(
bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager"
)
except dbus.exceptions.DBusException:
raise BluetoothDisabled

for path, ifaces in manager.GetManagedObjects().items():
if ifaces.get('org.bluez.Adapter1') is None:
if ifaces.get("org.bluez.Adapter1") is None:
continue
return path.split('/')[-1]
return path.split("/")[-1]
raise NoAdapterFound


class InfiniTimeManager(gatt.DeviceManager):
def __init__(self):
self.conf = config()
self.device_set = set()
self.adapter_name = get_default_adapter()
self.alias = None
self.scan_result = False
if not self.conf.get_property("paired"):
self.scan_result = False
self.adapter_name = get_default_adapter()
self.conf.set_property("adapter", self.adapter_name)
else:
self.scan_result = True
self.adapter_name = self.conf.get_property("adapter")
self.mac_address = None
super().__init__(self.adapter_name)

def get_scan_result(self):
if self.conf.get_property("paired"):
self.scan_result = True
return self.scan_result

def get_device_set(self):
if self.conf.get_property("paired"):
self.device_set.add(self.conf.get_property("last_paired_device"))
return self.device_set

def get_adapter_name(self):
if self.conf.get_property("paired"):
return self.conf.get_property("adapter")
return get_default_adapter()

def set_mac_address(self, mac_address):
self.mac_address = mac_address

def get_mac_address(self):
if self.conf.get_property("paired"):
self.mac_address = self.conf.get_property("last_paired_device")
return self.mac_address

def set_timeout(self, timeout):
Expand All @@ -81,7 +103,12 @@ def scan_for_infinitime(self):


class InfiniTimeDevice(gatt.Device):
def connect(self):
def __init__(self, mac_address, manager):
self.conf = config()
super().__init__(mac_address, manager)

def connect(self, sync_time):
self.sync_time = sync_time
self.successful_connection = True
super().connect()

Expand All @@ -99,20 +126,44 @@ def disconnect_succeeded(self):
print("[%s] Disconnected" % (self.mac_address))

def characteristic_write_value_succeeded(self, characteristic):
self.disconnect()
if not self.conf.get_property("paired"):
self.disconnect()

def services_resolved(self):
super().services_resolved()
serv = next(
self.serv = next(
s for s in self.services if s.uuid == "00001805-0000-1000-8000-00805f9b34fb"
)
char = next(
self.char = next(
c
for c in serv.characteristics
for c in self.serv.characteristics
if c.uuid == "00002a2b-0000-1000-8000-00805f9b34fb"
)

char.write_value(get_current_time())
self.alert_service = next(
a for a in self.services if a.uuid == "00001811-0000-1000-8000-00805f9b34fb"
)

self.new_alert_characteristic = next(
n
for n in self.alert_service.characteristics
if n.uuid == "00002a46-0000-1000-8000-00805f9b34fb"
)

if self.sync_time:
self.char.write_value(get_current_time())

def send_notification(self, alert_dict):
message = alert_dict["message"]
arr = bytearray(message, "utf-8")
# self.new_alert_characteristic.write_value(
# b" Reports of my death were greatly exaggerated. So how was your day?"
# )
self.new_alert_characteristic.write_value(arr)


class BluetoothDisabled(Exception):
pass


class BluetoothDisabled(Exception):
Expand Down
17 changes: 13 additions & 4 deletions src/config.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import configparser
import xdg.BaseDirectory
import distutils
import distutils.util
from pathlib import Path


class config:
# Class constants
default_config = {"mode": "singleton", "deploy_type": "quick"}
default_config = {
"mode": "singleton",
"deploy_type": "quick",
"last_paired_device": "None",
"paired": "False",
"adapter": "None"
}
config_dir = xdg.BaseDirectory.xdg_config_home
config_file = config_dir + "/siglo.ini"

Expand Down Expand Up @@ -33,13 +41,14 @@ def file_valid(self):
def get_property(self, key):
config = configparser.ConfigParser()
config.read(self.config_file)
return config["settings"][key]
prop = config["settings"][key]
if key == "paired":
prop = bool(distutils.util.strtobool(prop))
return prop

def set_property(self, key, val):
config = configparser.ConfigParser()
config.read(self.config_file)
config["settings"][key] = val
with open(self.config_file, "w") as f:
config.write(f)


37 changes: 37 additions & 0 deletions src/daemon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import gatt

import gi.repository.GLib as glib
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from .bluetooth import InfiniTimeManager, InfiniTimeDevice, NoAdapterFound
from .config import config


class daemon:
def __init__(self):
self.conf = config()
self.manager = InfiniTimeManager()
self.device = InfiniTimeDevice(manager=self.manager, mac_address=self.conf.get_property("last_paired_device"))
self.device.connect(sync_time=False)

def scan_for_notifications(self):
DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
bus.add_match_string_non_blocking(
"eavesdrop=true, interface='org.freedesktop.Notifications', member='Notify'"
)
bus.add_message_filter(self.notifications)
mainloop = glib.MainLoop()
mainloop.run()

def notifications(self, bus, message):
alert_dict = {}
for arg in message.get_args_list():
if isinstance(arg, dbus.Dictionary):
if arg["desktop-entry"] == "sm.puri.Chatty":
alert_dict["category"] = "SMS"
alert_dict["sender"] = message.get_args_list()[3]
alert_dict["message"] = " " + message.get_args_list()[4]
alert_dict_empty = not alert_dict
if len(alert_dict) > 0:
self.device.send_notification(alert_dict)
2 changes: 1 addition & 1 deletion src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ def gtk_style():

gtk_style()
app = Application()
return app.run(sys.argv)
return app.run(sys.argv)
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ configure_file(

siglo_sources = [
'__init__.py',
'daemon.py',
'quick_deploy.py',
'main.py',
'config.py',
Expand Down
27 changes: 20 additions & 7 deletions src/siglo.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import os
import sys
import signal
import gettext
import argparse

VERSION = '@VERSION@'
pkgdatadir = '@pkgdatadir@'
Expand All @@ -14,12 +15,24 @@ sys.path.insert(1, pkgdatadir)
signal.signal(signal.SIGINT, signal.SIG_DFL)
gettext.install('siglo', localedir)

if __name__ == '__main__':
import gi
def main():
p = argparse.ArgumentParser(description="app to sync InfiniTime watch")
p.add_argument('--daemon', '-d', required=False, action='store_true', help="run as a service")
args = p.parse_args()

if args.daemon:
from siglo import daemon
d = daemon.daemon()
d.scan_for_notifications()
else:
import gi

from gi.repository import Gio
resource = Gio.Resource.load(os.path.join(pkgdatadir, 'siglo.gresource'))
resource._register()
from gi.repository import Gio
resource = Gio.Resource.load(os.path.join(pkgdatadir, 'siglo.gresource'))
resource._register()

from siglo import main
sys.exit(main.main(VERSION))
from siglo import main
sys.exit(main.main(VERSION))

if __name__ == '__main__':
main()
Loading