Merge d1f428ba5f
into e76a4afd85
commit
09d44f6b0d
|
@ -167,6 +167,10 @@ simulator:
|
|||
:alt: Software selection app running on the wasp-os simulator
|
||||
:width: 179
|
||||
|
||||
.. image:: res/PhoneApp.png
|
||||
:alt: Phone application running on the wasp-os simulator
|
||||
:width: 179
|
||||
|
||||
|
||||
wasp-os also contains a library of additional applications for you to choose.
|
||||
These are disabled by default but can be easily enabled using the Software
|
||||
|
|
|
@ -36,6 +36,8 @@ Built-in
|
|||
|
||||
.. automodule:: apps.pager
|
||||
|
||||
.. automodule:: apps.phone
|
||||
|
||||
Applications
|
||||
------------
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 432 B |
Binary file not shown.
After Width: | Height: | Size: 525 B |
|
@ -0,0 +1,150 @@
|
|||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
# Copyright (C) 2020 Daniel Thompson
|
||||
# Copyright (C) 2020 Carlos Gil
|
||||
|
||||
"""Phone for GadgetBridge and wasp-os companion
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. figure:: res/PhoneApp.png
|
||||
:width: 179
|
||||
|
||||
Screenshot of the Phone application
|
||||
|
||||
Phone Controller:
|
||||
|
||||
* Touch: answer/end
|
||||
* Event BACK: ignore/close
|
||||
|
||||
"""
|
||||
|
||||
import wasp
|
||||
|
||||
import icons
|
||||
import time
|
||||
|
||||
from micropython import const
|
||||
|
||||
DISPLAY_WIDTH = const(240)
|
||||
ICON_SIZE = const(72)
|
||||
CENTER_AT = const((DISPLAY_WIDTH - ICON_SIZE) // 2)
|
||||
|
||||
class PhoneApp(object):
|
||||
""" Phone application."""
|
||||
NAME = 'Phone'
|
||||
|
||||
def __init__(self):
|
||||
self._anwser = wasp.widgets.GfxButton(24, CENTER_AT, icons.phone)
|
||||
self._end = wasp.widgets.GfxButton(DISPLAY_WIDTH - ICON_SIZE - 24, CENTER_AT, icons.hangup)
|
||||
self._state = "end"
|
||||
self._name = ''
|
||||
self._number = ''
|
||||
self._state_changed = True
|
||||
self._name_changed = True
|
||||
self._number_changed = True
|
||||
|
||||
def _send_cmd(self, cmd):
|
||||
print('\r')
|
||||
for i in range(1):
|
||||
for i in range(0, len(cmd), 20):
|
||||
print(cmd[i: i + 20], end='')
|
||||
time.sleep(0.2)
|
||||
print(' ')
|
||||
print(' ')
|
||||
|
||||
def _fill_space(self, key):
|
||||
if key == 'top':
|
||||
wasp.watch.drawable.fill(
|
||||
x=0, y=0, w=DISPLAY_WIDTH, h=CENTER_AT)
|
||||
elif key == 'down':
|
||||
wasp.watch.drawable.fill(x=0, y=CENTER_AT + ICON_SIZE,
|
||||
w=DISPLAY_WIDTH,
|
||||
h=DISPLAY_WIDTH - (CENTER_AT + ICON_SIZE))
|
||||
|
||||
def foreground(self):
|
||||
"""Activate the application."""
|
||||
number = wasp.system.phonestate.get('number')
|
||||
name = wasp.system.phonestate.get('name')
|
||||
state = wasp.system.phonestate.get('cmd')
|
||||
|
||||
if number:
|
||||
self._number = number
|
||||
if name:
|
||||
self._name = name
|
||||
if state:
|
||||
self._state = state
|
||||
wasp.watch.drawable.fill()
|
||||
self.draw()
|
||||
wasp.system.request_tick(1000)
|
||||
wasp.system.request_event(wasp.EventMask.TOUCH)
|
||||
|
||||
def background(self):
|
||||
"""De-activate the application (without losing state)."""
|
||||
self._state_changed = True
|
||||
self._name_changed = True
|
||||
self._number_changed = True
|
||||
|
||||
def tick(self, ticks):
|
||||
wasp.system.keep_awake()
|
||||
state_now = wasp.system.phonestate.get('cmd')
|
||||
name_now = wasp.system.phonestate.get('name')
|
||||
number_now = wasp.system.phonestate.get('number')
|
||||
if state_now:
|
||||
if state_now != self._state:
|
||||
self._state = state_now
|
||||
self._state_changed = True
|
||||
else:
|
||||
self._state_changed = False
|
||||
if name_now:
|
||||
if name_now != self._name:
|
||||
self._name = name_now
|
||||
self._name_changed = True
|
||||
else:
|
||||
self._name_changed = False
|
||||
if number_now:
|
||||
if number_now != self._number:
|
||||
self._number = number_now
|
||||
self._number_changed = True
|
||||
else:
|
||||
self._number_changed = False
|
||||
wasp.system.phonestate = {}
|
||||
self._update()
|
||||
|
||||
def touch(self, event):
|
||||
if self._anwser.touch(event):
|
||||
self._send_cmd('{"t":"call", "n":"ACCEPT"} ')
|
||||
wasp.system.navigate(wasp.EventType.BACK)
|
||||
elif self._end.touch(event):
|
||||
self._send_cmd('{"t":"call", "n":"REJECT"} ')
|
||||
wasp.system.navigate(wasp.EventType.BACK)
|
||||
|
||||
def draw(self):
|
||||
"""Redraw the display from scratch."""
|
||||
self._draw()
|
||||
|
||||
def _draw(self):
|
||||
"""Redraw the updated zones."""
|
||||
if self._state_changed:
|
||||
self._anwser.draw()
|
||||
if self._name_changed:
|
||||
self._draw_label(self._name, 24 + 144)
|
||||
if self._number_changed:
|
||||
self._draw_label(self._number, 12)
|
||||
self._end.draw()
|
||||
|
||||
def _draw_label(self, label, pos):
|
||||
"""Redraw label info"""
|
||||
if label:
|
||||
draw = wasp.watch.drawable
|
||||
chunks = draw.wrap(label, 240)
|
||||
self._fill_space(pos)
|
||||
for i in range(len(chunks)-1):
|
||||
sub = label[chunks[i]:chunks[i+1]].rstrip()
|
||||
draw.string(sub, 0, pos + 24 * i, 240)
|
||||
|
||||
def _update(self):
|
||||
if(self._state == "start" or self._state == "incoming"):
|
||||
wasp.watch.vibrator.pulse(ms=wasp.system.notify_duration)
|
||||
|
||||
|
||||
def update(self):
|
||||
pass
|
|
@ -17,6 +17,7 @@ manifest = (
|
|||
'apps/launcher.py',
|
||||
'apps/pager.py',
|
||||
'apps/play2048.py',
|
||||
'apps/phone.py',
|
||||
'apps/settings.py',
|
||||
'apps/software.py',
|
||||
'apps/steps.py',
|
||||
|
|
|
@ -13,6 +13,12 @@ wasp.system.set_music_info({
|
|||
'artist': 'Dreams of Bamboo',
|
||||
})
|
||||
|
||||
wasp.system.set_phone_state({
|
||||
'cmd': 'end',
|
||||
'name': '5555555555',
|
||||
'number': 'Unknown Caller',
|
||||
})
|
||||
|
||||
|
||||
# Increase the display blanking time to avoid spamming the console
|
||||
# with backlight activations.
|
||||
|
|
|
@ -11,3 +11,5 @@ settings = 'Default settings icon'
|
|||
torch = 'Default torch or flashlight icon'
|
||||
up_arrow = 'Small (16x9) up arrow'
|
||||
down_arrow = 'Small (16x9) down arrow'
|
||||
phone = 'A phone icon rotated to look as if it is picked up'
|
||||
hangup = 'A phone icon'
|
|
@ -56,6 +56,8 @@ def GB(cmd):
|
|||
wasp.system.toggle_music(cmd)
|
||||
elif task == 'musicinfo':
|
||||
wasp.system.set_music_info(cmd)
|
||||
elif task == 'call':
|
||||
wasp.system.set_phone_state(cmd)
|
||||
else:
|
||||
pass
|
||||
#_info('Command "{}" is not implemented'.format(cmd))
|
||||
|
|
|
@ -303,3 +303,29 @@ checkbox = (
|
|||
b'Z\xc7X\xe4\x01\xde\x03\xdc\x02'
|
||||
)
|
||||
|
||||
# 2-bit RLE, generated from res/phone.png, 126 bytes
|
||||
phone = (
|
||||
b'\x02'
|
||||
b'HH'
|
||||
b'?\xff\xff\xa8\xc4?\x03\xc7?\x01\xc9>\xcb<\xcc;'
|
||||
b'\xce:\xcf8\xd07\xd26\xd26\xd25\xd44\xd44'
|
||||
b'\xd44\xd35\xd35\xd26\xd17\xcf9\xce:\xcd<'
|
||||
b'\xcc<\xcc<\xcc=\xcb=\xcc<\xcd<\xcc<\xcd<'
|
||||
b"\xcc<\xcd<\xcd<\xcd<\xcd\x0e\xc5(\xce\x0c\xc8'"
|
||||
b'\xce\n\xcb&\xce\x07\xce&\xd0\x03\xd0&\xe3&\xe3&'
|
||||
b"\xe3&\xe2'\xe1(\xe0)\xdf*\xdd,\xdc.\xd90"
|
||||
b'\xd63\xd47\xcf<\xc9?\xff\xff\xa9'
|
||||
)
|
||||
|
||||
# 2-bit RLE, generated from res/hangup.png, 104 bytes
|
||||
hangup = (
|
||||
b'\x02'
|
||||
b'HH'
|
||||
b'?\xff\xff\xff\xff\xff8\xd40\xdc)\xe3"\xe7 \xea'
|
||||
b'\x1c\xee\x19\xf0\x17\xf2\x15\xf4\x13\xf6\x11\xda\x05\xd8\x11\xd4'
|
||||
b'\x10\xd4\x0f\xd2\x15\xd2\x0f\xd1\x17\xd2\x0e\xd1\x17\xd2\r\xd2'
|
||||
b'\x17\xd2\r\xd2\x17\xd2\r\xd2\x17\xd2\r\xd2\x17\xd2\r\xd2'
|
||||
b'\x17\xd2\r\xd2\x17\xd2\r\xd2\x18\xd1\r\xd1\x19\xd1\r\xd1'
|
||||
b'\x1a\xd0\r\xd0\x1d\xce\x0e\xcd!\xcb\x10\xc8?\xff\xff\xff'
|
||||
b'\xff\xff\xff\xffP'
|
||||
)
|
|
@ -30,6 +30,7 @@ from apps.settings import SettingsApp
|
|||
from apps.steps import StepCounterApp
|
||||
from apps.software import SoftwareApp
|
||||
from apps.stopwatch import StopwatchApp
|
||||
from apps.phone import PhoneApp
|
||||
|
||||
class EventType():
|
||||
"""Enumerated interface actions.
|
||||
|
@ -117,6 +118,8 @@ class Manager():
|
|||
self.notifications = {}
|
||||
self.musicstate = {}
|
||||
self.musicinfo = {}
|
||||
self.call = PhoneApp()
|
||||
self.phonestate = {}
|
||||
|
||||
self._theme = (
|
||||
b'\x7b\xef' # ble
|
||||
|
@ -320,6 +323,12 @@ class Manager():
|
|||
def set_music_info(self, info):
|
||||
self.musicinfo = info
|
||||
|
||||
def set_phone_state(self, info):
|
||||
self.phonestate = info
|
||||
if(self.phonestate.get("cmd") == "start" or self.phonestate.get("cmd") == "incoming"):
|
||||
self.wake()
|
||||
self.switch(self.call)
|
||||
|
||||
def set_alarm(self, time, action):
|
||||
"""Queue an alarm.
|
||||
|
||||
|
|
Loading…
Reference in New Issue