1
0
mirror of https://codeberg.org/vanous/huafetcher synced 2024-09-27 10:10:41 +02:00
huafetcher/main.py

503 lines
20 KiB
Python
Raw Normal View History

2020-11-24 23:12:25 +01:00
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.utils import platform
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from functools import partial
from kivy.clock import Clock
from kivy.logger import Logger
from kivy.uix.dropdown import DropDown
from huami_token import HuamiAmazfit
import urls as urls
from kivy.core.clipboard import Clipboard
from kivy.storage.jsonstore import JsonStore
DEBUG=False
2020-12-06 18:27:47 +01:00
#DEBUG=True
2020-11-24 23:12:25 +01:00
def debug_print(*xargs):
if DEBUG:
print(*xargs)
SPACING=2
Builder.load_string('''
<MyInputy>:
font_size: 30
halign: 'left'
color: 1,1,1,1
bcolor: .1, 0, .6, 0
canvas.before:
Color:
rgba: root.bcolor
Rectangle:
size: (self.width -2, self.height -2)
pos: (self.x+1,self.y +1)
<MyLabel>:
font_size: 30
halign: 'center'
bcolor: .7, .7, .7, 1
canvas.before:
Color:
rgba: root.bcolor
Rectangle:
size: self.size
pos: self.pos
<MyLeftLabel>:
font_size: 30
halign: 'left'
bcolor: .7, .7, .7, 1
canvas.before:
Color:
rgba: root.bcolor
Rectangle:
size: self.size
pos: self.pos
<MyButton>:
font_size: 30
bcolor: .7, .7, .7, 1
background_color: .1, 0, .5, 0
canvas.before:
Color:
rgba: root.bcolor
Rectangle:
size: self.size
pos: self.pos
''')
class MyLabel(Label):
pass
class MyLeftLabel(Label):
pass
class MyButton(Button):
pass
class MyInput(TextInput):
pass
class Main(App):
def build(self):
self.huamidevice=HuamiAmazfit()
self.store = JsonStore('credentials.json')
screen_layout = BoxLayout(orientation="vertical", spacing=SPACING)
buttons_layout = BoxLayout(orientation="horizontal", spacing=SPACING)
rows_layout = BoxLayout(orientation="vertical", spacing=SPACING)
top_title_label=MyLeftLabel(text='Huafetcher', halign="left")
self.instructions_label=MyLeftLabel(text='Press "Get token", sign in, copy URL and paste here', halign="left", valign="middle", padding_x="20")
self.instructions_label.bind(size=self.instructions_label.setter('text_size'))
rows_layout.add_widget(top_title_label)
2020-11-24 23:12:25 +01:00
dropdown = DropDown()
xiaomi_button = MyButton(text='Xiaomi', size_hint_y=None, height=150)
xiaomi_button.bind(on_press=lambda a:self.set_login_method('xiaomi'))
xiaomi_button.bind(on_release=lambda btn: dropdown.select(btn.text))
amazfit_button = MyButton(text='Amazfit', size_hint_y=None, height=150)
amazfit_button.bind(on_press=lambda a:self.set_login_method('amazfit'))
amazfit_button.bind(on_release=lambda btn: dropdown.select(btn.text))
dropdown.add_widget(xiaomi_button)
dropdown.add_widget(amazfit_button)
dropdown_button = MyButton(text='Login method')
dropdown_button.bind(on_release=dropdown.open)
#dropdown_button.bind(on_press=lambda x: setattr(dropdown_button,'text','Select'))
dropdown.bind(on_select=lambda instance, x: setattr(dropdown_button, 'text', x))
self.get_token_button = MyButton(text='Get token')
self.get_token_button.bind(on_press=self.on_press_button_gettoken)
2020-11-24 23:12:25 +01:00
self.fetch_key_button = MyButton(text='Fetch key')
self.fetch_key_button.bind(on_press=self.on_press_button_fetch_key)
self.fetch_key_button.disabled=True
2020-11-24 23:12:25 +01:00
self.fetch_agps_button = MyButton(text='Fetch aGPS')
self.fetch_agps_button.bind(on_press=self.on_press_button_agps)
self.fetch_agps_button.disabled=True
2020-11-24 23:12:25 +01:00
share_agps_button = MyButton(text='Share aGPS')
share_agps_button.bind(on_press=self.on_press_button_share_agps)
buttons_layout.add_widget(self.get_token_button)
2020-11-24 23:12:25 +01:00
#buttons_layout.add_widget(login_button)
buttons_layout.add_widget(self.fetch_key_button)
buttons_layout.add_widget(self.fetch_agps_button)
2020-11-24 23:12:25 +01:00
#sharing doesn't work
#buttons_layout.add_widget(share_agps_button)
self.paste_token_input_layout = BoxLayout(orientation="horizontal", spacing=SPACING)
2020-11-24 23:12:25 +01:00
paste_token_input_label=MyLabel(text='URL result')
self.paste_token_input_layout.disabled=True
2020-11-24 23:12:25 +01:00
self.paste_token_input = MyInput(text='',
multiline=False,
)
self.paste_token_input.bind(text=self.set_token)
paste_token_url_button=MyButton(text='Paste', size_hint=(.3, 1))
paste_token_url_button.bind(on_press=lambda instance: self.on_press_paste(self.paste_token_input) )
2020-11-24 23:12:25 +01:00
self.paste_token_input_layout.add_widget(paste_token_input_label)
self.paste_token_input_layout.add_widget(paste_token_url_button)
self.paste_token_input_layout.add_widget(self.paste_token_input)
2020-11-24 23:12:25 +01:00
credentials_email_label=MyButton(text='Email' , size_hint=(.7, 1))
self.credentials_email_input = MyInput(text='',
multiline=False,
)
self.credentials_email_input.bind(text=lambda instance,x: setattr(self.huamidevice,'email',x))
email_paste_button=MyButton(text='Paste', size_hint=(.3, 1))
email_paste_button.bind(on_press=lambda instance: self.on_press_paste(self.credentials_email_input) )
2020-11-24 23:12:25 +01:00
email_save_button=MyButton(text='Save', size_hint=(.3, 1))
2020-11-24 23:12:25 +01:00
#load_button1.bind(on_press=lambda instance: )
email_save_button.bind(on_press=lambda instance: self.on_press_save(self.credentials_email_input, 'email') )
2020-11-24 23:12:25 +01:00
self.credentials_email_layout = BoxLayout(orientation="horizontal", spacing=SPACING)
self.credentials_email_layout.add_widget(credentials_email_label)
#credentials_email_layout.add_widget(load_button1)
self.credentials_email_layout.add_widget(email_save_button)
self.credentials_email_layout.add_widget(email_paste_button)
2020-11-24 23:12:25 +01:00
self.credentials_email_layout.add_widget(self.credentials_email_input)
credentials_password_label=MyLabel(text='Password', size_hint=(.7, 1))
self.credentials_password_input = MyInput(text='',
multiline=False,
)
self.credentials_password_input.bind(text=lambda instance,x: setattr(self.huamidevice,'password',x))
credentials_password_label.bind(on_press=self.on_press_paste_password)
password_paste_button=MyButton(text='Paste', size_hint=(.3, 1))
password_paste_button.bind(on_press=lambda instance: self.on_press_paste(self.credentials_password_input) )
2020-11-24 23:12:25 +01:00
password_save_button=MyButton(text='Save', size_hint=(.3, 1))
password_save_button.bind(on_press=lambda instance: self.on_press_save(self.credentials_password_input, 'password') )
2020-11-24 23:12:25 +01:00
self.credentials_password_layout = BoxLayout(orientation="horizontal", spacing=SPACING)
self.credentials_password_layout.add_widget(credentials_password_label)
self.credentials_password_layout.add_widget(password_save_button)
self.credentials_password_layout.add_widget(password_paste_button)
2020-11-24 23:12:25 +01:00
self.credentials_password_layout.add_widget(self.credentials_password_input)
rows_layout.add_widget(dropdown_button)
rows_layout.add_widget(self.credentials_email_layout)
rows_layout.add_widget(self.credentials_password_layout)
rows_layout.add_widget(self.paste_token_input_layout)
2020-11-24 23:12:25 +01:00
result_value_label=MyButton(text='Found key')
self.result_value_value=TextInput()
copy_key_button=MyButton(text='Copy', size_hint=(.3, 1))
copy_key_button.bind(on_press=lambda instance: self.on_press_copy(self.result_value_value) )
2020-11-24 23:12:25 +01:00
self.result_value_layout = BoxLayout(orientation="horizontal", spacing=SPACING)
self.result_value_layout.add_widget(result_value_label)
self.result_value_layout.add_widget(copy_key_button)
self.result_value_layout.add_widget(self.result_value_value)
2020-11-24 23:12:25 +01:00
result_value_label.bind(on_press=self.on_press_copy_result)
self.result_value_layout.disabled=True
2020-11-24 23:12:25 +01:00
rows_layout.add_widget(self.result_value_layout)
2020-11-24 23:12:25 +01:00
rows_layout.add_widget(buttons_layout)
rows_layout.add_widget(self.instructions_label)
2020-11-24 23:12:25 +01:00
screen_layout.add_widget(rows_layout)
self.on_press_load(self.credentials_email_input, 'email')
self.on_press_load(self.credentials_password_input, 'password')
#self.set_login_method('xiaomi')
#dropdown_button.text='Xiaomi'
self.set_login_method('amazfit')
dropdown_button.text='Amazfit'
2020-11-24 23:12:25 +01:00
return screen_layout
def set_visibility(self, widget_id, hide=True):
debug_print(hide)
if hasattr(widget_id, 'saved_attrs'):
debug_print(widget_id.saved_attrs)
if not hide:
widget_id.height, widget_id.size_hint_y, widget_id.opacity, widget_id.disabled = widget_id.saved_attrs
del widget_id.saved_attrs
elif hide:
widget_id.saved_attrs = widget_id.height, widget_id.size_hint_y, widget_id.opacity, widget_id.disabled
widget_id.height, widget_id.size_hint_y, widget_id.opacity, widget_id.disabled = 0, None, 0, True
2020-11-24 23:12:25 +01:00
def set_login_method(self,method):
debug_print(method)
self.huamidevice.method=method
if method == 'xiaomi':
self.instructions_label.text='Press "Get token", sign in, copy URL and paste here'
self.set_visibility(self.credentials_email_layout, hide=True)
self.set_visibility(self.credentials_password_layout, hide=True)
self.set_visibility(self.paste_token_input_layout, hide=False)
self.set_visibility(self.result_value_layout, hide=False)
self.get_token_button.disabled=False
self.fetch_agps_button.disabled=True
self.fetch_key_button.disabled=True
else: #amazfit
self.instructions_label.text='Email and password must be filled, then use Fetch key or Fetch aGPS'
self.set_visibility(self.credentials_email_layout, hide=False)
self.set_visibility(self.credentials_password_layout, hide=False)
self.set_visibility(self.paste_token_input_layout, hide=True)
#self.set_visibility(self.result_value_layout, hide=True)
self.get_token_button.disabled=True
self.fetch_agps_button.disabled=False
self.fetch_key_button.disabled=False
2020-11-24 23:12:25 +01:00
def set_token(self, instance, text):
debug_print("got", text)
debug_print(self.huamidevice)
self.huamidevice.parse_token(text)
debug_print(self.huamidevice)
if self.huamidevice.access_token is not None:
self.fetch_agps_button.disabled=False
self.fetch_key_button.disabled=False
self.instructions_label.text='now press "Fetch key" or "Fetch aGPS"'
else:
if self.paste_token_input_layout.disabled==False:
self.instructions_label.text='token not found in the url, repeat sign in a copy/paste url'
2020-11-24 23:12:25 +01:00
def on_press_button_gettoken(self, instance):
debug_print('You pressed the button login!')
self.result_value_value.text=''
self.paste_token_input.text=''
self.fetch_agps_button.disabled=True
self.fetch_key_button.disabled=True
self.result_value_layout.disabled=True
self.instructions_label.text="log in and paste url here"
2020-11-24 23:12:25 +01:00
debug_print(self.huamidevice)
if self.huamidevice.method == 'xiaomi':
self.instructions_label.text="log in and paste url here"
2020-11-24 23:12:25 +01:00
login_url = urls.URLS["login_xiaomi"]
if ( platform != 'android' ):
import webbrowser
webbrowser.open(login_url, new = 2)
else:
from jnius import autoclass
from jnius import cast
PythonActivity = autoclass('org.kivy.android.PythonActivity')
Intent = autoclass('android.content.Intent')
Uri = autoclass('android.net.Uri')
intent = Intent()
intent.setAction(Intent.ACTION_VIEW)
intent.setData(Uri.parse(login_url))
currentActivity = cast('android.app.Activity', PythonActivity.mActivity)
currentActivity.startActivity(intent)
self.paste_token_input_layout.disabled=False
return
else:
#login method amazfit
try:
res=self.huamidevice.get_access_token()
print("amazfit get access token result", res)
if res:
#if self.huamidevice.user_id is not None:
# self.instructions_label.text="Signed in as: {}, getting data".format(self.huamidevice.user_id)
#else:
# self.instructions_label.text="You must sign in first"
self.fetch_key_button.disabled=False
self.fetch_agps_button.disabled=False
except Exception as e:
debug_print(e)
self.instructions_label.text=f"{e}"
2020-11-24 23:12:25 +01:00
def on_press_button_fetch_key(self, instance):
debug_print('You pressed the button fetch!')
if self.huamidevice.method=='amazfit':
res=False
try:
res=self.huamidevice.get_access_token()
except Exception as e:
debug_print(e)
self.instructions_label.text=f"{e}"
if not res:
self.instructions_label.text="amazfit login failed"
self.result_value_value.text=''
self.paste_token_input.text=''
self.result_value_layout.disabled=True
self.paste_token_input_layout.disabled=True
if self.huamidevice.method!='amazfit':
self.fetch_key_button.disabled=True
self.fetch_agps_button.disabled=True
2020-11-24 23:12:25 +01:00
debug_print(self.huamidevice)
self.instructions_label.text="signing in and getting keys"
Clock.schedule_once(self.fetch_keys, 1)
def fetch_keys(self, *xargs):
try:
res=self.huamidevice.login()
if res:
self.instructions_label.text="Signed in as: {}, getting data".format(self.huamidevice.user_id)
except Exception as e:
debug_print(e)
self.instructions_label.text=f"{e}"
return
2020-11-24 23:12:25 +01:00
device_keys = self.huamidevice.get_wearable_auth_keys()
self.result_value_layout.disabled=False
2020-11-24 23:12:25 +01:00
self.result_value_value.text=""
key=""
2020-11-24 23:12:25 +01:00
for device_key in device_keys:
debug_print(f"{device_key} {device_keys[device_key]}")
key=f"{device_key} {device_keys[device_key]}"
2020-11-24 23:12:25 +01:00
if key=="":
self.instructions_label.text="No keys on the server"
else:
self.instructions_label.text="Got the key, use the Copy button"
self.result_value_value.text=f"{key}"
2020-11-24 23:12:25 +01:00
#Clock.schedule_once(partial(self.doit), 1)
def on_press_paste_token(self, instance):
self.paste_token_input.text=Clipboard.paste()
def on_press_paste_email(self, instance):
self.credentials_email_input.text=Clipboard.paste()
def on_press_paste_password(self, instance):
self.credentials_password_input.text=Clipboard.paste()
def on_press_copy_result(self, instance):
Clipboard.copy(self.result_value_value.text)
2020-11-24 23:12:25 +01:00
def on_press_paste(self, instance):
instance.text=Clipboard.paste()
def on_press_copy(self, instance):
Clipboard.copy(instance.text)
self.instructions_label.text='value copied to clipboard'
2020-11-24 23:12:25 +01:00
def on_press_load(self, instance, key):
if self.store.exists(key):
instance.text=self.store.get(key)["value"]
def on_press_save(self, instance, key):
self.store.put(key, value=instance.text)
def on_press_button_agps(self, instance):
debug_print('You pressed the button agps!')
if self.huamidevice.method=='amazfit':
res=False
try:
res=self.huamidevice.get_access_token()
except Exception as e:
debug_print(e)
self.instructions_label.text=f"{e}"
if not res:
self.instructions_label.text="amazfit login failed"
self.result_value_value.text=''
self.paste_token_input.text=''
self.result_value_layout.disabled=True
self.paste_token_input_layout.disabled=True
if self.huamidevice.method!='amazfit':
self.fetch_key_button.disabled=True
self.fetch_agps_button.disabled=True
2020-11-24 23:12:25 +01:00
debug_print(self.huamidevice)
self.instructions_label.text="signing in and getting files"
Clock.schedule_once (self.get_agps_files, 1)
def get_agps_files(self, *xargs):
import zipfile
try:
res=self.huamidevice.login()
if res:
self.instructions_label.text="Signed in as: {}, getting data".format(self.huamidevice.user_id)
except Exception as e:
debug_print(e)
self.instructions_label.text=f"{e}"
return
2020-11-24 23:12:25 +01:00
self.huamidevice.get_gps_data()
agps_file_names = ["cep_alm_pak.zip"]
if ( platform == 'android' ):
import shutil
import os
from jnius import autoclass
from jnius import cast
Environment = autoclass('android.os.Environment')
File = autoclass('java.io.File')
data_dir = Environment.getExternalStorageDirectory().getPath()
debug_print(data_dir)
for filename in agps_file_names:
sdpathfile = os.path.join(data_dir, filename)
shutil.copyfile(filename, sdpathfile)
with zipfile.ZipFile(filename, "r") as zip_f:
#zip_f.extractall()
zip_f.extractall(data_dir)
self.instructions_label.text="Files downloaded and extracted"
2020-11-24 23:12:25 +01:00
#Clock.schedule_once(partial(self.doit), 1)
def on_press_button_share_agps(self, instance):
#not working because android broke it
if ( platform == 'android' ):
import os
from jnius import autoclass
from jnius import cast
Environment = autoclass('android.os.Environment')
File = autoclass('java.io.File')
data_dir = Environment.getExternalStorageDirectory().getPath()
PythonActivity = autoclass('org.kivy.android.PythonActivity')
Intent = autoclass('android.content.Intent')
Uri = autoclass('android.net.Uri')
intent = Intent()
intent.setAction(Intent.ACTION_VIEW)
data_dir = getattr(self, 'user_data_dir')
file_target=File(os.path.join(data_dir, "cep_pak.bin"))
#target=Uri.parse(os.path.join("file:///", data_dir, "cep_pak.bin"))
target=Uri.fromFile(file_target)
#intent.setData(Uri.parse(os.path.join("file:///", data_dir, "cep_pak.bin")))
#intent.setType("application/octet-stream")
intent.setDataAndType(target, "application/octet-stream")
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
currentActivity = cast('android.app.Activity', PythonActivity.mActivity)
currentActivity.startActivity(intent)
#intent = Intent()
#intent.setAction(Intent.ACTION_VIEW)
#intent.setData(Uri.parse("gps_alm.bin"))
#currentActivity = cast('android.app.Activity', PythonActivity.mActivity)
#currentActivity.startActivity(intent)
#def doit(self, *kargs):
def openweb(url):
debug_print("open ", url)
if __name__ == '__main__':
app = Main()
app.run()