Browse Source

Merge pull request #55 from BohdanSmetanyuk/feature/sync_edge_from_controller

Feature/sync edge from controller
pull/2436/head
VoBa 6 years ago
committed by GitHub
parent
commit
d5f9419b6e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  2. 18
      application/src/main/java/org/thingsboard/server/controller/EdgeController.java
  3. 9
      application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java
  4. 56
      application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java
  5. 4
      rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
  6. 14
      ui/src/app/api/edge.service.js
  7. 6
      ui/src/app/edge/edge-fieldset.tpl.html
  8. 13
      ui/src/app/edge/edge.directive.js
  9. 2
      ui/src/app/locale/locale.constant-de_DE.json
  10. 2
      ui/src/app/locale/locale.constant-en_US.json
  11. 2
      ui/src/app/locale/locale.constant-es_ES.json
  12. 2
      ui/src/app/locale/locale.constant-fr_FR.json

12
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -104,6 +104,8 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.edge.EdgeNotificationService;
import org.thingsboard.server.service.edge.rpc.EdgeGrpcService;
import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService;
import org.thingsboard.server.service.queue.TbClusterService;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.AccessControlService;
@ -202,12 +204,18 @@ public abstract class BaseController {
@Autowired
protected TbQueueProducerProvider producerProvider;
@Autowired
@Autowired(required = false)
protected EdgeService edgeService;
@Autowired
@Autowired(required = false)
protected EdgeNotificationService edgeNotificationService;
@Autowired(required = false)
protected SyncEdgeService syncEdgeService;
@Autowired(required = false)
protected EdgeGrpcService edgeGrpcService;
@Value("${server.log_controller_error_stack_trace}")
@Getter
private boolean logControllerErrorStackTrace;

18
application/src/main/java/org/thingsboard/server/controller/EdgeController.java

@ -46,6 +46,7 @@ import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.EdgeGrpcSession;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
@ -409,6 +410,23 @@ public class EdgeController extends BaseController {
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/sync", method = RequestMethod.POST)
public void syncEdge(@RequestBody EdgeId edgeId) throws ThingsboardException {
try {
edgeId = checkNotNull(edgeId);
if (isEdgesSupportEnabled()) {
EdgeGrpcSession session = edgeGrpcService.getEdgeGrpcSessionById(edgeId);
Edge edge = session.getEdge();
syncEdgeService.sync(edge);
} else {
throw new ThingsboardException("Edges support disabled", ThingsboardErrorCode.GENERAL);
}
} catch (Exception e) {
throw handleException(e);
}
}
@RequestMapping(value = "/license/checkInstance", method = RequestMethod.POST)
@ResponseBody
public Object checkInstance(@RequestBody Object request) throws ThingsboardException {

9
application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java

@ -146,6 +146,15 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, System.currentTimeMillis());
}
public EdgeGrpcSession getEdgeGrpcSessionById(EdgeId edgeId) {
EdgeGrpcSession session = sessions.get(edgeId);
if (session != null && session.isConnected()) {
return session;
} else {
throw new RuntimeException("Edge is not connected");
}
}
private void processHandleMessages() {
executor.submit(() -> {
while (!Thread.interrupted()) {

56
application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java

@ -24,9 +24,11 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
@ -34,6 +36,10 @@ import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.edge.imitator.EdgeImitator;
import org.thingsboard.server.gen.edge.AssetUpdateMsg;
import org.thingsboard.server.gen.edge.DeviceUpdateMsg;
import org.thingsboard.server.gen.edge.RuleChainUpdateMsg;
import java.util.ArrayList;
import java.util.Collections;
@ -641,4 +647,54 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
Assert.assertEquals(0, pageData.getData().size());
}
@Test
public void testSyncEdge() throws Exception {
Edge edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class);
Device device = new Device();
device.setName("Edge Device 1");
device.setType("test");
Device savedDevice = doPost("/api/device", device, Device.class);
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/device/" + savedDevice.getId().getId().toString(), Device.class);
Asset asset = new Asset();
asset.setName("Edge Asset 1");
asset.setType("test");
Asset savedAsset = doPost("/api/asset", asset, Asset.class);
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
EdgeImitator edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret());
// should be 3, but 3 events from sync service + 3 from controller. will be fixed in next releases
edgeImitator.expectMessageAmount(6);
edgeImitator.connect();
edgeImitator.waitForMessages();
Assert.assertEquals(6, edgeImitator.getDownlinkMsgs().size());
Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent());
Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent());
Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent());
edgeImitator.getDownlinkMsgs().clear();
edgeImitator.expectMessageAmount(3);
doPost("/api/edge/sync", edge.getId());
edgeImitator.waitForMessages();
Assert.assertEquals(3, edgeImitator.getDownlinkMsgs().size());
Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent());
Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent());
Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent());
edgeImitator.disconnect();
doDelete("/api/device/" + savedDevice.getId().getId().toString())
.andExpect(status().isOk());
doDelete("/api/asset/" + savedAsset.getId().getId().toString())
.andExpect(status().isOk());
doDelete("/api/edge/" + edge.getId().getId().toString())
.andExpect(status().isOk());
}
}

