Open pdev77 opened 1 year ago
I'm not a python programmer but I've been doing the same - a simple script that was running every 5 mins to grab the data (logging in every time) - but that's now borked with the 2FA. I'm assuming there must be some way that we can save the session info to a file, then reuse that on the next run?
My code was even simpler:
from pyhiveapi import Hive, SMS_REQUIRED
session = Hive(username="username", password="password")
login = session.login()
if login.get("ChallengeName") == SMS_REQUIRED:
code = input("Enter 2FA code: ")
session.sms_2fa(code, login)
session.startSession()
HeatingDevices = session.deviceList["climate"]
if len(HeatingDevices) >= 1:
HeatingZone_1 = HeatingDevices[0]
print("temperature=" + str(session.heating.getCurrentTemperature(HeatingZone_1)))
print("targetTemperature=" + str(session.heating.getTargetTemperature(HeatingZone_1)))
print("state=" + str(session.heating.getCurrentOperation(HeatingZone_1)))
Using the examples posted here: (https://pyhass.github.io/pyhiveapi.docs/docs/examples/session/) I've managed to get it all working again - using device authentication.
First - see https://github.com/Pyhass/Pyhiveapi/issues/57 - you will need to apply the fix to session.py.
Then - onetime only - you need to do the step "Log in - Using Hive Username and Password with MFA(if required)" to get the deviceKey/Password etc - then save them to a file / use them in the subsequent gather scripts.
For the data gather loop , then you need to follow steps "Log in - Using Hive Device Authentication" & start the session. You can then utilise the session object to extract data. No need to relogon with username/password each time - the deviceKey etc doesnt expire.
Yep, that's helped me sort it too 👍
Using the examples posted here: (https://pyhass.github.io/pyhiveapi.docs/docs/examples/session/) I've managed to get it all working again - using device authentication.
First - see #57 - you will need to apply the fix to session.py.
Then - onetime only - you need to do the step "Log in - Using Hive Username and Password with MFA(if required)" to get the deviceKey/Password etc - then save them to a file / use them in the subsequent gather scripts.
For the data gather loop , then you need to follow steps "Log in - Using Hive Device Authentication" & start the session. You can then utilise the session object to extract data. No need to relogon with username/password each time - the deviceKey etc doesnt expire.
sorry for being a little dumb i am trying to do what you have successfully done
but for me the session login with with MFA just throws back erros after putting the 2FA code in it
Ok, my code is now split into two programs. You'd run this one first (and thankfully only once) to get a device authenticated. You'll need to punch in whatever 2FA code they text you:
from pyhiveapi import Hive, SMS_REQUIRED
session = Hive(username="username", password="password")
login = session.login()
if login.get("ChallengeName") == SMS_REQUIRED:
code = input("Enter 2FA code: ")
session.sms2fa(code, login)
Device data is need for future device logins
session.auth.device_registration('pi4')
deviceData = session.auth.get_device_data()
print(deviceData)
That'll print out a bunch of tokens. You then need to feed them into something like the following, where the same tokens can be reused over and over:
from pyhiveapi import Hive, SMS_REQUIRED
session = Hive(username="username", password="password")
DEVICE_REQUIRED = "DEVICE_SRP_AUTH"
# This time tell the auth object about the device:
session.auth.device_group_key = 'FIRST_TOKEN'
session.auth.device_key = 'SECOND_TOKEN'
session.auth.device_password = 'THIRD_TOKEN'
# Now login - should be challenged with device login
login = session.login()
if login.get("ChallengeName") == DEVICE_REQUIRED:
session.deviceLogin()
else:
print("Are you sure device is registered?")
session.startSession()
HeatingDevices = session.deviceList["climate"]
if len(HeatingDevices) >= 1:
HeatingZone_1 = HeatingDevices[0]
print("temperature=" + str(session.heating.getCurrentTemperature(HeatingZone_1)))
print("targetTemperature=" + str(session.heating.getTargetTemperature(HeatingZone_1)))
print("state=" + str(session.heating.getCurrentOperation(HeatingZone_1)))
However, note that you do still have to make the edits to session.py that were mentioned earlier.
edited please see below comment
Ok, my code is now split into two programs. You'd run this one first (and thankfully only once) to get a device authenticated. You'll need to punch in whatever 2FA code they text you:
from pyhiveapi import Hive, SMS_REQUIRED session = Hive(username="username", password="password") login = session.login() if login.get("ChallengeName") == SMS_REQUIRED: code = input("Enter 2FA code: ") session.sms2fa(code, login) Device data is need for future device logins session.auth.device_registration('pi4') deviceData = session.auth.get_device_data() print(deviceData)
That'll print out a bunch of tokens. You then need to feed them into something like the following, where the same tokens can be reused over and over:
from pyhiveapi import Hive, SMS_REQUIRED session = Hive(username="username", password="password") DEVICE_REQUIRED = "DEVICE_SRP_AUTH" # This time tell the auth object about the device: session.auth.device_group_key = 'FIRST_TOKEN' session.auth.device_key = 'SECOND_TOKEN' session.auth.device_password = 'THIRD_TOKEN' # Now login - should be challenged with device login login = session.login() if login.get("ChallengeName") == DEVICE_REQUIRED: session.deviceLogin() else: print("Are you sure device is registered?") session.startSession() HeatingDevices = session.deviceList["climate"] if len(HeatingDevices) >= 1: HeatingZone_1 = HeatingDevices[0] print("temperature=" + str(session.heating.getCurrentTemperature(HeatingZone_1))) print("targetTemperature=" + str(session.heating.getTargetTemperature(HeatingZone_1))) print("state=" + str(session.heating.getCurrentOperation(HeatingZone_1)))
However, note that you do still have to make the edits to session.py that were mentioned earlier.
ok so the first part has worked great now and registered the device i do however have another question now
from the second part your example mentions this
DEVICE_REQUIRED = "DEVICE_SRP_AUTH"
from where would this information be gathered please
thanks
You can leave that as is. It's literally what the code is, rather than anything that needs to be replaced.
You can leave that as is. It's literally what the code is, rather than anything that needs to be replaced.
i just realised that
i have one final question please if you dont mind
with the second part you posted it outputs the temp which is great and proof of working concept
my project relies on me transfering the IdToken to php to interact with the rest of the project is there a way using the examples about i can vies the IdTokens so i can save them to file
or will this not work
thank you again for your help
Sorry, but I'm fairly clueless with python (Java is my day job). Even hacking this into a working state tested the limits of my python coding "skills".
Sorry, but I'm fairly clueless with python (Java is my day job). Even hacking this into a working state tested the limits of my python coding "skills".
haha no problem i am useless with python too
all i need it to do now is print me a refresh token as in you example the token isnt ever seen
but i am also useless with python and also java
thanks
I think I've fixed this by following some AWS docs about how to refresh tokens with devices - I've been collecting temperature data every 5 minutes for 26 hours now with only one 2FA request at the start. Not quite as handy as "only one 2FA ever" if you do the device login dance but still nice to have it working! Will clean up my patches and submit a PR.
Hi I'm simply using pyhiveapi to pull data from hive periodically. It has worked fine for months - but now they have introduced mandatory 2fa - I would have to 2fa at every data pull once the session["IdToken"] expires. This I guess is what the session["RefreshToken"] is for - but I cant figure how to use it. I've tried
newTokens = hive_auth.refresh_token(authData['AuthenticationResult']['IdToken'])
but it throwsbotocore.errorfactory.NotAuthorizedException: An error occurred (NotAuthorizedException) when calling the InitiateAuth operation: Invalid Refresh Token.
I'm definitely passing the right token - but if anyone can tell what is a miss it would be appreciated!
full sample code