]> git.basschouten.com Git - openhab-addons.git/blob
9c191c0f0c74b82ee375830bce2ae7cec2eabb5f
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.icloud.internal;
14
15 import static java.nio.charset.StandardCharsets.UTF_8;
16
17 import java.io.IOException;
18 import java.net.URI;
19 import java.net.URISyntaxException;
20 import java.time.Duration;
21 import java.util.Base64;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.openhab.binding.icloud.internal.json.request.ICloudAccountDataRequest;
25 import org.openhab.binding.icloud.internal.json.request.ICloudFindMyDeviceRequest;
26 import org.openhab.core.io.net.http.HttpRequestBuilder;
27
28 import com.google.gson.Gson;
29 import com.google.gson.GsonBuilder;
30
31 /**
32  * Handles communication with the Apple server. Provides methods to
33  * get device information and to find a device.
34  *
35  * @author Patrik Gfeller - Initial Contribution
36  * @author Patrik Gfeller - SOCKET_TIMEOUT changed from 2500 to 10000
37  * @author Martin van Wingerden - add support for custom CA of https://fmipmobile.icloud.com
38  */
39 @NonNullByDefault
40 public class ICloudConnection {
41     private static final String ICLOUD_URL = "https://www.icloud.com";
42     private static final String ICLOUD_API_BASE_URL = "https://fmipmobile.icloud.com";
43     private static final String ICLOUD_API_URL = ICLOUD_API_BASE_URL + "/fmipservice/device/";
44     private static final String ICLOUD_API_COMMAND_PING_DEVICE = "/playSound";
45     private static final String ICLOUD_API_COMMAND_REQUEST_DATA = "/initClient";
46     private static final int SOCKET_TIMEOUT = 15;
47
48     private final Gson gson = new GsonBuilder().create();
49     private final String iCloudDataRequest = gson.toJson(ICloudAccountDataRequest.defaultInstance());
50
51     private final String authorization;
52     private final String iCloudDataRequestURL;
53     private final String iCloudFindMyDeviceURL;
54
55     public ICloudConnection(String appleId, String password) throws URISyntaxException {
56         authorization = new String(Base64.getEncoder().encode((appleId + ":" + password).getBytes()), UTF_8);
57         iCloudDataRequestURL = new URI(ICLOUD_API_URL + appleId + ICLOUD_API_COMMAND_REQUEST_DATA).toASCIIString();
58         iCloudFindMyDeviceURL = new URI(ICLOUD_API_URL + appleId + ICLOUD_API_COMMAND_PING_DEVICE).toASCIIString();
59     }
60
61     /***
62      * Sends a "find my device" request.
63      *
64      * @throws IOException
65      */
66     public void findMyDevice(String id) throws IOException {
67         callApi(iCloudFindMyDeviceURL, gson.toJson(new ICloudFindMyDeviceRequest(id)));
68     }
69
70     public String requestDeviceStatusJSON() throws IOException {
71         return callApi(iCloudDataRequestURL, iCloudDataRequest);
72     }
73
74     private String callApi(String url, String payload) throws IOException {
75         // @formatter:off
76         return HttpRequestBuilder.postTo(url)
77             .withTimeout(Duration.ofSeconds(SOCKET_TIMEOUT))
78             .withHeader("Authorization", "Basic " + authorization)
79             .withHeader("User-Agent", "Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)")
80             .withHeader("Origin", ICLOUD_URL)
81             .withHeader("charset", "utf-8")
82             .withHeader("Accept-language", "en-us")
83             .withHeader("Connection", "keep-alive")
84             .withHeader("X-Apple-Find-Api-Ver", "2.0")
85             .withHeader("X-Apple-Authscheme", "UserIdGuest")
86             .withHeader("X-Apple-Realm-Support", "1.0")
87             .withHeader("X-Client-Name", "iPad")
88             .withHeader("Content-Type", "application/json")
89             .withContent(payload)
90             .getContentAsString();
91         // @formatter:on
92     }
93 }