增加http业务组件

V0.5.x
xiwa 2022-04-24 04:59:23 +08:00
parent b9d6054198
commit a0e23dea2b
34 changed files with 449 additions and 269 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

View File

@ -41,7 +41,7 @@ public final class JsonUtil {
public static Object toObject(ScriptObjectMirror mirror) {
if (mirror.isEmpty()) {
return null;
return new Object();
}
if (mirror.isArray()) {
List<Object> list = new ArrayList<>();

BIN
manager/.DS_Store vendored

Binary file not shown.

View File

@ -0,0 +1,58 @@
package cc.iotkit.manager.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String wrapResponse = request.getHeader("wrap-response");
return "json".equals(wrapResponse);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof GlobalExceptionHandler.RequestResult) {
GlobalExceptionHandler.RequestResult requestResult = (GlobalExceptionHandler.RequestResult) body;
return new ApiResponse(Integer.parseInt(requestResult.getCode()), requestResult.getMessage(),
"", System.currentTimeMillis());
} else if (body instanceof Map) {
Map map = (Map) body;
//spring mvc内部异常
if (map.containsKey("timestamp") && map.containsKey("status") && map.containsKey("error")) {
return new ApiResponse((Integer) map.get("status"), (String) map.get("error"),
"", System.currentTimeMillis());
}
}
return new ApiResponse(200, "", body, System.currentTimeMillis());
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class ApiResponse {
private int status;
private String message;
private Object data;
private long timestamp;
}
}

View File

@ -10,6 +10,7 @@ import cc.iotkit.manager.model.query.DeviceQuery;
import cc.iotkit.manager.service.DataOwnerService;
import cc.iotkit.manager.service.DeviceService;
import cc.iotkit.manager.utils.AuthUtil;
import cc.iotkit.model.InvokeResult;
import cc.iotkit.model.Paging;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.message.DeviceProperty;
@ -55,44 +56,21 @@ public class DeviceController {
private DeviceBehaviourService behaviourService;
@PostMapping(Constants.API.DEVICE_INVOKE_SERVICE)
public String invokeService(@PathVariable("deviceId") String deviceId,
@PathVariable("service") String service,
@RequestBody Map<String, Object> args) {
public InvokeResult invokeService(@PathVariable("deviceId") String deviceId,
@PathVariable("service") String service,
@RequestBody Map<String, Object> args) {
if (StringUtils.isBlank(deviceId) || StringUtils.isBlank(service)) {
throw new RuntimeException("deviceId/service is blank.");
}
dataOwnerService.checkWriteRole();
return deviceService.invokeService(deviceId, service, args);
return new InvokeResult(deviceService.invokeService(deviceId, service, args));
}
@PostMapping(Constants.API.DEVICE_SET_PROPERTIES)
public String setProperty(@PathVariable("deviceId") String deviceId,
@RequestBody Map<String, Object> args) {
public InvokeResult setProperty(@PathVariable("deviceId") String deviceId,
@RequestBody Map<String, Object> args) {
dataOwnerService.checkWriteRole();
return deviceService.setProperty(deviceId, args);
}
@PostMapping("/list")
public Paging<DeviceInfo> getDevices(int page,
int size,
String pk,
Boolean online,
String dn) {
Criteria condition = new Criteria();
if (!AuthUtil.isAdmin()) {
condition.and("uid").is(AuthUtil.getUserId());
}
if (StringUtils.isNotBlank(pk)) {
condition.and("productKey").is(pk);
}
if (StringUtils.isNotBlank(dn)) {
condition.and("deviceName").regex(".*" + dn + ".*");
}
if (online != null) {
condition.and("state.online").is(online);
}
return deviceDao.find(condition, size, page);
return new InvokeResult(deviceService.setProperty(deviceId, args));
}
@PostMapping("/list/{size}/{page}")
@ -121,8 +99,8 @@ public class DeviceController {
condition.and("deviceName").regex(".*" + dn + ".*");
}
String state = query.getState();
if (state != null) {
condition.and("state.online").is(state);
if (StringUtils.isNotBlank(state)) {
condition.and("state.online").is(state.equals("online"));
}
return deviceDao.find(condition, size, page);

View File

@ -3,7 +3,7 @@ package cc.iotkit.manager.controller;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.common.utils.ReflectUtil;
import cc.iotkit.comps.DeviceComponentManager;
import cc.iotkit.comps.ComponentManager;
import cc.iotkit.comps.config.ComponentConfig;
import cc.iotkit.dao.ProtocolComponentRepository;
import cc.iotkit.dao.ProtocolConverterRepository;
@ -50,7 +50,7 @@ public class ProtocolController {
private UserInfoRepository userInfoRepository;
@Autowired
private DeviceComponentManager deviceComponentManager;
private ComponentManager componentManager;
@PostMapping("/uploadJar")
public String uploadJar(@RequestParam("file") MultipartFile file, String id) {
@ -112,8 +112,9 @@ public class ProtocolController {
ProtocolComponent oldComponent = getAndCheckComponent(id);
component = ReflectUtil.copyNoNulls(component, oldComponent);
try {
deviceComponentManager.deRegister(id);
componentManager.deRegister(id);
protocolComponentRepository.save(component);
} catch (Throwable e) {
throw new BizException("add protocol component error", e);
@ -144,7 +145,7 @@ public class ProtocolController {
script = JsonUtil.parse(script, String.class);
FileUtils.writeStringToFile(file, script, "UTF-8", false);
deviceComponentManager.deRegister(id);
componentManager.deRegister(id);
} catch (Throwable e) {
throw new BizException("save protocol component script error", e);
}
@ -164,7 +165,7 @@ public class ProtocolController {
public void deleteComponent(@PathVariable("id") String id) {
ProtocolComponent component = getAndCheckComponent(id);
try {
deviceComponentManager.deRegister(id);
componentManager.deRegister(id);
Path path = Paths.get(String.format("%s/%s", componentConfig.getComponentDir(), id))
.toAbsolutePath().normalize();
@ -190,8 +191,10 @@ public class ProtocolController {
@PathVariable("page") int page) {
Page<ProtocolComponent> components = protocolComponentRepository.findAll(
PageRequest.of(page - 1, size, Sort.by(Sort.Order.desc("createAt"))));
components.getContent().forEach(c -> c.setState(deviceComponentManager.isRunning(c.getId()) ?
ProtocolComponent.STATE_RUNNING : ProtocolComponent.STATE_STOPPED));
components.getContent().forEach(c -> c.setState(
componentManager.isRunning(c.getId()) ?
ProtocolComponent.STATE_RUNNING : ProtocolComponent.STATE_STOPPED
));
return new Paging<>(components.getTotalElements(), components.getContent());
}
@ -294,14 +297,17 @@ public class ProtocolController {
public void changeComponentState(@PathVariable("id") String id,
@PathVariable("state") String state) {
ProtocolComponent component = getAndCheckComponent(id);
String converterId = component.getConverter();
getAndCheckConverter(converterId);
if(ProtocolComponent.TYPE_DEVICE.equals(component.getType())){
String converterId = component.getConverter();
getAndCheckConverter(converterId);
}
if (ProtocolComponent.STATE_RUNNING.equals(state)) {
deviceComponentManager.register(component);
deviceComponentManager.start(component.getId());
componentManager.register(component);
componentManager.start(component.getId());
component.setState(ProtocolComponent.STATE_RUNNING);
} else {
deviceComponentManager.deRegister(id);
componentManager.deRegister(id);
component.setState(ProtocolComponent.STATE_STOPPED);
}
protocolComponentRepository.save(component);

View File

@ -2,23 +2,17 @@ package cc.iotkit.manager.controller.aligenie;
import cc.iotkit.common.Constants;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.exception.OfflineException;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.common.utils.UniqueIdUtil;
import cc.iotkit.dao.*;
import cc.iotkit.manager.service.DataOwnerService;
import cc.iotkit.manager.service.DeviceService;
import cc.iotkit.manager.utils.AuthUtil;
import cc.iotkit.model.InvokeResult;
import cc.iotkit.model.UserInfo;
import cc.iotkit.model.aligenie.AligenieDevice;
import cc.iotkit.model.aligenie.AligenieProduct;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.message.ThingModelMessage;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pulsar.client.api.Producer;
import org.apache.pulsar.client.api.PulsarClient;
import org.apache.pulsar.client.api.PulsarClientException;
@ -131,44 +125,6 @@ public class AligenieDeviceController {
.build());
}
@ApiOperation("设备服务调用")
@PostMapping("/invoke/{deviceId}/{service}")
public InvokeResult invokeService(@PathVariable("deviceId") String deviceId,
@PathVariable("service") String service,
String args) {
InvokeResult result = new InvokeResult("", InvokeResult.FAILED_UNKNOWN);
AligenieDevice device = aligenieDeviceRepository.findByUidAndDeviceId(AuthUtil.getUserId(), deviceId);
if (device == null) {
result.setCode(InvokeResult.FAILED_NO_AUTH);
return result;
}
if (StringUtils.isBlank(deviceId) || StringUtils.isBlank(service)) {
log.error("deviceId/service is blank");
result.setCode(InvokeResult.FAILED_PARAM_ERROR);
return result;
}
try {
String requestId;
if ("set".equals(service)) {
requestId = deviceService.setProperty(deviceId,
JsonUtil.parse(args, Map.class), false);
} else {
requestId = deviceService.invokeService(deviceId,
service, JsonUtil.parse(args, Map.class), false);
}
result.setRequestId(requestId);
result.setCode(InvokeResult.SUCCESS);
} catch (OfflineException e) {
log.error("sendMsg failed", e);
result.setCode(InvokeResult.FAILED_OFFLINE);
return result;
}
return result;
}
@Data
public static class Device {
private String deviceId;

View File

@ -1,7 +1,5 @@
package cc.iotkit.manager.controller.api;
import cc.iotkit.common.exception.OfflineException;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.dao.AppDesignRepository;
import cc.iotkit.dao.DeviceRepository;
import cc.iotkit.dao.SpaceDeviceRepository;
@ -10,7 +8,6 @@ import cc.iotkit.manager.model.vo.AppPageNode;
import cc.iotkit.manager.service.AppDesignService;
import cc.iotkit.manager.service.DeviceService;
import cc.iotkit.manager.utils.AuthUtil;
import cc.iotkit.model.InvokeResult;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.space.SpaceDevice;
import io.swagger.annotations.ApiImplicitParam;
@ -20,10 +17,12 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@ -72,74 +71,6 @@ public class DeviceController {
.collect(Collectors.toList());
}
@ApiOperation("设备服务调用")
@ApiImplicitParams({
@ApiImplicitParam(value = "设备ID", name = "deviceId", required = true, dataType = "String"),
@ApiImplicitParam(value = "服务名", name = "service", required = true, dataType = "String"),
@ApiImplicitParam(value = "参数", name = "args", required = true, dataType = "String"),
})
@PostMapping("/{deviceId}/service/{service}")
public InvokeResult invokeService(@PathVariable("deviceId") String deviceId,
@PathVariable("service") String service,
String args) {
InvokeResult result = new InvokeResult("", InvokeResult.FAILED_UNKNOWN);
SpaceDevice device = checkOwner(deviceId);
if (device == null) {
result.setCode(InvokeResult.FAILED_NO_AUTH);
return result;
}
if (StringUtils.isBlank(deviceId) || StringUtils.isBlank(service)) {
log.error("deviceId/service is blank");
result.setCode(InvokeResult.FAILED_PARAM_ERROR);
return result;
}
try {
String requestId;
if ("property/set".equals(service)) {
requestId = deviceService.setProperty(deviceId,
JsonUtil.parse(args, Map.class));
} else {
requestId = deviceService.invokeService(deviceId, service,
JsonUtil.parse(args, Map.class));
}
result.setRequestId(requestId);
result.setCode(InvokeResult.SUCCESS);
} catch (OfflineException e) {
log.error("sendMsg failed", e);
result.setCode(InvokeResult.FAILED_OFFLINE);
return result;
}
return result;
}
@ApiOperation("设备属性调用")
@ApiImplicitParams({
@ApiImplicitParam(value = "设备ID", name = "deviceId", required = true, dataType = "String"),
@ApiImplicitParam(value = "参数", name = "args", required = true, dataType = "String"),
})
@PostMapping("/{deviceId}/service/property/set")
public InvokeResult setProperty(@PathVariable("deviceId") String deviceId,
String args) {
checkOwner(deviceId);
if (StringUtils.isBlank(deviceId) || StringUtils.isBlank(args)) {
throw new RuntimeException("deviceId/args is blank.");
}
return invokeService(deviceId, "property/set", args);
}
/**
*
*/
private SpaceDevice checkOwner(String deviceId) {
return spaceDeviceRepository.findOne(Example.of(SpaceDevice.builder()
.uid(AuthUtil.getUserId()).deviceId(deviceId).build()))
.orElse(null);
}
@GetMapping("/detailPage/{deviceId}")
public List<AppPageNode> deviceDetailPage(@PathVariable("deviceId") String deviceId) {
DeviceInfo device = deviceRepository.findById(deviceId).orElseThrow(() -> new RuntimeException("device not found"));

View File

View File

@ -9,13 +9,12 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
public class InvokeResult {
public static final String SUCCESS = "success";
public static final String FAILED_UNKNOWN = "unknown";
public static final String FAILED_OFFLINE = "offline";
public static final String FAILED_PARAM_ERROR = "param_error";
public static final String FAILED_NO_AUTH = "no_auth";
private String requestId;
private String code;
private long time;
public InvokeResult(String requestId) {
this.requestId = requestId;
this.time = System.currentTimeMillis();
}
}

View File

@ -27,6 +27,7 @@
<properties>
<java.version>1.8</java.version>
<keycloak-spring.version>17.0.0</keycloak-spring.version>
<vertx.version>4.2.2</vertx.version>
</properties>
<dependencyManagement>
@ -175,25 +176,25 @@
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>4.2.6</version>
<version>${vertx.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mqtt</artifactId>
<version>4.2.6</version>
<version>${vertx.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-proxy</artifactId>
<version>4.2.6</version>
<version>${vertx.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-client</artifactId>
<version>4.2.6</version>
<version>${vertx.version}</version>
</dependency>
<dependency>

Binary file not shown.

View File

@ -42,6 +42,11 @@
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-client</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>

View File

@ -1,14 +1,16 @@
package cc.iotkit.comp.biz;
package cc.iotkit.comps;
import cc.iotkit.common.Constants;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.client.HttpRequest;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.nio.file.Paths;
import java.util.HashMap;
@ -20,6 +22,7 @@ import java.util.concurrent.atomic.AtomicReference;
/**
* API
*/
@Slf4j
public class ApiTool {
private static final Vertx vertx;
@ -48,17 +51,19 @@ public class ApiTool {
ApiTool.timeout = timeout;
}
private static String getPath(String path) {
return Paths.get(Constants.API.DEVICE_BASE, path).toString();
}
/**
*
*/
public static ApiResponse getDevices(String token) {
HttpRequest<Buffer> request = client
.post(port, host, Paths.get(Constants.API.DEVICE_BASE, Constants.API.DEVICE_LIST
.replace("size", "1000")
.replace("page", "1")).toString())
.timeout(timeout)
.putHeader("authorization", "Bearer " + token);
return sendJson(request, new HashMap<>());
.post(port, host, getPath(Constants.API.DEVICE_LIST
.replace("{size}", "1000")
.replace("{page}", "1")));
return send(token, HttpMethod.POST, request, new HashMap<>());
}
/**
@ -66,11 +71,9 @@ public class ApiTool {
*/
public static ApiResponse getDeviceDetail(String token, String deviceId) {
HttpRequest<Buffer> request = client
.post(port, host, Paths.get(Constants.API.DEVICE_BASE, Constants.API.DEVICE_DETAIL
.replace("deviceId", deviceId)).toString())
.timeout(timeout)
.putHeader("authorization", "Bearer " + token);
return sendJson(request, new HashMap<>());
.get(port, host, getPath(Constants.API.DEVICE_DETAIL
.replace("{deviceId}", deviceId)));
return send(token, HttpMethod.GET, request, new HashMap<>());
}
/**
@ -78,11 +81,9 @@ public class ApiTool {
*/
public static ApiResponse setProperties(String token, String deviceId, Map<String, Object> properties) {
HttpRequest<Buffer> request = client
.post(port, host, Paths.get(Constants.API.DEVICE_BASE, Constants.API.DEVICE_SET_PROPERTIES
.replace("deviceId", deviceId)).toString())
.timeout(timeout)
.putHeader("authorization", "Bearer " + token);
return sendJson(request, properties);
.post(port, host, getPath(Constants.API.DEVICE_SET_PROPERTIES
.replace("{deviceId}", deviceId)));
return send(token, HttpMethod.POST, request, properties);
}
/**
@ -90,48 +91,70 @@ public class ApiTool {
*/
public static ApiResponse invokeService(String token, String deviceId, String service, Map<String, Object> params) {
HttpRequest<Buffer> request = client
.post(port, host, Paths.get(Constants.API.DEVICE_BASE, Constants.API.DEVICE_INVOKE_SERVICE
.replace("deviceId", deviceId)
.replace("service", service)).toString())
.timeout(timeout)
.putHeader("authorization", "Bearer " + token);
return sendJson(request, params);
.post(port, host, getPath(Constants.API.DEVICE_INVOKE_SERVICE
.replace("{deviceId}", deviceId)
.replace("{service}", service)));
return send(token, HttpMethod.POST, request, params);
}
private static ApiResponse sendJson(HttpRequest<Buffer> request, Map<String, Object> params) {
AtomicReference<ApiResponse> apiResponse = new AtomicReference<>(new ApiResponse(500, "", null));
private static ApiResponse send(String token, HttpMethod method, HttpRequest<Buffer> request, Map<String, Object> params) {
request = request
.timeout(timeout)
.putHeader("wrap-response", "json")
.putHeader("authorization", "Bearer " + token);
AtomicReference<ApiResponse> apiResponse = new AtomicReference<>(
new ApiResponse(500, "", null, System.currentTimeMillis()));
try {
//转为同步模式便于提供给js调用
CountDownLatch wait = new CountDownLatch(1);
request.sendJson(params)
.onSuccess((response) -> {
System.out.println(response.bodyAsString());
apiResponse.set(response.bodyAsJson(ApiResponse.class));
wait.countDown();
})
.onFailure((err) -> {
err.printStackTrace();
wait.countDown();
});
if (method == HttpMethod.POST) {
request.sendJson(params)
.onSuccess((response) -> {
System.out.println(response.bodyAsString());
apiResponse.set(response.bodyAsJson(ApiResponse.class));
wait.countDown();
})
.onFailure((err) -> {
err.printStackTrace();
wait.countDown();
});
} else if (method == HttpMethod.GET) {
request.send()
.onSuccess((response) -> {
apiResponse.set(response.bodyAsJson(ApiResponse.class));
wait.countDown();
})
.onFailure((err) -> {
err.printStackTrace();
wait.countDown();
});
}
if (wait.await(timeout, TimeUnit.MILLISECONDS)) {
return apiResponse.get();
} else {
apiResponse.get().setCode(500);
apiResponse.get().setStatus(500);
apiResponse.get().setMessage("request timeout");
}
} catch (Throwable e) {
apiResponse.get().setCode(500);
apiResponse.get().setStatus(500);
apiResponse.get().setMessage(e.getMessage());
}
return apiResponse.get();
}
public static void log(String msg) {
log.info(msg);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class ApiResponse {
private int code;
private int status;
private String message;
private Object data;
private long timestamp;
}
}

View File

@ -61,16 +61,16 @@ public class BizComponentManager {
} catch (Throwable e) {
throw new BizException("get component instance error");
}
componentInstance.create(new CompConfig(300, component.getConfig()));
try {
String componentScript = FileUtils.readFileToString(path.
resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile(), "UTF-8");
componentInstance.setScript(componentScript);
register(id, componentInstance);
} catch (IOException e) {
throw new BizException("get component script error", e);
}
componentInstance.create(new CompConfig(300, component.getConfig()));
register(id, componentInstance);
}
public void register(String id, IComponent component) {

View File

@ -0,0 +1,48 @@
package cc.iotkit.comps;
import cc.iotkit.model.protocol.ProtocolComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ComponentManager {
@Autowired
private BizComponentManager bizComponentManager;
@Autowired
private DeviceComponentManager deviceComponentManager;
public void register(ProtocolComponent component) {
String type = component.getType();
if (ProtocolComponent.TYPE_BIZ.equals(type)) {
bizComponentManager.register(component);
} else if (ProtocolComponent.TYPE_DEVICE.equals(type)) {
deviceComponentManager.register(component);
}
}
public void deRegister(String id) {
bizComponentManager.deRegister(id);
deviceComponentManager.deRegister(id);
}
public void start(String id) {
bizComponentManager.start(id);
deviceComponentManager.start(id);
}
public void stop(String id) {
bizComponentManager.stop(id);
deviceComponentManager.stop(id);
}
public boolean isRunning(String id) {
return bizComponentManager.isRunning(id) || deviceComponentManager.isRunning(id);
}
}

View File

@ -50,7 +50,8 @@ public class DeviceComponentManager {
@PostConstruct
public void init() {
try {
List<ProtocolComponent> componentList = componentRepository.findByState(ProtocolComponent.STATE_RUNNING);
List<ProtocolComponent> componentList = componentRepository.findByStateAndType(
ProtocolComponent.STATE_RUNNING, ProtocolComponent.TYPE_DEVICE);
for (ProtocolComponent component : componentList) {
register(component);
start(component.getId());

View File

@ -43,19 +43,19 @@
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>4.2.6</version>
<version>4.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-proxy</artifactId>
<version>4.2.6</version>
<version>4.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mqtt</artifactId>
<version>4.2.6</version>
<version>4.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>

Binary file not shown.

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>protocol-gateway</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>http-biz-component</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactSet>
<includes>
<include>io.vertx:vertx-web-proxy</include>
<include>io.vertx:vertx-web</include>
<include>io.vertx:vertx-bridge-common</include>
<include>io.vertx:vertx-http-proxy</include>
<include>io.vertx:vertx-core</include>
<include>io.netty:netty-codec-http2</include>
</includes>
</artifactSet>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-proxy</artifactId>
<version>4.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>component</artifactId>
<version>0.1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>

44
protocol-gateway/http-biz-component/pom.xml Normal file → Executable file
View File

@ -28,17 +28,49 @@
<artifactId>vertx-web-proxy</artifactId>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-client</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>component</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactSet>
<includes>
<include>io.vertx:vertx-web-proxy</include>
<include>io.vertx:vertx-web</include>
<include>io.vertx:vertx-bridge-common</include>
<include>io.vertx:vertx-http-proxy</include>
<include>io.vertx:vertx-core</include>
<include>io.netty:netty-codec-http2</include>
</includes>
</artifactSet>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -6,6 +6,7 @@ import cc.iotkit.comp.IComponent;
import io.vertx.core.MultiMap;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
@ -14,16 +15,21 @@ import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
import static java.nio.charset.StandardCharsets.UTF_8;
@Data
@Slf4j
public class HttpBizComponent implements IComponent {
private final Vertx vertx = Vertx.vertx();
@ -32,7 +38,9 @@ public class HttpBizComponent implements IComponent {
private Object scriptObj;
private HttpConfig config;
private CompConfig config;
private HttpConfig httpConfig;
private String script;
@ -40,7 +48,7 @@ public class HttpBizComponent implements IComponent {
@Override
public void create(CompConfig config) {
this.config = JsonUtil.parse(config.getOther(), HttpConfig.class);
this.httpConfig = JsonUtil.parse(config.getOther(), HttpConfig.class);
try {
scriptObj = engine.eval(String.format("new (function () {\n%s})()", script));
} catch (ScriptException e) {
@ -54,53 +62,75 @@ public class HttpBizComponent implements IComponent {
Router backendRouter = Router.router(vertx);
backendRouter.route().handler(BodyHandler.create())
.handler(rc -> {
Map<String, Object> httpHeader = getData(rc.request().headers());
log.info("request header:{}", JsonUtil.toJsonString(httpHeader));
Map<String, List<Object>> httpParams = getListData(rc.request().params());
log.info("request params:{}", JsonUtil.toJsonString(httpParams));
try {
Map<String, Object> httpHeader = getData(rc.request().headers());
log.info("request header:{}", JsonUtil.toJsonString(httpHeader));
Map<String, List<Object>> httpParams = getListData(rc.request().params());
log.info("request params:{}", JsonUtil.toJsonString(httpParams));
String contentType = rc.request().headers().get("Content-Type");
JsonObject responseHeader = new JsonObject();
if ("application/json".equals(contentType)) {
String bodyStr = rc.toString();
Map body = JsonUtil.parse(bodyStr, Map.class);
log.info("request body:{}", bodyStr);
HttpServerRequest httpRequest = rc.request();
String contentType = httpRequest.headers().get("Content-Type");
JsonObject responseHeader = new JsonObject();
if ("application/json".equals(contentType)) {
String bodyStr = rc.getBody().toString();
Map body = JsonUtil.parse(bodyStr, Map.class);
log.info("request body:{}", bodyStr);
String response = "unknown error";
String name = "onReceive";
if (((ScriptObjectMirror) scriptObj).get(name) != null) {
try {
Object result = engine.invokeMethod(scriptObj, name, body);
Object resultObj = JsonUtil.toObject((ScriptObjectMirror) result);
if (resultObj instanceof Map) {
JsonObject data = JsonObject.mapFrom(resultObj);
responseHeader = data.getJsonObject("header");
response = data.getString("content");
String response = "unknown error";
String name = "onReceive";
if (((ScriptObjectMirror) scriptObj).get(name) != null) {
try {
Object result = engine.invokeMethod(scriptObj,
name,
httpRequest.method().name(),
httpRequest.path(),
httpHeader,
httpParams,
body);
Object resultObj = JsonUtil.toObject((ScriptObjectMirror) result);
if (resultObj instanceof Map) {
JsonObject data = JsonObject.mapFrom(resultObj);
responseHeader = data.getJsonObject("header");
response = data.getString("content");
response = response == null ? "" : response;
}
} catch (Throwable e) {
log.error("invokeMethod onReceive error", e);
response = e.getMessage();
}
} catch (Throwable e) {
log.error("invokeMethod onReceive error", e);
response = e.getMessage();
} else {
log.error("required [onReceive] method");
}
HttpServerResponse httpServerResponse = rc.response();
//设置响应头
responseHeader.getMap().forEach((key, value) -> {
//大写转换
key = key.replaceAll("([A-Z])", "-$1").toLowerCase();
httpServerResponse.putHeader(key, value.toString());
});
log.info("response,header:{},content:{}", responseHeader, response);
//设置响应内容
httpServerResponse
.end(response);
} else {
log.error("required [onReceive] method");
rc.response().end("");
}
HttpServerResponse httpServerResponse = rc.response();
//设置响应头
responseHeader.getMap().forEach((key, value) -> {
//大写转换
key = key.replaceAll("([A-Z])", "-$1").toLowerCase();
httpServerResponse.putHeader(key, value.toString());
});
log.info("response,header:{},content:{}", responseHeader, response);
//设置响应内容
httpServerResponse
.end(response);
} catch (Throwable e) {
log.error("handle request error", e);
rc.response().end("server error:" + e.getMessage());
}
});
backendServer.requestHandler(backendRouter).listen(config.getPort());
backendServer.requestHandler(backendRouter)
.listen(httpConfig.getPort(), (http) -> {
if (http.succeeded()) {
log.info("http server create succeed,port:{}", httpConfig.getPort());
} else {
log.error("http server create failed", http.cause());
}
});
}
@Override
@ -131,4 +161,11 @@ public class HttpBizComponent implements IComponent {
return data;
}
public static void main(String[] args) throws IOException {
HttpBizComponent component = new HttpBizComponent();
component.setScript(FileUtils.readFileToString(new File("/Users/sjg/home/gitee/open-source/iotkit-parent/protocol-gateway/http-biz-component/src/main/resources/component.js"), UTF_8));
component.create(new CompConfig(1000, "{\"port\":9081}"));
component.start();
}
}

View File

@ -0,0 +1,36 @@
//引用api工具类
var apiTool = Java.type("cc.iotkit.comp.biz.ApiTool");
//api配置
apiTool.config("http://localhost",8086,3000);
this.onReceive=function(method,path,header,params,body){
//methodpost、get、delete...
//path请求路径
//headerhttp请求头数据,结构:{xx:xx,yy:yy}
//params请求参数结构{xx:[...],yy:[...]}
//body请求体当提交的数据为json格式时使用结构{xx:xx,yy:yy}
apiTool.log("onReceive method:"+method);
apiTool.log("onReceive path:"+path);
apiTool.log("onReceive header:"+header);
apiTool.log("onReceive params:"+params);
apiTool.log("onReceive body:"+body);
var duHeader=body.header;
var namespace=duHeader.namespace;
var requestName=duHeader.name;
var messageId=duHeader.messageId;
var duPayload=duHeader.payload;
var token=duHeader.accessToken;
//设备发现
if(namespace=="DuerOS.ConnectedHome.Discovery" && requestName=="DiscoverAppliancesRequest"){
}
return {
url:"xx",//不指定直接作为响应返回
header:{
contentType:"xx"
},
content:"xx"
}
}

View File

View File

@ -11,8 +11,8 @@ public class Application {
public static void main(String[] args) throws IOException {
if (args.length == 0) {
// Mqtt.broker = "tcp://127.0.0.1:1883";
Mqtt.broker = "tcp://120.76.96.206:1883";
Mqtt.broker = "tcp://127.0.0.1:1883";
// Mqtt.broker = "tcp://120.76.96.206:1883";
} else {
Mqtt.broker = args[0];
}

View File

@ -43,13 +43,13 @@
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>4.2.6</version>
<version>4.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mqtt</artifactId>
<version>4.2.6</version>
<version>4.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>