diff --git a/README.rst b/README.rst index afef113..1051621 100644 --- a/README.rst +++ b/README.rst @@ -149,6 +149,10 @@ simulator: :alt: Simple always-on demo for showing off wasp-os at conferences and shows :width: 179 +.. image:: res/DisaBLEApp.png + :alt: Small application for disabling bluetooth to save power and enhance security + :width: 179 + .. image:: res/HeartApp.png :alt: Heart rate application running on the wasp-os simulator :width: 179 diff --git a/docs/apps.rst b/docs/apps.rst index 99ec0fc..74dca13 100644 --- a/docs/apps.rst +++ b/docs/apps.rst @@ -47,6 +47,8 @@ Applications .. automodule:: apps.demo +.. automodule:: apps.disaBLE + .. automodule:: apps.flashlight .. automodule:: apps.haiku diff --git a/res/DisaBLEApp.png b/res/DisaBLEApp.png new file mode 100644 index 0000000..2530187 Binary files /dev/null and b/res/DisaBLEApp.png differ diff --git a/res/disaBLE_icon.png b/res/disaBLE_icon.png new file mode 100644 index 0000000..1446293 Binary files /dev/null and b/res/disaBLE_icon.png differ diff --git a/wasp/apps/disaBLE.py b/wasp/apps/disaBLE.py new file mode 100644 index 0000000..4293eed --- /dev/null +++ b/wasp/apps/disaBLE.py @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2021 Francesco Gazzetta + +"""DisaBLE +~~~~~~~~~~ + +Disable BLE to save energy and enhance privacy. + +This app shows the bluetooth status and provides a button to disable/enable it. +Unfortunately, re-enabling bluetooth normally has some issues, so as a +workaround the "enable" button restarts the watch. + +.. figure:: res/DisaBLEApp.png + :width: 179 +""" + +import wasp +import widgets +import ble + +class DisaBLEApp(): + NAME = 'DisaBLE' + # 1-bit RLE, 96x64, generated from res/disaBLE_icon.png, 167 bytes + ICON = ( + 96, 64, + b'\xff\x00\xff\x00\xff\x00\xff\x00g\x02]\x03\\\x03\\\x03' + b'\\\x03J\x01\x11\x03K\x02\x0f\x03L\x03\r\x03M\x04' + b'\x0b\x03N\x05\t\x03O\x06\x07\x03P\x07\x05\x03Q\x03' + b'\x01\x04\x03\x03L\x02\x04\x03\x02\x04\x01\x03L\x04\x03\x03' + b'\x03\x06N\x04\x02\x03\x02\x06P\x04\x01\x03\x01\x06R\r' + b'T\x0bV\tX\x07Y\x06Y\x07X\tV\x0bT\x08' + b'\x01\x04R\t\x02\x04P\x06\x01\x03\x03\x04P\x04\x02\x03' + b'\x02\x04Q\x03\x03\x03\x01\x04Q\x03\x04\x07Q\x03\x05\x06' + b'Q\x03\x06\x05Q\x03\x07\x04Q\x03\x08\x03Q\x03\t\x02' + b'Q\x03\n\x01Q\x03\\\x03\\\x03\\\x03]\x02\xff\x00' + b'\xff\x00\xff\x00\xff\x00g' + ) + + + def __init__(self): + self._btn = widgets.Button(10, 120, 220, 80, 'Disable' if ble.enabled() else 'Reboot to enable') + + def foreground(self): + self._draw() + wasp.system.request_event(wasp.EventMask.TOUCH) + + def _draw(self): + draw = wasp.watch.drawable + draw.set_color(wasp.system.theme('bright')) + draw.fill() + draw.string('BLE status: ' + ('ON' if ble.enabled() else 'OFF'), 0, 60, width=240) + self._btn.draw() + + def touch(self, event): + if self._btn.touch(event): + if ble.enabled(): + ble.disable() + self._btn = widgets.Button(10, 120, 220, 80, 'Reboot to enable') + self._draw() + else: + wasp.machine.reset() diff --git a/wasp/apps/software.py b/wasp/apps/software.py index 7ae3094..7ee1461 100644 --- a/wasp/apps/software.py +++ b/wasp/apps/software.py @@ -41,6 +41,7 @@ class SoftwareApp(): db = [] db.append(('alarm', factory('Alarm'))) db.append(('calc', factory('Calculator'))) + db.append(('disaBLE', factory('DisaBLE'))) db.append(('faces', factory('Faces'))) db.append(('gameoflife', factory('Game Of Life'))) db.append(('musicplayer', factory('Music Player'))) diff --git a/wasp/boards/manifest_240x240.py b/wasp/boards/manifest_240x240.py index f0eb474..48fe577 100644 --- a/wasp/boards/manifest_240x240.py +++ b/wasp/boards/manifest_240x240.py @@ -7,6 +7,7 @@ manifest = ( 'apps/calc.py', 'apps/clock.py', 'apps/chrono.py', + 'apps/disaBLE.py', 'apps/dual_clock.py', 'apps/faces.py', 'apps/fibonacci_clock.py', diff --git a/wasp/boards/simulator/ble.py b/wasp/boards/simulator/ble.py new file mode 100644 index 0000000..0aec53d --- /dev/null +++ b/wasp/boards/simulator/ble.py @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2021 Francesco Gazzetta + +_is_enabled = True + +def enable(): + global _is_enabled + _is_enabled = True + +def disable(): + global _is_enabled + _is_enabled = False + +def enabled(): + return _is_enabled diff --git a/wasp/boards/simulator/machine.py b/wasp/boards/simulator/machine.py index 891b635..9596c0a 100644 --- a/wasp/boards/simulator/machine.py +++ b/wasp/boards/simulator/machine.py @@ -130,3 +130,8 @@ def lightsleep(ms=10): def deepsleep(ms=10): lightsleep(ms) + +def reset(): + # We don't simulate an actual watch reset, but it should be enough for what + # we want to test + print("RESET") diff --git a/wasp/boards/sphinx/ble.py b/wasp/boards/sphinx/ble.py new file mode 100644 index 0000000..e3d7ce2 --- /dev/null +++ b/wasp/boards/sphinx/ble.py @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2021 Francesco Gazzetta + +class enable(): + pass + +class disable(): + pass + +class enabled(): + pass