4
rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java

@ -2372,6 +2372,10 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
params).getBody();
}
public void syncEdge(EdgeId edgeId) {
restTemplate.postForEntity(baseURL + "/api/edge/sync", edgeId, EdgeId.class);
}
@Deprecated
public Optional<JsonNode> getAttributes(String accessToken, String clientKeys, String sharedKeys) {
Map<String, String> params = new HashMap<>();

14
ui/src/app/api/edge.service.js

@ -33,7 +33,8 @@ function EdgeService($http, $q, customerService) {
unassignEdgeFromCustomer: unassignEdgeFromCustomer,
makeEdgePublic: makeEdgePublic,
setRootRuleChain: setRootRuleChain,
getEdgeEvents: getEdgeEvents
getEdgeEvents: getEdgeEvents,
syncEdge: syncEdge
};
return service;
@ -262,4 +263,15 @@ function EdgeService($http, $q, customerService) {
});
return deferred.promise;
}
function syncEdge(edgeId) {
var deferred = $q.defer();
var url = '/api/edge/sync';
$http.post(url, edgeId).then(function success(response) {
deferred.resolve(response);
}, function fail(response) {
deferred.reject(response.data);
});
return deferred.promise;
}
}

6
ui/src/app/edge/edge-fieldset.tpl.html

@ -48,6 +48,12 @@
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon>
<span translate>edge.copy-id</span>
</md-button>
<md-button ng-click="onEdgeSync(edge.id)"
ng-show="!isEdit"
class="md-raised">
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon>
<span translate>edge.sync</span>
</md-button>
</div>
<md-content class="md-padding" layout="column">

13
ui/src/app/edge/edge.directive.js

@ -20,7 +20,7 @@ import edgeFieldsetTemplate from './edge-fieldset.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, utils, toast, types, customerService) {
export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, utils, toast, types, customerService, edgeService) {
var linker = function (scope, element) {
var template = $templateCache.get(edgeFieldsetTemplate);
element.html(template);
@ -69,6 +69,17 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD
toast.showSuccess($translate.instant('edge.id-copied-message'), 750, angular.element(element).parent().parent(), 'bottom left');
};
scope.onEdgeSync = function (edgeId) {
edgeService.syncEdge(edgeId).then(
function success() {
toast.showSuccess($translate.instant('edge.sync-message'), 750, angular.element(element).parent().parent(), 'bottom left');
},
function fail(error) {
toast.showError(error);
}
);
}
$compile(element.contents())(scope);
scope.onEdgeInfoCopied = function(type) {

2
ui/src/app/locale/locale.constant-de_DE.json

@ -756,6 +756,8 @@
"details": "Details",
"copy-id": "Regelketten-ID kopieren",
"id-copied-message": "Regelketten-ID wurde in die Zwischenablage kopiert",
"sync": "Sync Edge",
"sync-message": "Edge wurde synchronisiert",
"permissions": "Berechtigungen",
"edge-required": "Rand ist erforderlich.",
"edge-type": "Randtyp",

2
ui/src/app/locale/locale.constant-en_US.json

@ -788,6 +788,8 @@
"events": "Events",
"copy-id": "Copy Edge Id",
"id-copied-message": "Edge Id has been copied to clipboard",
"sync": "Sync Edge",
"sync-message": "Edge has been synchronized",
"permissions": "Permissions",
"edge-required": "Edge required",
"edge-type": "Edge type",

2
ui/src/app/locale/locale.constant-es_ES.json

@ -769,6 +769,8 @@
"details": "Detalles",
"copy-id": "Copiar ID de borde",
"id-copied-message": "El ID de borde se ha copiado al portapapeles",
"sync": "Sinc Edge",
"sync-message": "Edge se ha sincronizado",
"permissions": "Permisos",
"edge-required": "Edge required",
"edge-type": "Type de la bordure",

2
ui/src/app/locale/locale.constant-fr_FR.json

@ -774,6 +774,8 @@
"details": "Détails de l'entité",
"copy-id": "Copier borudre Id",
"id-copied-message": "Id de la bordure a été copié dans le presse-papier",
"sync": "Sync Edge",
"sync-message": "Edge a été synchronisé",
"permissions": "Autorisations",
"edge-required": "Bordure est requise",
"edge-type": "Type de la bordure",

Loading…
Cancel
Save