/**
* Copyright © 2016-2018 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.http;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
import org.thingsboard.server.common.msg.core.*;
import org.thingsboard.server.common.transport.SessionMsgProcessor;
import org.thingsboard.server.common.transport.auth.DeviceAuthService;
import org.thingsboard.server.common.transport.quota.host.HostRequestsQuotaService;
import org.thingsboard.server.transport.http.session.HttpSessionCtx;
import javax.servlet.http.HttpServletRequest;
/**
* @author Andrew Shvayka
*/
@RestController
@ConditionalOnProperty(prefix = "transport.http", value = "enabled", havingValue = "true")
@RequestMapping("/api/v1")
@Slf4j
public class DeviceApiController {
@Value("${http.request_timeout}")
private long defaultTimeout;
@Autowired(required = false)
private SessionMsgProcessor processor;
@Autowired(required = false)
private DeviceAuthService authService;
@Autowired(required = false)
private HostRequestsQuotaService quotaService;
@RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.GET, produces = "application/json")
public DeferredResult<ResponseEntity> getDeviceAttributes(@PathVariable("deviceToken") String deviceToken,
@RequestParam(value = "clientKeys", required = false, defaultValue = "") String clientKeys,
@RequestParam(value = "sharedKeys", required = false, defaultValue = "") String sharedKeys,
HttpServletRequest httpRequest) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
if (quotaExceeded(httpRequest, responseWriter)) {
return responseWriter;
}
// HttpSessionCtx ctx = getHttpSessionCtx(responseWriter);
// if (ctx.login(new DeviceTokenCredentials(deviceToken))) {
// GetAttributesRequest request;
// if (StringUtils.isEmpty(clientKeys) && StringUtils.isEmpty(sharedKeys)) {
// request = new BasicGetAttributesRequest(0);
// } else {
// Set<String> clientKeySet = !StringUtils.isEmpty(clientKeys) ? new HashSet<>(Arrays.asList(clientKeys.split(","))) : null;
// Set<String> sharedKeySet = !StringUtils.isEmpty(sharedKeys) ? new HashSet<>(Arrays.asList(sharedKeys.split(","))) : null;
// request = new BasicGetAttributesRequest(0, clientKeySet, sharedKeySet);
// }
// process(ctx, request);
// } else {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
// }
return responseWriter;
}
@RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> postDeviceAttributes(@PathVariable("deviceToken") String deviceToken,
@RequestBody String json, HttpServletRequest request) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
if (quotaExceeded(request, responseWriter)) {
return responseWriter;
}
// HttpSessionCtx ctx = getHttpSessionCtx(responseWriter);
// if (ctx.login(new DeviceTokenCredentials(deviceToken))) {
// try {
// process(ctx, JsonConverter.convertToAttributes(new JsonParser().parse(json)));
// } catch (IllegalStateException | JsonSyntaxException ex) {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
// }
// } else {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
// }
return responseWriter;
}
@RequestMapping(value = "/{deviceToken}/telemetry", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> postTelemetry(@PathVariable("deviceToken") String deviceToken,
@RequestBody String json, HttpServletRequest request) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
if (quotaExceeded(request, responseWriter)) {
return responseWriter;
}
HttpSessionCtx ctx = getHttpSessionCtx(responseWriter);
// if (ctx.login(new DeviceTokenCredentials(deviceToken))) {
// try {
// process(ctx, JsonConverter.convertToTelemetry(new JsonParser().parse(json)));
// } catch (IllegalStateException | JsonSyntaxException ex) {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
// }
// } else {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
// }
return responseWriter;
}
@RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.GET, produces = "application/json")
public DeferredResult<ResponseEntity> subscribeToCommands(@PathVariable("deviceToken") String deviceToken,
@RequestParam(value = "timeout", required = false, defaultValue = "0") long timeout,
HttpServletRequest request) {
// return subscribe(deviceToken, timeout, new RpcSubscribeMsg(), request);
return null;
}
@RequestMapping(value = "/{deviceToken}/rpc/{requestId}", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> replyToCommand(@PathVariable("deviceToken") String deviceToken,
@PathVariable("requestId") Integer requestId,
@RequestBody String json, HttpServletRequest request) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
if (quotaExceeded(request, responseWriter)) {
return responseWriter;
}
// HttpSessionCtx ctx = getHttpSessionCtx(responseWriter);
// if (ctx.login(new DeviceTokenCredentials(deviceToken))) {
// try {
// JsonObject response = new JsonParser().parse(json).getAsJsonObject();
// process(ctx, new ToDeviceRpcResponseMsg(requestId, response.toString()));
// } catch (IllegalStateException | JsonSyntaxException ex) {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
// }
// } else {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
// }
return responseWriter;
}
@RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> postRpcRequest(@PathVariable("deviceToken") String deviceToken,
@RequestBody String json, HttpServletRequest httpRequest) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
if (quotaExceeded(httpRequest, responseWriter)) {
return responseWriter;
}
HttpSessionCtx ctx = getHttpSessionCtx(responseWriter);
// if (ctx.login(new DeviceTokenCredentials(deviceToken))) {
// try {
// JsonObject request = new JsonParser().parse(json).getAsJsonObject();
// process(ctx, new ToServerRpcRequestMsg(0,
// request.get("method").getAsString(),
// request.get("params").toString()));
// } catch (IllegalStateException | JsonSyntaxException ex) {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
// }
// } else {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
// }
return responseWriter;
}
@RequestMapping(value = "/{deviceToken}/attributes/updates", method = RequestMethod.GET, produces = "application/json")
public DeferredResult<ResponseEntity> subscribeToAttributes(@PathVariable("deviceToken") String deviceToken,
@RequestParam(value = "timeout", required = false, defaultValue = "0") long timeout,
HttpServletRequest httpRequest) {
return null;
// return subscribe(deviceToken, timeout, new AttributesSubscribeMsg(), httpRequest);
}
// private DeferredResult<ResponseEntity> subscribe(String deviceToken, long timeout, FromDeviceMsg msg, HttpServletRequest httpRequest) {
// DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
// if (quotaExceeded(httpRequest, responseWriter)) {
// return responseWriter;
// }
// HttpSessionCtx ctx = getHttpSessionCtx(responseWriter, timeout);
// if (ctx.login(new DeviceTokenCredentials(deviceToken))) {
// try {
// process(ctx, msg);
// } catch (IllegalStateException | JsonSyntaxException ex) {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
// }
// } else {
// responseWriter.setResult(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
// }
// return responseWriter;
// }
private HttpSessionCtx getHttpSessionCtx(DeferredResult<ResponseEntity> responseWriter) {
return getHttpSessionCtx(responseWriter, defaultTimeout);
}
private HttpSessionCtx getHttpSessionCtx(DeferredResult<ResponseEntity> responseWriter, long timeout) {
return null;
// return new HttpSessionCtx(processor, authService, responseWriter, timeout != 0 ? timeout : defaultTimeout);
}
// private void process(HttpSessionCtx ctx, FromDeviceMsg request) {
// AdaptorToSessionActorMsg msg = new BasicAdaptorToSessionActorMsg(ctx, request);
//// processor.process(new BasicTransportToDeviceSessionActorMsg(ctx.getDevice(), msg));
// }
private boolean quotaExceeded(HttpServletRequest request, DeferredResult<ResponseEntity> responseWriter) {
if (quotaService.isQuotaExceeded(request.getRemoteAddr())) {
log.warn("REST Quota exceeded for [{}] . Disconnect", request.getRemoteAddr());
responseWriter.setResult(new ResponseEntity<>(HttpStatus.BANDWIDTH_LIMIT_EXCEEDED));
return true;
}
return false;
}
}