Hello.
I am unable to install pyicloud. My OpenHabian does not know the PIP command.
How do I go about it step by step?
First of all thank you very much for publishing the solution wirth the Python Script.
I also installed Python and pyicloud and wanted to test the login into icloud. So I tested with
icloud --username=myaccount@example.com --list
and I typed in my password correctly, but I only get the following errors:
Enter iCloud password for myaccount@example.com:
Bad username or password for myaccount@example.com
Enter iCloud password for myaccount@example.com:
Bad username or password for myaccount@example.com
Enter iCloud password for myaccount@example.com:
Traceback (most recent call last):
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\pyicloud\base.py", line 351, in _authenticate_with_token
req = self.session.post(
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\requests\sessions.py", line 635, in post
return self.request("POST", url, data=data, json=json, **kwargs)
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\pyicloud\base.py", line 160, in request
self._raise_error(code, reason)
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\pyicloud\base.py", line 189, in _raise_error
raise api_error
pyicloud.exceptions.PyiCloudAPIResponseException: Missing apple_id field
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\pyicloud\cmdline.py", line 191, in main
api = PyiCloudService(username.strip(), password.strip())
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\pyicloud\base.py", line 271, in __init__
self.authenticate()
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\pyicloud\base.py", line 335, in authenticate
self._authenticate_with_token()
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\pyicloud\base.py", line 357, in _authenticate_with_token
raise PyiCloudFailedLoginException(msg, error) from error
pyicloud.exceptions.PyiCloudFailedLoginException: ('Invalid authentication token.', PyiCloudAPIResponseException('Missing apple_id field'))
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Program Files\Python310\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Program Files\Python310\lib\runpy.py", line 86, in _run_code
exec(code, run_globals)
File "C:\code\python\icloud.exe\__main__.py", line 7, in <module>
File "C:\Users\marti\AppData\Roaming\Python\Python310\site-packages\pyicloud\cmdline.py", line 262, in main
raise RuntimeError(message) from err
RuntimeError: Bad username or password for myaccount@example.com
When I login to icloud via the Webpage the same Apple ID and password work flawless.
Do you have any ideas what I am doing wrong?
Thanks for any hints!
First you have to set/store the credentials as described here:
→ means use command without “-list”
→ but I don’t know how exactly it works in Windows, I’m using CentOS
→ in Linux, if you want to use it via OpenHAB, you have to execute the command under openhab user
sudo -u openhab /usr/local/bin/icloud --username your_iCloud_username
→ 2FA is required probably (accept from an i-device and enter 2FA code in prompt), now the credentials can be stored in the keyring and further calls do not require authentication
Thanks for your help. I also tried without “-list” but unfortunately the result is the same
That might be the cause, I do not use 2FA so far and I would like not to activate 2FA.
Is anybody here using the pyicloud solution successfully without 2FA?
I activated 2FA now and it works. So 2FA is required.
I created a Python script which creates a JSON output containing all devices/attributes listed in:
sudo -u openhab /usr/local/bin/icloud --username icloud_username --llist
The output can be easily parsed with json transformation (I use jython rules).
I guess the only downside will be the required reauthentication every 2 months as mentioned in the pyicloud documentation. But I’ll see …
Script (I put it in /etc/openhab/scripts/)
from pyicloud import PyiCloudService
import subprocess
# functions
def is_int(str):
try:
int(str)
return True
except ValueError:
return False
def is_float(str):
try:
float(str)
return True
except ValueError:
return False
# icloud username
username = "put_your_icloud_username_here"
inputString = subprocess.check_output(r'/usr/local/bin/icloud --username {0} --llist'.format(username.rstrip()), shell=True).decode(sys.stdout.encoding).strip().split("\n")
# initialize output
outputJson = ''
# read content line by line
for lineContent in inputString :
if '-----' in lineContent :
# remove last comma if a new device section begins
outputJson = outputJson.strip(',')
# add end bracket for previous device section
outputJson = outputJson + '},'
elif not ' - ' in lineContent :
# new device section does not contain " - "
outputJson = outputJson + '"' + lineContent.rstrip('\r\n') + '": {'
elif ' - ' in lineContent :
# add attribute name
outputJson = outputJson + '"' + lineContent.split()[0] + '": '
# add value without quotes when starting with {
if lineContent.rsplit(" - ",1)[1].rstrip('\r\n').startswith('{') :
outputJson = outputJson + lineContent.rsplit(" - ",1)[1].rstrip('\r\n') + ','
# add value without quotes when starting with [
elif lineContent.rsplit(" - ",1)[1].rstrip('\r\n').startswith('[') :
outputJson = outputJson + lineContent.rsplit(" - ",1)[1].rstrip('\r\n') + ','
# add value without quotes when value is integer
elif is_int(lineContent.rsplit(" - ",1)[1].rstrip('\r\n')) :
outputJson = outputJson + lineContent.rsplit(" - ",1)[1].rstrip('\r\n') + ','
# add value without quotes when value is float
elif is_float(lineContent.rsplit(" - ",1)[1].rstrip('\r\n')) :
outputJson = outputJson + lineContent.rsplit(" - ",1)[1].rstrip('\r\n') + ','
else :
# generally remove " in attribute value to prevent JSON parsing issues
outputJson = outputJson + '"' + lineContent.rsplit(" - ",1)[1].rstrip('\r\n').replace('"', '' ) + '",'
# clean-up outputJson
outputJson = '{' + outputJson.strip('},') + '} }'
outputJson = outputJson.replace("'", "\"")
outputJson = outputJson.replace("\"True\"", "true")
outputJson = outputJson.replace("True", "true")
outputJson = outputJson.replace("\"False\"", "false")
outputJson = outputJson.replace("False", "false")
outputJson = outputJson.replace(" None, ", " \"None\", ")
# print out result
print(outputJson)
Jython rule (I run it every 5 minutes):
"""
pyicloud control
Authorize once after reboot:
sudo -u openhab /usr/local/bin/icloud --username your_icloud_username
"""
from core.rules import rule
from core.triggers import when
from core.log import logging, LOG_PREFIX
from core import osgi
import sys
from core.actions import ScriptExecution
from core.actions import Transformation
import json
#pyicloud
from core.actions import Exec
from java.time import Duration
import math
log = logging.getLogger("org.eclipse.smarthome.model.script.pyicloud")
@rule("Pyicloud updater", description="updates the iCloud devices", tags=["pyicloud"])
@when("Time cron 5 1/5 * * * ?")
def pyicloudUpdater(event):
#log.warn("Rule: Pyicloud updater started.")
output = Exec.executeCommandLine(Duration.ofSeconds(15), "python3", "/etc/openhab/scripts/icloud.py")
##################
# iPhone
##################
#log.warn("iPhone")
batteryLevel = Transformation.transform("JSONPATH","$.iPhone.batteryLevel",output)
#log.warn("batteryLevel=" + batteryLevel)
deviceStatus = Transformation.transform("JSONPATH","$.iPhone.deviceStatus",output)
#log.warn("deviceStatus=" + deviceStatus)
timeStamp = Transformation.transform("JSONPATH","$.iPhone.location.timeStamp",output)
#log.warn("timeStamp=" + timeStamp)
latitude = Transformation.transform("JSONPATH","$.iPhone.location.latitude",output)
#log.warn("latitude=" + latitude)
longitude = Transformation.transform("JSONPATH","$.iPhone.location.longitude",output)
#log.warn("longitude=" + longitude)
latitudeAcc = Transformation.transform("JSONPATH","$.iPhone.location.horizontalAccuracy",output)
#log.warn("latitudeAcc=" + latitudeAcc)
longitudeAcc = Transformation.transform("JSONPATH","$.iPhone.location.verticalAccuracy",output)
#log.warn("longitudeAcc=" + longitudeAcc)
batteryStatus = Transformation.transform("JSONPATH","$.iPhone.batteryStatus",output)
#log.warn("batteryStatus=" + batteryStatus)
# update OH items
if deviceStatus.startswith("20") :
#log.warn("OK")
try:
accuracy = float(math.sqrt((float(latitudeAcc)*float(latitudeAcc)) + (float(longitudeAcc) * float(longitudeAcc))))
except:
accuracy = 0.0
events.postUpdate("iPhone_BatteryLevel",str(int(float(batteryLevel)*100)))
events.postUpdate("iPhone_Location",str(latitude + ", " + longitude + ", 0.0"))
events.postUpdate("iPhone_LocationLast",str(timeStamp))
events.postUpdate("iPhone_LocationAccuracy",str(accuracy))
events.postUpdate("iPhone_BatteryStatus",str(batteryStatus))
else :
events.postUpdate("iPhone_BatteryStatus","Unknown")
... add additional devices the same way here ...
Hello. i tried connecting to icloud according to GitHub - Krata4/icloud: icloud library which is using pyicloud
Everything is ok until point 7. I’m not sure about point 7.
When i try command in putty “python /etc/openhab/scripts/icloud.py -l “your phone key””, show error:
File "/etc/openhab/scripts/icloud.py", line 9
async def icloud():
^
SyntaxError: invalid syntax
Item in icloud.py have:
item_name = "Location_Output"
Items:
String Location_Output
Thanks for help
Hello, try python3 instead of python. Async was added in python from version 3.5.
In my case python command using version 2.7 and python3 using version 3.9.
Hello. I am using an openhab on raspberry pi as openhabian. sudo -u openhab icloud --username=xxxx@yyyyyyy.com --list doesn’t work: PermissionError: [Errno 13] Permission denied: ‘/tmp/pyicloud/openhab’. This dir does not exist, but /tmp/pyicloud/openhabian does. Everything seems to work when I use “-u openhabian” but then the openhab command Thing icreated gives error: No pyicloud password for xxxx@yyyyyyy.com could be found in the system keychain. Use the --store-in-keyring
command-line option for storing a password for this username.
I have tried all possible options I could think of but cannot get this to work. Any tips?
Hi,
try switch user like “sudo su - openhab -s /bin/bash” and than " icloud –username=xxxx@yyyyyyy.com --list"
Thanks
Jirka
Thanks Jiri, unfortunately same error: PermissionError: [Errno 13] Permission denied: ‘/tmp/pyicloud/openhab’
User openhab is different from user openhabian:
- openhabian:x:1000:115:,:/home/openhabian:/bin/bash
- openhab:x:110:115:openhab runtime user,:/var/lib/openhab:/bin/false
This error is appear when?which command…
could it be that you initially used the user openhabian instead of openhab to create the keyring entry ? Thus the folder openhabian was created under /tmp/pyicloud instead of under openhab.
hello, i try rule with exec:
output = Exec.executeCommandLine(Duration.ofSeconds(15), "python3", "/etc/openhab/scripts/icloud.py")
but reply to this command is:
Please enter password for encrypted keyring:
how run icloud.py with keyring password as parameter?
Hello, you have to run script in console firstly. First run is setup of password.
Team,
Not sure if it helps… but I am one more from the many of us trying to get icloud at my openhab, and the history loops always to the same problem with the broken plugin. I was a little bit desperate looking for alternatives, and thanks to this community I found some people experiencing with pyicloud python. I am a python person, and realized with some small coding I can build my own icloud extractor being openhab agnostic. This code can retrieve the info of every icloud device under my account, and by config I can propagate it thru mqtt or thru direct openhab apis to feed data. I also added an specific message to propagate also by mqtt or openhab items that when 2factor credentials are expired, to be noticed
If you are interested, feel free to take a look at GitHub - redcorjo/mqtt_pyicloud . Just published today and still very basic description how to use it. Mainly, ensure to run install pyicloud first at your desktop (I use mac and raspberry), and run under the same account planned to execute this script also the initializing of icloud --username user@domain.com value
Did you see that there is an updated binding available ?
Hi, yes I have done that, because openhab user does not allow me to execute the initial script.
sudo -u openhab icloud –username=xxxx@yyyyyyy.com --list deliver this error message: PermissionError: [Errno 13] Permission denied: ‘/tmp/pyicloud/openhab’. With username -u openhabian it does work. I get pyicloud working from the command line, but not from openhab UI.
I have two openhab related users on system:
- openhabian:x:1000:115:,:/home/openhabian:/bin/bash
- openhab:x:110:115:openhab runtime user,:/var/lib/openhab:/bin/false
It looks like openhab is defined as a runtime user and therefor I cannot use the user to create the keyring. Does that make sense?
Hi, can I install the new binding from the paper UI or should I manually install via .jar file?
It is an openHAB 3 binding, there is no PaperUI.
Place the .jar into your addons folder after uninstalling the old binding.