Manually add a Webex Account to authorize it here.
"; + private static final String HTML_USER_AUTHORIZED = "
"; + private static final String HTML_ERROR = "Call to Webex failed with error: %s
"; + + private static final Pattern MESSAGE_KEY_PATTERN = Pattern.compile("\\$\\{([^\\}]+)\\}"); + + // Keys present in the index.html + private static final String KEY_PAGE_REFRESH = "pageRefresh"; + private static final String HTML_META_REFRESH_CONTENT = ""; + private static final String KEY_AUTHORIZED_USER = "authorizedUser"; + private static final String KEY_ERROR = "error"; + private static final String KEY_ACCOUNTS = "accounts"; + private static final String KEY_REDIRECT_URI = "redirectUri"; + + // Keys present in the account.html + private static final String ACCOUNT_ID = "account.id"; + private static final String ACCOUNT_NAME = "account.name"; + private static final String ACCOUNT_USER_ID = "account.user"; + private static final String ACCOUNT_TYPE = "account.type"; + private static final String ACCOUNT_AUTHORIZE = "account.authorize"; + private static final String ACCOUNT_SHOWBTN = "account.showbtn"; + private static final String ACCOUNT_SHWOMSG = "account.showmsg"; + private static final String ACCOUNT_MSG = "account.msg"; + + private final Logger logger = LoggerFactory.getLogger(WebexAuthServlet.class); + private final WebexAuthService authService; + private final String indexTemplate; + private final String accountTemplate; + + public WebexAuthServlet(WebexAuthService authService, String indexTemplate, String accountTemplate) { + this.authService = authService; + this.indexTemplate = indexTemplate; + this.accountTemplate = accountTemplate; + } + + @Override + protected void doGet(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp) + throws ServletException, IOException { + if (req != null && resp != null) { + logger.debug("Webex auth callback servlet received GET request {}.", req.getRequestURI()); + final String servletBaseURL = req.getRequestURL().toString(); + final Maptrue
, if sending the message has been successful and
+ * false
in all other cases.
+ */
+ public boolean sendMessage(String msg) {
+ Message message = new Message();
+ message.setRoomId(config.roomId);
+ message.setMarkdown(msg);
+ logger.debug("Sending message to default room ({})", config.roomId);
+ return sendMessage(message);
+ }
+
+ /**
+ * Sends a message with file attachment to the default room.
+ *
+ * @param msg markdown text string to be sent
+ * @param attach URL of the attachment
+ *
+ * @return true
, if sending the message has been successful and
+ * false
in all other cases.
+ */
+ public boolean sendMessage(String msg, String attach) {
+ Message message = new Message();
+ message.setRoomId(config.roomId);
+ message.setMarkdown(msg);
+ message.setFile(attach);
+ logger.debug("Sending message with attachment to default room ({})", config.roomId);
+ return sendMessage(message);
+ }
+
+ /**
+ * Send a message to a specific room
+ *
+ * @param roomId roomId of the room to send to
+ * @param msg markdown text string to be sent
+ * @return true
, if sending the message has been successful and
+ * false
in all other cases.
+ */
+ public boolean sendRoomMessage(String roomId, String msg) {
+ Message message = new Message();
+ message.setRoomId(roomId);
+ message.setMarkdown(msg);
+ logger.debug("Sending message to room {}", roomId);
+ return sendMessage(message);
+ }
+
+ /**
+ * Send a message to a specific room, with attachment
+ *
+ * @param roomId roomId of the room to send to
+ * @param msg markdown text string to be sent
+ * @param attach URL of the attachment
+ *
+ * @return true
, if sending the message has been successful and
+ * false
in all other cases.
+ */
+ public boolean sendRoomMessage(String roomId, String msg, String attach) {
+ Message message = new Message();
+ message.setRoomId(roomId);
+ message.setMarkdown(msg);
+ message.setFile(attach);
+ logger.debug("Sending message with attachment to room {}", roomId);
+ return sendMessage(message);
+ }
+
+ /**
+ * Sends a message to a specific person, identified by email
+ *
+ * @param personEmail email address of the person to send to
+ * @param msg markdown text string to be sent
+ * @return true
, if sending the message has been successful and
+ * false
in all other cases.
+ */
+ public boolean sendPersonMessage(String personEmail, String msg) {
+ Message message = new Message();
+ message.setToPersonEmail(personEmail);
+ message.setMarkdown(msg);
+ logger.debug("Sending message to {}", personEmail);
+ return sendMessage(message);
+ }
+
+ /**
+ * Sends a message to a specific person, identified by email, with attachment
+ *
+ * @param personEmail email address of the person to send to
+ * @param msg markdown text string to be sent
+ * @param attach URL of the attachment*
+ * @return true
, if sending the message has been successful and
+ * false
in all other cases.
+ */
+ public boolean sendPersonMessage(String personEmail, String msg, String attach) {
+ Message message = new Message();
+ message.setToPersonEmail(personEmail);
+ message.setMarkdown(msg);
+ message.setFile(attach);
+ logger.debug("Sending message to {}", personEmail);
+ return sendMessage(message);
+ }
+
+ /**
+ * Sends a Message
+ *
+ * @param msg the Message
to be sent
+ * @return true
, if sending the message has been successful and
+ * false
in all other cases.
+ */
+ private boolean sendMessage(Message msg) {
+ try {
+ WebexTeamsApi client = this.client;
+ if (client != null) {
+ client.sendMessage(msg);
+ return true;
+ } else {
+ logger.warn("Client not properly initialized");
+ return false;
+ }
+ } catch (WebexTeamsException e) {
+ logger.warn("Failed to send message: {}", e.getMessage());
+ }
+ return false;
+ }
+
+ @Override
+ public void onAccessTokenResponse(AccessTokenResponse tokenResponse) {
+ }
+}
diff --git a/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/WebexTeamsHandlerFactory.java b/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/WebexTeamsHandlerFactory.java
new file mode 100644
index 00000000000..a61ef52566d
--- /dev/null
+++ b/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/WebexTeamsHandlerFactory.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2010-2022 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.webexteams.internal;
+
+import static org.openhab.binding.webexteams.internal.WebexTeamsBindingConstants.*;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.openhab.core.auth.client.oauth2.OAuthFactory;
+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 WebexTeamsHandlerFactory} is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Tom Deckers - Initial contribution
+ */
+@NonNullByDefault
+@Component(configurationPid = "binding.webexteams", service = ThingHandlerFactory.class)
+public class WebexTeamsHandlerFactory extends BaseThingHandlerFactory {
+
+ private static final SetMessage
that is sent or received through the API.
+ *
+ * @author Tom Deckers - Initial contribution
+ */
+@NonNullByDefault
+public class Message {
+ private @Nullable String id;
+ private @Nullable String roomId;
+ private @Nullable String toPersonEmail;
+ private @Nullable String text;
+ private @Nullable String markdown;
+ private @Nullable String file;
+
+ @Nullable
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @Nullable
+ public String getRoomId() {
+ return roomId;
+ }
+
+ public void setRoomId(String roomId) {
+ this.roomId = roomId;
+ }
+
+ @Nullable
+ public String getToPersonEmail() {
+ return toPersonEmail;
+ }
+
+ public void setToPersonEmail(String toPersonEmail) {
+ this.toPersonEmail = toPersonEmail;
+ }
+
+ @Nullable
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ @Nullable
+ public String getMarkdown() {
+ return markdown;
+ }
+
+ public void setMarkdown(String markdown) {
+ this.markdown = markdown;
+ }
+
+ @Nullable
+ public String getFile() {
+ return file;
+ }
+
+ public void setFile(String file) {
+ this.file = file;
+ }
+}
diff --git a/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/api/Person.java b/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/api/Person.java
new file mode 100644
index 00000000000..8fff7606415
--- /dev/null
+++ b/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/api/Person.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2010-2022 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.webexteams.internal.api;
+
+import java.util.Date;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * a Person
object that is received from the Webex API.
+ *
+ * @author Tom Deckers - Initial contribution
+ */
+@NonNullByDefault
+public class Person {
+ private @Nullable String id;
+ private @Nullable String displayName;
+ private @Nullable String firstName;
+ private @Nullable String lastName;
+ private @Nullable String avatar;
+ private @Nullable Date lastActivity;
+ private @Nullable String status;
+ private @Nullable String type;
+
+ @Nullable
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @Nullable
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ @Nullable
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ @Nullable
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ @Nullable
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ @Nullable
+ public Date getLastActivity() {
+ return lastActivity;
+ }
+
+ public void setLastActivity(Date lastActivity) {
+ this.lastActivity = lastActivity;
+ }
+
+ @Nullable
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ @Nullable
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/api/WebexTeamsApi.java b/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/api/WebexTeamsApi.java
new file mode 100644
index 00000000000..b239078adb1
--- /dev/null
+++ b/bundles/org.openhab.binding.webexteams/src/main/java/org/openhab/binding/webexteams/internal/api/WebexTeamsApi.java
@@ -0,0 +1,176 @@
+/**
+ * Copyright (c) 2010-2022 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.webexteams.internal.api;
+
+import static org.openhab.binding.webexteams.internal.WebexTeamsBindingConstants.*;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+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.StringContentProvider;
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.http.HttpStatus;
+import org.openhab.binding.webexteams.internal.WebexAuthenticationException;
+import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
+import org.openhab.core.auth.client.oauth2.OAuthClientService;
+import org.openhab.core.auth.client.oauth2.OAuthException;
+import org.openhab.core.auth.client.oauth2.OAuthResponseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * WebexTeamsApi implements API integration with Webex Teams.
+ *
+ * Not using webex-java-sdk since it's not in a public maven repo, and it doesn't easily
+ * support caching refresh tokens between openhab restarts, etc..
+ *
+ * @author Tom Deckers - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class WebexTeamsApi {
+
+ private final Logger logger = LoggerFactory.getLogger(WebexTeamsApi.class);
+
+ private final OAuthClientService authService;
+ private final HttpClient httpClient;
+
+ public WebexTeamsApi(OAuthClientService authService, HttpClient httpClient) {
+ this.authService = authService;
+ this.httpClient = httpClient;
+ }
+
+ /**
+ * Get a Person
object for the account.
+ *
+ * @return a Person
object
+ * @throws WebexAuthenticationException when authentication fails
+ * @throws WebexTeamsApiException for other failures
+ */
+ public Person getPerson() throws WebexTeamsApiException, WebexAuthenticationException {
+ URI url = getUri(WEBEX_API_ENDPOINT + "/people/me");
+
+ Person person = request(url, HttpMethod.GET, Person.class, null);
+ return person;
+ }
+
+ private URI getUri(String url) throws WebexTeamsApiException {
+ URI uri;
+ try {
+ uri = new URI(url);
+ } catch (URISyntaxException e) {
+ throw new WebexTeamsApiException("bad url", e);
+ }
+ return uri;
+ }
+
+ private O request(URI url, HttpMethod method, ClassOn this page you can authorize your openHAB Webex Teams Account configured with the clientId and clientSecret of the Webex API on your Developer account.
+To use this binding the following requirements apply:
++ The redirect URI to use with the Webex API for this openHAB installation is + ${redirectUri} +
+ +