<name>openHAB Add-ons :: Bundles :: IO :: Hue Emulation Service</name>
- <properties>
- <bnd.importpackage>org.glassfish.jersey.*;resolution:="optional"</bnd.importpackage>
- </properties>
-
<dependencies>
<!-- https://mvnrepository.com/artifact/org.glassfish.grizzly/grizzly-http-server -->
<dependency>
*
* @author David Graeff - Initial contribution
*/
-@Component(immediate = false, service = { ConfigStore.class }, configurationPid = {
- HueEmulationService.CONFIG_PID }, property = "com.eclipsesource.jaxrs.publish=false")
+@Component(immediate = false, service = ConfigStore.class, configurationPid = HueEmulationService.CONFIG_PID)
@ConfigurableService(category = "io", label = "Hue Emulation", description_uri = "io:hueemulation")
@NonNullByDefault
public class ConfigStore {
import java.util.Dictionary;
import java.util.Hashtable;
+import java.util.Set;
-import javax.servlet.ServletException;
-import javax.ws.rs.ApplicationPath;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.http.HttpHeader;
-import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.server.ServerProperties;
-import org.glassfish.jersey.servlet.ServletContainer;
-import org.glassfish.jersey.servlet.ServletProperties;
import org.openhab.io.hueemulation.internal.rest.ConfigurationAccess;
import org.openhab.io.hueemulation.internal.rest.LightsAndGroups;
import org.openhab.io.hueemulation.internal.rest.Rules;
import org.openhab.io.hueemulation.internal.rest.UserManagement;
import org.openhab.io.hueemulation.internal.upnp.UpnpServer;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
-import org.osgi.service.http.HttpService;
-import org.osgi.service.http.NamespaceException;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @author David Graeff - Initial Contribution
*/
@NonNullByDefault
-@Component(immediate = true, service = { HueEmulationService.class }, property = {
- "com.eclipsesource.jaxrs.publish=false" })
+@Component(immediate = true, service = HueEmulationService.class)
public class HueEmulationService implements EventHandler {
public static final String CONFIG_PID = "org.openhab.hueemulation";
public static final String RESTAPI_PATH = "/api";
-
- @ApplicationPath(RESTAPI_PATH)
- public static class JerseyApplication extends Application {
-
- }
+ public static final String REST_APP_NAME = "HueEmulation";
@PreMatching
public class RequestInterceptor implements ContainerRequestFilter {
}
private final ContainerRequestFilter requestCleaner = new RequestInterceptor();
+
+ /**
+ * The Jax-RS application that starts up all REST activities.
+ * It registers itself as a Jax-RS Whiteboard service and all Jax-RS resources that are targeting REST_APP_NAME will
+ * start up.
+ */
+ @JaxrsName(REST_APP_NAME)
+ private class RESTapplication extends Application {
+ private String root;
+
+ RESTapplication(String root) {
+ this.root = root;
+ }
+
+ @NonNullByDefault({})
+ @Override
+ public Set<Object> getSingletons() {
+ return Set.of(userManagement, configurationAccess, lightItems, sensors, scenes, schedules, rules,
+ statusResource, accessInterceptor);
+ }
+
+ Dictionary<String, String> serviceProperties() {
+ Dictionary<String, String> dict = new Hashtable<>();
+ dict.put(JaxrsWhiteboardConstants.JAX_RS_APPLICATION_BASE, root);
+ return dict;
+ }
+ }
+
private final Logger logger = LoggerFactory.getLogger(HueEmulationService.class);
private final LogAccessInterceptor accessInterceptor = new LogAccessInterceptor();
@Reference
protected @NonNullByDefault({}) StatusResource statusResource;
- @Reference
- protected @NonNullByDefault({}) HttpService httpService;
- private @NonNullByDefault({}) ServiceRegistration<?> eventHandler;
+ private @Nullable ServiceRegistration<?> eventHandler;
+ private @Nullable ServiceRegistration<Application> restService;
@Activate
protected void activate(BundleContext bc) {
@Deactivate
protected void deactivate() {
- try {
- if (eventHandler != null) {
- eventHandler.unregister();
- }
- } catch (IllegalStateException ignore) {
- }
- try {
- httpService.unregister(RESTAPI_PATH);
- } catch (IllegalArgumentException ignore) {
+ unregisterEventHandler();
+
+ ServiceRegistration<Application> localRestService = restService;
+ if (localRestService != null) {
+ localRestService.unregister();
}
}
*/
@Override
public void handleEvent(@Nullable Event event) {
- try { // Only receive this event once
- eventHandler.unregister();
- eventHandler = null;
- } catch (IllegalStateException ignore) {
+ unregisterEventHandler();
+
+ ServiceRegistration<Application> localRestService = restService;
+ if (localRestService == null) {
+ RESTapplication app = new RESTapplication(RESTAPI_PATH);
+ BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext();
+ restService = context.registerService(Application.class, app, app.serviceProperties());
+ logger.info("Hue Emulation service available under {}", RESTAPI_PATH);
}
+ }
- ResourceConfig resourceConfig = ResourceConfig.forApplicationClass(JerseyApplication.class);
- resourceConfig.property(ServerProperties.APPLICATION_NAME, "HueEmulation");
- // don't look for implementations described by META-INF/services/*
- resourceConfig.property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
- // disable auto discovery on server, as it's handled via OSGI
- resourceConfig.property(ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true);
-
- resourceConfig.property(ServerProperties.PROCESSING_RESPONSE_ERRORS_ENABLED, true);
-
- resourceConfig.registerInstances(userManagement, configurationAccess, lightItems, sensors, scenes, schedules,
- rules, statusResource, accessInterceptor, requestCleaner);
-
- try {
- Hashtable<String, String> initParams = new Hashtable<>();
- initParams.put("com.sun.jersey.api.json.POJOMappingFeature", "false");
- initParams.put(ServletProperties.PROVIDER_WEB_APP, "false");
- httpService.registerServlet(RESTAPI_PATH, new ServletContainer(resourceConfig), initParams, null);
- UpnpServer localDiscovery = discovery;
- if (localDiscovery == null) {
- logger.warn("The UPnP Server service has not been started!");
- } else if (!localDiscovery.upnpAnnouncementThreadRunning()) {
- localDiscovery.handleEvent(null);
+ private void unregisterEventHandler() {
+ ServiceRegistration<?> localEventHandler = eventHandler;
+ if (localEventHandler != null) {
+ try {
+ localEventHandler.unregister();
+ eventHandler = null;
+ } catch (IllegalStateException e) {
+ logger.debug("EventHandler already unregistered", e);
}
- statusResource.startUpnpSelfTest();
- logger.info("Hue Emulation service available under {}", RESTAPI_PATH);
- } catch (ServletException | NamespaceException e) {
- logger.warn("Could not start Hue Emulation service: {}", e.getMessage(), e);
}
}
}
/**
* Return a json serializer that behaves like the default one, but updates the UTC and localtime fields
- * before each serializion.
+ * before each serialization.
*/
@NonNullByDefault({})
public static class Serializer implements JsonSerializer<HueAuthorizedConfig> {
public class HueStateBulb extends HueStatePlug {
// https://github.com/openhab/openhab-addons/issues/2881
// Apparently the maximum brightness is 254
- public static int MAX_BRI = 254;
+ public static final int MAX_BRI = 254;
public int bri = 0;
/** white color temperature, 154 (cold) - 500 (warm) */
- public static int MAX_CT = 500;
+ public static final int MAX_CT = 500;
public int ct = 500;
protected HueStateBulb() {
*
*/
public class HueStateColorBulb extends HueStateBulb {
- public static int MAX_HUE = 65535; // For extended color light bulbs
+ public static final int MAX_HUE = 65535; // For extended color light bulbs
public int hue = 0;
- public static int MAX_SAT = 254;
+ public static final int MAX_SAT = 254;
public int sat = 0;
// color as array of xy-coordinates
import java.util.List;
/**
- * A POST message on a light entpoint will contain this change message body.
+ * A POST message on a light endpoint will contain this change message body.
* Not all fields will be set and always need to be checked.
*
* @author David Graeff - Initial contribution
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.io.hueemulation.internal.ConfigStore;
+import org.openhab.io.hueemulation.internal.HueEmulationService;
import org.openhab.io.hueemulation.internal.NetworkUtils;
import org.openhab.io.hueemulation.internal.dto.HueUnauthorizedConfig;
import org.openhab.io.hueemulation.internal.dto.changerequest.HueChangeRequest;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import com.google.gson.reflect.TypeToken;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
/**
* @author David Graeff - Initial contribution
*/
-@Component(immediate = false, service = {
- ConfigurationAccess.class }, property = "com.eclipsesource.jaxrs.publish=false")
+@Component(immediate = false, service = ConfigurationAccess.class)
+@JaxrsResource
+@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + HueEmulationService.REST_APP_NAME + ")")
@NonNullByDefault
@Path("")
@Produces(MediaType.APPLICATION_JSON)
@GET
@Path("config")
@Produces(MediaType.APPLICATION_JSON)
- @ApiOperation(value = "Return the reduced configuration")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return the reduced configuration", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response getReducedConfigApi() {
return Response.ok(cs.gson.toJson(cs.ds.config, new TypeToken<HueUnauthorizedConfig>() {
}.getType())).build();
@GET
@Path("{username}")
@Produces(MediaType.APPLICATION_JSON)
- @ApiOperation(value = "Return the full data store")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return the full data store", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response getAllApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/config")
@Produces(MediaType.APPLICATION_JSON)
- @ApiOperation(value = "Return the configuration")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return the configuration", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response getFullConfigApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@PUT
@Path("{username}/config")
@Produces(MediaType.APPLICATION_JSON)
- @ApiOperation(value = "Return the reduced configuration")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return the reduced configuration", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response putFullConfigApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username, String body) {
+ @PathParam("username") @Parameter(description = "username") String username, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
import org.openhab.core.types.Command;
import org.openhab.io.hueemulation.internal.ConfigStore;
import org.openhab.io.hueemulation.internal.DeviceType;
+import org.openhab.io.hueemulation.internal.HueEmulationService;
import org.openhab.io.hueemulation.internal.NetworkUtils;
import org.openhab.io.hueemulation.internal.StateUtils;
import org.openhab.io.hueemulation.internal.dto.HueGroupEntry;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.reflect.TypeToken;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
/**
* Listens to the ItemRegistry for items that fulfill one of these criteria:
* @author David Graeff - Initial contribution
* @author Florian Schmidt - Removed base type restriction from Group items
*/
-@Component(immediate = false, service = { LightsAndGroups.class }, property = "com.eclipsesource.jaxrs.publish=false")
+@Component(immediate = false, service = LightsAndGroups.class)
+@JaxrsResource
+@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + HueEmulationService.REST_APP_NAME + ")")
@NonNullByDefault
@Path("")
@Produces(MediaType.APPLICATION_JSON)
@GET
@Path("{username}/lights")
- @ApiOperation(value = "Return all lights")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return all lights", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getAllLightsApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/lights/new")
- @ApiOperation(value = "Return new lights since last scan. Returns an empty list for openHAB as we do not cache that information.")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return new lights since last scan. Returns an empty list for openHAB as we do not cache that information.", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response getNewLights(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@POST
@Path("{username}/lights")
- @ApiOperation(value = "Starts a new scan for compatible items. This is usually not necessary, because we are observing the item registry.")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Starts a new scan for compatible items. This is usually not necessary, because we are observing the item registry.", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response postNewLights(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/lights/{id}")
- @ApiOperation(value = "Return a light")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return a light", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getLightApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "light id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "light id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@DELETE
@Path("{username}/lights/{id}")
- @ApiOperation(value = "Deletes the item that is represented by this id")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "The item got removed"),
- @ApiResponse(code = 403, message = "Access denied") })
+ @Operation(summary = "Deletes the item that is represented by this id", responses = {
+ @ApiResponse(responseCode = "200", description = "The item got removed"),
+ @ApiResponse(responseCode = "403", description = "Access denied") })
public Response removeLightAPI(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@PUT
@Path("{username}/lights/{id}")
- @ApiOperation(value = "Rename a light")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Rename a light", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response renameLightApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "light id") String id, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "light id") String id, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@PUT
@Path("{username}/lights/{id}/state")
- @ApiOperation(value = "Set light state")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Set light state", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response setLightStateApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "light id") String id, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "light id") String id, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@PUT
@Path("{username}/groups/{id}/action")
- @ApiOperation(value = "Initiate group action")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Initiate group action", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response setGroupActionApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "group id") String id, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "group id") String id, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/groups")
- @ApiOperation(value = "Return all groups")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return all groups", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getAllGroupsApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/groups/{id}")
- @ApiOperation(value = "Return a group")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return a group", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getGroupApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "group id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "group id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@POST
@Path("{username}/groups")
- @ApiOperation(value = "Create a new group")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Create a new group", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response postNewGroup(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username, String body) {
+ @PathParam("username") @Parameter(description = "username") String username, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@DELETE
@Path("{username}/groups/{id}")
- @ApiOperation(value = "Deletes the item that is represented by this id")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "The item got removed"),
- @ApiResponse(code = 403, message = "Access denied") })
+ @Operation(summary = "Deletes the item that is represented by this id", responses = {
+ @ApiResponse(responseCode = "200", description = "The item got removed"),
+ @ApiResponse(responseCode = "403", description = "Access denied") })
public Response removeGroupAPI(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemRegistry;
import org.openhab.io.hueemulation.internal.ConfigStore;
+import org.openhab.io.hueemulation.internal.HueEmulationService;
import org.openhab.io.hueemulation.internal.NetworkUtils;
import org.openhab.io.hueemulation.internal.RuleUtils;
import org.openhab.io.hueemulation.internal.dto.HueRuleEntry;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
/**
* Handles Hue rules via the automation subsystem and the corresponding REST interface
*
* @author David Graeff - Initial contribution
*/
-@Component(immediate = false, service = { Rules.class }, property = "com.eclipsesource.jaxrs.publish=false")
+@Component(immediate = false, service = Rules.class)
+@JaxrsResource
+@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + HueEmulationService.REST_APP_NAME + ")")
@NonNullByDefault
@Path("")
@Produces(MediaType.APPLICATION_JSON)
@GET
@Path("{username}/rules")
@Produces(MediaType.APPLICATION_JSON)
- @ApiOperation(value = "Return all rules")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return all rules", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getRulesApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/rules/{id}")
- @ApiOperation(value = "Return a rule")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return a rule", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getRuleApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "rule id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "rule id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@DELETE
@Path("{username}/rules/{id}")
- @ApiOperation(value = "Deletes a rule")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "The user got removed"),
- @ApiResponse(code = 403, message = "Access denied") })
+ @Operation(summary = "Deletes a rule", responses = {
+ @ApiResponse(responseCode = "200", description = "The user got removed"),
+ @ApiResponse(responseCode = "403", description = "Access denied") })
public Response removeRuleApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "Rule to remove") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "Rule to remove") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@PUT
@Path("{username}/rules/{id}")
- @ApiOperation(value = "Set rule attributes")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Set rule attributes", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response modifyRuleApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "rule id") String id, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "rule id") String id, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null" })
@POST
@Path("{username}/rules")
- @ApiOperation(value = "Create a new rule")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Create a new rule", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response postNewRule(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username, String body) {
+ @PathParam("username") @Parameter(description = "username") String username, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.io.hueemulation.internal.ConfigStore;
+import org.openhab.io.hueemulation.internal.HueEmulationService;
import org.openhab.io.hueemulation.internal.NetworkUtils;
import org.openhab.io.hueemulation.internal.StateUtils;
import org.openhab.io.hueemulation.internal.automation.dto.ItemCommandActionConfig;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
/**
* Handles Hue scenes via the automation subsystem and the corresponding REST interface
*
* @author David Graeff - Initial contribution
*/
-@Component(immediate = false, service = { Scenes.class }, property = "com.eclipsesource.jaxrs.publish=false")
+@Component(immediate = false, service = Scenes.class)
+@JaxrsResource
+@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + HueEmulationService.REST_APP_NAME + ")")
@NonNullByDefault
@Path("")
@Produces(MediaType.APPLICATION_JSON)
@GET
@Path("{username}/scenes")
@Produces(MediaType.APPLICATION_JSON)
- @ApiOperation(value = "Return all scenes")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return all scenes", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getScenesApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "unused", "null" })
@GET
@Path("{username}/scenes/{id}")
- @ApiOperation(value = "Return a scene")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return a scene", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getSceneApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "scene id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "scene id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@DELETE
@Path("{username}/scenes/{id}")
- @ApiOperation(value = "Deletes a scene")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "The user got removed"),
- @ApiResponse(code = 403, message = "Access denied") })
+ @Operation(summary = "Deletes a scene", responses = {
+ @ApiResponse(responseCode = "200", description = "The user got removed"),
+ @ApiResponse(responseCode = "403", description = "Access denied") })
public Response removeSceneApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "Scene to remove") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "Scene to remove") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
*/
@PUT
@Path("{username}/scenes/{id}")
- @ApiOperation(value = "Set scene attributes")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Set scene attributes", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response modifySceneApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "scene id") String id, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "scene id") String id, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null" })
@POST
@Path("{username}/scenes")
- @ApiOperation(value = "Create a new scene")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Create a new scene", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response postNewScene(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username, String body) {
+ @PathParam("username") @Parameter(description = "username") String username, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@PUT
@Path("{username}/scenes/{id}/lightstates/{lightid}")
- @ApiOperation(value = "Set scene attributes")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Set scene attributes", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response modifySceneLightStateApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "scene id") String id,
- @PathParam("lightid") @ApiParam(value = "light id") String lightid, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "scene id") String id,
+ @PathParam("lightid") @Parameter(description = "light id") String lightid, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
import org.openhab.core.common.registry.RegistryChangeListener;
import org.openhab.core.config.core.Configuration;
import org.openhab.io.hueemulation.internal.ConfigStore;
+import org.openhab.io.hueemulation.internal.HueEmulationService;
import org.openhab.io.hueemulation.internal.NetworkUtils;
import org.openhab.io.hueemulation.internal.RuleUtils;
import org.openhab.io.hueemulation.internal.dto.HueDataStore;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
/**
* Enables the schedule part of the Hue REST API. Uses automation rules with GenericCronTrigger, TimerTrigger and
*
* @author David Graeff - Initial contribution
*/
-@Component(immediate = false, service = { Schedules.class }, property = "com.eclipsesource.jaxrs.publish=false")
+@Component(immediate = false, service = Schedules.class)
+@JaxrsResource
+@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + HueEmulationService.REST_APP_NAME + ")")
@NonNullByDefault
@Path("")
@Produces(MediaType.APPLICATION_JSON)
@GET
@Path("{username}/schedules")
@Produces(MediaType.APPLICATION_JSON)
- @ApiOperation(value = "Return all schedules")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return all schedules", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getSchedulesApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/schedules/{id}")
- @ApiOperation(value = "Return a schedule")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return a schedule", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getScheduleApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "schedule id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "schedule id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@DELETE
@Path("{username}/schedules/{id}")
- @ApiOperation(value = "Deletes a schedule")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "The user got removed"),
- @ApiResponse(code = 403, message = "Access denied") })
+ @Operation(summary = "Deletes a schedule", responses = {
+ @ApiResponse(responseCode = "200", description = "The user got removed"),
+ @ApiResponse(responseCode = "403", description = "Access denied") })
public Response removeScheduleApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "Schedule to remove") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "Schedule to remove") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@PUT
@Path("{username}/schedules/{id}")
- @ApiOperation(value = "Set schedule attributes")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Set schedule attributes", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response modifyScheduleApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "schedule id") String id, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "schedule id") String id, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null" })
@POST
@Path("{username}/schedules")
- @ApiOperation(value = "Create a new schedule")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Create a new schedule", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response postNewSchedule(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username, String body) {
+ @PathParam("username") @Parameter(description = "username") String username, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.library.CoreItemFactory;
import org.openhab.io.hueemulation.internal.ConfigStore;
+import org.openhab.io.hueemulation.internal.HueEmulationService;
import org.openhab.io.hueemulation.internal.NetworkUtils;
import org.openhab.io.hueemulation.internal.dto.HueNewLights;
import org.openhab.io.hueemulation.internal.dto.HueSensorEntry;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
/**
* Listens to the ItemRegistry and add all DecimalType, OnOffType, ContactType, DimmerType items
*
* @author David Graeff - Initial contribution
*/
-@Component(immediate = false, service = { Sensors.class }, property = "com.eclipsesource.jaxrs.publish=false")
+@Component(immediate = false, service = Sensors.class)
+@JaxrsResource
+@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + HueEmulationService.REST_APP_NAME + ")")
@NonNullByDefault
@Path("")
@Produces(MediaType.APPLICATION_JSON)
@GET
@Path("{username}/sensors")
- @ApiOperation(value = "Return all sensors")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return all sensors", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getAllSensorsApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/sensors/new")
- @ApiOperation(value = "Return new sensors since last scan. Returns an empty list for openHAB as we do not cache that information.")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return new sensors since last scan. Returns an empty list for openHAB as we do not cache that information.", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response getNewSensors(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@POST
@Path("{username}/sensors")
- @ApiOperation(value = "Starts a new scan for compatible items. This is usually not necessary, because we are observing the item registry.")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Starts a new scan for compatible items. This is usually not necessary, because we are observing the item registry.", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response postNewLights(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/sensors/{id}")
- @ApiOperation(value = "Return a sensor")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return a sensor", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getSensorApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "sensor id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "sensor id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@GET
@Path("{username}/sensors/{id}/config")
- @ApiOperation(value = "Return a sensor config. Always empty")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return a sensor config. Always empty", responses = {
+ @ApiResponse(responseCode = "200", description = "OK") })
public Response getSensorConfigApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "sensor id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "sensor id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@DELETE
@Path("{username}/sensors/{id}")
- @ApiOperation(value = "Deletes the sensor that is represented by this id")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "The item got removed"),
- @ApiResponse(code = 403, message = "Access denied") })
+ @Operation(summary = "Deletes the sensor that is represented by this id", responses = {
+ @ApiResponse(responseCode = "200", description = "The item got removed"),
+ @ApiResponse(responseCode = "403", description = "Access denied") })
public Response removeSensorAPI(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "id") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "id") String id) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@SuppressWarnings({ "null", "unused" })
@PUT
@Path("{username}/sensors/{id}")
- @ApiOperation(value = "Rename a sensor")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Rename a sensor", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response renameLightApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "light id") String id, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "light id") String id, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@PUT
@Path("{username}/sensors/{id}/state")
- @ApiOperation(value = "Set sensor state")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Set sensor state", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response setSensorStateApi(@Context UriInfo uri, //
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "sensor id") String id, String body) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "sensor id") String id, String body) {
if (!userManagement.authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
import org.jupnp.registry.Registry;
import org.jupnp.registry.RegistryListener;
import org.openhab.io.hueemulation.internal.ConfigStore;
+import org.openhab.io.hueemulation.internal.HueEmulationService;
import org.openhab.io.hueemulation.internal.upnp.UpnpServer;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicyOption;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*
* @author David Graeff - Initial contribution
*/
-@Component(immediate = false, service = { StatusResource.class }, property = "com.eclipsesource.jaxrs.publish=false")
-@Path("")
+@Component(immediate = false, service = StatusResource.class)
+@JaxrsResource
+@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + HueEmulationService.REST_APP_NAME + ")")
@NonNullByDefault
+@Path("")
public class StatusResource implements RegistryListener {
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
protected @Nullable UpnpServer discovery;
import org.openhab.core.common.registry.DefaultAbstractManagedProvider;
import org.openhab.core.storage.StorageService;
import org.openhab.io.hueemulation.internal.ConfigStore;
+import org.openhab.io.hueemulation.internal.HueEmulationService;
import org.openhab.io.hueemulation.internal.NetworkUtils;
import org.openhab.io.hueemulation.internal.dto.HueUserAuth;
import org.openhab.io.hueemulation.internal.dto.HueUserAuthWithSecrets;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
+import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.reflect.TypeToken;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
/**
* Manages users of this emulated HUE bridge. Stores users in the frameworks storage backend.
*
* @author David Graeff - Initial contribution
*/
-@Component(immediate = false, service = { UserManagement.class }, property = "com.eclipsesource.jaxrs.publish=false")
+@Component(immediate = false, service = UserManagement.class)
+@JaxrsResource
+@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + HueEmulationService.REST_APP_NAME + ")")
@NonNullByDefault
@Path("")
@Produces(MediaType.APPLICATION_JSON)
}
@POST
- @ApiOperation(value = "Create an API Key")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "API Key created"),
- @ApiResponse(code = 403, message = "Link button not pressed") })
+ @Operation(summary = "Create an API Key", responses = {
+ @ApiResponse(responseCode = "200", description = "API Key created"),
+ @ApiResponse(responseCode = "403", description = "Link button not pressed") })
public Response createNewUser(@Context UriInfo uri, String body) {
if (!cs.ds.config.linkbutton) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.LINK_BUTTON_NOT_PRESSED,
@GET
@Path("{username}/config/whitelist/{userid}")
- @ApiOperation(value = "Return a user")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return a user", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getUserApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("userid") @ApiParam(value = "User ID") String userid) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("userid") @Parameter(description = "User ID") String userid) {
if (!authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@GET
@Path("{username}/config/whitelist")
- @ApiOperation(value = "Return all users")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
+ @Operation(summary = "Return all users", responses = { @ApiResponse(responseCode = "200", description = "OK") })
public Response getAllUsersApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username) {
+ @PathParam("username") @Parameter(description = "username") String username) {
if (!authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
@DELETE
@Path("{username}/config/whitelist/{id}")
- @ApiOperation(value = "Deletes a user")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "The user got removed"),
- @ApiResponse(code = 403, message = "Access denied") })
+ @Operation(summary = "Deletes a user", responses = {
+ @ApiResponse(responseCode = "200", description = "The user got removed"),
+ @ApiResponse(responseCode = "403", description = "Access denied") })
public Response removeUserApi(@Context UriInfo uri,
- @PathParam("username") @ApiParam(value = "username") String username,
- @PathParam("id") @ApiParam(value = "User to remove") String id) {
+ @PathParam("username") @Parameter(description = "username") String username,
+ @PathParam("id") @Parameter(description = "User to remove") String id) {
if (!authorizeUser(username)) {
return NetworkUtils.singleError(cs.gson, uri, HueResponse.UNAUTHORIZED, "Not Authorized");
}
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.glassfish.jersey.client.ClientConfig;
-import org.glassfish.jersey.client.ClientProperties;
import org.openhab.io.hueemulation.internal.ConfigStore;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@NonNullByDefault
@Component(immediate = false, // Don't start the upnp server on its own. Must be pulled in by HueEmulationService.
configurationPolicy = ConfigurationPolicy.IGNORE, property = {
- EventConstants.EVENT_TOPIC + "=" + ConfigStore.EVENT_ADDRESS_CHANGED,
- "com.eclipsesource.jaxrs.publish=false" }, //
+ EventConstants.EVENT_TOPIC + "=" + ConfigStore.EVENT_ADDRESS_CHANGED }, //
service = { UpnpServer.class, EventHandler.class })
public class UpnpServer extends HttpServlet implements Consumer<HueEmulationConfigWithRuntime>, EventHandler {
/**
@Reference
protected @NonNullByDefault({}) HttpService httpService;
+ @Reference
+ protected @NonNullByDefault({}) ClientBuilder clientBuilder;
+
public boolean overwriteReadyToFalse = false;
private HueEmulationConfigWithRuntime config;
}
selfTests.clear();
-
- ClientConfig configuration = new ClientConfig();
- configuration = configuration.property(ClientProperties.CONNECT_TIMEOUT, 1000);
- configuration = configuration.property(ClientProperties.READ_TIMEOUT, 1000);
- Client client = ClientBuilder.newClient(configuration);
+ Client client = clientBuilder.connectTimeout(1, TimeUnit.SECONDS).readTimeout(1, TimeUnit.SECONDS).build();
Response response;
String url = "";
try {
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.logging.LoggingFeature.Verbosity;
import org.glassfish.jersey.server.ResourceConfig;
-import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.mockito.junit.jupiter.MockitoSettings;
-import org.mockito.quality.Strictness;
+import org.mockito.MockitoAnnotations;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.items.MetadataRegistry;
import org.openhab.core.net.NetworkAddressService;
*
* @author David Graeff - Initial contribution
*/
-@ExtendWith(MockitoExtension.class)
-@MockitoSettings(strictness = Strictness.WARN)
public class CommonSetup {
- public UserManagement userManagement;
+ public String basePath;
+ public Client client;
+ public ConfigStore cs;
+ public HttpServer server;
- public @Mock EventPublisher eventPublisher;
+ UserManagement userManagement;
- public ConfigStore cs;
+ AutoCloseable mocksCloseable;
+
+ @Mock
+ EventPublisher eventPublisher;
@Mock
ConfigurationAdmin configAdmin;
}
};
- public Client client;
- public HttpServer server;
- public String basePath;
-
public CommonSetup(boolean withMetadata) throws IOException {
+ mocksCloseable = MockitoAnnotations.openMocks(this);
+
when(configAdmin.getConfiguration(anyString())).thenReturn(configAdminConfig);
when(configAdmin.getConfiguration(anyString(), any())).thenReturn(configAdminConfig);
Dictionary<String, Object> mockProperties = new Hashtable<>();
client = ClientBuilder.newClient();
}
- public void dispose() {
+ public void dispose() throws Exception {
if (client != null) {
client.close();
}
if (server != null) {
server.shutdownNow();
}
+
+ mocksCloseable.close();
}
}
}
@AfterEach
- public void tearDown() {
+ public void tearDown() throws Exception {
commonSetup.dispose();
}
}
@AfterEach
- public void tearDown() {
+ public void tearDown() throws Exception {
commonSetup.dispose();
}
*/
@NonNullByDefault
public class RulesTests {
+
protected @NonNullByDefault({}) CommonSetup commonSetup;
protected @NonNullByDefault({}) ConfigStore cs;
protected @NonNullByDefault({}) ItemRegistry itemRegistry;
}
@AfterEach
- public void tearDown() {
+ public void tearDown() throws Exception {
RuleUtils.random = new Random();
commonSetup.dispose();
}
}
@AfterEach
- public void tearDown() {
+ public void tearDown() throws Exception {
commonSetup.dispose();
}
}
@AfterEach
- public void tearDown() {
+ public void tearDown() throws Exception {
RuleUtils.random = new Random();
commonSetup.dispose();
}
}
@AfterEach
- public void tearDown() {
+ public void tearDown() throws Exception {
commonSetup.dispose();
}
}
@AfterEach
- public void tearDown() {
+ public void tearDown() throws Exception {
commonSetup.dispose();
}
import java.util.concurrent.ScheduledExecutorService;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.items.Item;
import org.openhab.core.net.NetworkAddressService;
*
* @author David Graeff - Initial contribution
*/
+@NonNullByDefault
public class ConfigStoreWithoutMetadata extends ConfigStore {
public ConfigStoreWithoutMetadata(NetworkAddressService networkAddressService, ConfigurationAdmin configAdmin,
}
@Override
- public @NonNull String mapItemUIDtoHueID(@Nullable Item item) {
+ public String mapItemUIDtoHueID(@Nullable Item item) {
if (item == null) {
throw new IllegalArgumentException();
}
return items.values();
}
- @NonNullByDefault({})
@Override
public Stream<Rule> stream() {
return items.values().stream();
return put;
}
- @NonNullByDefault({})
@Override
- public Collection<Rule> getByTag(String tag) {
+ public Collection<Rule> getByTag(@Nullable String tag) {
return Collections.emptyList();
}
- @NonNullByDefault({})
@Override
public Collection<Rule> getByTags(String... tags) {
return Collections.emptyList();
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
import org.glassfish.grizzly.osgi.httpservice.HttpServiceImpl;
return null;
}).when(executor).execute(ArgumentMatchers.any());
subject = new UpnpServer(executor);
+ subject.clientBuilder = ClientBuilder.newBuilder();
subject.httpService = httpServiceImpl;
subject.cs = commonSetup.cs;
subject.overwriteReadyToFalse = true;
}
@AfterAll
- public static void tearDownHttp() {
+ public static void tearDownHttp() throws Exception {
mainHttpHandler.unregisterAll();
commonSetup.dispose();
}
<modules>
<!-- io -->
<module>org.openhab.io.homekit</module>
+ <module>org.openhab.io.hueemulation</module>
<module>org.openhab.io.imperihome</module>
+ <module>org.openhab.io.mqttembeddedbroker</module>
<module>org.openhab.io.neeo</module>
<module>org.openhab.io.openhabcloud</module>
<module>org.openhab.io.transport.modbus</module>
- <module>org.openhab.io.mqttembeddedbroker</module>
<!-- transformations -->
<module>org.openhab.transform.bin2json</module>
<module>org.openhab.transform.exec</module>
<!-- temporarily exclude add-ons, which are still excluded from the build -->
<exclude name="**/org.openhab.binding.netatmo/**/feature.xml"/>
- <exclude name="**/org.openhab.io.hueemulation/**/feature.xml"/>
</fileset>
<filterchain>
<linecontainsRegExp>