mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[pushbullet] Add link and file push type support (#17472)
* [pushbullet] Add link and file push type support Signed-off-by: jsetton <jeremy.setton@gmail.com> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
3b474220fb
commit
72eb7773d8
@ -48,6 +48,11 @@ Two different actions available:
|
||||
|
||||
- `sendPushbulletNote(String recipient, String messsage)`
|
||||
- `sendPushbulletNote(String recipient, String title, String messsage)`
|
||||
- `sendPushbulletLink(String recipient, String url)`
|
||||
- `sendPushbulletLink(String recipient, String title, String messsage, String url)`
|
||||
- `sendPushbulletFile(String recipient, String content)`
|
||||
- `sendPushbulletFile(String recipient, String title, String messsage, String content)`
|
||||
- `sendPushbulletFile(String recipient, String title, String messsage, String content, String fileName)`
|
||||
|
||||
Since there is a separate rule action instance for each `bot` thing, this needs to be retrieved through `getActions(scope, thingUID)`.
|
||||
The first parameter always has to be `pushbullet` and the second is the full Thing UID of the bot that should be used.
|
||||
@ -56,11 +61,25 @@ Once this action instance is retrieved, you can invoke the action method on it.
|
||||
The recipient can either be an email address, a channel tag or `null`.
|
||||
If it is not specified or properly formatted, the note will be broadcast to all of the user account's devices.
|
||||
|
||||
The file content can be an image URL, a local file path or an Image item state.
|
||||
|
||||
The file name is used in the upload link and how it appears in the push message for non-image content.
|
||||
If it is not specified, it is automatically determined from the image URL or file path.
|
||||
For Image item state content, it defaults to `image.jpg`.
|
||||
|
||||
For the `sendPushbulletNote` action, parameter `message` is required.
|
||||
Likewise, for `sendPushbulletLink`, `url` and for `sendPushbulletFile`, `content` parameters are required.
|
||||
Any other parameters for these actions are optional and can be set to `null`.
|
||||
|
||||
Examples:
|
||||
|
||||
```java
|
||||
val actions = getActions("pushbullet", "pushbullet:bot:r2d2")
|
||||
val result = actions.sendPushbulletNote("someone@example.com", "R2D2 talks here...", "This is the pushed note.")
|
||||
actions.sendPushbulletNote("someone@example.com", "Note Example", "This is the pushed note.")
|
||||
actions.sendPushbulletLink("someone@example.com", "Link Example", "This is the pushed link", "https://example.com")
|
||||
actions.sendPushbulletFile("someone@example.com", "File Example", "This is the pushed file", "https://example.com/image.png")
|
||||
actions.sendPushbulletFile("someone@example.com", null, null, "/path/to/somefile.pdf", "document.pdf")
|
||||
actions.sendPushbulletFile("someone@example.com", ImageItem.state.toFullString)
|
||||
```
|
||||
|
||||
## Full Example
|
||||
|
@ -22,11 +22,12 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Jeremy Setton - Add link and file push type support
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushbulletBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "pushbullet";
|
||||
public static final String BINDING_ID = "pushbullet";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_BOT = new ThingTypeUID(BINDING_ID, "bot");
|
||||
@ -38,8 +39,16 @@ public class PushbulletBindingConstants {
|
||||
public static final String TITLE = "title";
|
||||
public static final String MESSAGE = "message";
|
||||
|
||||
// Binding logic constants
|
||||
public static final String API_METHOD_PUSHES = "pushes";
|
||||
// Thing properties
|
||||
public static final String PROPERTY_EMAIL = "email";
|
||||
public static final String PROPERTY_NAME = "name";
|
||||
|
||||
public static final int TIMEOUT = 30 * 1000; // 30 seconds
|
||||
// Binding logic constants
|
||||
public static final String API_ENDPOINT_PUSHES = "/pushes";
|
||||
public static final String API_ENDPOINT_UPLOAD_REQUEST = "/upload-request";
|
||||
public static final String API_ENDPOINT_USERS_ME = "/users/me";
|
||||
|
||||
public static final String IMAGE_FILE_NAME = "image.jpg";
|
||||
|
||||
public static final int MAX_UPLOAD_SIZE = 26214400;
|
||||
}
|
||||
|
@ -19,37 +19,26 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
* The {@link PushbulletConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Jeremy Setton - Add link and file push type support
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushbulletConfiguration {
|
||||
|
||||
private @Nullable String name;
|
||||
|
||||
private String token = "invalid";
|
||||
private String token = "";
|
||||
|
||||
private String apiUrlBase = "invalid";
|
||||
private String apiUrlBase = "https://api.pushbullet.com/v2";
|
||||
|
||||
public @Nullable String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
public String getAccessToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getApiUrlBase() {
|
||||
return apiUrlBase;
|
||||
}
|
||||
|
||||
public void setApiUrlBase(String apiUrlBase) {
|
||||
this.apiUrlBase = apiUrlBase;
|
||||
}
|
||||
}
|
||||
|
@ -16,24 +16,36 @@ import static org.openhab.binding.pushbullet.internal.PushbulletBindingConstants
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.pushbullet.internal.handler.PushbulletHandler;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link PushbulletHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Jeremy Setton - Add link and file push type support
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.pushbullet", service = ThingHandlerFactory.class)
|
||||
public class PushbulletHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
@Activate
|
||||
public PushbulletHandlerFactory(final @Reference HttpClientFactory httpClientFactory) {
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
@ -44,7 +56,7 @@ public class PushbulletHandlerFactory extends BaseThingHandlerFactory {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_BOT.equals(thingTypeUID)) {
|
||||
return new PushbulletHandler(thing);
|
||||
return new PushbulletHandler(thing, httpClient);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -0,0 +1,203 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.BytesContentProvider;
|
||||
import org.eclipse.jetty.client.util.MultiPartContentProvider;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.openhab.binding.pushbullet.internal.exception.PushbulletApiException;
|
||||
import org.openhab.binding.pushbullet.internal.exception.PushbulletAuthenticationException;
|
||||
import org.openhab.binding.pushbullet.internal.model.InstantDeserializer;
|
||||
import org.openhab.core.OpenHAB;
|
||||
import org.openhab.core.library.types.RawType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link PushbulletHttpClient} handles requests to Pushbullet API
|
||||
*
|
||||
* @author Jeremy Setton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushbulletHttpClient {
|
||||
private static final String AGENT = "openHAB/" + OpenHAB.getVersion();
|
||||
|
||||
private static final int TIMEOUT = 30; // in seconds
|
||||
|
||||
private static final String HEADER_RATELIMIT_RESET = "X-Ratelimit-Reset";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PushbulletHttpClient.class);
|
||||
|
||||
private final Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(Instant.class, new InstantDeserializer())
|
||||
.create();
|
||||
|
||||
private PushbulletConfiguration config = new PushbulletConfiguration();
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public PushbulletHttpClient(HttpClient httpClient) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
public void setConfiguration(PushbulletConfiguration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes an api request
|
||||
*
|
||||
* @param apiEndpoint the request api endpoint
|
||||
* @param responseType the response type
|
||||
* @return the unpacked response
|
||||
* @throws PushbulletApiException
|
||||
*/
|
||||
public <T> T executeRequest(String apiEndpoint, Class<T> responseType) throws PushbulletApiException {
|
||||
return executeRequest(apiEndpoint, null, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes an api request
|
||||
*
|
||||
* @param apiEndpoint the request api endpoint
|
||||
* @param body the request body object
|
||||
* @param responseType the response type
|
||||
* @return the unpacked response
|
||||
* @throws PushbulletApiException
|
||||
*/
|
||||
public <T> T executeRequest(String apiEndpoint, @Nullable Object body, Class<T> responseType)
|
||||
throws PushbulletApiException {
|
||||
String url = config.getApiUrlBase() + apiEndpoint;
|
||||
String accessToken = config.getAccessToken();
|
||||
|
||||
Request request = newRequest(url).header("Access-Token", accessToken);
|
||||
|
||||
if (body != null) {
|
||||
StringContentProvider content = new StringContentProvider(gson.toJson(body));
|
||||
String contentType = MimeTypes.Type.APPLICATION_JSON.asString();
|
||||
|
||||
request.method(HttpMethod.POST).content(content, contentType);
|
||||
}
|
||||
|
||||
String responseBody = sendRequest(request);
|
||||
|
||||
try {
|
||||
T response = Objects.requireNonNull(gson.fromJson(responseBody, responseType));
|
||||
logger.debug("Unpacked Response: {}", response);
|
||||
return response;
|
||||
} catch (JsonSyntaxException e) {
|
||||
logger.debug("Failed to unpack response as '{}': {}", responseType.getSimpleName(), e.getMessage());
|
||||
throw new PushbulletApiException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads a file
|
||||
*
|
||||
* @param url the upload url
|
||||
* @param data the file data
|
||||
* @throws PushbulletApiException
|
||||
*/
|
||||
public void uploadFile(String url, RawType data) throws PushbulletApiException {
|
||||
MultiPartContentProvider content = new MultiPartContentProvider();
|
||||
content.addFieldPart("file", new BytesContentProvider(data.getMimeType(), data.getBytes()), null);
|
||||
|
||||
Request request = newRequest(url).method(HttpMethod.POST).content(content);
|
||||
|
||||
sendRequest(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new http request
|
||||
*
|
||||
* @param url the request url
|
||||
* @return the new Request object with default parameters
|
||||
*/
|
||||
private Request newRequest(String url) {
|
||||
return httpClient.newRequest(url).agent(AGENT).timeout(TIMEOUT, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a http request
|
||||
*
|
||||
* @param request the request to send
|
||||
* @return the response body
|
||||
* @throws PushbulletApiException
|
||||
*/
|
||||
private String sendRequest(Request request) throws PushbulletApiException {
|
||||
try {
|
||||
logger.debug("Request {} {}", request.getMethod(), request.getURI());
|
||||
logger.debug("Request Headers: {}", request.getHeaders());
|
||||
|
||||
ContentResponse response = request.send();
|
||||
|
||||
int statusCode = response.getStatus();
|
||||
String statusReason = response.getReason();
|
||||
String responseBody = response.getContentAsString();
|
||||
|
||||
logger.debug("Got HTTP {} Response: '{}'", statusCode, responseBody);
|
||||
|
||||
switch (statusCode) {
|
||||
case HttpStatus.OK_200:
|
||||
case HttpStatus.NO_CONTENT_204:
|
||||
return responseBody;
|
||||
case HttpStatus.UNAUTHORIZED_401:
|
||||
case HttpStatus.FORBIDDEN_403:
|
||||
throw new PushbulletAuthenticationException(statusReason);
|
||||
case HttpStatus.TOO_MANY_REQUESTS_429:
|
||||
logger.warn("Rate limited for making too many requests until {}",
|
||||
getRateLimitResetTime(response.getHeaders()));
|
||||
default:
|
||||
throw new PushbulletApiException(statusReason);
|
||||
}
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||
logger.debug("Failed to send request: {}", e.getMessage());
|
||||
throw new PushbulletApiException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rate limit reset time included in response headers
|
||||
*
|
||||
* @param headers the response headers
|
||||
* @return the rate limit reset time if found in headers, otherwise null
|
||||
*/
|
||||
private @Nullable Instant getRateLimitResetTime(HttpFields headers) {
|
||||
try {
|
||||
long resetTime = headers.getLongField(HEADER_RATELIMIT_RESET);
|
||||
if (resetTime != -1) {
|
||||
return Instant.ofEpochSecond(resetTime);
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
|
||||
* The {@link PushbulletActions} class defines rule actions for sending notifications
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Jeremy Setton - Add link and file push type support
|
||||
*/
|
||||
@Component(scope = ServiceScope.PROTOTYPE, service = PushbulletActions.class)
|
||||
@ThingActionsScope(name = "pushbullet")
|
||||
@ -52,9 +53,9 @@ public class PushbulletActions implements ThingActions {
|
||||
|
||||
@RuleAction(label = "@text/actionSendPushbulletNoteLabel", description = "@text/actionSendPushbulletNoteDesc")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletNote(
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc") @Nullable String recipient,
|
||||
@ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc") @Nullable String title,
|
||||
@ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc") @Nullable String message) {
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient,
|
||||
@ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc", type = "java.lang.String") @Nullable String title,
|
||||
@ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String", required = true) String message) {
|
||||
logger.trace("sendPushbulletNote '{}', '{}', '{}'", recipient, title, message);
|
||||
|
||||
PushbulletHandler localHandler = handler;
|
||||
@ -63,18 +64,18 @@ public class PushbulletActions implements ThingActions {
|
||||
return false;
|
||||
}
|
||||
|
||||
return localHandler.sendPush(recipient, title, message, "note");
|
||||
return localHandler.sendPushNote(recipient, title, message);
|
||||
}
|
||||
|
||||
public static boolean sendPushbulletNote(ThingActions actions, @Nullable String recipient, @Nullable String title,
|
||||
@Nullable String message) {
|
||||
String message) {
|
||||
return ((PushbulletActions) actions).sendPushbulletNote(recipient, title, message);
|
||||
}
|
||||
|
||||
@RuleAction(label = "@text/actionSendPushbulletNoteLabel", description = "@text/actionSendPushbulletNoteDesc")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletNote(
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc") @Nullable String recipient,
|
||||
@ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc") @Nullable String message) {
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient,
|
||||
@ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String", required = true) String message) {
|
||||
logger.trace("sendPushbulletNote '{}', '{}'", recipient, message);
|
||||
|
||||
PushbulletHandler localHandler = handler;
|
||||
@ -83,11 +84,115 @@ public class PushbulletActions implements ThingActions {
|
||||
return false;
|
||||
}
|
||||
|
||||
return localHandler.sendPush(recipient, message, "note");
|
||||
return localHandler.sendPushNote(recipient, null, message);
|
||||
}
|
||||
|
||||
public static boolean sendPushbulletNote(ThingActions actions, @Nullable String recipient,
|
||||
@Nullable String message) {
|
||||
public static boolean sendPushbulletNote(ThingActions actions, @Nullable String recipient, String message) {
|
||||
return ((PushbulletActions) actions).sendPushbulletNote(recipient, message);
|
||||
}
|
||||
|
||||
@RuleAction(label = "@text/actionSendPushbulletLinkLabel", description = "@text/actionSendPushbulletLinkDesc")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletLink(
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient,
|
||||
@ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc", type = "java.lang.String") @Nullable String title,
|
||||
@ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String") @Nullable String message,
|
||||
@ActionInput(name = "url", label = "@text/actionSendPushbulletLinkInputUrlLabel", description = "@text/actionSendPushbulletLinkInputUrlDesc", type = "java.lang.String", required = true) String url) {
|
||||
logger.trace("sendPushbulletLink '{}', '{}', '{}', '{}'", recipient, title, message, url);
|
||||
|
||||
PushbulletHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
logger.warn("Pushbullet service Handler is null!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return localHandler.sendPushLink(recipient, title, message, url);
|
||||
}
|
||||
|
||||
public static boolean sendPushbulletLink(ThingActions actions, @Nullable String recipient, @Nullable String title,
|
||||
@Nullable String message, String url) {
|
||||
return ((PushbulletActions) actions).sendPushbulletLink(recipient, title, message, url);
|
||||
}
|
||||
|
||||
@RuleAction(label = "@text/actionSendPushbulletLinkLabel", description = "@text/actionSendPushbulletLinkDesc")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletLink(
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient,
|
||||
@ActionInput(name = "url", label = "@text/actionSendPushbulletLinkInputUrlLabel", description = "@text/actionSendPushbulletLinkInputUrlDesc", type = "java.lang.String", required = true) String url) {
|
||||
logger.trace("sendPushbulletLink '{}', '{}'", recipient, url);
|
||||
|
||||
PushbulletHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
logger.warn("Pushbullet service Handler is null!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return localHandler.sendPushLink(recipient, null, null, url);
|
||||
}
|
||||
|
||||
public static boolean sendPushbulletLink(ThingActions actions, @Nullable String recipient, String url) {
|
||||
return ((PushbulletActions) actions).sendPushbulletLink(recipient, url);
|
||||
}
|
||||
|
||||
@RuleAction(label = "@text/actionSendPushbulletFileLabel", description = "@text/actionSendPushbulletFileDesc")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletFile(
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient,
|
||||
@ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc", type = "java.lang.String") @Nullable String title,
|
||||
@ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String") @Nullable String message,
|
||||
@ActionInput(name = "content", label = "@text/actionSendPushbulletFileInputContent", description = "@text/actionSendPushbulletFileInputContentDesc", type = "java.lang.String", required = true) String content,
|
||||
@ActionInput(name = "filename", label = "@text/actionSendPushbulletFileInputName", description = "@text/actionSendPushbulletFileInputNameDesc", type = "java.lang.String") @Nullable String fileName) {
|
||||
logger.trace("sendPushbulletFile '{}', '{}', '{}', '{}', '{}'", recipient, title, message, content, fileName);
|
||||
|
||||
PushbulletHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
logger.warn("Pushbullet service Handler is null!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return localHandler.sendPushFile(recipient, title, message, content, fileName);
|
||||
}
|
||||
|
||||
public static boolean sendPushbulletFile(ThingActions actions, @Nullable String recipient, @Nullable String title,
|
||||
@Nullable String message, String content, @Nullable String filename) {
|
||||
return ((PushbulletActions) actions).sendPushbulletFile(recipient, title, message, content, filename);
|
||||
}
|
||||
|
||||
@RuleAction(label = "@text/actionSendPushbulletFileLabel", description = "@text/actionSendPushbulletFileDesc")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletFile(
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient,
|
||||
@ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc", type = "java.lang.String") @Nullable String title,
|
||||
@ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String") @Nullable String message,
|
||||
@ActionInput(name = "content", label = "@text/actionSendPushbulletFileInputContent", description = "@text/actionSendPushbulletFileInputContentDesc", type = "java.lang.String", required = true) String content) {
|
||||
logger.trace("sendPushbulletFile '{}', '{}', '{}', '{}'", recipient, title, message, content);
|
||||
|
||||
PushbulletHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
logger.warn("Pushbullet service Handler is null!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return localHandler.sendPushFile(recipient, title, message, content, null);
|
||||
}
|
||||
|
||||
public static boolean sendPushbulletFile(ThingActions actions, @Nullable String recipient, @Nullable String title,
|
||||
@Nullable String message, String content) {
|
||||
return ((PushbulletActions) actions).sendPushbulletFile(recipient, title, message, content);
|
||||
}
|
||||
|
||||
@RuleAction(label = "@text/actionSendPushbulletFileLabel", description = "@text/actionSendPushbulletFileDesc")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletFile(
|
||||
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient,
|
||||
@ActionInput(name = "content", label = "@text/actionSendPushbulletFileInputContent", description = "@text/actionSendPushbulletFileInputContentDesc", type = "java.lang.String", required = true) String content) {
|
||||
logger.trace("sendPushbulletFile '{}', '{}'", recipient, content);
|
||||
|
||||
PushbulletHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
logger.warn("Pushbullet service Handler is null!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return localHandler.sendPushFile(recipient, null, null, content, null);
|
||||
}
|
||||
|
||||
public static boolean sendPushbulletFile(ThingActions actions, @Nullable String recipient, String content) {
|
||||
return ((PushbulletActions) actions).sendPushbulletFile(recipient, content);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link PushbulletApiException} represents a Pushbullet API exception
|
||||
*
|
||||
* @author Jeremy Setton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushbulletApiException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public PushbulletApiException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PushbulletApiException(Exception exception) {
|
||||
super(exception);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link PushbulletAuthenticationException} represents a Pushbullet authentication exception
|
||||
*
|
||||
* @author Jeremy Setton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushbulletAuthenticationException extends PushbulletApiException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public PushbulletAuthenticationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -14,14 +14,14 @@ package org.openhab.binding.pushbullet.internal.handler;
|
||||
|
||||
import static org.openhab.binding.pushbullet.internal.PushbulletBindingConstants.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.Properties;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.mail.internet.AddressException;
|
||||
@ -29,49 +29,51 @@ import javax.mail.internet.InternetAddress;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.pushbullet.internal.PushbulletConfiguration;
|
||||
import org.openhab.binding.pushbullet.internal.PushbulletHttpClient;
|
||||
import org.openhab.binding.pushbullet.internal.action.PushbulletActions;
|
||||
import org.openhab.binding.pushbullet.internal.model.Push;
|
||||
import org.openhab.binding.pushbullet.internal.exception.PushbulletApiException;
|
||||
import org.openhab.binding.pushbullet.internal.exception.PushbulletAuthenticationException;
|
||||
import org.openhab.binding.pushbullet.internal.model.PushRequest;
|
||||
import org.openhab.binding.pushbullet.internal.model.PushResponse;
|
||||
import org.openhab.binding.pushbullet.internal.model.PushType;
|
||||
import org.openhab.binding.pushbullet.internal.model.UploadRequest;
|
||||
import org.openhab.binding.pushbullet.internal.model.UploadResponse;
|
||||
import org.openhab.binding.pushbullet.internal.model.User;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.openhab.core.library.types.RawType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.osgi.framework.FrameworkUtil;
|
||||
import org.osgi.framework.Version;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
/**
|
||||
* The {@link PushbulletHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Jeremy Setton - Add link and file push type support
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushbulletHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PushbulletHandler.class);
|
||||
|
||||
private final Gson gson = new GsonBuilder().create();
|
||||
|
||||
private static final Version VERSION = FrameworkUtil.getBundle(PushbulletHandler.class).getVersion();
|
||||
|
||||
private static final Pattern CHANNEL_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]+$");
|
||||
|
||||
private @Nullable PushbulletConfiguration config;
|
||||
private final Logger logger = LoggerFactory.getLogger(PushbulletHandler.class);
|
||||
|
||||
public PushbulletHandler(Thing thing) {
|
||||
private final PushbulletHttpClient httpClient;
|
||||
|
||||
private int maxUploadSize;
|
||||
|
||||
public PushbulletHandler(Thing thing, HttpClient httpClient) {
|
||||
super(thing);
|
||||
this.httpClient = new PushbulletHttpClient(httpClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -86,13 +88,42 @@ public class PushbulletHandler extends BaseThingHandler {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Start initializing!");
|
||||
config = getConfigAs(PushbulletConfiguration.class);
|
||||
logger.debug("Starting {}", thing.getUID());
|
||||
|
||||
// Name and Token are both "required", so set the Thing immediately ONLINE.
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
PushbulletConfiguration config = getConfigAs(PushbulletConfiguration.class);
|
||||
|
||||
logger.debug("Finished initializing!");
|
||||
if (config.getAccessToken().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Undefined access token.");
|
||||
return;
|
||||
}
|
||||
|
||||
httpClient.setConfiguration(config);
|
||||
|
||||
scheduler.execute(() -> retrieveAccountInfo());
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
}
|
||||
|
||||
private void retrieveAccountInfo() {
|
||||
try {
|
||||
User user = httpClient.executeRequest(API_ENDPOINT_USERS_ME, User.class);
|
||||
|
||||
maxUploadSize = Objects.requireNonNullElse(user.getMaxUploadSize(), MAX_UPLOAD_SIZE);
|
||||
|
||||
logger.debug("Set maximum upload size for {} to {} bytes", thing.getUID(), maxUploadSize);
|
||||
|
||||
updateProperty(PROPERTY_NAME, user.getName());
|
||||
updateProperty(PROPERTY_EMAIL, user.getEmail());
|
||||
|
||||
logger.debug("Updated properties for {} to {}", thing.getUID(), thing.getProperties());
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (PushbulletAuthenticationException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid access token.");
|
||||
} catch (PushbulletApiException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Unable to retrieve account info.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,125 +131,227 @@ public class PushbulletHandler extends BaseThingHandler {
|
||||
return Set.of(PushbulletActions.class);
|
||||
}
|
||||
|
||||
public boolean sendPush(@Nullable String recipient, @Nullable String message, String type) {
|
||||
return sendPush(recipient, "", message, type);
|
||||
/**
|
||||
* Sends a push note
|
||||
*
|
||||
* @param recipient the recipient
|
||||
* @param title the title
|
||||
* @param message the message
|
||||
* @return true if successful
|
||||
*/
|
||||
public boolean sendPushNote(@Nullable String recipient, @Nullable String title, String message) {
|
||||
PushRequest request = newPushRequest(recipient, title, message, PushType.NOTE);
|
||||
|
||||
return sendPush(request);
|
||||
}
|
||||
|
||||
public boolean sendPush(@Nullable String recipient, @Nullable String title, @Nullable String message, String type) {
|
||||
boolean result = false;
|
||||
/**
|
||||
* Sends a push link
|
||||
*
|
||||
* @param recipient the recipient
|
||||
* @param title the title
|
||||
* @param message the message
|
||||
* @param url the message url
|
||||
* @return true if successful
|
||||
*/
|
||||
public boolean sendPushLink(@Nullable String recipient, @Nullable String title, @Nullable String message,
|
||||
String url) {
|
||||
PushRequest request = newPushRequest(recipient, title, message, PushType.LINK);
|
||||
request.setUrl(url);
|
||||
|
||||
logger.debug("sendPush is called for ");
|
||||
logger.debug("Thing {}", thing);
|
||||
logger.debug("Thing Label: '{}'", thing.getLabel());
|
||||
return sendPush(request);
|
||||
}
|
||||
|
||||
PushbulletConfiguration configuration = getConfigAs(PushbulletConfiguration.class);
|
||||
logger.debug("CFG {}", configuration);
|
||||
|
||||
Properties headers = prepareRequestHeaders(configuration);
|
||||
|
||||
String request = prepareMessageBody(recipient, title, message, type);
|
||||
|
||||
try (InputStream stream = new ByteArrayInputStream(request.getBytes(StandardCharsets.UTF_8))) {
|
||||
String pushAPI = configuration.getApiUrlBase() + "/" + API_METHOD_PUSHES;
|
||||
|
||||
String responseString = HttpUtil.executeUrl(HttpMethod.POST.asString(), pushAPI, headers, stream,
|
||||
MimeTypes.Type.APPLICATION_JSON.asString(), TIMEOUT);
|
||||
|
||||
logger.debug("Got Response: {}", responseString);
|
||||
PushResponse response = gson.fromJson(responseString, PushResponse.class);
|
||||
|
||||
logger.debug("Unpacked Response: {}", response);
|
||||
|
||||
if ((null != response) && (null == response.getPushError())) {
|
||||
result = true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.warn("IO problems pushing note: {}", e.getMessage());
|
||||
/**
|
||||
* Sends a push file
|
||||
*
|
||||
* @param recipient the recipient
|
||||
* @param title the title
|
||||
* @param message the message
|
||||
* @param content the file content
|
||||
* @param fileName the file name
|
||||
* @return true if successful
|
||||
*/
|
||||
public boolean sendPushFile(@Nullable String recipient, @Nullable String title, @Nullable String message,
|
||||
String content, @Nullable String fileName) {
|
||||
UploadResponse upload = uploadFile(content, fileName);
|
||||
if (upload == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return result;
|
||||
PushRequest request = newPushRequest(recipient, title, message, PushType.FILE);
|
||||
request.setFileName(upload.getFileName());
|
||||
request.setFileType(upload.getFileType());
|
||||
request.setFileUrl(upload.getFileUrl());
|
||||
|
||||
return sendPush(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to populate the request headers
|
||||
* Helper method to send a push request
|
||||
*
|
||||
* @param configuration
|
||||
* @return
|
||||
* @param request the push request
|
||||
* @return true if successful
|
||||
*/
|
||||
private Properties prepareRequestHeaders(PushbulletConfiguration configuration) {
|
||||
Properties headers = new Properties();
|
||||
headers.put(HttpHeader.USER_AGENT, "openHAB / Pushbullet binding " + VERSION);
|
||||
headers.put(HttpHeader.CONTENT_TYPE, MimeTypes.Type.APPLICATION_JSON.asString());
|
||||
headers.put("Access-Token", configuration.getToken());
|
||||
private boolean sendPush(PushRequest request) {
|
||||
logger.debug("Sending push notification for {}", thing.getUID());
|
||||
logger.debug("Push Request: {}", request);
|
||||
|
||||
logger.debug("Headers: {}", headers);
|
||||
|
||||
return headers;
|
||||
try {
|
||||
httpClient.executeRequest(API_ENDPOINT_PUSHES, request, PushResponse.class);
|
||||
return true;
|
||||
} catch (PushbulletApiException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to create a message body from data to be transferred.
|
||||
* Helper method to upload a file to use in push message
|
||||
*
|
||||
* @param recipient
|
||||
* @param title
|
||||
* @param message
|
||||
* @param type
|
||||
*
|
||||
* @return the message as a String to be posted
|
||||
* @param content the file content
|
||||
* @param fileName the file name
|
||||
* @return the upload response if successful, otherwise null
|
||||
*/
|
||||
private String prepareMessageBody(@Nullable String recipient, @Nullable String title, @Nullable String message,
|
||||
String type) {
|
||||
private @Nullable UploadResponse uploadFile(String content, @Nullable String fileName) {
|
||||
RawType data = getContentData(content);
|
||||
if (data == null) {
|
||||
logger.warn("Failed to get content data from '{}'", content);
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.debug("Content Data: {}", data);
|
||||
|
||||
int size = data.getBytes().length;
|
||||
if (size > maxUploadSize) {
|
||||
logger.warn("Content data size {} is greater than maximum upload size {}", size, maxUploadSize);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
UploadRequest request = new UploadRequest();
|
||||
request.setFileName(fileName != null ? fileName : getContentFileName(content));
|
||||
request.setFileType(data.getMimeType());
|
||||
|
||||
logger.debug("Upload Request: {}", request);
|
||||
|
||||
UploadResponse response = httpClient.executeRequest(API_ENDPOINT_UPLOAD_REQUEST, request,
|
||||
UploadResponse.class);
|
||||
|
||||
String uploadUrl = response.getUploadUrl();
|
||||
if (uploadUrl == null) {
|
||||
throw new PushbulletApiException("Undefined upload url");
|
||||
}
|
||||
|
||||
httpClient.uploadFile(uploadUrl, data);
|
||||
|
||||
return response;
|
||||
} catch (PushbulletApiException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the data for a given content
|
||||
*
|
||||
* @param content the file content
|
||||
* @return the data raw type if available, otherwise null
|
||||
*/
|
||||
private @Nullable RawType getContentData(String content) {
|
||||
try {
|
||||
if (content.startsWith("data:")) {
|
||||
return RawType.valueOf(content);
|
||||
} else if (content.startsWith("http")) {
|
||||
return HttpUtil.downloadImage(content);
|
||||
} else {
|
||||
Path path = Path.of(content);
|
||||
byte[] bytes = Files.readAllBytes(path);
|
||||
String mimeType = Files.probeContentType(path);
|
||||
return new RawType(bytes, mimeType);
|
||||
}
|
||||
} catch (IllegalArgumentException | IOException e) {
|
||||
logger.debug("Failed to get content data: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the file name for a given content
|
||||
*
|
||||
* @param content the file content
|
||||
* @return the file name if available, otherwise null
|
||||
*/
|
||||
private @Nullable String getContentFileName(String content) {
|
||||
if (content.startsWith("data:")) {
|
||||
return IMAGE_FILE_NAME;
|
||||
}
|
||||
try {
|
||||
Path fileName = Path.of(content.startsWith("http") ? new URL(content).getPath() : content).getFileName();
|
||||
if (fileName != null) {
|
||||
return fileName.toString();
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
logger.debug("Malformed url content: {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create a push request
|
||||
*
|
||||
* @param recipient the recipient
|
||||
* @param title the title
|
||||
* @param message the message
|
||||
* @param type the push type
|
||||
*
|
||||
* @return the push request object
|
||||
*/
|
||||
private PushRequest newPushRequest(@Nullable String recipient, @Nullable String title, @Nullable String message,
|
||||
PushType type) {
|
||||
logger.debug("Recipient is '{}'", recipient);
|
||||
logger.debug("Title is '{}'", title);
|
||||
logger.debug("Message is '{}'", message);
|
||||
logger.debug("Type is '{}'", type);
|
||||
|
||||
Push push = new Push();
|
||||
push.setTitle(title);
|
||||
push.setBody(message);
|
||||
push.setType(type);
|
||||
PushRequest request = new PushRequest();
|
||||
request.setTitle(title);
|
||||
request.setBody(message);
|
||||
request.setType(type);
|
||||
|
||||
if (recipient != null) {
|
||||
if (isValidEmail(recipient)) {
|
||||
logger.debug("Recipient is an email address");
|
||||
push.setEmail(recipient);
|
||||
request.setEmail(recipient);
|
||||
} else if (isValidChannel(recipient)) {
|
||||
logger.debug("Recipient is a channel tag");
|
||||
push.setChannel(recipient);
|
||||
request.setChannel(recipient);
|
||||
} else {
|
||||
logger.warn("Invalid recipient: {}", recipient);
|
||||
logger.warn("Message will be broadcast to all user's devices.");
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Push: {}", push);
|
||||
|
||||
String request = gson.toJson(push);
|
||||
logger.debug("Packed Request: {}", request);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method checking if channel tag is valid.
|
||||
* Helper method checking if channel tag is valid
|
||||
*
|
||||
* @param channel
|
||||
* @return
|
||||
* @param channel the channel tag
|
||||
* @return true if matches pattern
|
||||
*/
|
||||
private static boolean isValidChannel(String channel) {
|
||||
Matcher m = CHANNEL_PATTERN.matcher(channel);
|
||||
return m.matches();
|
||||
return CHANNEL_PATTERN.matcher(channel).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method checking if email address is valid.
|
||||
* Helper method checking if email address is valid
|
||||
*
|
||||
* @param email
|
||||
* @return
|
||||
* @param email the email address
|
||||
* @return true if parsed successfully
|
||||
*/
|
||||
private static boolean isValidEmail(String email) {
|
||||
try {
|
||||
InternetAddress emailAddr = new InternetAddress(email);
|
||||
emailAddr.validate();
|
||||
new InternetAddress(email, true);
|
||||
return true;
|
||||
} catch (AddressException e) {
|
||||
return false;
|
||||
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* The {@link InstantDeserializer} deserializes a timestamp returned by the API.
|
||||
*
|
||||
* @author Jeremy Setton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class InstantDeserializer implements JsonDeserializer<Instant> {
|
||||
|
||||
@Override
|
||||
public @Nullable Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
|
||||
BigDecimal timestamp = json.getAsBigDecimal();
|
||||
BigDecimal[] parts = timestamp.divideAndRemainder(BigDecimal.ONE);
|
||||
long seconds = parts[0].longValueExact();
|
||||
long nanos = parts[1].movePointRight(9).longValue();
|
||||
return Instant.ofEpochSecond(seconds, nanos);
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* This class represents the push request sent to the API.
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Hakan Tandogan - Migrated from openHAB 1 action with the same name
|
||||
*/
|
||||
public class Push {
|
||||
|
||||
@SerializedName("title")
|
||||
private String title;
|
||||
|
||||
@SerializedName("body")
|
||||
private String body;
|
||||
|
||||
@SerializedName("type")
|
||||
private String type;
|
||||
|
||||
@SerializedName("email")
|
||||
private String email;
|
||||
|
||||
@SerializedName("channel_tag")
|
||||
private String channelTag;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getChannel() {
|
||||
return channelTag;
|
||||
}
|
||||
|
||||
public void setChannel(String channelTag) {
|
||||
this.channelTag = channelTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Push {" + "title='" + title + '\'' + ", body='" + body + '\'' + ", type='" + type + '\'' + ", email='"
|
||||
+ email + '\'' + ", channelTag='" + channelTag + '\'' + '}';
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* This class represents errors in the response fetched from the API.
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Hakan Tandogan - Migrated from openHAB 1 action with the same name
|
||||
*/
|
||||
public class PushError {
|
||||
|
||||
@SerializedName("type")
|
||||
private String type;
|
||||
|
||||
@SerializedName("message")
|
||||
private String message;
|
||||
|
||||
@SerializedName("param")
|
||||
private String param;
|
||||
|
||||
@SerializedName("cat")
|
||||
private String cat;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getParam() {
|
||||
return param;
|
||||
}
|
||||
|
||||
public void setParam(String param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
public String getCat() {
|
||||
return cat;
|
||||
}
|
||||
|
||||
public void setCat(String cat) {
|
||||
this.cat = cat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PushError {" + "type='" + type + '\'' + ", message='" + message + '\'' + ", param='" + param + '\''
|
||||
+ ", cat='" + cat + '\'' + '}';
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* This class represents the push request sent to the API.
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Hakan Tandogan - Migrated from openHAB 1 action with the same name
|
||||
* @author Jeremy Setton - Add link and file push type support
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushRequest {
|
||||
|
||||
@SerializedName("type")
|
||||
private @Nullable PushType type;
|
||||
|
||||
@SerializedName("title")
|
||||
private @Nullable String title;
|
||||
|
||||
@SerializedName("body")
|
||||
private @Nullable String body;
|
||||
|
||||
@SerializedName("url")
|
||||
private @Nullable String url;
|
||||
|
||||
@SerializedName("file_name")
|
||||
private @Nullable String fileName;
|
||||
|
||||
@SerializedName("file_type")
|
||||
private @Nullable String fileType;
|
||||
|
||||
@SerializedName("file_url")
|
||||
private @Nullable String fileUrl;
|
||||
|
||||
@SerializedName("source_device_iden")
|
||||
private @Nullable String sourceDeviceIden;
|
||||
|
||||
@SerializedName("device_iden")
|
||||
private @Nullable String deviceIden;
|
||||
|
||||
@SerializedName("client_iden")
|
||||
private @Nullable String clientIden;
|
||||
|
||||
@SerializedName("channel_tag")
|
||||
private @Nullable String channelTag;
|
||||
|
||||
@SerializedName("email")
|
||||
private @Nullable String email;
|
||||
|
||||
@SerializedName("guid")
|
||||
private @Nullable String guid;
|
||||
|
||||
public void setTitle(@Nullable String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void setType(@Nullable PushType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setBody(@Nullable String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public void setUrl(@Nullable String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void setFileName(@Nullable String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public void setFileType(@Nullable String fileType) {
|
||||
this.fileType = fileType;
|
||||
}
|
||||
|
||||
public void setFileUrl(@Nullable String fileUrl) {
|
||||
this.fileUrl = fileUrl;
|
||||
}
|
||||
|
||||
public void setSourceDeviceIden(@Nullable String sourceDeviceIden) {
|
||||
this.sourceDeviceIden = sourceDeviceIden;
|
||||
}
|
||||
|
||||
public void setDeviceIden(@Nullable String deviceIden) {
|
||||
this.deviceIden = deviceIden;
|
||||
}
|
||||
|
||||
public void setClientIden(@Nullable String clientIden) {
|
||||
this.clientIden = clientIden;
|
||||
}
|
||||
|
||||
public void setChannel(@Nullable String channelTag) {
|
||||
this.channelTag = channelTag;
|
||||
}
|
||||
|
||||
public void setEmail(@Nullable String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public void setGuid(@Nullable String guid) {
|
||||
this.guid = guid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Push {type='" + type + "', title='" + title + "', body='" + body + "', url='" + url + "', fileName='"
|
||||
+ fileName + "', fileType='" + fileType + "', fileUrl='" + fileUrl + "', sourceDeviceIden='"
|
||||
+ sourceDeviceIden + "', deviceIden='" + deviceIden + "', clientIden='" + clientIden + "', channelTag='"
|
||||
+ channelTag + "', email='" + email + "', guid='" + guid + "'}";
|
||||
}
|
||||
}
|
@ -12,200 +12,238 @@
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* This class represents the answer to pushes provided by the API.
|
||||
* This class represents the push response received from the API.
|
||||
*
|
||||
* @author Hakan Tandogan - Initial contribution
|
||||
* @author Hakan Tandogan - Migrated from openHAB 1 action with the same name
|
||||
* @author Jeremy Setton - Add link and file push type support
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushResponse {
|
||||
|
||||
@SerializedName("active")
|
||||
private String active;
|
||||
|
||||
@SerializedName("iden")
|
||||
private String iden;
|
||||
private @Nullable String iden;
|
||||
|
||||
@SerializedName("active")
|
||||
private @Nullable Boolean active;
|
||||
|
||||
@SerializedName("created")
|
||||
private @Nullable Instant created;
|
||||
|
||||
@SerializedName("modified")
|
||||
private @Nullable Instant modified;
|
||||
|
||||
@SerializedName("type")
|
||||
private String type;
|
||||
private @Nullable PushType type;
|
||||
|
||||
@SerializedName("dismissed")
|
||||
private Boolean dismissed;
|
||||
private @Nullable Boolean dismissed;
|
||||
|
||||
@SerializedName("guid")
|
||||
private @Nullable String guid;
|
||||
|
||||
@SerializedName("direction")
|
||||
private String direction;
|
||||
private @Nullable String direction;
|
||||
|
||||
@SerializedName("sender_iden")
|
||||
private String senderIdentifier;
|
||||
private @Nullable String senderIdentifier;
|
||||
|
||||
@SerializedName("sender_email")
|
||||
private String senderEmail;
|
||||
private @Nullable String senderEmail;
|
||||
|
||||
@SerializedName("sender_email_normalized")
|
||||
private String senderEmailNormalized;
|
||||
private @Nullable String senderEmailNormalized;
|
||||
|
||||
@SerializedName("sender_name")
|
||||
private String senderName;
|
||||
private @Nullable String senderName;
|
||||
|
||||
@SerializedName("receiver_iden")
|
||||
private String receiverIdentifier;
|
||||
private @Nullable String receiverIdentifier;
|
||||
|
||||
@SerializedName("receiver_email")
|
||||
private String receiverEmail;
|
||||
private @Nullable String receiverEmail;
|
||||
|
||||
@SerializedName("receiver_email_normalized")
|
||||
private String receiverEmailNormalized;
|
||||
private @Nullable String receiverEmailNormalized;
|
||||
|
||||
@SerializedName("target_device_iden")
|
||||
private @Nullable String targetDeviceIden;
|
||||
|
||||
@SerializedName("source_device_iden")
|
||||
private @Nullable String sourceDeviceIden;
|
||||
|
||||
@SerializedName("client_iden")
|
||||
private @Nullable String clientIden;
|
||||
|
||||
@SerializedName("channel_iden")
|
||||
private @Nullable String channelIden;
|
||||
|
||||
@SerializedName("awake_app_guids")
|
||||
private @Nullable List<String> awakeAppGuids;
|
||||
|
||||
@SerializedName("title")
|
||||
private String title;
|
||||
private @Nullable String title;
|
||||
|
||||
@SerializedName("body")
|
||||
private String body;
|
||||
private @Nullable String body;
|
||||
|
||||
@SerializedName("error_code")
|
||||
private String errorCode;
|
||||
@SerializedName("url")
|
||||
private @Nullable String url;
|
||||
|
||||
@SerializedName("error")
|
||||
private PushError pushError;
|
||||
@SerializedName("file_name")
|
||||
private @Nullable String fileName;
|
||||
|
||||
public String getActive() {
|
||||
return active;
|
||||
}
|
||||
@SerializedName("file_type")
|
||||
private @Nullable String fileType;
|
||||
|
||||
public void setActive(String active) {
|
||||
this.active = active;
|
||||
}
|
||||
@SerializedName("file_url")
|
||||
private @Nullable String fileUrl;
|
||||
|
||||
public String getIden() {
|
||||
@SerializedName("image_url")
|
||||
private @Nullable String imageUrl;
|
||||
|
||||
@SerializedName("image_width")
|
||||
private @Nullable Integer imageWidth;
|
||||
|
||||
@SerializedName("image_height")
|
||||
private @Nullable Integer imageHeight;
|
||||
|
||||
public @Nullable String getIden() {
|
||||
return iden;
|
||||
}
|
||||
|
||||
public void setIden(String iden) {
|
||||
this.iden = iden;
|
||||
public @Nullable Boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
public @Nullable Instant getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public @Nullable Instant getModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public @Nullable PushType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Boolean getDismissed() {
|
||||
public @Nullable Boolean getDismissed() {
|
||||
return dismissed;
|
||||
}
|
||||
|
||||
public void setDismissed(Boolean dismissed) {
|
||||
this.dismissed = dismissed;
|
||||
public @Nullable String getGuid() {
|
||||
return guid;
|
||||
}
|
||||
|
||||
public String getDirection() {
|
||||
public @Nullable String getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setDirection(String direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public String getSenderIdentifier() {
|
||||
public @Nullable String getSenderIdentifier() {
|
||||
return senderIdentifier;
|
||||
}
|
||||
|
||||
public void setSenderIdentifier(String senderIdentifier) {
|
||||
this.senderIdentifier = senderIdentifier;
|
||||
}
|
||||
|
||||
public String getSenderEmail() {
|
||||
public @Nullable String getSenderEmail() {
|
||||
return senderEmail;
|
||||
}
|
||||
|
||||
public void setSenderEmail(String senderEmail) {
|
||||
this.senderEmail = senderEmail;
|
||||
}
|
||||
|
||||
public String getSenderEmailNormalized() {
|
||||
public @Nullable String getSenderEmailNormalized() {
|
||||
return senderEmailNormalized;
|
||||
}
|
||||
|
||||
public void setSenderEmailNormalized(String senderEmailNormalized) {
|
||||
this.senderEmailNormalized = senderEmailNormalized;
|
||||
}
|
||||
|
||||
public String getSenderName() {
|
||||
public @Nullable String getSenderName() {
|
||||
return senderName;
|
||||
}
|
||||
|
||||
public void setSenderName(String senderName) {
|
||||
this.senderName = senderName;
|
||||
}
|
||||
|
||||
public String getReceiverIdentifier() {
|
||||
public @Nullable String getReceiverIdentifier() {
|
||||
return receiverIdentifier;
|
||||
}
|
||||
|
||||
public void setReceiverIdentifier(String receiverIdentifier) {
|
||||
this.receiverIdentifier = receiverIdentifier;
|
||||
}
|
||||
|
||||
public String getReceiverEmail() {
|
||||
public @Nullable String getReceiverEmail() {
|
||||
return receiverEmail;
|
||||
}
|
||||
|
||||
public void setReceiverEmail(String receiverEmail) {
|
||||
this.receiverEmail = receiverEmail;
|
||||
}
|
||||
|
||||
public String getReceiverEmailNormalized() {
|
||||
public @Nullable String getReceiverEmailNormalized() {
|
||||
return receiverEmailNormalized;
|
||||
}
|
||||
|
||||
public void setReceiverEmailNormalized(String receiverEmailNormalized) {
|
||||
this.receiverEmailNormalized = receiverEmailNormalized;
|
||||
public @Nullable String getTargetDeviceIden() {
|
||||
return targetDeviceIden;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
public @Nullable String getSourceDeviceIden() {
|
||||
return sourceDeviceIden;
|
||||
}
|
||||
|
||||
public @Nullable String getClientIden() {
|
||||
return clientIden;
|
||||
}
|
||||
|
||||
public @Nullable String getChannelIden() {
|
||||
return channelIden;
|
||||
}
|
||||
|
||||
public @Nullable List<String> getAwakeAppGuids() {
|
||||
return awakeAppGuids;
|
||||
}
|
||||
|
||||
public @Nullable String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
public @Nullable String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
public @Nullable String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
public @Nullable String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setErrorCode(String errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
public @Nullable String getFileType() {
|
||||
return fileType;
|
||||
}
|
||||
|
||||
public PushError getPushError() {
|
||||
return pushError;
|
||||
public @Nullable String getFileUrl() {
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
public void setPushError(PushError pushError) {
|
||||
this.pushError = pushError;
|
||||
public @Nullable String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public @Nullable Integer getImageWidth() {
|
||||
return imageWidth;
|
||||
}
|
||||
|
||||
public @Nullable Integer getImageHeight() {
|
||||
return imageHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PushResponse {" + "active='" + active + '\'' + ", iden='" + iden + '\'' + ", type='" + type + '\''
|
||||
+ ", dismissed=" + dismissed + ", direction='" + direction + '\'' + ", senderIdentifier='"
|
||||
+ senderIdentifier + '\'' + ", senderEmail='" + senderEmail + '\'' + ", senderEmailNormalized='"
|
||||
+ senderEmailNormalized + '\'' + ", senderName='" + senderName + '\'' + ", receiverIdentifier='"
|
||||
+ receiverIdentifier + '\'' + ", receiverEmail='" + receiverEmail + '\'' + ", receiverEmailNormalized='"
|
||||
+ receiverEmailNormalized + '\'' + ", title='" + title + '\'' + ", body='" + body + '\''
|
||||
+ ", errorCode='" + errorCode + '\'' + ", pushError=" + pushError + '}';
|
||||
return "PushResponse {iden='" + iden + ", active='" + active + "', created='" + created + "', modified='"
|
||||
+ modified + "', type='" + type + "', dismissed='" + dismissed + "', guid='" + guid + "', direction='"
|
||||
+ direction + "', senderIdentifier='" + senderIdentifier + "', senderEmail='" + senderEmail
|
||||
+ "', senderEmailNormalized='" + senderEmailNormalized + "', senderName='" + senderName
|
||||
+ "', receiverIdentifier='" + receiverIdentifier + "', receiverEmail='" + receiverEmail
|
||||
+ "', receiverEmailNormalized='" + receiverEmailNormalized + "', targetDeviceIden='" + targetDeviceIden
|
||||
+ "', sourceDeviceIden='" + sourceDeviceIden + "', clientIden='" + clientIden + "', channelIden='"
|
||||
+ channelIden + "', awakeAppGuids='" + awakeAppGuids + "', title='" + title + "', body='" + body
|
||||
+ "', url='" + url + "', fileName='" + fileName + "', fileType='" + fileType + "', fileUrl='" + fileUrl
|
||||
+ "', imageUrl='" + imageUrl + "', imageWidth='" + imageWidth + "', imageHeight='" + imageHeight + "'}";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* This class represents the push type.
|
||||
*
|
||||
* @author Jeremy Setton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum PushType {
|
||||
@SerializedName("note")
|
||||
NOTE,
|
||||
@SerializedName("link")
|
||||
LINK,
|
||||
@SerializedName("file")
|
||||
FILE
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* This class represents the upload request sent to the API.
|
||||
*
|
||||
* @author Jeremy Setton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UploadRequest {
|
||||
|
||||
@SerializedName("file_name")
|
||||
private @Nullable String fileName;
|
||||
|
||||
@SerializedName("file_type")
|
||||
private @Nullable String fileType;
|
||||
|
||||
public void setFileName(@Nullable String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public void setFileType(@Nullable String fileType) {
|
||||
this.fileType = fileType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UploadRequest {fileName='" + fileName + "', fileType='" + fileType + "'}";
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* This class represents the upload response received from the API.
|
||||
*
|
||||
* @author Jeremy Setton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UploadResponse {
|
||||
|
||||
@SerializedName("file_name")
|
||||
private @Nullable String fileName;
|
||||
|
||||
@SerializedName("file_type")
|
||||
private @Nullable String fileType;
|
||||
|
||||
@SerializedName("file_url")
|
||||
private @Nullable String fileUrl;
|
||||
|
||||
@SerializedName("upload_url")
|
||||
private @Nullable String uploadUrl;
|
||||
|
||||
public @Nullable String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public @Nullable String getFileType() {
|
||||
return fileType;
|
||||
}
|
||||
|
||||
public @Nullable String getFileUrl() {
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
public @Nullable String getUploadUrl() {
|
||||
return uploadUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UploadResponse {fileName='" + fileName + "', fileType='" + fileType + "', fileUrl='" + fileUrl
|
||||
+ "', uploadUrl='" + uploadUrl + "'}";
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pushbullet.internal.model;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* This class represents the user object received from the API.
|
||||
*
|
||||
* @author Jeremy Setton - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class User {
|
||||
|
||||
@SerializedName("iden")
|
||||
private @Nullable String iden;
|
||||
|
||||
@SerializedName("active")
|
||||
private @Nullable Boolean active;
|
||||
|
||||
@SerializedName("created")
|
||||
private @Nullable Instant created;
|
||||
|
||||
@SerializedName("modified")
|
||||
private @Nullable Instant modified;
|
||||
|
||||
@SerializedName("email")
|
||||
private @Nullable String email;
|
||||
|
||||
@SerializedName("email_normalized")
|
||||
private @Nullable String emailNormalized;
|
||||
|
||||
@SerializedName("name")
|
||||
private @Nullable String name;
|
||||
|
||||
@SerializedName("image_url")
|
||||
private @Nullable String imageUrl;
|
||||
|
||||
@SerializedName("max_upload_size")
|
||||
private @Nullable Integer maxUploadSize;
|
||||
|
||||
@SerializedName("referred_count")
|
||||
private @Nullable Integer referredCount;
|
||||
|
||||
@SerializedName("referrer_iden")
|
||||
private @Nullable String referrerIden;
|
||||
|
||||
public @Nullable String getIden() {
|
||||
return iden;
|
||||
}
|
||||
|
||||
public @Nullable Boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public @Nullable Instant getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public @Nullable Instant getModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public @Nullable String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public @Nullable String getEmailNormalized() {
|
||||
return emailNormalized;
|
||||
}
|
||||
|
||||
public @Nullable String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public @Nullable String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public @Nullable Integer getMaxUploadSize() {
|
||||
return maxUploadSize;
|
||||
}
|
||||
|
||||
public @Nullable Integer getReferredCount() {
|
||||
return referredCount;
|
||||
}
|
||||
|
||||
public @Nullable String getReferrerIden() {
|
||||
return referrerIden;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User {iden='" + iden + ", active='" + active + "', created='" + created + "', modified='" + modified
|
||||
+ "', email='" + email + "', emailNormalized='" + emailNormalized + "', name='" + name + "', imageUrl='"
|
||||
+ imageUrl + "', maxUploadSize='" + maxUploadSize + "', referredCount='" + referredCount
|
||||
+ "', referrerIden='" + referrerIden + "'}";
|
||||
}
|
||||
}
|
@ -4,8 +4,8 @@
|
||||
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
|
||||
|
||||
<type>binding</type>
|
||||
<name>@text/addon.pushbullet.name</name>
|
||||
<description>@text/addon.pushbullet.description</description>
|
||||
<name>Pushbullet Binding</name>
|
||||
<description>The Pushbullet binding allows you to send messages to other users of the Pushbullet service.</description>
|
||||
<connection>cloud</connection>
|
||||
|
||||
</addon:addon>
|
||||
|
@ -2,9 +2,33 @@
|
||||
addon.pushbullet.name = Pushbullet Binding
|
||||
addon.pushbullet.description = The Pushbullet binding allows you to send messages to other users of the Pushbullet service.
|
||||
|
||||
# thing types
|
||||
thing-type.pushbullet.bot.label = Pushbullet Bot
|
||||
thing-type.pushbullet.bot.description = Bot to send messages with.
|
||||
|
||||
# thing types config
|
||||
thing-type.config.pushbullet.bot.name.label = Name
|
||||
thing-type.config.pushbullet.bot.name.description = Explicit Name of Bot, if wanted
|
||||
thing-type.config.pushbullet.bot.token.label = Access Token
|
||||
thing-type.config.pushbullet.bot.token.description = Access token obtained from the account settings page
|
||||
thing-type.config.pushbullet.bot.apiUrlBase.label = API Server
|
||||
thing-type.config.pushbullet.bot.apiUrlBase.description = The Pushbullet API Server to use, for local testing
|
||||
|
||||
# channel types
|
||||
channel-type.pushbullet.recipient-channel.label = Recipient
|
||||
channel-type.pushbullet.recipient-channel.description = Mail address or Channel Name
|
||||
channel-type.pushbullet.title-channel.label = Title
|
||||
channel-type.pushbullet.title-channel.description = Title of the message
|
||||
channel-type.pushbullet.message-channel.label = Message
|
||||
channel-type.pushbullet.message-channel.description = The text that is to be sent
|
||||
|
||||
# action
|
||||
actionSendPushbulletNoteLabel = publish a Pushbullet message
|
||||
actionSendPushbulletNoteDesc = Publishes a Title to the given Pushbullet Recipient.
|
||||
actionSendPushbulletNoteDesc = Publishes a note to the given Pushbullet Recipient.
|
||||
actionSendPushbulletLinkLabel = publish a Pushbullet message with link
|
||||
actionSendPushbulletLinkDesc = Publishes a link to the given Pushbullet Recipient.
|
||||
actionSendPushbulletFileLabel = publish a Pushbullet message with file
|
||||
actionSendPushbulletFileDesc = Publishes a file to the given Pushbullet Recipient.
|
||||
|
||||
actionSendPushbulletNoteInputRecipientLabel = Pushbullet Recipient
|
||||
actionSendPushbulletNoteInputRecipientDesc = The Recipient to publish a Title to.
|
||||
@ -12,6 +36,12 @@ actionSendPushbulletNoteInputTitleLabel = Title
|
||||
actionSendPushbulletNoteInputTitleDesc = The Title to publish
|
||||
actionSendPushbulletNoteInputMessageLabel = Message
|
||||
actionSendPushbulletNoteInputMessageDesc = The Message to publish
|
||||
actionSendPushbulletLinkInputUrlLabel = Link URL
|
||||
actionSendPushbulletLinkInputUrlDesc = The Link URL to publish
|
||||
actionSendPushbulletFileInputContent = File Content
|
||||
actionSendPushbulletFileInputContentDesc = The File Content to publish
|
||||
actionSendPushbulletFileInputName = File Name
|
||||
actionSendPushbulletFileInputNameDesc = The File Name to publish
|
||||
|
||||
# error texts
|
||||
offline.conf-error-httpresponseexception = The pushbullet server reported an error, possibly an expired token. Check on web site
|
||||
|
@ -22,8 +22,8 @@
|
||||
</parameter>
|
||||
|
||||
<parameter name="token" type="text" required="true">
|
||||
<label>Token</label>
|
||||
<description>Token as obtained from the server</description>
|
||||
<label>Access Token</label>
|
||||
<description>Access token obtained from the account settings page</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="apiUrlBase" type="text" required="true">
|
||||
|
Loading…
Reference in New Issue
Block a user