Skip to content

Commit

Permalink
Add a lot of improvements
Browse files Browse the repository at this point in the history
- sort imports
- get mac and auth key from file or from command line options
- mac address and auth key validation
- output warning about bricking the Mi Band when restoring firmware
- add @ mark to features which require auth key
  • Loading branch information
MikeWent committed Nov 30, 2019
1 parent 1e3afe5 commit 5d706e1
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 43 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,4 +1,5 @@
*.pyc
.vscode
auth_key.txt
mac.txt

145 changes: 102 additions & 43 deletions miband4_console.py
@@ -1,42 +1,87 @@
#!/usr/bin/env python3
import argparse
import subprocess
import time
from datetime import datetime

from bluepy.btle import BTLEDisconnectError
from cursesmenu import *
from cursesmenu.items import *
from miband import miband
from bluepy.btle import BTLEDisconnectError
import argparse
import time

from constants import MUSICSTATE
from datetime import datetime
from miband import miband

parser = argparse.ArgumentParser()
parser.add_argument('-m', '--mac', required=True, help='Set mac address of the device')
parser.add_argument('-m', '--mac', required=False, help='Set mac address of the device')
parser.add_argument('-k', '--authkey', required=False, help='Set Auth Key for the device')
args = parser.parse_args()

MAC_ADDR = args.mac
# Try to obtain MAC from the file
try:
with open("mac.txt", "r") as f:
mac_from_file = f.read().strip()
except FileNotFoundError:
mac_from_file = None

# Use appropriate MAC
if args.mac:
MAC_ADDR = args.mac
elif mac_from_file:
MAC_ADDR = mac_from_file
else:
print("Error:")
print(" Please specify MAC address of the MiBand")
print(" Pass the --mac option with MAC address or put your MAC to 'mac.txt' file")
print(" Example of the MAC: a1:c2:3d:4e:f5:6a")
exit(1)

# Validate MAC address
if 1 < len(MAC_ADDR) != 17:
print("Error:")
print(" Your MAC length is not 17, please check the format")
print(" Example of the MAC: a1:c2:3d:4e:f5:6a")
exit(1)

# Try to obtain Auth Key from file
try:
with open("auth_key.txt", "r") as f:
auth_key = f.read().strip()
if 1 < len(auth_key) != 32:
print("Error:")
print(" Your AUTH KEY length is not 32, please check the format")
print(" Example of the AUTH KEY: 8fa9b42078627a654d22beff985655db")
AUTH_KEY = bytes.fromhex(auth_key)
auth_key_from_file = f.read().strip()
except FileNotFoundError:
AUTH_KEY = None
auth_key_from_file = None

# Use appropriate Auth Key
if args.authkey:
AUTH_KEY = args.authkey
elif auth_key_from_file:
AUTH_KEY = auth_key_from_file
else:
print("Warning:")
print(" To use additional features of this script please put your AUTH KEY to 'auth_key.txt'")
print(" Example of the AUTH KEY: 8fa9b42078627a654d22beff985655db")
print(" To use additional features of this script please put your Auth Key to 'auth_key.txt' or pass the --authkey option with your Auth Key")
print()
AUTH_KEY = None

# Validate Auth Key
if AUTH_KEY:
if 1 < len(AUTH_KEY) != 32:
print("Error:")
print(" Your AUTH KEY length is not 32, please check the format")
print(" Example of the Auth Key: 8fa9b42078627a654d22beff985655db")
exit(1)

# Convert Auth Key from hex to byte format
if AUTH_KEY:
AUTH_KEY = bytes.fromhex(AUTH_KEY)

#Needs Auth
# Needs Auth
def get_step_count():
binfo = band.get_steps()
print ('Number of steps: ', binfo['steps'])
print ('Fat Burned: ', binfo['fat_burned'])
print ('Calories: ', binfo['calories'])
print ('Distance travelled in meters: ', binfo['meters'])
input('Press a key to continue')


def general_info():
print ('MiBand')
print ('Soft revision:',band.get_revision())
Expand All @@ -46,6 +91,7 @@ def general_info():
print ('Time:', band.get_current_time()['date'].isoformat())
input('Press a key to continue')


def send_notif():
msg = input ("Enter message or phone number to be displayed: ")
ty= int(input ("1 for Message / 2 for Missed Call / 3 for Call: "))
Expand All @@ -56,31 +102,38 @@ def send_notif():
a=[5,4,3]
band.send_custom_alert(a[ty-1],msg)

#Needs Auth

# Needs Auth
def get_heart_rate():
print ('Latest heart rate is : %i' % band.get_heart_rate_one_time())
input('Press a key to continue')

def logger(data):

def heart_logger(data):
print ('Realtime heart BPM:', data)

#Needs Auth

# Needs Auth
def get_realtime():
band.start_heart_rate_realtime(heart_measure_callback=logger)
band.start_heart_rate_realtime(heart_measure_callback=heart_logger)
input('Press Enter to continue')

#Needs Auth.This feature has the potential to brick your Mi Band 4. You are doing this at your own risk.

# Needs Auth
def restore_firmware():
print("This feature has the potential to brick your Mi Band 4. You are doing this at your own risk.")
path = input("Enter the path of the firmware file :")
band.dfuUpdate(path)

#Needs Auths


# Needs Auths
def set_time():
now = datetime.now()
print ('Set time to:', now)
band.set_current_time(now)

#default callbacks


# default callbacks
def _default_music_play():
print("Played")
def _default_music_pause():
Expand All @@ -98,6 +151,7 @@ def _default_music_focus_in():
def _default_music_focus_out():
print("Music focus out")


def set_music():
band.setMusicCallback(_default_music_play,_default_music_pause,_default_music_forward,_default_music_back,_default_music_vup,_default_music_vdown,_default_music_focus_in,_default_music_focus_out)
fi = input("Set music track to : ")
Expand All @@ -107,30 +161,35 @@ def set_music():
continue
input("enter any key")


if __name__ == "__main__":
while True :
success = False
while not success:
try:
if (AUTH_KEY):
band = miband(MAC_ADDR,AUTH_KEY,debug=True)
band.initialize()
band = miband(MAC_ADDR, AUTH_KEY, debug=True)
success = band.initialize()
else:
band=miband(MAC_ADDR,debug=True)
band = miband(MAC_ADDR, debug=True)
success = True
break
except BTLEDisconnectError:
print('connection to the MIBand failed. Trying out again')
print('Connection to the MIBand failed. Trying out again in 3 seconds')
time.sleep(3)
continue

menu = CursesMenu("MIBand4", "Some of the feature requires authentication.")
info_item = FunctionItem ("Get general info of the device",general_info)
steps_item = FunctionItem ("Get Steps/Meters/Calories/Fat Burned",get_step_count)
call_item = FunctionItem ("Send Call/ Missed Call/Message",send_notif)
single_heart_rate_item = FunctionItem ("Get Heart Rate",get_heart_rate)
real_time_heart_rate_item = FunctionItem ("Get realtime heart rate data", get_realtime)
set_time_item= FunctionItem ("Set the band's time to system time", set_time)
set_music_item = FunctionItem ("Set the band's music and receive music controls", set_music)
dfu_update_item = FunctionItem ("Restore/Update Firmware", restore_firmware )


except KeyboardInterrupt:
print("\nExit.")
exit()

menu = CursesMenu("MIBand4", "Features marked with @ require Auth Key")
info_item = FunctionItem("Get general info of the device", general_info)
call_item = FunctionItem("Send Call/ Missed Call/Message", send_notif)
set_music_item = FunctionItem("Set the band's music and receive music controls", set_music)
steps_item = FunctionItem("@ Get Steps/Meters/Calories/Fat Burned", get_step_count)
single_heart_rate_item = FunctionItem("@ Get Heart Rate", get_heart_rate)
real_time_heart_rate_item = FunctionItem("@ Get realtime heart rate data", get_realtime)
set_time_item= FunctionItem("@ Set the band's time to system time", set_time)
dfu_update_item = FunctionItem("@ Restore/Update Firmware", restore_firmware)

menu.append_item(info_item)
menu.append_item(steps_item)
Expand Down

0 comments on commit 5d706e1

Please sign in to comment.