Commit 0045f00613ac04e27f25ee7c986c7c9b9b17a921

Authored by Andrew Shvayka
Committed by GitHub
2 parents b1712430 3c1682f5

Merge pull request #4451 from ViacheslavKlimov/master-to-snmp

Merge 'master' into 'develop/snmp'
Showing 82 changed files with 1583 additions and 658 deletions

Too many changes to show.

To preserve performance only 82 of 217 files are displayed.

@@ -455,6 +455,24 @@ @@ -455,6 +455,24 @@
455 "dataKeySettingsSchema": "{}\n", 455 "dataKeySettingsSchema": "{}\n",
456 "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Photo camera input\",\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"showLegend\":false,\"actions\":{}}" 456 "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Photo camera input\",\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
457 } 457 }
  458 + },
  459 + {
  460 + "alias": "update_json_attribute",
  461 + "name": "Update JSON attribute",
  462 + "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADhCAMAAACZWwyuAAAB71BMVEX////w8PDt7e3z8/Pg4ODAwMDc3Nz19fUZhJQ4lKK9vb17e3v9/f2mpqbj4+P4+Pi+vr58fHzT09P7+/uTxcz2+/ucy9GpqakCAgK93OHNzc0eh5b09PSw1dusrKwvkZ+ampqysrIzMzPV1dXCwsKurq4iiZnZ2dnX19fIyMgrj50ABsiKiopmZmbo8/XQ5+ro6OjPz89JnqqCgoLX6u2cnJwmjJv39/ff39+12N7ExMQ2NjaioqKYmJjs7OzD4OTS0tLKysrh8PLq6uq6uroCCMjDw8OOjo6hzdO0tLQuj56UlJS4uvDZ7O7l5eVvsrw0k6EchZWEhIRwcHDU6ezG4eaGv8d1tb+3t7dCmqeIiIj4+/3j8fO62+AKD8tWpbGgoKBqamouLi7u7u47lqTP0PWr0tgXHM1/u8N6uMFqsLpfqrVNoKxFRUXU1faYyM92dnY7Ozvz+Pry8vK5ubm4uLh+fn5sbGzGx/OipOtzduG42t8uM9KNw8pTo690dHT6+vrt9viOkefb29um0NYfHx/p6vu9vvGqrO2YmulXW9uhztRnrrgmJiYQEBDt7fzk5frf4PjL4+eMj+a/3eJpbN9MUNk7P9SQxMuNwslfX19TU1OcnurI4uY9QdYyN9ImK9BVVVVPT097fuNYWFjSJwPyAAALvElEQVR42uzbTWviQBjA8ad5qgNONI05FCSIshUNKERCSFlM2WIxSKCH5FI8RfoFCrvVYwv7xTfG4susxqgpqJkfHoLM6c9MTCYROI7jOC4doiIRoqrEkhQRuIOJEsEVROI1Dw2pIkPlMQ8PyWMez8ItLOD2QnArAlxyIsEYhK/x5CSMJQGX0Cfu8AmXTCEqbkWUPQaBiDtd8hJXMJ6SbNByeWd3iROMRxIPAhEx09MSd1ATDwIJMdPTEndJNIid4D/kkLk4yMbFZTop2fXdonSZktb2XuFKpwRnBzeoGoeklNZS1tjj+BVu2hDKfYhxKXUXTtnXHIqgXd+esk/pNSK+GrQcjZsbuotBVrKUFmzSGs++b1djZqVV1m01D6crqlSpVOldpYKFSmzKWUCN0nI0bq5bWAwiuHquNNnj+JOlSDWA144OJW86KUcp38oAtQZIPZ/mICQEBvWGcLpw7i6acu0iCkXDtQ1hcos4MtdTOt4VYs2h5dk42y4azj3ejhYpVUyEwEZ1F+BpBJKviQVfWUkZuOTZz0e5ba8FJ4xNWZcLPw0De97vezpYTzmUK1iiL18p5T+aEaymxGRU2OhhTMAbgFISATvCMqU0LgEUo4U/KOreKV9LsSlHAeKtgY+09STr6ylvzABfRuWvlC5i4DCz8oiU4Az6Uwug25blzsMyZb8zDpkQkgj04YSxKSf16FwpTOquzZwrnx5lvT3sLlP21lKSoxY4aM4wANCn10DmKemvaFZ2HuBMMCnDT5QSe205x6R8ufICWqowKQ/92WFJ/lsTID+9vhp29FlKpye1/AbUXELqTTgDbMq60S2PDMRHKutsSqzTGrIpD74YYvUohBr+x1D+O0tZMqaO0wASfPjmWdwjbfgFd0wDUZjY+F/Ke6ptSRl/iZ6Nm3Dc4sq7Se/GMRtbQ7hZvjrR+XZGKimrhoZ7pOSbbKntV/Kt39R20fkDiZSf7Yi4i3rBkzLVJ46g4M7mHH+l4Bjpv+hiXfTyTr9lVk+U38Diqzs1n1l8XeibiJaKLP7O74FEiYdMT/RfE0RVJZICe8txSSRKmU9KEIRm8V0QnitNIWvST6m93whhy3/sm/lTEmEYx7/SOLPbdFgjCDGEWm0FBUVEGRRF0WEmlCgxeFSaeKHpNF1ajWW3V4cddh9/aLs078PqCMOCxjrs55dn3mff9/3hM7x7fGfYrSs1ll9leUWFrmrK+ERXahSk0uc9srTKJ7c31+hKjQJUHnnorc2g0lijK9eVGgWovHF1fUaV5zSVyg54RUaVNzWVearcK5FWWWPcqanMU2VjU1NTI6kcNjbpNJX5HvDGq43pA7510/Q+TaVylcyl/F65z1iuqVSi8vgpX23VqaUfO5c1lUpUrq+V2LXUh6PxnPbhuExxhnHrfi3OKFylbseV8ic/tz/WlRoroFK8V9ZMGad0pUZuKstyBSWMpnJ1qfS0tXmk6hhFHmRfR/sXnQJUVswPJy8dy0Vlvd9fL1WDFXmRfR3tv5hn39oT9+JU5TyyNwBQi8rOz3vWVnurc1HZ5XR2rZhK2n8x68buNbwNPqIq43lCVSrLpB/k1aZcVD5wODoAXOQk9ND3hD39DrzhzR39QgiIhs22Xj1YH4EQL5hjQIQ3C5OO9DrbWaCSZ9dpPu2PjdeuHZK7BPD+JdU0g4nrQVWplPizJxeVAaAVgLvF5na7gT6+rnlgAJZ6p6ujWfCD72uesEWpDxP3qvlrGzA+6hwNh2gdU8mus/m0PzYYjYexkO/3qBLxsbtQnUpf8vDCRi4HNcBFADcXsPDoDcF1FnwlYOFaWV9UpQdjiGfrSCW7TvPTVB/FQl4knlIlfr+H6lRWDZ8uU66yjjOLcM2Syj64DCmV41wd65PK1sl6m9WWUSXNz8zd9jtUiaftg6pTuXX4VFkeKk2c84KIXlTZE2IqRzgT65PKrgF/pEem0jpEKuX7ZDPZQDXNC3swGLSnnkNqUbnfW6PwFb1bgEgr1w0JUSXAVJq4AOszVSNcHTBho3VwRUkl7bOQg9WQMdj+nOo/vnwBMDMoEnwxA0AtKm/MbxE5qUBlhGt5Z9AjKtw3WSwylTFLd7gfrM9Uge/wO3ts6XWfhFf+PlJJ84nFj52XH66LxKli1m5/DQl2wM9MX1aFyl//8koFKvHRY3Y5sO5+2Gxtkau0CpMjYH1SdaFDMNf3p9fpo8LF+hBdp/nEopehH3aJ11QRHxuLL1D5y3hbFSqXAvnAV6JIbJuu1lQuC0eStRs1lctC1aU16njsaCFb8VRW5pCxvWnBauW/5ZXZDvKQJ0K6ednYMarGXHIFVFZ99ib36BTklRlVRjmTXCWNDdaccsmgXaIBSlGPSt9BMa/0KcgrM6rUOyFTSWNSmT2XxB2RucQsFKMalRLztxTklbxVEKJ6FktQXhngOK4OIiOTgjXGszHllA5p1Mo1L5FLErPtd6EcFansXDt8TkFeyff7J4RPTCXllXG3+2JKXX/YYhFVsjHllLFewCLEs+WSc2MoOoWoXFtbu6kzg8pM74+9LlJJeSWQUhfg/Kk+G9MBb+GB3g5kySWfioFF0SlE5b4TV4YvKVQ5ZCWVLK9k6tq4kaVVOjk3YkPIwtuECv4gV+C90uc9pkzlWRvljiyvZOpMmVSiq2WciyALH+ZQfApUuV65SsodKRkCPN2p/NGS6rMx5ZQYCk+Es+SSmAk+Q/EpQOX5mgpf8mGZYpUsd5SpfDBgMugR8hikPhtTTolxwdqDzLkkntlHUHzyV9l5I+lNHmhUrpLljjKVzpg55kC8x2a2hsDGlFMCvVwEmXNJPEpABayOOMPggvpZBSrHnRaPCepnBVRuOFFefmIDlg3TX/buXqVhKIzD+FuonEEJJQ4eKogEOrjFQRRSisEiuIl3YPYOvQId7Kg34OSdGgd1SaD5aPmH8zwQsv8g5Jx3OOf08c0GUP+UUezMXDzA8/3lKHNnZS630Oqf8sAK//5QvkKrG+VVsqygXEQvGyibUc5WlZTl44+gbEJ5u5pm1ZT3/hjKBpSLr5NRDeWFf4WyyR78eVRHeecnUG5PebOOaynt0K8ttNpTzpMsy5LkvIry+uNpZqHVnjK6LMvm4yrKqXd84A2X6PzBd0mZux/KERvHfsYZE884o5ch2/LscxOe5C4orfDFxMJrAFP0oQQllHpBCaVeUEKpF5RQ6gUllHpBCaVeUEKpF5RQ6gUllHpBCaVeUEKpF5RQ6gUllHpBCaVeUEKpF5RQ6gUllHpBCaVeUEKpF5RQ6gUllHpBCaVeUEKpF5RQ6gUllHpBCaVeUEKpF5RQ6gUllHpBuWdK2qLwDj8lIiIiIiIKLpdG45ZFqTP6y407heV/aTfK1Oi3qBtlgNdmfLdrxypyw0AAhifJ2AeDZtcohUAEgZGFrdJVjIsgk2DY5urt9xFu9wn2xWMFLklzV3gb45u/GHD7YSML5s3wwUASSqHcbkIplNtLKIVyewll7onaZR7oB/yfJ/UYZfvLmbMXyscpy2CKxplOKB+mtBwRNRcflLJJvhh/Anybir4nBV9sMeJKyonnZaYO/cm4GX1+JC6xr02dPgAlpaFpFMTq7onUsRkx0WEd5RD42ucP3YWJeMJQI4YTJj7H2tz3TzkBlPR0oQEgkUK6AEzz2mPnxhx6LPsW0RA2XHYc8ebKwXPcP2UPgPTynAk9KV2pTHtcRZkxZ8Ma9dkZvqJmO3KLjnPFTimP1EEm/PyP8tMfSp8p7/R9FWWyy9BMrTnp1lwRA53zNx70UrtTSmjiMhIdXykvdADQpDCT2katoiTWiC1Xli0OmbJyZkQ8m4XR7/XYASQ7JNLwSglxfh4qUl+bETUNsIqyM66YAyfPdaz5hpiYuzzDWLHeKyUcYhEH9Zcy/wzZRApebDUOa2873dWZ2iJG54oQENHVuGRrE+Ju30q5g28qoRTK7SWUQrm9hFIot5dQCuX2kvUrWQrcXrKqKgvUkiRJkiRJkiS9328dj4CaN1dagAAAAABJRU5ErkJggg==",
  463 + "description": "Simple form to input new JSON value for pre-defined attribute/timeseries key.",
  464 + "descriptor": {
  465 + "type": "latest",
  466 + "sizeX": 7.5,
  467 + "sizeY": 3,
  468 + "resources": [],
  469 + "templateHtml": "<tb-json-input-widget \n [ctx]=\"ctx\">\n</tb-json-input-widget>",
  470 + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.attribute-update-form__grid {\n display: flex;\n}\n.grid__element:first-child {\n flex: 1;\n}\n.grid__element:last-child {\n margin-top: 19px;\n margin-left: 7px;\n}\n.grid__element {\n display: flex;\n}\n\n.attribute-update-form .mat-button.mat-icon-button {\n width: 32px;\n min-width: 32px;\n height: 32px;\n min-height: 32px;\n padding: 0 !important;\n margin: 0 !important;\n line-height: 20px;\n}\n\n.attribute-update-form .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}",
  471 + "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.jsonInputWidget.onDataUpdated();\n}\n\nself.onResize = function() {\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n }\n}\n\nself.onDestroy = function() {\n}",
  472 + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"AdvancedSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"widgetMode\": {\n \"title\": \"Widget mode\",\n \"type\": \"string\",\n \"default\": \"ATTRIBUTE\"\n },\n \"attributeScope\": {\n \"title\": \"Attribute scope\",\n \"type\": \"string\",\n \"default\": \"SERVER_SCOPE\"\n },\n \"showLabel\":{\n \"title\": \"Show label\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"attributeRequired\": {\n \"title\": \"Value required\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showResultMessage\": {\n \"title\": \"Show result message\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n {\n \"key\": \"widgetMode\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"ATTRIBUTE\",\n \"label\": \"Update attribute\"\n },\n {\n \"value\": \"TIME_SERIES\",\n \"label\": \"Update timeseries\"\n }\n ]\n },\n {\n \"key\": \"attributeScope\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"condition\": \"model.widgetMode === 'ATTRIBUTE'\",\n \"items\": [\n {\n \"value\": \"SERVER_SCOPE\",\n \"label\": \"Server attribute\"\n },\n {\n \"value\": \"SHARED_SCOPE\",\n \"label\": \"Shared attribute\"\n }\n ]\n },\n \"showLabel\",\n {\n \"key\": \"labelValue\",\n \"condition\": \"model.showLabel\"\n },\n \"attributeRequired\",\n \"showResultMessage\"\n ]\n}",
  473 + "dataKeySettingsSchema": "{}",
  474 + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"attributeScope\":\"SERVER_SCOPE\",\"showLabel\":true,\"attributeRequired\":true,\"showResultMessage\":true},\"title\":\"Update JSON attribute\",\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}"
  475 + }
458 } 476 }
459 ] 477 ]
460 } 478 }
@@ -21,7 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping; @@ -21,7 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
21 @Controller 21 @Controller
22 public class WebConfig { 22 public class WebConfig {
23 23
24 - @RequestMapping(value = "/{path:^(?!api$)(?!assets$)(?!static$)(?!webjars$)[^\\.]*}/**") 24 + @RequestMapping(value = {"/assets", "/assets/", "/{path:^(?!api$)(?!assets$)(?!static$)(?!webjars$)[^\\.]*}/**"})
25 public String redirect() { 25 public String redirect() {
26 return "forward:/index.html"; 26 return "forward:/index.html";
27 } 27 }
@@ -46,8 +46,6 @@ import org.thingsboard.server.queue.util.TbCoreComponent; @@ -46,8 +46,6 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
46 import org.thingsboard.server.service.security.permission.Operation; 46 import org.thingsboard.server.service.security.permission.Operation;
47 import org.thingsboard.server.service.security.permission.Resource; 47 import org.thingsboard.server.service.security.permission.Resource;
48 48
49 -import java.util.UUID;  
50 -  
51 @RestController 49 @RestController
52 @TbCoreComponent 50 @TbCoreComponent
53 @RequestMapping("/api") 51 @RequestMapping("/api")
@@ -177,7 +175,6 @@ public class AlarmController extends BaseController { @@ -177,7 +175,6 @@ public class AlarmController extends BaseController {
177 @RequestParam(required = false) String sortOrder, 175 @RequestParam(required = false) String sortOrder,
178 @RequestParam(required = false) Long startTime, 176 @RequestParam(required = false) Long startTime,
179 @RequestParam(required = false) Long endTime, 177 @RequestParam(required = false) Long endTime,
180 - @RequestParam(required = false) String offset,  
181 @RequestParam(required = false) Boolean fetchOriginator 178 @RequestParam(required = false) Boolean fetchOriginator
182 ) throws ThingsboardException { 179 ) throws ThingsboardException {
183 checkParameter("EntityId", strEntityId); 180 checkParameter("EntityId", strEntityId);
@@ -191,12 +188,9 @@ public class AlarmController extends BaseController { @@ -191,12 +188,9 @@ public class AlarmController extends BaseController {
191 } 188 }
192 checkEntityId(entityId, Operation.READ); 189 checkEntityId(entityId, Operation.READ);
193 TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); 190 TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
194 - UUID idOffsetUuid = null;  
195 - if (StringUtils.isNotEmpty(offset)) {  
196 - idOffsetUuid = toUUID(offset);  
197 - } 191 +
198 try { 192 try {
199 - return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator, idOffsetUuid)).get()); 193 + return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get());
200 } catch (Exception e) { 194 } catch (Exception e) {
201 throw handleException(e); 195 throw handleException(e);
202 } 196 }
@@ -110,7 +110,6 @@ import org.thingsboard.server.dao.model.ModelConstants; @@ -110,7 +110,6 @@ import org.thingsboard.server.dao.model.ModelConstants;
110 import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; 110 import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService;
111 import org.thingsboard.server.dao.oauth2.OAuth2Service; 111 import org.thingsboard.server.dao.oauth2.OAuth2Service;
112 import org.thingsboard.server.dao.relation.RelationService; 112 import org.thingsboard.server.dao.relation.RelationService;
113 -import org.thingsboard.server.dao.resource.TbResourceService;  
114 import org.thingsboard.server.dao.rule.RuleChainService; 113 import org.thingsboard.server.dao.rule.RuleChainService;
115 import org.thingsboard.server.dao.tenant.TbTenantProfileCache; 114 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
116 import org.thingsboard.server.dao.tenant.TenantProfileService; 115 import org.thingsboard.server.dao.tenant.TenantProfileService;
@@ -130,6 +129,7 @@ import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService; @@ -130,6 +129,7 @@ import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService;
130 import org.thingsboard.server.service.lwm2m.LwM2MModelsRepository; 129 import org.thingsboard.server.service.lwm2m.LwM2MModelsRepository;
131 import org.thingsboard.server.service.profile.TbDeviceProfileCache; 130 import org.thingsboard.server.service.profile.TbDeviceProfileCache;
132 import org.thingsboard.server.service.queue.TbClusterService; 131 import org.thingsboard.server.service.queue.TbClusterService;
  132 +import org.thingsboard.server.service.resource.TbResourceService;
133 import org.thingsboard.server.service.security.model.SecurityUser; 133 import org.thingsboard.server.service.security.model.SecurityUser;
134 import org.thingsboard.server.service.security.permission.AccessControlService; 134 import org.thingsboard.server.service.security.permission.AccessControlService;
135 import org.thingsboard.server.service.security.permission.Operation; 135 import org.thingsboard.server.service.security.permission.Operation;
@@ -18,12 +18,14 @@ package org.thingsboard.server.controller; @@ -18,12 +18,14 @@ package org.thingsboard.server.controller;
18 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.security.access.prepost.PreAuthorize; 19 import org.springframework.security.access.prepost.PreAuthorize;
20 import org.springframework.web.bind.annotation.PathVariable; 20 import org.springframework.web.bind.annotation.PathVariable;
  21 +import org.springframework.web.bind.annotation.RequestBody;
21 import org.springframework.web.bind.annotation.RequestMapping; 22 import org.springframework.web.bind.annotation.RequestMapping;
22 import org.springframework.web.bind.annotation.RequestMethod; 23 import org.springframework.web.bind.annotation.RequestMethod;
23 import org.springframework.web.bind.annotation.RequestParam; 24 import org.springframework.web.bind.annotation.RequestParam;
24 import org.springframework.web.bind.annotation.ResponseBody; 25 import org.springframework.web.bind.annotation.ResponseBody;
25 import org.springframework.web.bind.annotation.RestController; 26 import org.springframework.web.bind.annotation.RestController;
26 import org.thingsboard.server.common.data.Event; 27 import org.thingsboard.server.common.data.Event;
  28 +import org.thingsboard.server.common.data.event.EventFilter;
27 import org.thingsboard.server.common.data.exception.ThingsboardException; 29 import org.thingsboard.server.common.data.exception.ThingsboardException;
28 import org.thingsboard.server.common.data.id.EntityId; 30 import org.thingsboard.server.common.data.id.EntityId;
29 import org.thingsboard.server.common.data.id.EntityIdFactory; 31 import org.thingsboard.server.common.data.id.EntityIdFactory;
@@ -31,6 +33,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -31,6 +33,7 @@ import org.thingsboard.server.common.data.id.TenantId;
31 import org.thingsboard.server.common.data.page.PageData; 33 import org.thingsboard.server.common.data.page.PageData;
32 import org.thingsboard.server.common.data.page.TimePageLink; 34 import org.thingsboard.server.common.data.page.TimePageLink;
33 import org.thingsboard.server.dao.event.EventService; 35 import org.thingsboard.server.dao.event.EventService;
  36 +import org.thingsboard.server.dao.model.ModelConstants;
34 import org.thingsboard.server.queue.util.TbCoreComponent; 37 import org.thingsboard.server.queue.util.TbCoreComponent;
35 import org.thingsboard.server.service.security.permission.Operation; 38 import org.thingsboard.server.service.security.permission.Operation;
36 39
@@ -101,4 +104,38 @@ public class EventController extends BaseController { @@ -101,4 +104,38 @@ public class EventController extends BaseController {
101 } 104 }
102 } 105 }
103 106
  107 + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
  108 + @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.POST)
  109 + @ResponseBody
  110 + public PageData<Event> getEvents(
  111 + @PathVariable("entityType") String strEntityType,
  112 + @PathVariable("entityId") String strEntityId,
  113 + @RequestParam("tenantId") String strTenantId,
  114 + @RequestParam int pageSize,
  115 + @RequestParam int page,
  116 + @RequestBody EventFilter eventFilter,
  117 + @RequestParam(required = false) String textSearch,
  118 + @RequestParam(required = false) String sortProperty,
  119 + @RequestParam(required = false) String sortOrder,
  120 + @RequestParam(required = false) Long startTime,
  121 + @RequestParam(required = false) Long endTime) throws ThingsboardException {
  122 + checkParameter("EntityId", strEntityId);
  123 + checkParameter("EntityType", strEntityType);
  124 + try {
  125 + TenantId tenantId = new TenantId(toUUID(strTenantId));
  126 +
  127 + EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId);
  128 + checkEntityId(entityId, Operation.READ);
  129 +
  130 + if(sortProperty != null && sortProperty.equals("createdTime") && eventFilter.hasFilterForJsonBody()) {
  131 + sortProperty = ModelConstants.CREATED_TIME_PROPERTY;
  132 + }
  133 +
  134 + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
  135 + return checkNotNull(eventService.findEventsByFilter(tenantId, entityId, eventFilter, pageLink));
  136 + } catch (Exception e) {
  137 + throw handleException(e);
  138 + }
  139 + }
  140 +
104 } 141 }
@@ -244,7 +244,8 @@ public class RuleChainController extends BaseController { @@ -244,7 +244,8 @@ public class RuleChainController extends BaseController {
244 } 244 }
245 245
246 RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId(), Operation.WRITE); 246 RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId(), Operation.WRITE);
247 - RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData)); 247 + checkNotNull(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData) ? true : null);
  248 + RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId()));
248 249
249 if (RuleChainType.CORE.equals(ruleChain.getType())) { 250 if (RuleChainType.CORE.equals(ruleChain.getType())) {
250 tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED); 251 tbClusterService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED);
@@ -36,8 +36,8 @@ import org.thingsboard.server.common.data.lwm2m.LwM2mObject; @@ -36,8 +36,8 @@ import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
36 import org.thingsboard.server.common.data.page.PageData; 36 import org.thingsboard.server.common.data.page.PageData;
37 import org.thingsboard.server.common.data.page.PageLink; 37 import org.thingsboard.server.common.data.page.PageLink;
38 import org.thingsboard.server.common.data.security.Authority; 38 import org.thingsboard.server.common.data.security.Authority;
39 -import org.thingsboard.server.dao.resource.TbResourceService;  
40 import org.thingsboard.server.queue.util.TbCoreComponent; 39 import org.thingsboard.server.queue.util.TbCoreComponent;
  40 +import org.thingsboard.server.service.resource.TbResourceService;
41 import org.thingsboard.server.service.security.permission.Operation; 41 import org.thingsboard.server.service.security.permission.Operation;
42 import org.thingsboard.server.service.security.permission.Resource; 42 import org.thingsboard.server.service.security.permission.Resource;
43 43
@@ -52,12 +52,6 @@ public class TbResourceController extends BaseController { @@ -52,12 +52,6 @@ public class TbResourceController extends BaseController {
52 52
53 public static final String RESOURCE_ID = "resourceId"; 53 public static final String RESOURCE_ID = "resourceId";
54 54
55 - private final TbResourceService resourceService;  
56 -  
57 - public TbResourceController(TbResourceService resourceService) {  
58 - this.resourceService = resourceService;  
59 - }  
60 -  
61 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 55 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
62 @RequestMapping(value = "/resource/{resourceId}/download", method = RequestMethod.GET) 56 @RequestMapping(value = "/resource/{resourceId}/download", method = RequestMethod.GET)
63 @ResponseBody 57 @ResponseBody
@@ -40,8 +40,6 @@ public class DeviceProfileMsgConstructor { @@ -40,8 +40,6 @@ public class DeviceProfileMsgConstructor {
40 .setName(deviceProfile.getName()) 40 .setName(deviceProfile.getName())
41 .setDefault(deviceProfile.isDefault()) 41 .setDefault(deviceProfile.isDefault())
42 .setType(deviceProfile.getType().name()) 42 .setType(deviceProfile.getType().name())
43 - .setTransportType(deviceProfile.getTransportType().name())  
44 - .setProvisionType(deviceProfile.getProvisionType().name())  
45 .setProfileDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile.getProfileData()))); 43 .setProfileDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile.getProfileData())));
46 // TODO: voba - should this be always null at the moment?? 44 // TODO: voba - should this be always null at the moment??
47 // if (deviceProfile.getDefaultRuleChainId() != null) { 45 // if (deviceProfile.getDefaultRuleChainId() != null) {
@@ -54,6 +52,12 @@ public class DeviceProfileMsgConstructor { @@ -54,6 +52,12 @@ public class DeviceProfileMsgConstructor {
54 if (deviceProfile.getDescription() != null) { 52 if (deviceProfile.getDescription() != null) {
55 builder.setDescription(deviceProfile.getDescription()); 53 builder.setDescription(deviceProfile.getDescription());
56 } 54 }
  55 + if (deviceProfile.getTransportType() != null) {
  56 + builder.setTransportType(deviceProfile.getTransportType().name());
  57 + }
  58 + if (deviceProfile.getProvisionType() != null) {
  59 + builder.setProvisionType(deviceProfile.getProvisionType().name());
  60 + }
57 if (deviceProfile.getProvisionDeviceKey() != null) { 61 if (deviceProfile.getProvisionDeviceKey() != null) {
58 builder.setProvisionDeviceKey(deviceProfile.getProvisionDeviceKey()); 62 builder.setProvisionDeviceKey(deviceProfile.getProvisionDeviceKey());
59 } 63 }
@@ -15,13 +15,13 @@ @@ -15,13 +15,13 @@
15 */ 15 */
16 package org.thingsboard.server.service.edge.rpc.constructor; 16 package org.thingsboard.server.service.edge.rpc.constructor;
17 17
  18 +import com.google.gson.reflect.TypeToken;
18 import com.google.gson.Gson; 19 import com.google.gson.Gson;
19 import com.google.gson.JsonArray; 20 import com.google.gson.JsonArray;
20 import com.google.gson.JsonElement; 21 import com.google.gson.JsonElement;
21 import com.google.gson.JsonObject; 22 import com.google.gson.JsonObject;
22 import lombok.extern.slf4j.Slf4j; 23 import lombok.extern.slf4j.Slf4j;
23 import org.springframework.stereotype.Component; 24 import org.springframework.stereotype.Component;
24 -import org.thingsboard.server.common.data.audit.ActionType;  
25 import org.thingsboard.server.common.data.edge.EdgeEventActionType; 25 import org.thingsboard.server.common.data.edge.EdgeEventActionType;
26 import org.thingsboard.server.common.data.id.EntityId; 26 import org.thingsboard.server.common.data.id.EntityId;
27 import org.thingsboard.server.common.transport.adaptor.JsonConverter; 27 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
@@ -82,7 +82,7 @@ public class EntityDataMsgConstructor { @@ -82,7 +82,7 @@ public class EntityDataMsgConstructor {
82 AttributeDeleteMsg.Builder attributeDeleteMsg = AttributeDeleteMsg.newBuilder(); 82 AttributeDeleteMsg.Builder attributeDeleteMsg = AttributeDeleteMsg.newBuilder();
83 attributeDeleteMsg.setScope(entityData.getAsJsonObject().getAsJsonPrimitive("scope").getAsString()); 83 attributeDeleteMsg.setScope(entityData.getAsJsonObject().getAsJsonPrimitive("scope").getAsString());
84 JsonArray jsonArray = entityData.getAsJsonObject().getAsJsonArray("keys"); 84 JsonArray jsonArray = entityData.getAsJsonObject().getAsJsonArray("keys");
85 - List<String> keys = new Gson().fromJson(jsonArray.toString(), List.class); 85 + List<String> keys = new Gson().fromJson(jsonArray.toString(), new TypeToken<>(){}.getType());
86 attributeDeleteMsg.addAllAttributeNames(keys); 86 attributeDeleteMsg.addAllAttributeNames(keys);
87 attributeDeleteMsg.build(); 87 attributeDeleteMsg.build();
88 builder.setAttributeDeleteMsg(attributeDeleteMsg); 88 builder.setAttributeDeleteMsg(attributeDeleteMsg);
@@ -58,11 +58,8 @@ import org.thingsboard.server.common.data.page.PageLink; @@ -58,11 +58,8 @@ import org.thingsboard.server.common.data.page.PageLink;
58 import org.thingsboard.server.common.data.query.BooleanFilterPredicate; 58 import org.thingsboard.server.common.data.query.BooleanFilterPredicate;
59 import org.thingsboard.server.common.data.query.DynamicValue; 59 import org.thingsboard.server.common.data.query.DynamicValue;
60 import org.thingsboard.server.common.data.query.DynamicValueSourceType; 60 import org.thingsboard.server.common.data.query.DynamicValueSourceType;
61 -import org.thingsboard.server.common.data.query.EntityKey;  
62 -import org.thingsboard.server.common.data.query.EntityKeyType;  
63 import org.thingsboard.server.common.data.query.EntityKeyValueType; 61 import org.thingsboard.server.common.data.query.EntityKeyValueType;
64 import org.thingsboard.server.common.data.query.FilterPredicateValue; 62 import org.thingsboard.server.common.data.query.FilterPredicateValue;
65 -import org.thingsboard.server.common.data.query.KeyFilter;  
66 import org.thingsboard.server.common.data.query.NumericFilterPredicate; 63 import org.thingsboard.server.common.data.query.NumericFilterPredicate;
67 import org.thingsboard.server.common.data.rule.RuleChainType; 64 import org.thingsboard.server.common.data.rule.RuleChainType;
68 import org.thingsboard.server.common.data.security.Authority; 65 import org.thingsboard.server.common.data.security.Authority;
@@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; @@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle;
35 import org.thingsboard.server.dao.dashboard.DashboardService; 35 import org.thingsboard.server.dao.dashboard.DashboardService;
36 import org.thingsboard.server.dao.exception.DataValidationException; 36 import org.thingsboard.server.dao.exception.DataValidationException;
37 import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; 37 import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService;
38 -import org.thingsboard.server.dao.resource.TbResourceService; 38 +import org.thingsboard.server.dao.resource.ResourceService;
39 import org.thingsboard.server.dao.rule.RuleChainService; 39 import org.thingsboard.server.dao.rule.RuleChainService;
40 import org.thingsboard.server.dao.widget.WidgetTypeService; 40 import org.thingsboard.server.dao.widget.WidgetTypeService;
41 import org.thingsboard.server.dao.widget.WidgetsBundleService; 41 import org.thingsboard.server.dao.widget.WidgetsBundleService;
@@ -97,7 +97,7 @@ public class InstallScripts { @@ -97,7 +97,7 @@ public class InstallScripts {
97 private OAuth2ConfigTemplateService oAuth2TemplateService; 97 private OAuth2ConfigTemplateService oAuth2TemplateService;
98 98
99 @Autowired 99 @Autowired
100 - private TbResourceService resourceService; 100 + private ResourceService resourceService;
101 101
102 private Path getTenantRuleChainsDir() { 102 private Path getTenantRuleChainsDir() {
103 return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR); 103 return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR);
@@ -259,18 +259,12 @@ public class InstallScripts { @@ -259,18 +259,12 @@ public class InstallScripts {
259 try { 259 try {
260 createDefaultRuleChains(tenantId); 260 createDefaultRuleChains(tenantId);
261 createDefaultRuleChain(tenantId, "Thermostat"); 261 createDefaultRuleChain(tenantId, "Thermostat");
262 - loadEdgeDemoRuleChains(tenantId);  
263 } catch (Exception e) { 262 } catch (Exception e) {
264 log.error("Unable to load dashboard from json", e); 263 log.error("Unable to load dashboard from json", e);
265 throw new RuntimeException("Unable to load dashboard from json", e); 264 throw new RuntimeException("Unable to load dashboard from json", e);
266 } 265 }
267 } 266 }
268 267
269 - private void loadEdgeDemoRuleChains(TenantId tenantId) throws Exception {  
270 - Path edgeDemoRuleChainsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, EDGE_MANAGEMENT, RULE_CHAINS_DIR);  
271 - loadRuleChainsFromPath(tenantId, edgeDemoRuleChainsDir);  
272 - }  
273 -  
274 public void createOAuth2Templates() throws Exception { 268 public void createOAuth2Templates() throws Exception {
275 Path oauth2ConfigTemplatesDir = Paths.get(getDataDir(), JSON_DIR, SYSTEM_DIR, OAUTH2_CONFIG_TEMPLATES_DIR); 269 Path oauth2ConfigTemplatesDir = Paths.get(getDataDir(), JSON_DIR, SYSTEM_DIR, OAUTH2_CONFIG_TEMPLATES_DIR);
276 try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(oauth2ConfigTemplatesDir, path -> path.toString().endsWith(JSON_EXT))) { 270 try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(oauth2ConfigTemplatesDir, path -> path.toString().endsWith(JSON_EXT))) {
@@ -159,7 +159,7 @@ public class CassandraDbHelper { @@ -159,7 +159,7 @@ public class CassandraDbHelper {
159 } else if (type.getProtocolCode() == ProtocolConstants.DataType.TIMESTAMP) { 159 } else if (type.getProtocolCode() == ProtocolConstants.DataType.TIMESTAMP) {
160 str = ""+row.getInstant(index).toEpochMilli(); 160 str = ""+row.getInstant(index).toEpochMilli();
161 } else if (type.getProtocolCode() == ProtocolConstants.DataType.BOOLEAN) { 161 } else if (type.getProtocolCode() == ProtocolConstants.DataType.BOOLEAN) {
162 - str = new Boolean(row.getBoolean(index)).toString(); 162 + str = Boolean.valueOf(row.getBoolean(index)).toString();
163 } else { 163 } else {
164 str = row.getString(index); 164 str = row.getString(index);
165 } 165 }
application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java renamed from dao/src/main/java/org/thingsboard/server/dao/resource/BaseTbResourceService.java
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.resource; 16 +package org.thingsboard.server.service.resource;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 import org.apache.commons.lang3.StringUtils; 19 import org.apache.commons.lang3.StringUtils;
@@ -21,12 +21,12 @@ import org.eclipse.leshan.core.model.DDFFileParser; @@ -21,12 +21,12 @@ import org.eclipse.leshan.core.model.DDFFileParser;
21 import org.eclipse.leshan.core.model.DefaultDDFFileValidator; 21 import org.eclipse.leshan.core.model.DefaultDDFFileValidator;
22 import org.eclipse.leshan.core.model.InvalidDDFFileException; 22 import org.eclipse.leshan.core.model.InvalidDDFFileException;
23 import org.eclipse.leshan.core.model.ObjectModel; 23 import org.eclipse.leshan.core.model.ObjectModel;
24 -import org.hibernate.exception.ConstraintViolationException;  
25 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
26 import org.thingsboard.server.common.data.ResourceType; 25 import org.thingsboard.server.common.data.ResourceType;
27 import org.thingsboard.server.common.data.TbResource; 26 import org.thingsboard.server.common.data.TbResource;
28 import org.thingsboard.server.common.data.TbResourceInfo; 27 import org.thingsboard.server.common.data.TbResourceInfo;
29 -import org.thingsboard.server.common.data.Tenant; 28 +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
  29 +import org.thingsboard.server.common.data.exception.ThingsboardException;
30 import org.thingsboard.server.common.data.id.TbResourceId; 30 import org.thingsboard.server.common.data.id.TbResourceId;
31 import org.thingsboard.server.common.data.id.TenantId; 31 import org.thingsboard.server.common.data.id.TenantId;
32 import org.thingsboard.server.common.data.lwm2m.LwM2mInstance; 32 import org.thingsboard.server.common.data.lwm2m.LwM2mInstance;
@@ -35,11 +35,7 @@ import org.thingsboard.server.common.data.lwm2m.LwM2mResourceObserve; @@ -35,11 +35,7 @@ import org.thingsboard.server.common.data.lwm2m.LwM2mResourceObserve;
35 import org.thingsboard.server.common.data.page.PageData; 35 import org.thingsboard.server.common.data.page.PageData;
36 import org.thingsboard.server.common.data.page.PageLink; 36 import org.thingsboard.server.common.data.page.PageLink;
37 import org.thingsboard.server.dao.exception.DataValidationException; 37 import org.thingsboard.server.dao.exception.DataValidationException;
38 -import org.thingsboard.server.dao.model.ModelConstants;  
39 -import org.thingsboard.server.dao.service.DataValidator;  
40 -import org.thingsboard.server.dao.service.PaginatedRemover;  
41 -import org.thingsboard.server.dao.service.Validator;  
42 -import org.thingsboard.server.dao.tenant.TenantDao; 38 +import org.thingsboard.server.dao.resource.ResourceService;
43 39
44 import java.io.ByteArrayInputStream; 40 import java.io.ByteArrayInputStream;
45 import java.io.IOException; 41 import java.io.IOException;
@@ -47,7 +43,6 @@ import java.util.ArrayList; @@ -47,7 +43,6 @@ import java.util.ArrayList;
47 import java.util.Base64; 43 import java.util.Base64;
48 import java.util.Comparator; 44 import java.util.Comparator;
49 import java.util.List; 45 import java.util.List;
50 -import java.util.Optional;  
51 import java.util.stream.Collectors; 46 import java.util.stream.Collectors;
52 47
53 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; 48 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
@@ -55,139 +50,120 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA @@ -55,139 +50,120 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA
55 import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID; 50 import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID;
56 import static org.thingsboard.server.dao.service.Validator.validateId; 51 import static org.thingsboard.server.dao.service.Validator.validateId;
57 52
58 -@Service  
59 @Slf4j 53 @Slf4j
60 -public class BaseTbResourceService implements TbResourceService { 54 +@Service
  55 +public class DefaultTbResourceService implements TbResourceService {
61 56
62 - public static final String INCORRECT_RESOURCE_ID = "Incorrect resourceId ";  
63 - private final TbResourceDao resourceDao;  
64 - private final TbResourceInfoDao resourceInfoDao;  
65 - private final TenantDao tenantDao; 57 + private final ResourceService resourceService;
66 private final DDFFileParser ddfFileParser; 58 private final DDFFileParser ddfFileParser;
67 59
68 - public BaseTbResourceService(TbResourceDao resourceDao, TbResourceInfoDao resourceInfoDao, TenantDao tenantDao) {  
69 - this.resourceDao = resourceDao;  
70 - this.resourceInfoDao = resourceInfoDao;  
71 - this.tenantDao = tenantDao; 60 + public DefaultTbResourceService(ResourceService resourceService) {
  61 + this.resourceService = resourceService;
72 this.ddfFileParser = new DDFFileParser(new DefaultDDFFileValidator()); 62 this.ddfFileParser = new DDFFileParser(new DefaultDDFFileValidator());
73 } 63 }
74 64
75 @Override 65 @Override
76 - public TbResource saveResource(TbResource resource) throws InvalidDDFFileException, IOException { 66 + public TbResource saveResource(TbResource resource) throws ThingsboardException {
77 log.trace("Executing saveResource [{}]", resource); 67 log.trace("Executing saveResource [{}]", resource);
78 if (StringUtils.isEmpty(resource.getData())) { 68 if (StringUtils.isEmpty(resource.getData())) {
79 throw new DataValidationException("Resource data should be specified!"); 69 throw new DataValidationException("Resource data should be specified!");
80 } 70 }
81 if (ResourceType.LWM2M_MODEL.equals(resource.getResourceType())) { 71 if (ResourceType.LWM2M_MODEL.equals(resource.getResourceType())) {
82 - List<ObjectModel> objectModels =  
83 - ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getData())), resource.getSearchText());  
84 - if (!objectModels.isEmpty()) {  
85 - ObjectModel objectModel = objectModels.get(0);  
86 -  
87 - String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion();  
88 - String name = objectModel.name;  
89 - resource.setResourceKey(resourceKey);  
90 - if (resource.getId() == null) {  
91 - resource.setTitle(name + " id=" + objectModel.id + " v" + objectModel.getVersion()); 72 + try {
  73 + List<ObjectModel> objectModels =
  74 + ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getData())), resource.getSearchText());
  75 + if (!objectModels.isEmpty()) {
  76 + ObjectModel objectModel = objectModels.get(0);
  77 +
  78 + String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion();
  79 + String name = objectModel.name;
  80 + resource.setResourceKey(resourceKey);
  81 + if (resource.getId() == null) {
  82 + resource.setTitle(name + " id=" + objectModel.id + " v" + objectModel.getVersion());
  83 + }
  84 + resource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name);
  85 + } else {
  86 + throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText()));
92 } 87 }
93 - resource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name);  
94 - } else { 88 + } catch (InvalidDDFFileException | IOException e) {
  89 + throw new ThingsboardException(e, ThingsboardErrorCode.GENERAL);
  90 + }
  91 + if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && toLwM2mObject(resource) == null) {
95 throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText())); 92 throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText()));
96 } 93 }
97 } else { 94 } else {
98 resource.setResourceKey(resource.getFileName()); 95 resource.setResourceKey(resource.getFileName());
99 } 96 }
100 97
101 - resourceValidator.validate(resource, TbResourceInfo::getTenantId);  
102 -  
103 - try {  
104 - return resourceDao.save(resource.getTenantId(), resource);  
105 - } catch (Exception t) {  
106 - ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);  
107 - if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("resource_unq_key")) {  
108 - String field = ResourceType.LWM2M_MODEL.equals(resource.getResourceType()) ? "resourceKey" : "fileName";  
109 - throw new DataValidationException("Resource with such " + field + " already exists!");  
110 - } else {  
111 - throw t;  
112 - }  
113 - }  
114 - 98 + return resourceService.saveResource(resource);
115 } 99 }
116 100
117 @Override 101 @Override
118 - public TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceKey) {  
119 - log.trace("Executing getResource [{}] [{}] [{}]", tenantId, resourceType, resourceKey);  
120 - return resourceDao.getResource(tenantId, resourceType, resourceKey); 102 + public TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId) {
  103 + return resourceService.getResource(tenantId, resourceType, resourceId);
121 } 104 }
122 105
123 @Override 106 @Override
124 public TbResource findResourceById(TenantId tenantId, TbResourceId resourceId) { 107 public TbResource findResourceById(TenantId tenantId, TbResourceId resourceId) {
125 - log.trace("Executing findResourceById [{}] [{}]", tenantId, resourceId);  
126 - Validator.validateId(resourceId, INCORRECT_RESOURCE_ID + resourceId);  
127 - return resourceDao.findById(tenantId, resourceId.getId()); 108 + return resourceService.findResourceById(tenantId, resourceId);
128 } 109 }
129 110
130 @Override 111 @Override
131 public TbResourceInfo findResourceInfoById(TenantId tenantId, TbResourceId resourceId) { 112 public TbResourceInfo findResourceInfoById(TenantId tenantId, TbResourceId resourceId) {
132 - log.trace("Executing findResourceInfoById [{}] [{}]", tenantId, resourceId);  
133 - Validator.validateId(resourceId, INCORRECT_RESOURCE_ID + resourceId);  
134 - return resourceInfoDao.findById(tenantId, resourceId.getId());  
135 - }  
136 -  
137 - @Override  
138 - public void deleteResource(TenantId tenantId, TbResourceId resourceId) {  
139 - log.trace("Executing deleteResource [{}] [{}]", tenantId, resourceId);  
140 - Validator.validateId(resourceId, INCORRECT_RESOURCE_ID + resourceId);  
141 - resourceDao.removeById(tenantId, resourceId.getId()); 113 + return resourceService.findResourceInfoById(tenantId, resourceId);
142 } 114 }
143 115
144 @Override 116 @Override
145 public PageData<TbResourceInfo> findAllTenantResourcesByTenantId(TenantId tenantId, PageLink pageLink) { 117 public PageData<TbResourceInfo> findAllTenantResourcesByTenantId(TenantId tenantId, PageLink pageLink) {
146 - log.trace("Executing findAllTenantResourcesByTenantId [{}]", tenantId);  
147 - validateId(tenantId, INCORRECT_TENANT_ID + tenantId);  
148 - return resourceInfoDao.findAllTenantResourcesByTenantId(tenantId.getId(), pageLink); 118 + return resourceService.findAllTenantResourcesByTenantId(tenantId, pageLink);
149 } 119 }
150 120
151 @Override 121 @Override
152 public PageData<TbResourceInfo> findTenantResourcesByTenantId(TenantId tenantId, PageLink pageLink) { 122 public PageData<TbResourceInfo> findTenantResourcesByTenantId(TenantId tenantId, PageLink pageLink) {
153 - log.trace("Executing findTenantResourcesByTenantId [{}]", tenantId);  
154 - validateId(tenantId, INCORRECT_TENANT_ID + tenantId);  
155 - return resourceInfoDao.findTenantResourcesByTenantId(tenantId.getId(), pageLink); 123 + return resourceService.findTenantResourcesByTenantId(tenantId, pageLink);
156 } 124 }
157 125
158 @Override 126 @Override
159 - public List<LwM2mObject> findLwM2mObjectPage(TenantId tenantId, String sortProperty, String sortOrder, PageLink pageLink) { 127 + public List<LwM2mObject> findLwM2mObject(TenantId tenantId, String sortOrder, String sortProperty, String[] objectIds) {
160 log.trace("Executing findByTenantId [{}]", tenantId); 128 log.trace("Executing findByTenantId [{}]", tenantId);
161 validateId(tenantId, INCORRECT_TENANT_ID + tenantId); 129 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
162 - PageData<TbResource> resourcePageData = resourceDao.findResourcesByTenantIdAndResourceType(  
163 - tenantId,  
164 - ResourceType.LWM2M_MODEL, pageLink);  
165 - return resourcePageData.getData().stream() 130 + List<TbResource> resources = resourceService.findTenantResourcesByResourceTypeAndObjectIds(tenantId, ResourceType.LWM2M_MODEL,
  131 + objectIds);
  132 + return resources.stream()
166 .map(this::toLwM2mObject) 133 .map(this::toLwM2mObject)
167 .sorted(getComparator(sortProperty, sortOrder)) 134 .sorted(getComparator(sortProperty, sortOrder))
168 .collect(Collectors.toList()); 135 .collect(Collectors.toList());
169 } 136 }
170 137
171 @Override 138 @Override
172 - public List<LwM2mObject> findLwM2mObject(TenantId tenantId, String sortOrder,  
173 - String sortProperty,  
174 - String[] objectIds) { 139 + public List<LwM2mObject> findLwM2mObjectPage(TenantId tenantId, String sortProperty, String sortOrder, PageLink pageLink) {
175 log.trace("Executing findByTenantId [{}]", tenantId); 140 log.trace("Executing findByTenantId [{}]", tenantId);
176 validateId(tenantId, INCORRECT_TENANT_ID + tenantId); 141 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
177 - List<TbResource> resources = resourceDao.findResourcesByTenantIdAndResourceType(tenantId, ResourceType.LWM2M_MODEL,  
178 - objectIds,  
179 - null);  
180 - return resources.stream() 142 + PageData<TbResource> resourcePageData = resourceService.findTenantResourcesByResourceTypeAndPageLink(tenantId, ResourceType.LWM2M_MODEL, pageLink);
  143 + return resourcePageData.getData().stream()
181 .map(this::toLwM2mObject) 144 .map(this::toLwM2mObject)
182 .sorted(getComparator(sortProperty, sortOrder)) 145 .sorted(getComparator(sortProperty, sortOrder))
183 .collect(Collectors.toList()); 146 .collect(Collectors.toList());
184 } 147 }
185 148
186 @Override 149 @Override
  150 + public void deleteResource(TenantId tenantId, TbResourceId resourceId) {
  151 + resourceService.deleteResource(tenantId, resourceId);
  152 + }
  153 +
  154 + @Override
187 public void deleteResourcesByTenantId(TenantId tenantId) { 155 public void deleteResourcesByTenantId(TenantId tenantId) {
188 - log.trace("Executing deleteResourcesByTenantId, tenantId [{}]", tenantId);  
189 - validateId(tenantId, INCORRECT_TENANT_ID + tenantId);  
190 - tenantResourcesRemover.removeEntities(tenantId, tenantId); 156 + resourceService.deleteResourcesByTenantId(tenantId);
  157 + }
  158 +
  159 + private Comparator<? super LwM2mObject> getComparator(String sortProperty, String sortOrder) {
  160 + Comparator<LwM2mObject> comparator;
  161 + if ("name".equals(sortProperty)) {
  162 + comparator = Comparator.comparing(LwM2mObject::getName);
  163 + } else {
  164 + comparator = Comparator.comparingLong(LwM2mObject::getId);
  165 + }
  166 + return "DESC".equals(sortOrder) ? comparator.reversed() : comparator;
191 } 167 }
192 168
193 private LwM2mObject toLwM2mObject(TbResource resource) { 169 private LwM2mObject toLwM2mObject(TbResource resource) {
@@ -223,69 +199,4 @@ public class BaseTbResourceService implements TbResourceService { @@ -223,69 +199,4 @@ public class BaseTbResourceService implements TbResourceService {
223 return null; 199 return null;
224 } 200 }
225 } 201 }
226 -  
227 - private Comparator<? super LwM2mObject> getComparator(String sortProperty, String sortOrder) {  
228 - Comparator<LwM2mObject> comparator;  
229 - if ("name".equals(sortProperty)) {  
230 - comparator = Comparator.comparing(LwM2mObject::getName);  
231 - } else {  
232 - comparator = Comparator.comparingLong(LwM2mObject::getId);  
233 - }  
234 - return "DESC".equals(sortOrder) ? comparator.reversed() : comparator;  
235 - }  
236 -  
237 - private DataValidator<TbResource> resourceValidator = new DataValidator<>() {  
238 -  
239 - @Override  
240 - protected void validateDataImpl(TenantId tenantId, TbResource resource) {  
241 - if (StringUtils.isEmpty(resource.getTitle())) {  
242 - throw new DataValidationException("Resource title should be specified!");  
243 - }  
244 - if (resource.getResourceType() == null) {  
245 - throw new DataValidationException("Resource type should be specified!");  
246 - }  
247 - if (StringUtils.isEmpty(resource.getFileName())) {  
248 - throw new DataValidationException("Resource file name should be specified!");  
249 - }  
250 - if (StringUtils.isEmpty(resource.getResourceKey())) {  
251 - throw new DataValidationException("Resource key should be specified!");  
252 - }  
253 - if (resource.getTenantId() == null) {  
254 - resource.setTenantId(new TenantId(ModelConstants.NULL_UUID));  
255 - }  
256 - if (!resource.getTenantId().getId().equals(ModelConstants.NULL_UUID)) {  
257 - Tenant tenant = tenantDao.findById(tenantId, resource.getTenantId().getId());  
258 - if (tenant == null) {  
259 - throw new DataValidationException("Resource is referencing to non-existent tenant!");  
260 - }  
261 - }  
262 - if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && toLwM2mObject(resource) == null) {  
263 - throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText()));  
264 - }  
265 - }  
266 - };  
267 -  
268 - private PaginatedRemover<TenantId, TbResource> tenantResourcesRemover =  
269 - new PaginatedRemover<>() {  
270 -  
271 - @Override  
272 - protected PageData<TbResource> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {  
273 - return resourceDao.findAllByTenantId(id, pageLink);  
274 - }  
275 -  
276 - @Override  
277 - protected void removeEntity(TenantId tenantId, TbResource entity) {  
278 - deleteResource(tenantId, new TbResourceId(entity.getUuidId()));  
279 - }  
280 - };  
281 -  
282 - protected Optional<ConstraintViolationException> extractConstraintViolationException(Exception t) {  
283 - if (t instanceof ConstraintViolationException) {  
284 - return Optional.of((ConstraintViolationException) t);  
285 - } else if (t.getCause() instanceof ConstraintViolationException) {  
286 - return Optional.of((ConstraintViolationException) (t.getCause()));  
287 - } else {  
288 - return Optional.empty();  
289 - }  
290 - }  
291 } 202 }
application/src/main/java/org/thingsboard/server/service/resource/TbResourceService.java renamed from common/dao-api/src/main/java/org/thingsboard/server/dao/resource/TbResourceService.java
@@ -13,24 +13,23 @@ @@ -13,24 +13,23 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.resource; 16 +package org.thingsboard.server.service.resource;
17 17
18 -import org.eclipse.leshan.core.model.InvalidDDFFileException; 18 +import org.thingsboard.server.common.data.ResourceType;
19 import org.thingsboard.server.common.data.TbResource; 19 import org.thingsboard.server.common.data.TbResource;
20 import org.thingsboard.server.common.data.TbResourceInfo; 20 import org.thingsboard.server.common.data.TbResourceInfo;
21 -import org.thingsboard.server.common.data.ResourceType; 21 +import org.thingsboard.server.common.data.exception.ThingsboardException;
22 import org.thingsboard.server.common.data.id.TbResourceId; 22 import org.thingsboard.server.common.data.id.TbResourceId;
23 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
24 import org.thingsboard.server.common.data.lwm2m.LwM2mObject; 24 import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
25 import org.thingsboard.server.common.data.page.PageData; 25 import org.thingsboard.server.common.data.page.PageData;
26 import org.thingsboard.server.common.data.page.PageLink; 26 import org.thingsboard.server.common.data.page.PageLink;
27 27
28 -import java.io.IOException;  
29 import java.util.List; 28 import java.util.List;
30 29
31 -  
32 public interface TbResourceService { 30 public interface TbResourceService {
33 - TbResource saveResource(TbResource resource) throws InvalidDDFFileException, IOException; 31 +
  32 + TbResource saveResource(TbResource resource) throws ThingsboardException;
34 33
35 TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); 34 TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId);
36 35
@@ -55,4 +54,5 @@ public interface TbResourceService { @@ -55,4 +54,5 @@ public interface TbResourceService {
55 void deleteResource(TenantId tenantId, TbResourceId resourceId); 54 void deleteResource(TenantId tenantId, TbResourceId resourceId);
56 55
57 void deleteResourcesByTenantId(TenantId tenantId); 56 void deleteResourcesByTenantId(TenantId tenantId);
  57 +
58 } 58 }
@@ -17,8 +17,10 @@ package org.thingsboard.server.service.security.auth.oauth2; @@ -17,8 +17,10 @@ package org.thingsboard.server.service.security.auth.oauth2;
17 17
18 import com.fasterxml.jackson.databind.ObjectMapper; 18 import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.fasterxml.jackson.databind.node.ObjectNode; 19 import com.fasterxml.jackson.databind.node.ObjectNode;
  20 +import lombok.Getter;
20 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.beans.factory.annotation.Value;
22 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 24 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
23 import org.springframework.security.core.userdetails.UsernameNotFoundException; 25 import org.springframework.security.core.userdetails.UsernameNotFoundException;
24 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 26 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -85,6 +87,10 @@ public abstract class AbstractOAuth2ClientMapper { @@ -85,6 +87,10 @@ public abstract class AbstractOAuth2ClientMapper {
85 @Autowired 87 @Autowired
86 protected TbClusterService tbClusterService; 88 protected TbClusterService tbClusterService;
87 89
  90 + @Value("${edges.enabled}")
  91 + @Getter
  92 + private boolean edgesEnabled;
  93 +
88 private final Lock userCreationLock = new ReentrantLock(); 94 private final Lock userCreationLock = new ReentrantLock();
89 95
90 protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2ClientRegistrationInfo clientRegistration) { 96 protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2ClientRegistrationInfo clientRegistration) {
@@ -171,6 +177,9 @@ public abstract class AbstractOAuth2ClientMapper { @@ -171,6 +177,9 @@ public abstract class AbstractOAuth2ClientMapper {
171 tenant.setTitle(tenantName); 177 tenant.setTitle(tenantName);
172 tenant = tenantService.saveTenant(tenant); 178 tenant = tenantService.saveTenant(tenant);
173 installScripts.createDefaultRuleChains(tenant.getId()); 179 installScripts.createDefaultRuleChains(tenant.getId());
  180 + if (edgesEnabled) {
  181 + installScripts.createDefaultEdgeRuleChains(tenant.getId());
  182 + }
174 tenantProfileCache.evict(tenant.getId()); 183 tenantProfileCache.evict(tenant.getId());
175 tbClusterService.onTenantChange(tenant, null); 184 tbClusterService.onTenantChange(tenant, null);
176 tbClusterService.onEntityStateChange(tenant.getId(), tenant.getId(), 185 tbClusterService.onEntityStateChange(tenant.getId(), tenant.getId(),
@@ -57,7 +57,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionFailedException; @@ -57,7 +57,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
57 import org.thingsboard.server.dao.device.provision.ProvisionRequest; 57 import org.thingsboard.server.dao.device.provision.ProvisionRequest;
58 import org.thingsboard.server.dao.device.provision.ProvisionResponse; 58 import org.thingsboard.server.dao.device.provision.ProvisionResponse;
59 import org.thingsboard.server.dao.relation.RelationService; 59 import org.thingsboard.server.dao.relation.RelationService;
60 -import org.thingsboard.server.dao.resource.TbResourceService; 60 +import org.thingsboard.server.dao.resource.ResourceService;
61 import org.thingsboard.server.dao.tenant.TbTenantProfileCache; 61 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
62 import org.thingsboard.server.gen.transport.TransportProtos; 62 import org.thingsboard.server.gen.transport.TransportProtos;
63 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; 63 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
@@ -117,7 +117,7 @@ public class DefaultTransportApiService implements TransportApiService { @@ -117,7 +117,7 @@ public class DefaultTransportApiService implements TransportApiService {
117 private final TbClusterService tbClusterService; 117 private final TbClusterService tbClusterService;
118 private final DataDecodingEncodingService dataDecodingEncodingService; 118 private final DataDecodingEncodingService dataDecodingEncodingService;
119 private final DeviceProvisionService deviceProvisionService; 119 private final DeviceProvisionService deviceProvisionService;
120 - private final TbResourceService resourceService; 120 + private final ResourceService resourceService;
121 121
122 private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>(); 122 private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>();
123 123
@@ -126,7 +126,7 @@ public class DefaultTransportApiService implements TransportApiService { @@ -126,7 +126,7 @@ public class DefaultTransportApiService implements TransportApiService {
126 RelationService relationService, DeviceCredentialsService deviceCredentialsService, 126 RelationService relationService, DeviceCredentialsService deviceCredentialsService,
127 DeviceStateService deviceStateService, DbCallbackExecutorService dbCallbackExecutorService, 127 DeviceStateService deviceStateService, DbCallbackExecutorService dbCallbackExecutorService,
128 TbClusterService tbClusterService, DataDecodingEncodingService dataDecodingEncodingService, 128 TbClusterService tbClusterService, DataDecodingEncodingService dataDecodingEncodingService,
129 - DeviceProvisionService deviceProvisionService, TbResourceService resourceService) { 129 + DeviceProvisionService deviceProvisionService, ResourceService resourceService) {
130 this.deviceProfileCache = deviceProfileCache; 130 this.deviceProfileCache = deviceProfileCache;
131 this.tenantProfileCache = tenantProfileCache; 131 this.tenantProfileCache = tenantProfileCache;
132 this.apiUsageStateService = apiUsageStateService; 132 this.apiUsageStateService = apiUsageStateService;
1 - ______ __ _ __ __  
2 - /_ __/ / /_ (_) ____ ____ _ _____ / /_ ____ ____ _ _____ ____/ /  
3 - / / / __ \ / / / __ \ / __ `/ / ___/ / __ \ / __ \ / __ `/ / ___/ / __ /  
4 - / / / / / / / / / / / / / /_/ / (__ ) / /_/ // /_/ // /_/ / / / / /_/ /  
5 -/_/ /_/ /_/ /_/ /_/ /_/ \__, / /____/ /_.___/ \____/ \__,_/ /_/ \__,_/ 1 + ______ __ _ ____ __
  2 + /_ __/ / /_ (_) ____ ____ _ _____ / __ ) ____ ____ _ _____ ____/ /
  3 + / / / __ \ / / / __ \ / __ `/ / ___/ / __ | / __ \ / __ `/ / ___/ / __ /
  4 + / / / / / / / / / / / / / /_/ / (__ ) / /_/ / / /_/ // /_/ / / / / /_/ /
  5 +/_/ /_/ /_/ /_/ /_/ /_/ \__, / /____/ /_____/ \____/ \__,_/ /_/ \__,_/
6 /____/ 6 /____/
7 7
8 =================================================== 8 ===================================================
@@ -38,6 +38,9 @@ @@ -38,6 +38,9 @@
38 <!-- <logger name="org.eclipse.californium.scandium.DTLSConnector" level="TRACE" />--> 38 <!-- <logger name="org.eclipse.californium.scandium.DTLSConnector" level="TRACE" />-->
39 <!-- <logger name="org.eclipse.californium.scandium.dtls.Handshaker" level="DEBUG" />--> 39 <!-- <logger name="org.eclipse.californium.scandium.dtls.Handshaker" level="DEBUG" />-->
40 40
  41 + <!-- Top Rule Nodes by max execution time -->
  42 +<!-- <logger name="org.thingsboard.server.service.queue.TbMsgPackProcessingContext" level="DEBUG" /> -->
  43 +
41 <logger name="com.microsoft.azure.servicebus.primitives.CoreMessageReceiver" level="OFF" /> 44 <logger name="com.microsoft.azure.servicebus.primitives.CoreMessageReceiver" level="OFF" />
42 45
43 <root level="INFO"> 46 <root level="INFO">
@@ -243,6 +243,7 @@ sql: @@ -243,6 +243,7 @@ sql:
243 batch_max_delay: "${SQL_TS_LATEST_BATCH_MAX_DELAY_MS:100}" 243 batch_max_delay: "${SQL_TS_LATEST_BATCH_MAX_DELAY_MS:100}"
244 stats_print_interval_ms: "${SQL_TS_LATEST_BATCH_STATS_PRINT_MS:10000}" 244 stats_print_interval_ms: "${SQL_TS_LATEST_BATCH_STATS_PRINT_MS:10000}"
245 batch_threads: "${SQL_TS_LATEST_BATCH_THREADS:4}" 245 batch_threads: "${SQL_TS_LATEST_BATCH_THREADS:4}"
  246 + update_by_latest_ts: "${SQL_TS_UPDATE_BY_LATEST_TIMESTAMP:true}"
246 # Specify whether to sort entities before batch update. Should be enabled for cluster mode to avoid deadlocks 247 # Specify whether to sort entities before batch update. Should be enabled for cluster mode to avoid deadlocks
247 batch_sort: "${SQL_BATCH_SORT:false}" 248 batch_sort: "${SQL_BATCH_SORT:false}"
248 # Specify whether to remove null characters from strValue of attributes and timeseries before insert 249 # Specify whether to remove null characters from strValue of attributes and timeseries before insert
@@ -516,7 +517,7 @@ js: @@ -516,7 +517,7 @@ js:
516 # Built-in JVM JavaScript environment properties 517 # Built-in JVM JavaScript environment properties
517 local: 518 local:
518 # Use Sandboxed (secured) JVM JavaScript environment 519 # Use Sandboxed (secured) JVM JavaScript environment
519 - use_js_sandbox: "${USE_LOCAL_JS_SANDBOX:false}" 520 + use_js_sandbox: "${USE_LOCAL_JS_SANDBOX:true}"
520 # Specify thread pool size for JavaScript sandbox resource monitor 521 # Specify thread pool size for JavaScript sandbox resource monitor
521 monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}" 522 monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}"
522 # Maximum CPU time in milliseconds allowed for script execution 523 # Maximum CPU time in milliseconds allowed for script execution
@@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.security.Authority; @@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.security.Authority;
38 import org.thingsboard.server.dao.model.ModelConstants; 38 import org.thingsboard.server.dao.model.ModelConstants;
39 import org.thingsboard.server.edge.imitator.EdgeImitator; 39 import org.thingsboard.server.edge.imitator.EdgeImitator;
40 import org.thingsboard.server.gen.edge.AssetUpdateMsg; 40 import org.thingsboard.server.gen.edge.AssetUpdateMsg;
  41 +import org.thingsboard.server.gen.edge.DeviceProfileUpdateMsg;
41 import org.thingsboard.server.gen.edge.DeviceUpdateMsg; 42 import org.thingsboard.server.gen.edge.DeviceUpdateMsg;
42 import org.thingsboard.server.gen.edge.RuleChainUpdateMsg; 43 import org.thingsboard.server.gen.edge.RuleChainUpdateMsg;
43 import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; 44 import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg;
@@ -672,28 +673,32 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { @@ -672,28 +673,32 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
672 edgeImitator.ignoreType(UserCredentialsUpdateMsg.class); 673 edgeImitator.ignoreType(UserCredentialsUpdateMsg.class);
673 edgeImitator.expectMessageAmount(7); 674 edgeImitator.expectMessageAmount(7);
674 edgeImitator.connect(); 675 edgeImitator.connect();
675 - edgeImitator.waitForMessages(); 676 + Assert.assertTrue(edgeImitator.waitForMessages());
676 677
677 Assert.assertEquals(7, edgeImitator.getDownlinkMsgs().size()); 678 Assert.assertEquals(7, edgeImitator.getDownlinkMsgs().size());
678 Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent()); 679 Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent());
  680 + Assert.assertTrue(edgeImitator.findMessageByType(DeviceProfileUpdateMsg.class).isPresent());
679 Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent()); 681 Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent());
680 Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); 682 Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent());
681 Assert.assertTrue(edgeImitator.findMessageByType(UserUpdateMsg.class).isPresent()); 683 Assert.assertTrue(edgeImitator.findMessageByType(UserUpdateMsg.class).isPresent());
682 684
683 edgeImitator.getDownlinkMsgs().clear(); 685 edgeImitator.getDownlinkMsgs().clear();
684 686
685 - edgeImitator.expectMessageAmount(4); 687 + edgeImitator.expectMessageAmount(7);
686 doPost("/api/edge/sync/" + edge.getId()); 688 doPost("/api/edge/sync/" + edge.getId());
687 - edgeImitator.waitForMessages(); 689 + Assert.assertTrue(edgeImitator.waitForMessages());
688 690
689 - Assert.assertEquals(4, edgeImitator.getDownlinkMsgs().size()); 691 + Assert.assertEquals(7, edgeImitator.getDownlinkMsgs().size());
690 Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent()); 692 Assert.assertTrue(edgeImitator.findMessageByType(RuleChainUpdateMsg.class).isPresent());
  693 + Assert.assertTrue(edgeImitator.findMessageByType(DeviceProfileUpdateMsg.class).isPresent());
691 Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent()); 694 Assert.assertTrue(edgeImitator.findMessageByType(DeviceUpdateMsg.class).isPresent());
692 Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent()); 695 Assert.assertTrue(edgeImitator.findMessageByType(AssetUpdateMsg.class).isPresent());
693 Assert.assertTrue(edgeImitator.findMessageByType(UserUpdateMsg.class).isPresent()); 696 Assert.assertTrue(edgeImitator.findMessageByType(UserUpdateMsg.class).isPresent());
694 697
695 edgeImitator.allowIgnoredTypes(); 698 edgeImitator.allowIgnoredTypes();
696 - edgeImitator.disconnect(); 699 + try {
  700 + edgeImitator.disconnect();
  701 + } catch (Exception ignored) {}
697 702
698 doDelete("/api/device/" + savedDevice.getId().getId().toString()) 703 doDelete("/api/device/" + savedDevice.getId().getId().toString())
699 .andExpect(status().isOk()); 704 .andExpect(status().isOk());
@@ -42,7 +42,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @@ -42,7 +42,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
42 public class BaseEdgeEventControllerTest extends AbstractControllerTest { 42 public class BaseEdgeEventControllerTest extends AbstractControllerTest {
43 43
44 private Tenant savedTenant; 44 private Tenant savedTenant;
45 - private TenantId tenantId;  
46 private User tenantAdmin; 45 private User tenantAdmin;
47 46
48 @Before 47 @Before
@@ -52,7 +51,6 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { @@ -52,7 +51,6 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest {
52 Tenant tenant = new Tenant(); 51 Tenant tenant = new Tenant();
53 tenant.setTitle("My tenant"); 52 tenant.setTitle("My tenant");
54 savedTenant = doPost("/api/tenant", tenant, Tenant.class); 53 savedTenant = doPost("/api/tenant", tenant, Tenant.class);
55 - tenantId = savedTenant.getId();  
56 Assert.assertNotNull(savedTenant); 54 Assert.assertNotNull(savedTenant);
57 55
58 tenantAdmin = new User(); 56 tenantAdmin = new User();
@@ -63,6 +61,10 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { @@ -63,6 +61,10 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest {
63 tenantAdmin.setLastName("Downs"); 61 tenantAdmin.setLastName("Downs");
64 62
65 tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); 63 tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");
  64 + // sleep 1 seconds to avoid CREDENTIALS updated message for the user
  65 + // user credentials is going to be stored and updated event pushed to edge notification service
  66 + // while service will be processing this event edge could be already added and additional message will be pushed
  67 + Thread.sleep(1000);
66 } 68 }
67 69
68 @After 70 @After
@@ -75,7 +77,6 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { @@ -75,7 +77,6 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest {
75 77
76 @Test 78 @Test
77 public void testGetEdgeEvents() throws Exception { 79 public void testGetEdgeEvents() throws Exception {
78 - Thread.sleep(500);  
79 Edge edge = constructEdge("TestEdge", "default"); 80 Edge edge = constructEdge("TestEdge", "default");
80 edge = doPost("/api/edge", edge, Edge.class); 81 edge = doPost("/api/edge", edge, Edge.class);
81 82
@@ -83,29 +84,31 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest { @@ -83,29 +84,31 @@ public class BaseEdgeEventControllerTest extends AbstractControllerTest {
83 Device savedDevice = doPost("/api/device", device, Device.class); 84 Device savedDevice = doPost("/api/device", device, Device.class);
84 85
85 doPost("/api/edge/" + edge.getId().toString() + "/device/" + savedDevice.getId().toString(), Device.class); 86 doPost("/api/edge/" + edge.getId().toString() + "/device/" + savedDevice.getId().toString(), Device.class);
86 - Thread.sleep(500);  
87 87
88 Asset asset = constructAsset("TestAsset", "default"); 88 Asset asset = constructAsset("TestAsset", "default");
89 Asset savedAsset = doPost("/api/asset", asset, Asset.class); 89 Asset savedAsset = doPost("/api/asset", asset, Asset.class);
90 90
91 doPost("/api/edge/" + edge.getId().toString() + "/asset/" + savedAsset.getId().toString(), Asset.class); 91 doPost("/api/edge/" + edge.getId().toString() + "/asset/" + savedAsset.getId().toString(), Asset.class);
92 - Thread.sleep(500);  
93 92
94 EntityRelation relation = new EntityRelation(savedAsset.getId(), savedDevice.getId(), EntityRelation.CONTAINS_TYPE); 93 EntityRelation relation = new EntityRelation(savedAsset.getId(), savedDevice.getId(), EntityRelation.CONTAINS_TYPE);
95 94
96 doPost("/api/relation", relation); 95 doPost("/api/relation", relation);
97 - Thread.sleep(500);  
98 96
99 - List<EdgeEvent> edgeEvents = doGetTypedWithTimePageLink("/api/edge/" + edge.getId().toString() + "/events?",  
100 - new TypeReference<PageData<EdgeEvent>>() {  
101 - }, new TimePageLink(4)).getData();  
102 -  
103 - Assert.assertFalse(edgeEvents.isEmpty()); 97 + // wait while edge event for the relation entity persisted to DB
  98 + Thread.sleep(100);
  99 + List<EdgeEvent> edgeEvents;
  100 + int attempt = 1;
  101 + do {
  102 + edgeEvents = doGetTypedWithTimePageLink("/api/edge/" + edge.getId().toString() + "/events?",
  103 + new TypeReference<PageData<EdgeEvent>>() {}, new TimePageLink(4)).getData();
  104 + attempt++;
  105 + Thread.sleep(100);
  106 + } while (edgeEvents.size() != 4 && attempt < 5);
104 Assert.assertEquals(4, edgeEvents.size()); 107 Assert.assertEquals(4, edgeEvents.size());
105 - Assert.assertEquals(EdgeEventType.RULE_CHAIN, edgeEvents.get(0).getType());  
106 - Assert.assertEquals(EdgeEventType.DEVICE, edgeEvents.get(1).getType());  
107 - Assert.assertEquals(EdgeEventType.ASSET, edgeEvents.get(2).getType());  
108 - Assert.assertEquals(EdgeEventType.RELATION, edgeEvents.get(3).getType()); 108 + Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.RULE_CHAIN.equals(ee.getType())));
  109 + Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.DEVICE.equals(ee.getType())));
  110 + Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.ASSET.equals(ee.getType())));
  111 + Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.RELATION.equals(ee.getType())));
109 } 112 }
110 113
111 private Device constructDevice(String name, String type) { 114 private Device constructDevice(String name, String type) {
@@ -32,10 +32,12 @@ import org.junit.Assert; @@ -32,10 +32,12 @@ import org.junit.Assert;
32 import org.junit.Before; 32 import org.junit.Before;
33 import org.junit.Test; 33 import org.junit.Test;
34 import org.springframework.beans.factory.annotation.Autowired; 34 import org.springframework.beans.factory.annotation.Autowired;
  35 +import org.thingsboard.common.util.JacksonUtil;
35 import org.thingsboard.server.common.data.Customer; 36 import org.thingsboard.server.common.data.Customer;
36 import org.thingsboard.server.common.data.Dashboard; 37 import org.thingsboard.server.common.data.Dashboard;
37 import org.thingsboard.server.common.data.DataConstants; 38 import org.thingsboard.server.common.data.DataConstants;
38 import org.thingsboard.server.common.data.Device; 39 import org.thingsboard.server.common.data.Device;
  40 +import org.thingsboard.server.common.data.DeviceProfile;
39 import org.thingsboard.server.common.data.EntityType; 41 import org.thingsboard.server.common.data.EntityType;
40 import org.thingsboard.server.common.data.EntityView; 42 import org.thingsboard.server.common.data.EntityView;
41 import org.thingsboard.server.common.data.Tenant; 43 import org.thingsboard.server.common.data.Tenant;
@@ -45,6 +47,15 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo; @@ -45,6 +47,15 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo;
45 import org.thingsboard.server.common.data.alarm.AlarmSeverity; 47 import org.thingsboard.server.common.data.alarm.AlarmSeverity;
46 import org.thingsboard.server.common.data.alarm.AlarmStatus; 48 import org.thingsboard.server.common.data.alarm.AlarmStatus;
47 import org.thingsboard.server.common.data.asset.Asset; 49 import org.thingsboard.server.common.data.asset.Asset;
  50 +import org.thingsboard.server.common.data.device.profile.AlarmCondition;
  51 +import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter;
  52 +import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey;
  53 +import org.thingsboard.server.common.data.device.profile.AlarmConditionKeyType;
  54 +import org.thingsboard.server.common.data.device.profile.AlarmRule;
  55 +import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration;
  56 +import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm;
  57 +import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
  58 +import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec;
48 import org.thingsboard.server.common.data.edge.Edge; 59 import org.thingsboard.server.common.data.edge.Edge;
49 import org.thingsboard.server.common.data.edge.EdgeEvent; 60 import org.thingsboard.server.common.data.edge.EdgeEvent;
50 import org.thingsboard.server.common.data.edge.EdgeEventActionType; 61 import org.thingsboard.server.common.data.edge.EdgeEventActionType;
@@ -57,6 +68,9 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -57,6 +68,9 @@ import org.thingsboard.server.common.data.id.TenantId;
57 import org.thingsboard.server.common.data.id.UserId; 68 import org.thingsboard.server.common.data.id.UserId;
58 import org.thingsboard.server.common.data.page.PageData; 69 import org.thingsboard.server.common.data.page.PageData;
59 import org.thingsboard.server.common.data.page.PageLink; 70 import org.thingsboard.server.common.data.page.PageLink;
  71 +import org.thingsboard.server.common.data.query.EntityKeyValueType;
  72 +import org.thingsboard.server.common.data.query.FilterPredicateValue;
  73 +import org.thingsboard.server.common.data.query.NumericFilterPredicate;
60 import org.thingsboard.server.common.data.relation.EntityRelation; 74 import org.thingsboard.server.common.data.relation.EntityRelation;
61 import org.thingsboard.server.common.data.relation.RelationTypeGroup; 75 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
62 import org.thingsboard.server.common.data.rule.RuleChain; 76 import org.thingsboard.server.common.data.rule.RuleChain;
@@ -71,7 +85,6 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; @@ -71,7 +85,6 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle;
71 import org.thingsboard.server.common.transport.adaptor.JsonConverter; 85 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
72 import org.thingsboard.server.controller.AbstractControllerTest; 86 import org.thingsboard.server.controller.AbstractControllerTest;
73 import org.thingsboard.server.dao.edge.EdgeEventService; 87 import org.thingsboard.server.dao.edge.EdgeEventService;
74 -import org.thingsboard.common.util.JacksonUtil;  
75 import org.thingsboard.server.edge.imitator.EdgeImitator; 88 import org.thingsboard.server.edge.imitator.EdgeImitator;
76 import org.thingsboard.server.gen.edge.AlarmUpdateMsg; 89 import org.thingsboard.server.gen.edge.AlarmUpdateMsg;
77 import org.thingsboard.server.gen.edge.AssetUpdateMsg; 90 import org.thingsboard.server.gen.edge.AssetUpdateMsg;
@@ -81,6 +94,7 @@ import org.thingsboard.server.gen.edge.CustomerUpdateMsg; @@ -81,6 +94,7 @@ import org.thingsboard.server.gen.edge.CustomerUpdateMsg;
81 import org.thingsboard.server.gen.edge.DashboardUpdateMsg; 94 import org.thingsboard.server.gen.edge.DashboardUpdateMsg;
82 import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; 95 import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg;
83 import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; 96 import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg;
  97 +import org.thingsboard.server.gen.edge.DeviceProfileUpdateMsg;
84 import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; 98 import org.thingsboard.server.gen.edge.DeviceRpcCallMsg;
85 import org.thingsboard.server.gen.edge.DeviceUpdateMsg; 99 import org.thingsboard.server.gen.edge.DeviceUpdateMsg;
86 import org.thingsboard.server.gen.edge.EdgeConfiguration; 100 import org.thingsboard.server.gen.edge.EdgeConfiguration;
@@ -106,6 +120,7 @@ import java.util.List; @@ -106,6 +120,7 @@ import java.util.List;
106 import java.util.Map; 120 import java.util.Map;
107 import java.util.Optional; 121 import java.util.Optional;
108 import java.util.Random; 122 import java.util.Random;
  123 +import java.util.TreeMap;
109 import java.util.UUID; 124 import java.util.UUID;
110 import java.util.concurrent.TimeUnit; 125 import java.util.concurrent.TimeUnit;
111 126
@@ -114,6 +129,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @@ -114,6 +129,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
114 @Slf4j 129 @Slf4j
115 abstract public class BaseEdgeTest extends AbstractControllerTest { 130 abstract public class BaseEdgeTest extends AbstractControllerTest {
116 131
  132 + private static final String CUSTOM_DEVICE_PROFILE_NAME = "Thermostat";
  133 +
117 private Tenant savedTenant; 134 private Tenant savedTenant;
118 private TenantId tenantId; 135 private TenantId tenantId;
119 private User tenantAdmin; 136 private User tenantAdmin;
@@ -145,17 +162,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -145,17 +162,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
145 tenantAdmin.setLastName("Downs"); 162 tenantAdmin.setLastName("Downs");
146 163
147 tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); 164 tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");
  165 + // sleep 1 seconds to avoid CREDENTIALS updated message for the user
  166 + // user credentials is going to be stored and updated event pushed to edge notification service
  167 + // while service will be processing this event edge could be already added and additional message will be pushed
  168 + Thread.sleep(1000);
  169 +
148 installation(); 170 installation();
149 171
150 edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); 172 edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret());
151 - // should be less, but events from SyncEdgeService stack with events from controller. will be fixed in next releases  
152 - edgeImitator.expectMessageAmount(7); 173 + // TODO: voba - should be less, but events from SyncEdgeService stack with events from controller. will be fixed in next releases
  174 + // so ideally sync process should check current edge queue and add only missing entities to the edge queue
  175 + edgeImitator.expectMessageAmount(10);
153 edgeImitator.connect(); 176 edgeImitator.connect();
154 } 177 }
155 178
156 @After 179 @After
157 public void afterTest() throws Exception { 180 public void afterTest() throws Exception {
158 - edgeImitator.disconnect(); 181 + try {
  182 + edgeImitator.disconnect();
  183 + } catch (Exception ignored) {}
159 184
160 loginSysAdmin(); 185 loginSysAdmin();
161 186
@@ -163,23 +188,63 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -163,23 +188,63 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
163 .andExpect(status().isOk()); 188 .andExpect(status().isOk());
164 } 189 }
165 190
166 -  
167 @Test 191 @Test
168 public void test() throws Exception { 192 public void test() throws Exception {
169 testReceivedInitialData(); 193 testReceivedInitialData();
  194 + int expectedDownlinkSize = 10;
  195 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  196 +
170 testDevices(); 197 testDevices();
  198 + expectedDownlinkSize = expectedDownlinkSize + 4;
  199 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  200 +
171 testAssets(); 201 testAssets();
  202 + expectedDownlinkSize = expectedDownlinkSize + 4;
  203 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  204 +
172 testRuleChains(); 205 testRuleChains();
  206 + expectedDownlinkSize = expectedDownlinkSize + 3;
  207 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  208 +
173 testDashboards(); 209 testDashboards();
  210 + expectedDownlinkSize = expectedDownlinkSize + 3;
  211 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  212 +
174 testRelations(); 213 testRelations();
  214 + expectedDownlinkSize = expectedDownlinkSize + 2;
  215 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  216 +
175 testAlarms(); 217 testAlarms();
  218 + expectedDownlinkSize = expectedDownlinkSize + 3;
  219 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  220 +
176 testEntityView(); 221 testEntityView();
  222 + expectedDownlinkSize = expectedDownlinkSize + 2;
  223 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  224 +
177 testCustomer(); 225 testCustomer();
  226 + expectedDownlinkSize = expectedDownlinkSize + 2;
  227 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  228 +
178 testWidgetsBundleAndWidgetType(); 229 testWidgetsBundleAndWidgetType();
  230 + expectedDownlinkSize = expectedDownlinkSize + 4;
  231 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  232 +
179 testTimeseries(); 233 testTimeseries();
  234 + expectedDownlinkSize = expectedDownlinkSize + 1;
  235 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  236 +
180 testAttributes(); 237 testAttributes();
  238 + expectedDownlinkSize = expectedDownlinkSize + 3;
  239 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  240 +
181 testSendMessagesToCloud(); 241 testSendMessagesToCloud();
  242 + expectedDownlinkSize = expectedDownlinkSize + 9;
  243 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
  244 +
182 testRpcCall(); 245 testRpcCall();
  246 + expectedDownlinkSize = expectedDownlinkSize + 1;
  247 + Assert.assertEquals(expectedDownlinkSize, edgeImitator.getDownlinkMsgs().size());
183 } 248 }
184 249
185 private Device findDeviceByName(String deviceName) throws Exception { 250 private Device findDeviceByName(String deviceName) throws Exception {
@@ -204,10 +269,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -204,10 +269,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
204 return asset; 269 return asset;
205 } 270 }
206 271
207 - private Device saveDevice(String deviceName) throws Exception { 272 + private Device saveDevice(String deviceName, String type) throws Exception {
208 Device device = new Device(); 273 Device device = new Device();
209 device.setName(deviceName); 274 device.setName(deviceName);
210 - device.setType("test"); 275 + device.setType(type);
211 return doPost("/api/device", device, Device.class); 276 return doPost("/api/device", device, Device.class);
212 } 277 }
213 278
@@ -233,7 +298,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -233,7 +298,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
233 edgeImitator.expectMessageAmount(1); 298 edgeImitator.expectMessageAmount(1);
234 edgeEventService.saveAsync(edgeEvent); 299 edgeEventService.saveAsync(edgeEvent);
235 clusterService.onEdgeEventUpdate(tenantId, edge.getId()); 300 clusterService.onEdgeEventUpdate(tenantId, edge.getId());
236 - edgeImitator.waitForMessages(); 301 + Assert.assertTrue(edgeImitator.waitForMessages());
237 302
238 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 303 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
239 Assert.assertTrue(latestMessage instanceof DeviceRpcCallMsg); 304 Assert.assertTrue(latestMessage instanceof DeviceRpcCallMsg);
@@ -243,7 +308,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -243,7 +308,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
243 308
244 private void testReceivedInitialData() throws Exception { 309 private void testReceivedInitialData() throws Exception {
245 log.info("Checking received data"); 310 log.info("Checking received data");
246 - edgeImitator.waitForMessages(); 311 + Assert.assertTrue(edgeImitator.waitForMessages());
247 312
248 EdgeConfiguration configuration = edgeImitator.getConfiguration(); 313 EdgeConfiguration configuration = edgeImitator.getConfiguration();
249 Assert.assertNotNull(configuration); 314 Assert.assertNotNull(configuration);
@@ -253,9 +318,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -253,9 +318,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
253 UserId userId = edgeImitator.getUserId(); 318 UserId userId = edgeImitator.getUserId();
254 Assert.assertNotNull(userId); 319 Assert.assertNotNull(userId);
255 320
256 - Optional<DeviceUpdateMsg> optionalMsg1 = edgeImitator.findMessageByType(DeviceUpdateMsg.class);  
257 - Assert.assertTrue(optionalMsg1.isPresent());  
258 - DeviceUpdateMsg deviceUpdateMsg = optionalMsg1.get(); 321 + Optional<DeviceUpdateMsg> deviceUpdateMsgOpt = edgeImitator.findMessageByType(DeviceUpdateMsg.class);
  322 + Assert.assertTrue(deviceUpdateMsgOpt.isPresent());
  323 + DeviceUpdateMsg deviceUpdateMsg = deviceUpdateMsgOpt.get();
259 Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); 324 Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType());
260 UUID deviceUUID = new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()); 325 UUID deviceUUID = new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB());
261 Device device = doGet("/api/device/" + deviceUUID.toString(), Device.class); 326 Device device = doGet("/api/device/" + deviceUUID.toString(), Device.class);
@@ -264,9 +329,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -264,9 +329,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
264 new TypeReference<PageData<Device>>() {}, new PageLink(100)).getData(); 329 new TypeReference<PageData<Device>>() {}, new PageLink(100)).getData();
265 Assert.assertTrue(edgeDevices.contains(device)); 330 Assert.assertTrue(edgeDevices.contains(device));
266 331
267 - Optional<AssetUpdateMsg> optionalMsg2 = edgeImitator.findMessageByType(AssetUpdateMsg.class);  
268 - Assert.assertTrue(optionalMsg2.isPresent());  
269 - AssetUpdateMsg assetUpdateMsg = optionalMsg2.get(); 332 + List<DeviceProfileUpdateMsg> deviceProfileUpdateMsgList = edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class);
  333 + Assert.assertEquals(3, deviceProfileUpdateMsgList.size());
  334 + Optional<DeviceProfileUpdateMsg> deviceProfileUpdateMsgOpt =
  335 + deviceProfileUpdateMsgList.stream().filter(dfum -> CUSTOM_DEVICE_PROFILE_NAME.equals(dfum.getName())).findAny();
  336 + Assert.assertTrue(deviceProfileUpdateMsgOpt.isPresent());
  337 + DeviceProfileUpdateMsg deviceProfileUpdateMsg = deviceProfileUpdateMsgOpt.get();
  338 + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceProfileUpdateMsg.getMsgType());
  339 + UUID deviceProfileUUID = new UUID(deviceProfileUpdateMsg.getIdMSB(), deviceProfileUpdateMsg.getIdLSB());
  340 + DeviceProfile deviceProfile = doGet("/api/deviceProfile/" + deviceProfileUUID.toString(), DeviceProfile.class);
  341 + Assert.assertNotNull(deviceProfile);
  342 + Assert.assertNotNull(deviceProfile.getProfileData());
  343 + Assert.assertNotNull(deviceProfile.getProfileData().getAlarms());
  344 + Assert.assertNotNull(deviceProfile.getProfileData().getAlarms().get(0).getClearRule());
  345 +
  346 + testAutoGeneratedCodeByProtobuf(deviceProfileUpdateMsg);
  347 +
  348 + Optional<AssetUpdateMsg> assetUpdateMsgOpt = edgeImitator.findMessageByType(AssetUpdateMsg.class);
  349 + Assert.assertTrue(assetUpdateMsgOpt.isPresent());
  350 + AssetUpdateMsg assetUpdateMsg = assetUpdateMsgOpt.get();
270 Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, assetUpdateMsg.getMsgType()); 351 Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, assetUpdateMsg.getMsgType());
271 UUID assetUUID = new UUID(assetUpdateMsg.getIdMSB(), assetUpdateMsg.getIdLSB()); 352 UUID assetUUID = new UUID(assetUpdateMsg.getIdMSB(), assetUpdateMsg.getIdLSB());
272 Asset asset = doGet("/api/asset/" + assetUUID.toString(), Asset.class); 353 Asset asset = doGet("/api/asset/" + assetUUID.toString(), Asset.class);
@@ -277,9 +358,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -277,9 +358,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
277 358
278 testAutoGeneratedCodeByProtobuf(assetUpdateMsg); 359 testAutoGeneratedCodeByProtobuf(assetUpdateMsg);
279 360
280 - Optional<RuleChainUpdateMsg> optionalMsg3 = edgeImitator.findMessageByType(RuleChainUpdateMsg.class);  
281 - Assert.assertTrue(optionalMsg3.isPresent());  
282 - RuleChainUpdateMsg ruleChainUpdateMsg = optionalMsg3.get(); 361 + Optional<RuleChainUpdateMsg> ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class);
  362 + Assert.assertTrue(ruleChainUpdateMsgOpt.isPresent());
  363 + RuleChainUpdateMsg ruleChainUpdateMsg = ruleChainUpdateMsgOpt.get();
283 Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, ruleChainUpdateMsg.getMsgType()); 364 Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, ruleChainUpdateMsg.getMsgType());
284 UUID ruleChainUUID = new UUID(ruleChainUpdateMsg.getIdMSB(), ruleChainUpdateMsg.getIdLSB()); 365 UUID ruleChainUUID = new UUID(ruleChainUpdateMsg.getIdMSB(), ruleChainUpdateMsg.getIdLSB());
285 RuleChain ruleChain = doGet("/api/ruleChain/" + ruleChainUUID.toString(), RuleChain.class); 366 RuleChain ruleChain = doGet("/api/ruleChain/" + ruleChainUUID.toString(), RuleChain.class);
@@ -296,13 +377,12 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -296,13 +377,12 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
296 private void testDevices() throws Exception { 377 private void testDevices() throws Exception {
297 log.info("Testing devices"); 378 log.info("Testing devices");
298 379
299 - Device savedDevice = saveDevice("Edge Device 2");  
300 - 380 + // 1
301 edgeImitator.expectMessageAmount(1); 381 edgeImitator.expectMessageAmount(1);
  382 + Device savedDevice = saveDevice("Edge Device 2", "Default");
302 doPost("/api/edge/" + edge.getId().getId().toString() 383 doPost("/api/edge/" + edge.getId().getId().toString()
303 + "/device/" + savedDevice.getId().getId().toString(), Device.class); 384 + "/device/" + savedDevice.getId().getId().toString(), Device.class);
304 - edgeImitator.waitForMessages();  
305 - 385 + Assert.assertTrue(edgeImitator.waitForMessages());
306 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 386 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
307 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); 387 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
308 DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; 388 DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
@@ -312,11 +392,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -312,11 +392,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
312 Assert.assertEquals(deviceUpdateMsg.getName(), savedDevice.getName()); 392 Assert.assertEquals(deviceUpdateMsg.getName(), savedDevice.getName());
313 Assert.assertEquals(deviceUpdateMsg.getType(), savedDevice.getType()); 393 Assert.assertEquals(deviceUpdateMsg.getType(), savedDevice.getType());
314 394
  395 + // 2
315 edgeImitator.expectMessageAmount(1); 396 edgeImitator.expectMessageAmount(1);
316 doDelete("/api/edge/" + edge.getId().getId().toString() 397 doDelete("/api/edge/" + edge.getId().getId().toString()
317 + "/device/" + savedDevice.getId().getId().toString(), Device.class); 398 + "/device/" + savedDevice.getId().getId().toString(), Device.class);
318 - edgeImitator.waitForMessages();  
319 - 399 + Assert.assertTrue(edgeImitator.waitForMessages());
320 latestMessage = edgeImitator.getLatestMessage(); 400 latestMessage = edgeImitator.getLatestMessage();
321 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); 401 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
322 deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; 402 deviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
@@ -324,11 +404,34 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -324,11 +404,34 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
324 Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits()); 404 Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits());
325 Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits()); 405 Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits());
326 406
  407 + // 3
327 edgeImitator.expectMessageAmount(1); 408 edgeImitator.expectMessageAmount(1);
328 doDelete("/api/device/" + savedDevice.getId().getId().toString()) 409 doDelete("/api/device/" + savedDevice.getId().getId().toString())
329 .andExpect(status().isOk()); 410 .andExpect(status().isOk());
330 - edgeImitator.waitForMessages(); 411 + // we should not get any message because device is not assigned to edge any more
  412 + Assert.assertFalse(edgeImitator.waitForMessages(1));
331 413
  414 + // 4
  415 + edgeImitator.expectMessageAmount(1);
  416 + savedDevice = saveDevice("Edge Device 3", "Default");
  417 + doPost("/api/edge/" + edge.getId().getId().toString()
  418 + + "/device/" + savedDevice.getId().getId().toString(), Device.class);
  419 + Assert.assertTrue(edgeImitator.waitForMessages());
  420 + latestMessage = edgeImitator.getLatestMessage();
  421 + Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
  422 + deviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
  423 + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType());
  424 + Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits());
  425 + Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits());
  426 + Assert.assertEquals(deviceUpdateMsg.getName(), savedDevice.getName());
  427 + Assert.assertEquals(deviceUpdateMsg.getType(), savedDevice.getType());
  428 +
  429 + // 5
  430 + edgeImitator.expectMessageAmount(1);
  431 + doDelete("/api/device/" + savedDevice.getId().getId().toString())
  432 + .andExpect(status().isOk());
  433 + // in this case we should get messages because device was assigned to edge
  434 + Assert.assertTrue(edgeImitator.waitForMessages());
332 latestMessage = edgeImitator.getLatestMessage(); 435 latestMessage = edgeImitator.getLatestMessage();
333 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); 436 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
334 deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; 437 deviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
@@ -342,13 +445,13 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -342,13 +445,13 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
342 445
343 private void testAssets() throws Exception { 446 private void testAssets() throws Exception {
344 log.info("Testing assets"); 447 log.info("Testing assets");
345 - Asset savedAsset = saveAsset("Edge Asset 2");  
346 448
  449 + // 1
347 edgeImitator.expectMessageAmount(1); 450 edgeImitator.expectMessageAmount(1);
  451 + Asset savedAsset = saveAsset("Edge Asset 2");
348 doPost("/api/edge/" + edge.getId().getId().toString() 452 doPost("/api/edge/" + edge.getId().getId().toString()
349 + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); 453 + "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
350 - edgeImitator.waitForMessages();  
351 - 454 + Assert.assertTrue(edgeImitator.waitForMessages());
352 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 455 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
353 Assert.assertTrue(latestMessage instanceof AssetUpdateMsg); 456 Assert.assertTrue(latestMessage instanceof AssetUpdateMsg);
354 AssetUpdateMsg assetUpdateMsg = (AssetUpdateMsg) latestMessage; 457 AssetUpdateMsg assetUpdateMsg = (AssetUpdateMsg) latestMessage;
@@ -358,11 +461,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -358,11 +461,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
358 Assert.assertEquals(assetUpdateMsg.getName(), savedAsset.getName()); 461 Assert.assertEquals(assetUpdateMsg.getName(), savedAsset.getName());
359 Assert.assertEquals(assetUpdateMsg.getType(), savedAsset.getType()); 462 Assert.assertEquals(assetUpdateMsg.getType(), savedAsset.getType());
360 463
  464 + // 2
361 edgeImitator.expectMessageAmount(1); 465 edgeImitator.expectMessageAmount(1);
362 doDelete("/api/edge/" + edge.getId().getId().toString() 466 doDelete("/api/edge/" + edge.getId().getId().toString()
363 + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); 467 + "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
364 - edgeImitator.waitForMessages();  
365 - 468 + Assert.assertTrue(edgeImitator.waitForMessages());
366 latestMessage = edgeImitator.getLatestMessage(); 469 latestMessage = edgeImitator.getLatestMessage();
367 Assert.assertTrue(latestMessage instanceof AssetUpdateMsg); 470 Assert.assertTrue(latestMessage instanceof AssetUpdateMsg);
368 assetUpdateMsg = (AssetUpdateMsg) latestMessage; 471 assetUpdateMsg = (AssetUpdateMsg) latestMessage;
@@ -370,11 +473,32 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -370,11 +473,32 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
370 Assert.assertEquals(assetUpdateMsg.getIdMSB(), savedAsset.getUuidId().getMostSignificantBits()); 473 Assert.assertEquals(assetUpdateMsg.getIdMSB(), savedAsset.getUuidId().getMostSignificantBits());
371 Assert.assertEquals(assetUpdateMsg.getIdLSB(), savedAsset.getUuidId().getLeastSignificantBits()); 474 Assert.assertEquals(assetUpdateMsg.getIdLSB(), savedAsset.getUuidId().getLeastSignificantBits());
372 475
  476 + // 3
373 edgeImitator.expectMessageAmount(1); 477 edgeImitator.expectMessageAmount(1);
374 doDelete("/api/asset/" + savedAsset.getId().getId().toString()) 478 doDelete("/api/asset/" + savedAsset.getId().getId().toString())
375 .andExpect(status().isOk()); 479 .andExpect(status().isOk());
376 - edgeImitator.waitForMessages(); 480 + Assert.assertFalse(edgeImitator.waitForMessages(1));
377 481
  482 + // 4
  483 + edgeImitator.expectMessageAmount(1);
  484 + savedAsset = saveAsset("Edge Asset 3");
  485 + doPost("/api/edge/" + edge.getId().getId().toString()
  486 + + "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
  487 + Assert.assertTrue(edgeImitator.waitForMessages());
  488 + latestMessage = edgeImitator.getLatestMessage();
  489 + Assert.assertTrue(latestMessage instanceof AssetUpdateMsg);
  490 + assetUpdateMsg = (AssetUpdateMsg) latestMessage;
  491 + Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, assetUpdateMsg.getMsgType());
  492 + Assert.assertEquals(assetUpdateMsg.getIdMSB(), savedAsset.getUuidId().getMostSignificantBits());
  493 + Assert.assertEquals(assetUpdateMsg.getIdLSB(), savedAsset.getUuidId().getLeastSignificantBits());
  494 + Assert.assertEquals(assetUpdateMsg.getName(), savedAsset.getName());
  495 + Assert.assertEquals(assetUpdateMsg.getType(), savedAsset.getType());
  496 +
  497 + // 5
  498 + edgeImitator.expectMessageAmount(1);
  499 + doDelete("/api/asset/" + savedAsset.getId().getId().toString())
  500 + .andExpect(status().isOk());
  501 + Assert.assertTrue(edgeImitator.waitForMessages());
378 latestMessage = edgeImitator.getLatestMessage(); 502 latestMessage = edgeImitator.getLatestMessage();
379 Assert.assertTrue(latestMessage instanceof AssetUpdateMsg); 503 Assert.assertTrue(latestMessage instanceof AssetUpdateMsg);
380 assetUpdateMsg = (AssetUpdateMsg) latestMessage; 504 assetUpdateMsg = (AssetUpdateMsg) latestMessage;
@@ -387,21 +511,21 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -387,21 +511,21 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
387 511
388 private void testRuleChains() throws Exception { 512 private void testRuleChains() throws Exception {
389 log.info("Testing RuleChains"); 513 log.info("Testing RuleChains");
  514 +
  515 + // 1
  516 + edgeImitator.expectMessageAmount(1);
390 RuleChain ruleChain = new RuleChain(); 517 RuleChain ruleChain = new RuleChain();
391 ruleChain.setName("Edge Test Rule Chain"); 518 ruleChain.setName("Edge Test Rule Chain");
392 ruleChain.setType(RuleChainType.EDGE); 519 ruleChain.setType(RuleChainType.EDGE);
393 RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class); 520 RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class);
394 -  
395 createRuleChainMetadata(savedRuleChain); 521 createRuleChainMetadata(savedRuleChain);
396 -  
397 - // Wait before rule chain metadata saved to database before rule chain is assigned to edge 522 + // sleep 1 seconds to avoid ENTITY_UPDATED_RPC_MESSAGE for the rule chain
  523 + // rule chain metadata is going to be stored and updated event pushed to edge notification service
  524 + // while service will be processing this event assignment rule chain to edge will be completed if bad timing
398 Thread.sleep(1000); 525 Thread.sleep(1000);
399 -  
400 - edgeImitator.expectMessageAmount(1);  
401 doPost("/api/edge/" + edge.getId().getId().toString() 526 doPost("/api/edge/" + edge.getId().getId().toString()
402 + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); 527 + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class);
403 - edgeImitator.waitForMessages();  
404 - 528 + Assert.assertTrue(edgeImitator.waitForMessages());
405 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 529 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
406 Assert.assertTrue(latestMessage instanceof RuleChainUpdateMsg); 530 Assert.assertTrue(latestMessage instanceof RuleChainUpdateMsg);
407 RuleChainUpdateMsg ruleChainUpdateMsg = (RuleChainUpdateMsg) latestMessage; 531 RuleChainUpdateMsg ruleChainUpdateMsg = (RuleChainUpdateMsg) latestMessage;
@@ -410,13 +534,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -410,13 +534,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
410 Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits()); 534 Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits());
411 Assert.assertEquals(ruleChainUpdateMsg.getName(), savedRuleChain.getName()); 535 Assert.assertEquals(ruleChainUpdateMsg.getName(), savedRuleChain.getName());
412 536
  537 + // 2
413 testRuleChainMetadataRequestMsg(savedRuleChain.getId()); 538 testRuleChainMetadataRequestMsg(savedRuleChain.getId());
414 539
  540 + // 3
415 edgeImitator.expectMessageAmount(1); 541 edgeImitator.expectMessageAmount(1);
416 doDelete("/api/edge/" + edge.getId().getId().toString() 542 doDelete("/api/edge/" + edge.getId().getId().toString()
417 + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); 543 + "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class);
418 - edgeImitator.waitForMessages();  
419 - 544 + Assert.assertTrue(edgeImitator.waitForMessages());
420 latestMessage = edgeImitator.getLatestMessage(); 545 latestMessage = edgeImitator.getLatestMessage();
421 Assert.assertTrue(latestMessage instanceof RuleChainUpdateMsg); 546 Assert.assertTrue(latestMessage instanceof RuleChainUpdateMsg);
422 ruleChainUpdateMsg = (RuleChainUpdateMsg) latestMessage; 547 ruleChainUpdateMsg = (RuleChainUpdateMsg) latestMessage;
@@ -424,17 +549,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -424,17 +549,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
424 Assert.assertEquals(ruleChainUpdateMsg.getIdMSB(), savedRuleChain.getUuidId().getMostSignificantBits()); 549 Assert.assertEquals(ruleChainUpdateMsg.getIdMSB(), savedRuleChain.getUuidId().getMostSignificantBits());
425 Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits()); 550 Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits());
426 551
  552 + // 4
427 edgeImitator.expectMessageAmount(1); 553 edgeImitator.expectMessageAmount(1);
428 doDelete("/api/ruleChain/" + savedRuleChain.getId().getId().toString()) 554 doDelete("/api/ruleChain/" + savedRuleChain.getId().getId().toString())
429 .andExpect(status().isOk()); 555 .andExpect(status().isOk());
430 - edgeImitator.waitForMessages();  
431 -  
432 - latestMessage = edgeImitator.getLatestMessage();  
433 - Assert.assertTrue(latestMessage instanceof RuleChainUpdateMsg);  
434 - ruleChainUpdateMsg = (RuleChainUpdateMsg) latestMessage;  
435 - Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, ruleChainUpdateMsg.getMsgType());  
436 - Assert.assertEquals(ruleChainUpdateMsg.getIdMSB(), savedRuleChain.getUuidId().getMostSignificantBits());  
437 - Assert.assertEquals(ruleChainUpdateMsg.getIdLSB(), savedRuleChain.getUuidId().getLeastSignificantBits()); 556 + Assert.assertFalse(edgeImitator.waitForMessages(1));
438 557
439 log.info("RuleChains tested successfully"); 558 log.info("RuleChains tested successfully");
440 } 559 }
@@ -452,8 +571,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -452,8 +571,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
452 edgeImitator.expectResponsesAmount(1); 571 edgeImitator.expectResponsesAmount(1);
453 edgeImitator.expectMessageAmount(1); 572 edgeImitator.expectMessageAmount(1);
454 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 573 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
455 - edgeImitator.waitForResponses();  
456 - edgeImitator.waitForMessages(); 574 + Assert.assertTrue(edgeImitator.waitForResponses());
  575 + Assert.assertTrue(edgeImitator.waitForMessages());
457 576
458 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 577 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
459 Assert.assertTrue(latestMessage instanceof RuleChainMetadataUpdateMsg); 578 Assert.assertTrue(latestMessage instanceof RuleChainMetadataUpdateMsg);
@@ -502,15 +621,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -502,15 +621,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
502 621
503 private void testDashboards() throws Exception { 622 private void testDashboards() throws Exception {
504 log.info("Testing Dashboards"); 623 log.info("Testing Dashboards");
  624 +
  625 + // 1
  626 + edgeImitator.expectMessageAmount(1);
505 Dashboard dashboard = new Dashboard(); 627 Dashboard dashboard = new Dashboard();
506 dashboard.setTitle("Edge Test Dashboard"); 628 dashboard.setTitle("Edge Test Dashboard");
507 Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class); 629 Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class);
508 -  
509 - edgeImitator.expectMessageAmount(1);  
510 doPost("/api/edge/" + edge.getId().getId().toString() 630 doPost("/api/edge/" + edge.getId().getId().toString()
511 + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); 631 + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
512 - edgeImitator.waitForMessages();  
513 - 632 + Assert.assertTrue(edgeImitator.waitForMessages());
514 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 633 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
515 Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); 634 Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg);
516 DashboardUpdateMsg dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; 635 DashboardUpdateMsg dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage;
@@ -518,25 +637,24 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -518,25 +637,24 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
518 Assert.assertEquals(dashboardUpdateMsg.getIdMSB(), savedDashboard.getUuidId().getMostSignificantBits()); 637 Assert.assertEquals(dashboardUpdateMsg.getIdMSB(), savedDashboard.getUuidId().getMostSignificantBits());
519 Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits()); 638 Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits());
520 Assert.assertEquals(dashboardUpdateMsg.getTitle(), savedDashboard.getName()); 639 Assert.assertEquals(dashboardUpdateMsg.getTitle(), savedDashboard.getName());
521 -  
522 testAutoGeneratedCodeByProtobuf(dashboardUpdateMsg); 640 testAutoGeneratedCodeByProtobuf(dashboardUpdateMsg);
523 641
  642 + // 2
524 edgeImitator.expectMessageAmount(1); 643 edgeImitator.expectMessageAmount(1);
525 savedDashboard.setTitle("Updated Edge Test Dashboard"); 644 savedDashboard.setTitle("Updated Edge Test Dashboard");
526 doPost("/api/dashboard", savedDashboard, Dashboard.class); 645 doPost("/api/dashboard", savedDashboard, Dashboard.class);
527 - edgeImitator.waitForMessages();  
528 - 646 + Assert.assertTrue(edgeImitator.waitForMessages());
529 latestMessage = edgeImitator.getLatestMessage(); 647 latestMessage = edgeImitator.getLatestMessage();
530 Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); 648 Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg);
531 dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; 649 dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage;
532 Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType()); 650 Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType());
533 Assert.assertEquals(dashboardUpdateMsg.getTitle(), savedDashboard.getName()); 651 Assert.assertEquals(dashboardUpdateMsg.getTitle(), savedDashboard.getName());
534 652
  653 + // 3
535 edgeImitator.expectMessageAmount(1); 654 edgeImitator.expectMessageAmount(1);
536 doDelete("/api/edge/" + edge.getId().getId().toString() 655 doDelete("/api/edge/" + edge.getId().getId().toString()
537 + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); 656 + "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
538 - edgeImitator.waitForMessages();  
539 - 657 + Assert.assertTrue(edgeImitator.waitForMessages());
540 latestMessage = edgeImitator.getLatestMessage(); 658 latestMessage = edgeImitator.getLatestMessage();
541 Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); 659 Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg);
542 dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; 660 dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage;
@@ -544,17 +662,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -544,17 +662,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
544 Assert.assertEquals(dashboardUpdateMsg.getIdMSB(), savedDashboard.getUuidId().getMostSignificantBits()); 662 Assert.assertEquals(dashboardUpdateMsg.getIdMSB(), savedDashboard.getUuidId().getMostSignificantBits());
545 Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits()); 663 Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits());
546 664
  665 + // 4
547 edgeImitator.expectMessageAmount(1); 666 edgeImitator.expectMessageAmount(1);
548 doDelete("/api/dashboard/" + savedDashboard.getId().getId().toString()) 667 doDelete("/api/dashboard/" + savedDashboard.getId().getId().toString())
549 .andExpect(status().isOk()); 668 .andExpect(status().isOk());
550 - edgeImitator.waitForMessages();  
551 -  
552 - latestMessage = edgeImitator.getLatestMessage();  
553 - Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg);  
554 - dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage;  
555 - Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType());  
556 - Assert.assertEquals(dashboardUpdateMsg.getIdMSB(), savedDashboard.getUuidId().getMostSignificantBits());  
557 - Assert.assertEquals(dashboardUpdateMsg.getIdLSB(), savedDashboard.getUuidId().getLeastSignificantBits()); 669 + Assert.assertFalse(edgeImitator.waitForMessages(1));
558 670
559 log.info("Dashboards tested successfully"); 671 log.info("Dashboards tested successfully");
560 } 672 }
@@ -562,19 +674,17 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -562,19 +674,17 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
562 private void testRelations() throws Exception { 674 private void testRelations() throws Exception {
563 log.info("Testing Relations"); 675 log.info("Testing Relations");
564 676
  677 + // 1
  678 + edgeImitator.expectMessageAmount(1);
565 Device device = findDeviceByName("Edge Device 1"); 679 Device device = findDeviceByName("Edge Device 1");
566 Asset asset = findAssetByName("Edge Asset 1"); 680 Asset asset = findAssetByName("Edge Asset 1");
567 -  
568 EntityRelation relation = new EntityRelation(); 681 EntityRelation relation = new EntityRelation();
569 relation.setType("test"); 682 relation.setType("test");
570 relation.setFrom(device.getId()); 683 relation.setFrom(device.getId());
571 relation.setTo(asset.getId()); 684 relation.setTo(asset.getId());
572 relation.setTypeGroup(RelationTypeGroup.COMMON); 685 relation.setTypeGroup(RelationTypeGroup.COMMON);
573 -  
574 - edgeImitator.expectMessageAmount(1);  
575 doPost("/api/relation", relation); 686 doPost("/api/relation", relation);
576 - edgeImitator.waitForMessages();  
577 - 687 + Assert.assertTrue(edgeImitator.waitForMessages());
578 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 688 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
579 Assert.assertTrue(latestMessage instanceof RelationUpdateMsg); 689 Assert.assertTrue(latestMessage instanceof RelationUpdateMsg);
580 RelationUpdateMsg relationUpdateMsg = (RelationUpdateMsg) latestMessage; 690 RelationUpdateMsg relationUpdateMsg = (RelationUpdateMsg) latestMessage;
@@ -588,6 +698,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -588,6 +698,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
588 Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name()); 698 Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name());
589 Assert.assertEquals(relationUpdateMsg.getTypeGroup(), relation.getTypeGroup().name()); 699 Assert.assertEquals(relationUpdateMsg.getTypeGroup(), relation.getTypeGroup().name());
590 700
  701 + // 2
591 edgeImitator.expectMessageAmount(1); 702 edgeImitator.expectMessageAmount(1);
592 doDelete("/api/relation?" + 703 doDelete("/api/relation?" +
593 "fromId=" + relation.getFrom().getId().toString() + 704 "fromId=" + relation.getFrom().getId().toString() +
@@ -597,8 +708,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -597,8 +708,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
597 "&toId=" + relation.getTo().getId().toString() + 708 "&toId=" + relation.getTo().getId().toString() +
598 "&toType=" + relation.getTo().getEntityType().name()) 709 "&toType=" + relation.getTo().getEntityType().name())
599 .andExpect(status().isOk()); 710 .andExpect(status().isOk());
600 - edgeImitator.waitForMessages();  
601 - 711 + Assert.assertTrue(edgeImitator.waitForMessages());
602 latestMessage = edgeImitator.getLatestMessage(); 712 latestMessage = edgeImitator.getLatestMessage();
603 Assert.assertTrue(latestMessage instanceof RelationUpdateMsg); 713 Assert.assertTrue(latestMessage instanceof RelationUpdateMsg);
604 relationUpdateMsg = (RelationUpdateMsg) latestMessage; 714 relationUpdateMsg = (RelationUpdateMsg) latestMessage;
@@ -617,18 +727,17 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -617,18 +727,17 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
617 727
618 private void testAlarms() throws Exception { 728 private void testAlarms() throws Exception {
619 log.info("Testing Alarms"); 729 log.info("Testing Alarms");
620 - Device device = findDeviceByName("Edge Device 1");  
621 730
  731 + // 1
  732 + edgeImitator.expectMessageAmount(1);
  733 + Device device = findDeviceByName("Edge Device 1");
622 Alarm alarm = new Alarm(); 734 Alarm alarm = new Alarm();
623 alarm.setOriginator(device.getId()); 735 alarm.setOriginator(device.getId());
624 alarm.setStatus(AlarmStatus.ACTIVE_UNACK); 736 alarm.setStatus(AlarmStatus.ACTIVE_UNACK);
625 alarm.setType("alarm"); 737 alarm.setType("alarm");
626 alarm.setSeverity(AlarmSeverity.CRITICAL); 738 alarm.setSeverity(AlarmSeverity.CRITICAL);
627 -  
628 - edgeImitator.expectMessageAmount(1);  
629 Alarm savedAlarm = doPost("/api/alarm", alarm, Alarm.class); 739 Alarm savedAlarm = doPost("/api/alarm", alarm, Alarm.class);
630 - edgeImitator.waitForMessages();  
631 - 740 + Assert.assertTrue(edgeImitator.waitForMessages());
632 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 741 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
633 Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg); 742 Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg);
634 AlarmUpdateMsg alarmUpdateMsg = (AlarmUpdateMsg) latestMessage; 743 AlarmUpdateMsg alarmUpdateMsg = (AlarmUpdateMsg) latestMessage;
@@ -639,10 +748,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -639,10 +748,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
639 Assert.assertEquals(alarmUpdateMsg.getStatus(), savedAlarm.getStatus().name()); 748 Assert.assertEquals(alarmUpdateMsg.getStatus(), savedAlarm.getStatus().name());
640 Assert.assertEquals(alarmUpdateMsg.getSeverity(), savedAlarm.getSeverity().name()); 749 Assert.assertEquals(alarmUpdateMsg.getSeverity(), savedAlarm.getSeverity().name());
641 750
  751 + // 2
642 edgeImitator.expectMessageAmount(1); 752 edgeImitator.expectMessageAmount(1);
643 doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/ack"); 753 doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/ack");
644 - edgeImitator.waitForMessages();  
645 - 754 + Assert.assertTrue(edgeImitator.waitForMessages());
646 latestMessage = edgeImitator.getLatestMessage(); 755 latestMessage = edgeImitator.getLatestMessage();
647 Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg); 756 Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg);
648 alarmUpdateMsg = (AlarmUpdateMsg) latestMessage; 757 alarmUpdateMsg = (AlarmUpdateMsg) latestMessage;
@@ -652,10 +761,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -652,10 +761,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
652 Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName()); 761 Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName());
653 Assert.assertEquals(alarmUpdateMsg.getStatus(), AlarmStatus.ACTIVE_ACK.name()); 762 Assert.assertEquals(alarmUpdateMsg.getStatus(), AlarmStatus.ACTIVE_ACK.name());
654 763
  764 + // 3
655 edgeImitator.expectMessageAmount(1); 765 edgeImitator.expectMessageAmount(1);
656 doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/clear"); 766 doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/clear");
657 - edgeImitator.waitForMessages();  
658 - 767 + Assert.assertTrue(edgeImitator.waitForMessages());
659 latestMessage = edgeImitator.getLatestMessage(); 768 latestMessage = edgeImitator.getLatestMessage();
660 Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg); 769 Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg);
661 alarmUpdateMsg = (AlarmUpdateMsg) latestMessage; 770 alarmUpdateMsg = (AlarmUpdateMsg) latestMessage;
@@ -665,26 +774,29 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -665,26 +774,29 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
665 Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName()); 774 Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName());
666 Assert.assertEquals(alarmUpdateMsg.getStatus(), AlarmStatus.CLEARED_ACK.name()); 775 Assert.assertEquals(alarmUpdateMsg.getStatus(), AlarmStatus.CLEARED_ACK.name());
667 776
  777 + // 4
  778 + edgeImitator.expectMessageAmount(1);
668 doDelete("/api/alarm/" + savedAlarm.getId().getId().toString()) 779 doDelete("/api/alarm/" + savedAlarm.getId().getId().toString())
669 .andExpect(status().isOk()); 780 .andExpect(status().isOk());
  781 + Assert.assertFalse(edgeImitator.waitForMessages(1));
  782 +
670 log.info("Alarms tested successfully"); 783 log.info("Alarms tested successfully");
671 } 784 }
672 785
673 private void testEntityView() throws Exception { 786 private void testEntityView() throws Exception {
674 log.info("Testing EntityView"); 787 log.info("Testing EntityView");
675 - Device device = findDeviceByName("Edge Device 1");  
676 788
  789 + // 1
  790 + edgeImitator.expectMessageAmount(1);
  791 + Device device = findDeviceByName("Edge Device 1");
677 EntityView entityView = new EntityView(); 792 EntityView entityView = new EntityView();
678 entityView.setName("Edge EntityView 1"); 793 entityView.setName("Edge EntityView 1");
679 entityView.setType("test"); 794 entityView.setType("test");
680 entityView.setEntityId(device.getId()); 795 entityView.setEntityId(device.getId());
681 EntityView savedEntityView = doPost("/api/entityView", entityView, EntityView.class); 796 EntityView savedEntityView = doPost("/api/entityView", entityView, EntityView.class);
682 -  
683 - edgeImitator.expectMessageAmount(1);  
684 doPost("/api/edge/" + edge.getId().getId().toString() 797 doPost("/api/edge/" + edge.getId().getId().toString()
685 + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class); 798 + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class);
686 - edgeImitator.waitForMessages();  
687 - 799 + Assert.assertTrue(edgeImitator.waitForMessages());
688 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 800 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
689 Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg); 801 Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg);
690 EntityViewUpdateMsg entityViewUpdateMsg = (EntityViewUpdateMsg) latestMessage; 802 EntityViewUpdateMsg entityViewUpdateMsg = (EntityViewUpdateMsg) latestMessage;
@@ -697,11 +809,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -697,11 +809,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
697 Assert.assertEquals(entityViewUpdateMsg.getEntityIdLSB(), device.getUuidId().getLeastSignificantBits()); 809 Assert.assertEquals(entityViewUpdateMsg.getEntityIdLSB(), device.getUuidId().getLeastSignificantBits());
698 Assert.assertEquals(entityViewUpdateMsg.getEntityType().name(), device.getId().getEntityType().name()); 810 Assert.assertEquals(entityViewUpdateMsg.getEntityType().name(), device.getId().getEntityType().name());
699 811
  812 + // 2
700 edgeImitator.expectMessageAmount(1); 813 edgeImitator.expectMessageAmount(1);
701 doDelete("/api/edge/" + edge.getId().getId().toString() 814 doDelete("/api/edge/" + edge.getId().getId().toString()
702 + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class); 815 + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class);
703 - edgeImitator.waitForMessages();  
704 - 816 + Assert.assertTrue(edgeImitator.waitForMessages());
705 latestMessage = edgeImitator.getLatestMessage(); 817 latestMessage = edgeImitator.getLatestMessage();
706 Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg); 818 Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg);
707 entityViewUpdateMsg = (EntityViewUpdateMsg) latestMessage; 819 entityViewUpdateMsg = (EntityViewUpdateMsg) latestMessage;
@@ -709,17 +821,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -709,17 +821,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
709 Assert.assertEquals(entityViewUpdateMsg.getIdMSB(), savedEntityView.getUuidId().getMostSignificantBits()); 821 Assert.assertEquals(entityViewUpdateMsg.getIdMSB(), savedEntityView.getUuidId().getMostSignificantBits());
710 Assert.assertEquals(entityViewUpdateMsg.getIdLSB(), savedEntityView.getUuidId().getLeastSignificantBits()); 822 Assert.assertEquals(entityViewUpdateMsg.getIdLSB(), savedEntityView.getUuidId().getLeastSignificantBits());
711 823
  824 + // 3
712 edgeImitator.expectMessageAmount(1); 825 edgeImitator.expectMessageAmount(1);
713 doDelete("/api/entityView/" + savedEntityView.getId().getId().toString()) 826 doDelete("/api/entityView/" + savedEntityView.getId().getId().toString())
714 .andExpect(status().isOk()); 827 .andExpect(status().isOk());
715 - edgeImitator.waitForMessages();  
716 -  
717 - latestMessage = edgeImitator.getLatestMessage();  
718 - Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg);  
719 - entityViewUpdateMsg = (EntityViewUpdateMsg) latestMessage;  
720 - Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, entityViewUpdateMsg.getMsgType());  
721 - Assert.assertEquals(entityViewUpdateMsg.getIdMSB(), savedEntityView.getUuidId().getMostSignificantBits());  
722 - Assert.assertEquals(entityViewUpdateMsg.getIdLSB(), savedEntityView.getUuidId().getLeastSignificantBits()); 828 + Assert.assertFalse(edgeImitator.waitForMessages(1));
723 829
724 log.info("EntityView tested successfully"); 830 log.info("EntityView tested successfully");
725 } 831 }
@@ -727,15 +833,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -727,15 +833,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
727 private void testCustomer() throws Exception { 833 private void testCustomer() throws Exception {
728 log.info("Testing Customer"); 834 log.info("Testing Customer");
729 835
  836 + // 1
  837 + edgeImitator.expectMessageAmount(1);
730 Customer customer = new Customer(); 838 Customer customer = new Customer();
731 customer.setTitle("Edge Customer 1"); 839 customer.setTitle("Edge Customer 1");
732 Customer savedCustomer = doPost("/api/customer", customer, Customer.class); 840 Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
733 -  
734 - edgeImitator.expectMessageAmount(1);  
735 doPost("/api/customer/" + savedCustomer.getId().getId().toString() 841 doPost("/api/customer/" + savedCustomer.getId().getId().toString()
736 + "/edge/" + edge.getId().getId().toString(), Edge.class); 842 + "/edge/" + edge.getId().getId().toString(), Edge.class);
737 - edgeImitator.waitForMessages();  
738 - 843 + Assert.assertTrue(edgeImitator.waitForMessages());
739 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 844 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
740 Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg); 845 Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg);
741 CustomerUpdateMsg customerUpdateMsg = (CustomerUpdateMsg) latestMessage; 846 CustomerUpdateMsg customerUpdateMsg = (CustomerUpdateMsg) latestMessage;
@@ -743,13 +848,12 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -743,13 +848,12 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
743 Assert.assertEquals(customerUpdateMsg.getIdMSB(), savedCustomer.getUuidId().getMostSignificantBits()); 848 Assert.assertEquals(customerUpdateMsg.getIdMSB(), savedCustomer.getUuidId().getMostSignificantBits());
744 Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits()); 849 Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits());
745 Assert.assertEquals(customerUpdateMsg.getTitle(), savedCustomer.getTitle()); 850 Assert.assertEquals(customerUpdateMsg.getTitle(), savedCustomer.getTitle());
746 -  
747 testAutoGeneratedCodeByProtobuf(customerUpdateMsg); 851 testAutoGeneratedCodeByProtobuf(customerUpdateMsg);
748 852
  853 + // 2
749 edgeImitator.expectMessageAmount(1); 854 edgeImitator.expectMessageAmount(1);
750 doDelete("/api/customer/edge/" + edge.getId().getId().toString(), Edge.class); 855 doDelete("/api/customer/edge/" + edge.getId().getId().toString(), Edge.class);
751 - edgeImitator.waitForMessages();  
752 - 856 + Assert.assertTrue(edgeImitator.waitForMessages());
753 latestMessage = edgeImitator.getLatestMessage(); 857 latestMessage = edgeImitator.getLatestMessage();
754 Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg); 858 Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg);
755 customerUpdateMsg = (CustomerUpdateMsg) latestMessage; 859 customerUpdateMsg = (CustomerUpdateMsg) latestMessage;
@@ -757,17 +861,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -757,17 +861,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
757 Assert.assertEquals(customerUpdateMsg.getIdMSB(), savedCustomer.getUuidId().getMostSignificantBits()); 861 Assert.assertEquals(customerUpdateMsg.getIdMSB(), savedCustomer.getUuidId().getMostSignificantBits());
758 Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits()); 862 Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits());
759 863
  864 + // 3
760 edgeImitator.expectMessageAmount(1); 865 edgeImitator.expectMessageAmount(1);
761 doDelete("/api/customer/" + savedCustomer.getId().getId().toString()) 866 doDelete("/api/customer/" + savedCustomer.getId().getId().toString())
762 .andExpect(status().isOk()); 867 .andExpect(status().isOk());
763 - edgeImitator.waitForMessages();  
764 -  
765 - latestMessage = edgeImitator.getLatestMessage();  
766 - Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg);  
767 - customerUpdateMsg = (CustomerUpdateMsg) latestMessage;  
768 - Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, customerUpdateMsg.getMsgType());  
769 - Assert.assertEquals(customerUpdateMsg.getIdMSB(), savedCustomer.getUuidId().getMostSignificantBits());  
770 - Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits()); 868 + Assert.assertFalse(edgeImitator.waitForMessages(1));
771 869
772 log.info("Customer tested successfully"); 870 log.info("Customer tested successfully");
773 } 871 }
@@ -775,13 +873,12 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -775,13 +873,12 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
775 private void testWidgetsBundleAndWidgetType() throws Exception { 873 private void testWidgetsBundleAndWidgetType() throws Exception {
776 log.info("Testing WidgetsBundle and WidgetType"); 874 log.info("Testing WidgetsBundle and WidgetType");
777 875
  876 + // 1
  877 + edgeImitator.expectMessageAmount(1);
778 WidgetsBundle widgetsBundle = new WidgetsBundle(); 878 WidgetsBundle widgetsBundle = new WidgetsBundle();
779 widgetsBundle.setTitle("Test Widget Bundle"); 879 widgetsBundle.setTitle("Test Widget Bundle");
780 -  
781 - edgeImitator.expectMessageAmount(1);  
782 WidgetsBundle savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class); 880 WidgetsBundle savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class);
783 - edgeImitator.waitForMessages();  
784 - 881 + Assert.assertTrue(edgeImitator.waitForMessages());
785 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 882 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
786 Assert.assertTrue(latestMessage instanceof WidgetsBundleUpdateMsg); 883 Assert.assertTrue(latestMessage instanceof WidgetsBundleUpdateMsg);
787 WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = (WidgetsBundleUpdateMsg) latestMessage; 884 WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = (WidgetsBundleUpdateMsg) latestMessage;
@@ -790,20 +887,18 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -790,20 +887,18 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
790 Assert.assertEquals(widgetsBundleUpdateMsg.getIdLSB(), savedWidgetsBundle.getUuidId().getLeastSignificantBits()); 887 Assert.assertEquals(widgetsBundleUpdateMsg.getIdLSB(), savedWidgetsBundle.getUuidId().getLeastSignificantBits());
791 Assert.assertEquals(widgetsBundleUpdateMsg.getAlias(), savedWidgetsBundle.getAlias()); 888 Assert.assertEquals(widgetsBundleUpdateMsg.getAlias(), savedWidgetsBundle.getAlias());
792 Assert.assertEquals(widgetsBundleUpdateMsg.getTitle(), savedWidgetsBundle.getTitle()); 889 Assert.assertEquals(widgetsBundleUpdateMsg.getTitle(), savedWidgetsBundle.getTitle());
793 -  
794 testAutoGeneratedCodeByProtobuf(widgetsBundleUpdateMsg); 890 testAutoGeneratedCodeByProtobuf(widgetsBundleUpdateMsg);
795 891
  892 + // 2
  893 + edgeImitator.expectMessageAmount(1);
796 WidgetType widgetType = new WidgetType(); 894 WidgetType widgetType = new WidgetType();
797 widgetType.setName("Test Widget Type"); 895 widgetType.setName("Test Widget Type");
798 widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); 896 widgetType.setBundleAlias(savedWidgetsBundle.getAlias());
799 ObjectNode descriptor = mapper.createObjectNode(); 897 ObjectNode descriptor = mapper.createObjectNode();
800 descriptor.put("key", "value"); 898 descriptor.put("key", "value");
801 widgetType.setDescriptor(descriptor); 899 widgetType.setDescriptor(descriptor);
802 -  
803 - edgeImitator.expectMessageAmount(1);  
804 WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); 900 WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class);
805 - edgeImitator.waitForMessages();  
806 - 901 + Assert.assertTrue(edgeImitator.waitForMessages());
807 latestMessage = edgeImitator.getLatestMessage(); 902 latestMessage = edgeImitator.getLatestMessage();
808 Assert.assertTrue(latestMessage instanceof WidgetTypeUpdateMsg); 903 Assert.assertTrue(latestMessage instanceof WidgetTypeUpdateMsg);
809 WidgetTypeUpdateMsg widgetTypeUpdateMsg = (WidgetTypeUpdateMsg) latestMessage; 904 WidgetTypeUpdateMsg widgetTypeUpdateMsg = (WidgetTypeUpdateMsg) latestMessage;
@@ -814,11 +909,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -814,11 +909,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
814 Assert.assertEquals(widgetTypeUpdateMsg.getName(), savedWidgetType.getName()); 909 Assert.assertEquals(widgetTypeUpdateMsg.getName(), savedWidgetType.getName());
815 Assert.assertEquals(JacksonUtil.toJsonNode(widgetTypeUpdateMsg.getDescriptorJson()), savedWidgetType.getDescriptor()); 910 Assert.assertEquals(JacksonUtil.toJsonNode(widgetTypeUpdateMsg.getDescriptorJson()), savedWidgetType.getDescriptor());
816 911
  912 + // 3
817 edgeImitator.expectMessageAmount(1); 913 edgeImitator.expectMessageAmount(1);
818 doDelete("/api/widgetType/" + savedWidgetType.getId().getId().toString()) 914 doDelete("/api/widgetType/" + savedWidgetType.getId().getId().toString())
819 .andExpect(status().isOk()); 915 .andExpect(status().isOk());
820 - edgeImitator.waitForMessages();  
821 - 916 + Assert.assertTrue(edgeImitator.waitForMessages());
822 latestMessage = edgeImitator.getLatestMessage(); 917 latestMessage = edgeImitator.getLatestMessage();
823 Assert.assertTrue(latestMessage instanceof WidgetTypeUpdateMsg); 918 Assert.assertTrue(latestMessage instanceof WidgetTypeUpdateMsg);
824 widgetTypeUpdateMsg = (WidgetTypeUpdateMsg) latestMessage; 919 widgetTypeUpdateMsg = (WidgetTypeUpdateMsg) latestMessage;
@@ -826,11 +921,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -826,11 +921,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
826 Assert.assertEquals(widgetTypeUpdateMsg.getIdMSB(), savedWidgetType.getUuidId().getMostSignificantBits()); 921 Assert.assertEquals(widgetTypeUpdateMsg.getIdMSB(), savedWidgetType.getUuidId().getMostSignificantBits());
827 Assert.assertEquals(widgetTypeUpdateMsg.getIdLSB(), savedWidgetType.getUuidId().getLeastSignificantBits()); 922 Assert.assertEquals(widgetTypeUpdateMsg.getIdLSB(), savedWidgetType.getUuidId().getLeastSignificantBits());
828 923
  924 + // 4
829 edgeImitator.expectMessageAmount(1); 925 edgeImitator.expectMessageAmount(1);
830 doDelete("/api/widgetsBundle/" + savedWidgetsBundle.getId().getId().toString()) 926 doDelete("/api/widgetsBundle/" + savedWidgetsBundle.getId().getId().toString())
831 .andExpect(status().isOk()); 927 .andExpect(status().isOk());
832 - edgeImitator.waitForMessages();  
833 - 928 + Assert.assertTrue(edgeImitator.waitForMessages());
834 latestMessage = edgeImitator.getLatestMessage(); 929 latestMessage = edgeImitator.getLatestMessage();
835 Assert.assertTrue(latestMessage instanceof WidgetsBundleUpdateMsg); 930 Assert.assertTrue(latestMessage instanceof WidgetsBundleUpdateMsg);
836 widgetsBundleUpdateMsg = (WidgetsBundleUpdateMsg) latestMessage; 931 widgetsBundleUpdateMsg = (WidgetsBundleUpdateMsg) latestMessage;
@@ -843,15 +938,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -843,15 +938,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
843 938
844 private void testTimeseries() throws Exception { 939 private void testTimeseries() throws Exception {
845 log.info("Testing timeseries"); 940 log.info("Testing timeseries");
846 - Device device = findDeviceByName("Edge Device 1");  
847 941
  942 + edgeImitator.expectMessageAmount(1);
  943 + Device device = findDeviceByName("Edge Device 1");
848 String timeseriesData = "{\"data\":{\"temperature\":25},\"ts\":" + System.currentTimeMillis() + "}"; 944 String timeseriesData = "{\"data\":{\"temperature\":25},\"ts\":" + System.currentTimeMillis() + "}";
849 JsonNode timeseriesEntityData = mapper.readTree(timeseriesData); 945 JsonNode timeseriesEntityData = mapper.readTree(timeseriesData);
850 - EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.TIMESERIES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData);  
851 - edgeImitator.expectMessageAmount(1);  
852 - edgeEventService.saveAsync(edgeEvent1); 946 + EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.TIMESERIES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData);
  947 + edgeEventService.saveAsync(edgeEvent);
853 clusterService.onEdgeEventUpdate(tenantId, edge.getId()); 948 clusterService.onEdgeEventUpdate(tenantId, edge.getId());
854 - edgeImitator.waitForMessages(); 949 + Assert.assertTrue(edgeImitator.waitForMessages());
855 950
856 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 951 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
857 Assert.assertTrue(latestMessage instanceof EntityDataProto); 952 Assert.assertTrue(latestMessage instanceof EntityDataProto);
@@ -890,7 +985,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -890,7 +985,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
890 edgeImitator.expectMessageAmount(1); 985 edgeImitator.expectMessageAmount(1);
891 edgeEventService.saveAsync(edgeEvent); 986 edgeEventService.saveAsync(edgeEvent);
892 clusterService.onEdgeEventUpdate(tenantId, edge.getId()); 987 clusterService.onEdgeEventUpdate(tenantId, edge.getId());
893 - edgeImitator.waitForMessages(); 988 + Assert.assertTrue(edgeImitator.waitForMessages());
894 989
895 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 990 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
896 Assert.assertTrue(latestMessage instanceof EntityDataProto); 991 Assert.assertTrue(latestMessage instanceof EntityDataProto);
@@ -916,7 +1011,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -916,7 +1011,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
916 edgeImitator.expectMessageAmount(1); 1011 edgeImitator.expectMessageAmount(1);
917 edgeEventService.saveAsync(edgeEvent); 1012 edgeEventService.saveAsync(edgeEvent);
918 clusterService.onEdgeEventUpdate(tenantId, edge.getId()); 1013 clusterService.onEdgeEventUpdate(tenantId, edge.getId());
919 - edgeImitator.waitForMessages(); 1014 + Assert.assertTrue(edgeImitator.waitForMessages());
920 1015
921 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1016 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
922 Assert.assertTrue(latestMessage instanceof EntityDataProto); 1017 Assert.assertTrue(latestMessage instanceof EntityDataProto);
@@ -941,7 +1036,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -941,7 +1036,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
941 edgeImitator.expectMessageAmount(1); 1036 edgeImitator.expectMessageAmount(1);
942 edgeEventService.saveAsync(edgeEvent1); 1037 edgeEventService.saveAsync(edgeEvent1);
943 clusterService.onEdgeEventUpdate(tenantId, edge.getId()); 1038 clusterService.onEdgeEventUpdate(tenantId, edge.getId());
944 - edgeImitator.waitForMessages(); 1039 + Assert.assertTrue(edgeImitator.waitForMessages());
945 1040
946 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1041 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
947 Assert.assertTrue(latestMessage instanceof EntityDataProto); 1042 Assert.assertTrue(latestMessage instanceof EntityDataProto);
@@ -996,8 +1091,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -996,8 +1091,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
996 1091
997 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1092 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
998 1093
999 - edgeImitator.waitForResponses();  
1000 - edgeImitator.waitForMessages(); 1094 + Assert.assertTrue(edgeImitator.waitForResponses());
  1095 + Assert.assertTrue(edgeImitator.waitForMessages());
1001 1096
1002 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1097 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
1003 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); 1098 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
@@ -1013,7 +1108,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1013,7 +1108,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1013 1108
1014 private void sendDeviceWithNameThatAlreadyExistsOnCloud() throws Exception { 1109 private void sendDeviceWithNameThatAlreadyExistsOnCloud() throws Exception {
1015 String deviceOnCloudName = RandomStringUtils.randomAlphanumeric(15); 1110 String deviceOnCloudName = RandomStringUtils.randomAlphanumeric(15);
1016 - Device deviceOnCloud = saveDevice(deviceOnCloudName); 1111 + Device deviceOnCloud = saveDevice(deviceOnCloudName, "Default");
1017 1112
1018 UUID uuid = Uuids.timeBased(); 1113 UUID uuid = Uuids.timeBased();
1019 1114
@@ -1033,8 +1128,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1033,8 +1128,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1033 1128
1034 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1129 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1035 1130
1036 - edgeImitator.waitForResponses();  
1037 - edgeImitator.waitForMessages(); 1131 + Assert.assertTrue(edgeImitator.waitForResponses());
  1132 + Assert.assertTrue(edgeImitator.waitForMessages());
1038 1133
1039 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1134 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
1040 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); 1135 Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
@@ -1063,7 +1158,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1063,7 +1158,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1063 1158
1064 edgeImitator.expectMessageAmount(1); 1159 edgeImitator.expectMessageAmount(1);
1065 doPost("/api/relation", relation); 1160 doPost("/api/relation", relation);
1066 - edgeImitator.waitForMessages(); 1161 + Assert.assertTrue(edgeImitator.waitForMessages());
1067 1162
1068 UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder(); 1163 UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
1069 RelationRequestMsg.Builder relationRequestMsgBuilder = RelationRequestMsg.newBuilder(); 1164 RelationRequestMsg.Builder relationRequestMsgBuilder = RelationRequestMsg.newBuilder();
@@ -1078,8 +1173,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1078,8 +1173,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1078 edgeImitator.expectResponsesAmount(1); 1173 edgeImitator.expectResponsesAmount(1);
1079 edgeImitator.expectMessageAmount(1); 1174 edgeImitator.expectMessageAmount(1);
1080 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1175 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1081 - edgeImitator.waitForResponses();  
1082 - edgeImitator.waitForMessages(); 1176 + Assert.assertTrue(edgeImitator.waitForResponses());
  1177 + Assert.assertTrue(edgeImitator.waitForMessages());
1083 1178
1084 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1179 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
1085 Assert.assertTrue(latestMessage instanceof RelationUpdateMsg); 1180 Assert.assertTrue(latestMessage instanceof RelationUpdateMsg);
@@ -1115,7 +1210,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1115,7 +1210,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1115 1210
1116 edgeImitator.expectResponsesAmount(1); 1211 edgeImitator.expectResponsesAmount(1);
1117 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1212 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1118 - edgeImitator.waitForResponses(); 1213 + Assert.assertTrue(edgeImitator.waitForResponses());
1119 1214
1120 1215
1121 List<AlarmInfo> alarms = doGetTypedWithPageLink("/api/alarm/{entityType}/{entityId}?", 1216 List<AlarmInfo> alarms = doGetTypedWithPageLink("/api/alarm/{entityType}/{entityId}?",
@@ -1158,7 +1253,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1158,7 +1253,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1158 1253
1159 edgeImitator.expectResponsesAmount(1); 1254 edgeImitator.expectResponsesAmount(1);
1160 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1255 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1161 - edgeImitator.waitForResponses(); 1256 + Assert.assertTrue(edgeImitator.waitForResponses());
1162 1257
1163 EntityRelation relation = doGet("/api/relation?" + 1258 EntityRelation relation = doGet("/api/relation?" +
1164 "&fromId=" + device2.getId().getId().toString() + 1259 "&fromId=" + device2.getId().getId().toString() +
@@ -1212,7 +1307,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1212,7 +1307,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1212 testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder2); 1307 testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder2);
1213 1308
1214 edgeImitator.sendUplinkMsg(uplinkMsgBuilder2.build()); 1309 edgeImitator.sendUplinkMsg(uplinkMsgBuilder2.build());
1215 - edgeImitator.waitForResponses(); 1310 + Assert.assertTrue(edgeImitator.waitForResponses());
1216 1311
1217 // Wait before device attributes saved to database before requesting them from controller 1312 // Wait before device attributes saved to database before requesting them from controller
1218 Thread.sleep(1000); 1313 Thread.sleep(1000);
@@ -1243,8 +1338,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1243,8 +1338,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1243 edgeImitator.expectResponsesAmount(1); 1338 edgeImitator.expectResponsesAmount(1);
1244 edgeImitator.expectMessageAmount(1); 1339 edgeImitator.expectMessageAmount(1);
1245 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1340 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1246 - edgeImitator.waitForResponses();  
1247 - edgeImitator.waitForMessages(); 1341 + Assert.assertTrue(edgeImitator.waitForResponses());
  1342 + Assert.assertTrue(edgeImitator.waitForMessages());;
1248 1343
1249 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1344 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
1250 Assert.assertTrue(latestMessage instanceof RuleChainMetadataUpdateMsg); 1345 Assert.assertTrue(latestMessage instanceof RuleChainMetadataUpdateMsg);
@@ -1270,8 +1365,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1270,8 +1365,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1270 edgeImitator.expectResponsesAmount(1); 1365 edgeImitator.expectResponsesAmount(1);
1271 edgeImitator.expectMessageAmount(1); 1366 edgeImitator.expectMessageAmount(1);
1272 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1367 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1273 - edgeImitator.waitForResponses();  
1274 - edgeImitator.waitForMessages(); 1368 + Assert.assertTrue(edgeImitator.waitForResponses());
  1369 + Assert.assertTrue(edgeImitator.waitForMessages());
1275 1370
1276 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1371 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
1277 Assert.assertTrue(latestMessage instanceof UserCredentialsUpdateMsg); 1372 Assert.assertTrue(latestMessage instanceof UserCredentialsUpdateMsg);
@@ -1299,8 +1394,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1299,8 +1394,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1299 edgeImitator.expectResponsesAmount(1); 1394 edgeImitator.expectResponsesAmount(1);
1300 edgeImitator.expectMessageAmount(1); 1395 edgeImitator.expectMessageAmount(1);
1301 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1396 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1302 - edgeImitator.waitForResponses();  
1303 - edgeImitator.waitForMessages(); 1397 + Assert.assertTrue(edgeImitator.waitForResponses());
  1398 + Assert.assertTrue(edgeImitator.waitForMessages());
1304 1399
1305 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1400 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
1306 Assert.assertTrue(latestMessage instanceof DeviceCredentialsUpdateMsg); 1401 Assert.assertTrue(latestMessage instanceof DeviceCredentialsUpdateMsg);
@@ -1327,7 +1422,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1327,7 +1422,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1327 1422
1328 edgeImitator.expectResponsesAmount(1); 1423 edgeImitator.expectResponsesAmount(1);
1329 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1424 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1330 - edgeImitator.waitForResponses(); 1425 + Assert.assertTrue(edgeImitator.waitForResponses());
1331 } 1426 }
1332 1427
1333 private void sendDeviceRpcResponse() throws Exception { 1428 private void sendDeviceRpcResponse() throws Exception {
@@ -1352,7 +1447,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1352,7 +1447,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1352 1447
1353 edgeImitator.expectResponsesAmount(1); 1448 edgeImitator.expectResponsesAmount(1);
1354 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1449 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1355 - edgeImitator.waitForResponses(); 1450 + Assert.assertTrue(edgeImitator.waitForResponses());
1356 } 1451 }
1357 1452
1358 private void sendAttributesRequest() throws Exception { 1453 private void sendAttributesRequest() throws Exception {
@@ -1383,8 +1478,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1383,8 +1478,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1383 edgeImitator.expectResponsesAmount(1); 1478 edgeImitator.expectResponsesAmount(1);
1384 edgeImitator.expectMessageAmount(1); 1479 edgeImitator.expectMessageAmount(1);
1385 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); 1480 edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build());
1386 - edgeImitator.waitForResponses();  
1387 - edgeImitator.waitForMessages(); 1481 + Assert.assertTrue(edgeImitator.waitForResponses());
  1482 + Assert.assertTrue(edgeImitator.waitForMessages());
1388 1483
1389 AbstractMessage latestMessage = edgeImitator.getLatestMessage(); 1484 AbstractMessage latestMessage = edgeImitator.getLatestMessage();
1390 Assert.assertTrue(latestMessage instanceof EntityDataProto); 1485 Assert.assertTrue(latestMessage instanceof EntityDataProto);
@@ -1416,7 +1511,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1416,7 +1511,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1416 1511
1417 edgeImitator.expectResponsesAmount(1); 1512 edgeImitator.expectResponsesAmount(1);
1418 edgeImitator.sendUplinkMsg(upLinkMsgBuilder.build()); 1513 edgeImitator.sendUplinkMsg(upLinkMsgBuilder.build());
1419 - edgeImitator.waitForResponses(); 1514 + Assert.assertTrue(edgeImitator.waitForResponses());
1420 device = doGet("/api/device/" + device.getId().getId().toString(), Device.class); 1515 device = doGet("/api/device/" + device.getId().getId().toString(), Device.class);
1421 Assert.assertNotNull(device); 1516 Assert.assertNotNull(device);
1422 List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?", 1517 List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?",
@@ -1428,7 +1523,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1428,7 +1523,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1428 private void installation() throws Exception { 1523 private void installation() throws Exception {
1429 edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); 1524 edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class);
1430 1525
1431 - Device savedDevice = saveDevice("Edge Device 1"); 1526 + DeviceProfile deviceProfile = this.createDeviceProfile(CUSTOM_DEVICE_PROFILE_NAME, null);
  1527 + extendDeviceProfileData(deviceProfile);
  1528 + doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
  1529 +
  1530 + Device savedDevice = saveDevice("Edge Device 1", CUSTOM_DEVICE_PROFILE_NAME);
1432 doPost("/api/edge/" + edge.getId().getId().toString() 1531 doPost("/api/edge/" + edge.getId().getId().toString()
1433 + "/device/" + savedDevice.getId().getId().toString(), Device.class); 1532 + "/device/" + savedDevice.getId().getId().toString(), Device.class);
1434 1533
@@ -1437,6 +1536,35 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { @@ -1437,6 +1536,35 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
1437 + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); 1536 + "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
1438 } 1537 }
1439 1538
  1539 + private void extendDeviceProfileData(DeviceProfile deviceProfile) {
  1540 + DeviceProfileData profileData = deviceProfile.getProfileData();
  1541 + List<DeviceProfileAlarm> alarms = new ArrayList<>();
  1542 + DeviceProfileAlarm deviceProfileAlarm = new DeviceProfileAlarm();
  1543 + deviceProfileAlarm.setAlarmType("High Temperature");
  1544 + AlarmRule alarmRule = new AlarmRule();
  1545 + alarmRule.setAlarmDetails("Alarm Details");
  1546 + AlarmCondition alarmCondition = new AlarmCondition();
  1547 + alarmCondition.setSpec(new SimpleAlarmConditionSpec());
  1548 + List<AlarmConditionFilter> condition = new ArrayList<>();
  1549 + AlarmConditionFilter alarmConditionFilter = new AlarmConditionFilter();
  1550 + alarmConditionFilter.setKey(new AlarmConditionFilterKey(AlarmConditionKeyType.ATTRIBUTE, "temperature"));
  1551 + NumericFilterPredicate predicate = new NumericFilterPredicate();
  1552 + predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER);
  1553 + predicate.setValue(new FilterPredicateValue<>(55.0));
  1554 + alarmConditionFilter.setPredicate(predicate);
  1555 + alarmConditionFilter.setValueType(EntityKeyValueType.NUMERIC);
  1556 + condition.add(alarmConditionFilter);
  1557 + alarmCondition.setCondition(condition);
  1558 + alarmRule.setCondition(alarmCondition);
  1559 + deviceProfileAlarm.setClearRule(alarmRule);
  1560 + TreeMap<AlarmSeverity, AlarmRule> createRules = new TreeMap<>();
  1561 + createRules.put(AlarmSeverity.CRITICAL, alarmRule);
  1562 + deviceProfileAlarm.setCreateRules(createRules);
  1563 + alarms.add(deviceProfileAlarm);
  1564 + profileData.setAlarms(alarms);
  1565 + profileData.setProvisionConfiguration(new AllowCreateNewDevicesDeviceProfileProvisionConfiguration("123"));
  1566 + }
  1567 +
1440 private EdgeEvent constructEdgeEvent(TenantId tenantId, EdgeId edgeId, EdgeEventActionType edgeEventAction, UUID entityId, EdgeEventType edgeEventType, JsonNode entityBody) { 1568 private EdgeEvent constructEdgeEvent(TenantId tenantId, EdgeId edgeId, EdgeEventActionType edgeEventAction, UUID entityId, EdgeEventType edgeEventType, JsonNode entityBody) {
1441 EdgeEvent edgeEvent = new EdgeEvent(); 1569 EdgeEvent edgeEvent = new EdgeEvent();
1442 edgeEvent.setEdgeId(edgeId); 1570 edgeEvent.setEdgeId(edgeId);
@@ -32,6 +32,7 @@ import org.thingsboard.server.gen.edge.CustomerUpdateMsg; @@ -32,6 +32,7 @@ import org.thingsboard.server.gen.edge.CustomerUpdateMsg;
32 import org.thingsboard.server.gen.edge.DashboardUpdateMsg; 32 import org.thingsboard.server.gen.edge.DashboardUpdateMsg;
33 import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg; 33 import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg;
34 import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg; 34 import org.thingsboard.server.gen.edge.DeviceCredentialsUpdateMsg;
  35 +import org.thingsboard.server.gen.edge.DeviceProfileUpdateMsg;
35 import org.thingsboard.server.gen.edge.DeviceRpcCallMsg; 36 import org.thingsboard.server.gen.edge.DeviceRpcCallMsg;
36 import org.thingsboard.server.gen.edge.DeviceUpdateMsg; 37 import org.thingsboard.server.gen.edge.DeviceUpdateMsg;
37 import org.thingsboard.server.gen.edge.DownlinkMsg; 38 import org.thingsboard.server.gen.edge.DownlinkMsg;
@@ -58,6 +59,7 @@ import java.util.concurrent.CountDownLatch; @@ -58,6 +59,7 @@ import java.util.concurrent.CountDownLatch;
58 import java.util.concurrent.TimeUnit; 59 import java.util.concurrent.TimeUnit;
59 import java.util.concurrent.locks.Lock; 60 import java.util.concurrent.locks.Lock;
60 import java.util.concurrent.locks.ReentrantLock; 61 import java.util.concurrent.locks.ReentrantLock;
  62 +import java.util.stream.Collectors;
61 63
62 @Slf4j 64 @Slf4j
63 public class EdgeImitator { 65 public class EdgeImitator {
@@ -154,88 +156,93 @@ public class EdgeImitator { @@ -154,88 +156,93 @@ public class EdgeImitator {
154 156
155 private ListenableFuture<List<Void>> processDownlinkMsg(DownlinkMsg downlinkMsg) { 157 private ListenableFuture<List<Void>> processDownlinkMsg(DownlinkMsg downlinkMsg) {
156 List<ListenableFuture<Void>> result = new ArrayList<>(); 158 List<ListenableFuture<Void>> result = new ArrayList<>();
157 - if (downlinkMsg.getDeviceUpdateMsgList() != null && !downlinkMsg.getDeviceUpdateMsgList().isEmpty()) { 159 + if (downlinkMsg.getDeviceUpdateMsgCount() > 0) {
158 for (DeviceUpdateMsg deviceUpdateMsg: downlinkMsg.getDeviceUpdateMsgList()) { 160 for (DeviceUpdateMsg deviceUpdateMsg: downlinkMsg.getDeviceUpdateMsgList()) {
159 result.add(saveDownlinkMsg(deviceUpdateMsg)); 161 result.add(saveDownlinkMsg(deviceUpdateMsg));
160 } 162 }
161 } 163 }
162 - if (downlinkMsg.getDeviceCredentialsUpdateMsgList() != null && !downlinkMsg.getDeviceCredentialsUpdateMsgList().isEmpty()) { 164 + if (downlinkMsg.getDeviceProfileUpdateMsgCount() > 0) {
  165 + for (DeviceProfileUpdateMsg deviceProfileUpdateMsg : downlinkMsg.getDeviceProfileUpdateMsgList()) {
  166 + result.add(saveDownlinkMsg(deviceProfileUpdateMsg));
  167 + }
  168 + }
  169 + if (downlinkMsg.getDeviceCredentialsUpdateMsgCount() > 0) {
163 for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg: downlinkMsg.getDeviceCredentialsUpdateMsgList()) { 170 for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg: downlinkMsg.getDeviceCredentialsUpdateMsgList()) {
164 result.add(saveDownlinkMsg(deviceCredentialsUpdateMsg)); 171 result.add(saveDownlinkMsg(deviceCredentialsUpdateMsg));
165 } 172 }
166 } 173 }
167 - if (downlinkMsg.getAssetUpdateMsgList() != null && !downlinkMsg.getAssetUpdateMsgList().isEmpty()) { 174 + if (downlinkMsg.getAssetUpdateMsgCount() > 0) {
168 for (AssetUpdateMsg assetUpdateMsg: downlinkMsg.getAssetUpdateMsgList()) { 175 for (AssetUpdateMsg assetUpdateMsg: downlinkMsg.getAssetUpdateMsgList()) {
169 result.add(saveDownlinkMsg(assetUpdateMsg)); 176 result.add(saveDownlinkMsg(assetUpdateMsg));
170 } 177 }
171 } 178 }
172 - if (downlinkMsg.getRuleChainUpdateMsgList() != null && !downlinkMsg.getRuleChainUpdateMsgList().isEmpty()) { 179 + if (downlinkMsg.getRuleChainUpdateMsgCount() > 0) {
173 for (RuleChainUpdateMsg ruleChainUpdateMsg: downlinkMsg.getRuleChainUpdateMsgList()) { 180 for (RuleChainUpdateMsg ruleChainUpdateMsg: downlinkMsg.getRuleChainUpdateMsgList()) {
174 result.add(saveDownlinkMsg(ruleChainUpdateMsg)); 181 result.add(saveDownlinkMsg(ruleChainUpdateMsg));
175 } 182 }
176 } 183 }
177 - if (downlinkMsg.getRuleChainMetadataUpdateMsgList() != null && !downlinkMsg.getRuleChainMetadataUpdateMsgList().isEmpty()) { 184 + if (downlinkMsg.getRuleChainMetadataUpdateMsgCount() > 0) {
178 for (RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg: downlinkMsg.getRuleChainMetadataUpdateMsgList()) { 185 for (RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg: downlinkMsg.getRuleChainMetadataUpdateMsgList()) {
179 result.add(saveDownlinkMsg(ruleChainMetadataUpdateMsg)); 186 result.add(saveDownlinkMsg(ruleChainMetadataUpdateMsg));
180 } 187 }
181 } 188 }
182 - if (downlinkMsg.getDashboardUpdateMsgList() != null && !downlinkMsg.getDashboardUpdateMsgList().isEmpty()) { 189 + if (downlinkMsg.getDashboardUpdateMsgCount() > 0) {
183 for (DashboardUpdateMsg dashboardUpdateMsg: downlinkMsg.getDashboardUpdateMsgList()) { 190 for (DashboardUpdateMsg dashboardUpdateMsg: downlinkMsg.getDashboardUpdateMsgList()) {
184 result.add(saveDownlinkMsg(dashboardUpdateMsg)); 191 result.add(saveDownlinkMsg(dashboardUpdateMsg));
185 } 192 }
186 } 193 }
187 - if (downlinkMsg.getRelationUpdateMsgList() != null && !downlinkMsg.getRelationUpdateMsgList().isEmpty()) { 194 + if (downlinkMsg.getRelationUpdateMsgCount() > 0) {
188 for (RelationUpdateMsg relationUpdateMsg: downlinkMsg.getRelationUpdateMsgList()) { 195 for (RelationUpdateMsg relationUpdateMsg: downlinkMsg.getRelationUpdateMsgList()) {
189 result.add(saveDownlinkMsg(relationUpdateMsg)); 196 result.add(saveDownlinkMsg(relationUpdateMsg));
190 } 197 }
191 } 198 }
192 - if (downlinkMsg.getAlarmUpdateMsgList() != null && !downlinkMsg.getAlarmUpdateMsgList().isEmpty()) { 199 + if (downlinkMsg.getAlarmUpdateMsgCount() > 0) {
193 for (AlarmUpdateMsg alarmUpdateMsg: downlinkMsg.getAlarmUpdateMsgList()) { 200 for (AlarmUpdateMsg alarmUpdateMsg: downlinkMsg.getAlarmUpdateMsgList()) {
194 result.add(saveDownlinkMsg(alarmUpdateMsg)); 201 result.add(saveDownlinkMsg(alarmUpdateMsg));
195 } 202 }
196 } 203 }
197 - if (downlinkMsg.getEntityDataList() != null && !downlinkMsg.getEntityDataList().isEmpty()) { 204 + if (downlinkMsg.getEntityDataCount() > 0) {
198 for (EntityDataProto entityData: downlinkMsg.getEntityDataList()) { 205 for (EntityDataProto entityData: downlinkMsg.getEntityDataList()) {
199 result.add(saveDownlinkMsg(entityData)); 206 result.add(saveDownlinkMsg(entityData));
200 } 207 }
201 } 208 }
202 - if (downlinkMsg.getEntityViewUpdateMsgList() != null && !downlinkMsg.getEntityViewUpdateMsgList().isEmpty()) { 209 + if (downlinkMsg.getEntityViewUpdateMsgCount() > 0) {
203 for (EntityViewUpdateMsg entityViewUpdateMsg: downlinkMsg.getEntityViewUpdateMsgList()) { 210 for (EntityViewUpdateMsg entityViewUpdateMsg: downlinkMsg.getEntityViewUpdateMsgList()) {
204 result.add(saveDownlinkMsg(entityViewUpdateMsg)); 211 result.add(saveDownlinkMsg(entityViewUpdateMsg));
205 } 212 }
206 } 213 }
207 - if (downlinkMsg.getCustomerUpdateMsgList() != null && !downlinkMsg.getCustomerUpdateMsgList().isEmpty()) { 214 + if (downlinkMsg.getCustomerUpdateMsgCount() > 0) {
208 for (CustomerUpdateMsg customerUpdateMsg: downlinkMsg.getCustomerUpdateMsgList()) { 215 for (CustomerUpdateMsg customerUpdateMsg: downlinkMsg.getCustomerUpdateMsgList()) {
209 result.add(saveDownlinkMsg(customerUpdateMsg)); 216 result.add(saveDownlinkMsg(customerUpdateMsg));
210 } 217 }
211 } 218 }
212 - if (downlinkMsg.getWidgetsBundleUpdateMsgList() != null && !downlinkMsg.getWidgetsBundleUpdateMsgList().isEmpty()) { 219 + if (downlinkMsg.getWidgetsBundleUpdateMsgCount() > 0) {
213 for (WidgetsBundleUpdateMsg widgetsBundleUpdateMsg: downlinkMsg.getWidgetsBundleUpdateMsgList()) { 220 for (WidgetsBundleUpdateMsg widgetsBundleUpdateMsg: downlinkMsg.getWidgetsBundleUpdateMsgList()) {
214 result.add(saveDownlinkMsg(widgetsBundleUpdateMsg)); 221 result.add(saveDownlinkMsg(widgetsBundleUpdateMsg));
215 } 222 }
216 } 223 }
217 - if (downlinkMsg.getWidgetTypeUpdateMsgList() != null && !downlinkMsg.getWidgetTypeUpdateMsgList().isEmpty()) { 224 + if (downlinkMsg.getWidgetTypeUpdateMsgCount() > 0) {
218 for (WidgetTypeUpdateMsg widgetTypeUpdateMsg: downlinkMsg.getWidgetTypeUpdateMsgList()) { 225 for (WidgetTypeUpdateMsg widgetTypeUpdateMsg: downlinkMsg.getWidgetTypeUpdateMsgList()) {
219 result.add(saveDownlinkMsg(widgetTypeUpdateMsg)); 226 result.add(saveDownlinkMsg(widgetTypeUpdateMsg));
220 } 227 }
221 } 228 }
222 - if (downlinkMsg.getUserUpdateMsgList() != null && !downlinkMsg.getUserUpdateMsgList().isEmpty()) { 229 + if (downlinkMsg.getUserUpdateMsgCount() > 0) {
223 for (UserUpdateMsg userUpdateMsg: downlinkMsg.getUserUpdateMsgList()) { 230 for (UserUpdateMsg userUpdateMsg: downlinkMsg.getUserUpdateMsgList()) {
224 onUserUpdate(userUpdateMsg); 231 onUserUpdate(userUpdateMsg);
225 result.add(saveDownlinkMsg(userUpdateMsg)); 232 result.add(saveDownlinkMsg(userUpdateMsg));
226 } 233 }
227 } 234 }
228 - if (downlinkMsg.getUserCredentialsUpdateMsgList() != null && !downlinkMsg.getUserCredentialsUpdateMsgList().isEmpty()) { 235 + if (downlinkMsg.getUserCredentialsUpdateMsgCount() > 0) {
229 for (UserCredentialsUpdateMsg userCredentialsUpdateMsg: downlinkMsg.getUserCredentialsUpdateMsgList()) { 236 for (UserCredentialsUpdateMsg userCredentialsUpdateMsg: downlinkMsg.getUserCredentialsUpdateMsgList()) {
230 result.add(saveDownlinkMsg(userCredentialsUpdateMsg)); 237 result.add(saveDownlinkMsg(userCredentialsUpdateMsg));
231 } 238 }
232 } 239 }
233 - if (downlinkMsg.getDeviceRpcCallMsgList() != null && !downlinkMsg.getDeviceRpcCallMsgList().isEmpty()) { 240 + if (downlinkMsg.getDeviceRpcCallMsgCount() > 0) {
234 for (DeviceRpcCallMsg deviceRpcCallMsg: downlinkMsg.getDeviceRpcCallMsgList()) { 241 for (DeviceRpcCallMsg deviceRpcCallMsg: downlinkMsg.getDeviceRpcCallMsgList()) {
235 result.add(saveDownlinkMsg(deviceRpcCallMsg)); 242 result.add(saveDownlinkMsg(deviceRpcCallMsg));
236 } 243 }
237 } 244 }
238 - if (downlinkMsg.getDeviceCredentialsRequestMsgList() != null && !downlinkMsg.getDeviceCredentialsRequestMsgList().isEmpty()) { 245 + if (downlinkMsg.getDeviceCredentialsRequestMsgCount() > 0) {
239 for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg: downlinkMsg.getDeviceCredentialsRequestMsgList()) { 246 for (DeviceCredentialsRequestMsg deviceCredentialsRequestMsg: downlinkMsg.getDeviceCredentialsRequestMsgList()) {
240 result.add(saveDownlinkMsg(deviceCredentialsRequestMsg)); 247 result.add(saveDownlinkMsg(deviceCredentialsRequestMsg));
241 } 248 }
@@ -256,21 +263,28 @@ public class EdgeImitator { @@ -256,21 +263,28 @@ public class EdgeImitator {
256 return Futures.immediateFuture(null); 263 return Futures.immediateFuture(null);
257 } 264 }
258 265
259 - public void waitForMessages() throws InterruptedException {  
260 - messagesLatch.await(5, TimeUnit.SECONDS); 266 + public boolean waitForMessages() throws InterruptedException {
  267 + return waitForMessages(5);
  268 + }
  269 +
  270 + public boolean waitForMessages(int timeout) throws InterruptedException {
  271 + return messagesLatch.await(timeout, TimeUnit.SECONDS);
261 } 272 }
262 273
263 public void expectMessageAmount(int messageAmount) { 274 public void expectMessageAmount(int messageAmount) {
264 messagesLatch = new CountDownLatch(messageAmount); 275 messagesLatch = new CountDownLatch(messageAmount);
265 } 276 }
266 277
267 - public void waitForResponses() throws InterruptedException { responsesLatch.await(5, TimeUnit.SECONDS); } 278 + public boolean waitForResponses() throws InterruptedException {
  279 + return responsesLatch.await(5, TimeUnit.SECONDS);
  280 + }
268 281
269 public void expectResponsesAmount(int messageAmount) { 282 public void expectResponsesAmount(int messageAmount) {
270 responsesLatch = new CountDownLatch(messageAmount); 283 responsesLatch = new CountDownLatch(messageAmount);
271 } 284 }
272 285
273 - public <T> Optional<T> findMessageByType(Class<T> tClass) { 286 + @SuppressWarnings("unchecked")
  287 + public <T extends AbstractMessage> Optional<T> findMessageByType(Class<T> tClass) {
274 Optional<T> result; 288 Optional<T> result;
275 try { 289 try {
276 lock.lock(); 290 lock.lock();
@@ -281,6 +295,18 @@ public class EdgeImitator { @@ -281,6 +295,18 @@ public class EdgeImitator {
281 return result; 295 return result;
282 } 296 }
283 297
  298 + @SuppressWarnings("unchecked")
  299 + public <T extends AbstractMessage> List<T> findAllMessagesByType(Class<T> tClass) {
  300 + List<T> result;
  301 + try {
  302 + lock.lock();
  303 + result = (List<T>) downlinkMsgs.stream().filter(downlinkMsg -> downlinkMsg.getClass().isAssignableFrom(tClass)).collect(Collectors.toList());
  304 + } finally {
  305 + lock.unlock();
  306 + }
  307 + return result;
  308 + }
  309 +
284 public AbstractMessage getLatestMessage() { 310 public AbstractMessage getLatestMessage() {
285 return downlinkMsgs.get(downlinkMsgs.size() - 1); 311 return downlinkMsgs.get(downlinkMsgs.size() - 1);
286 } 312 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.service;
  17 +
  18 +import org.junit.BeforeClass;
  19 +import org.junit.ClassRule;
  20 +import org.junit.extensions.cpsuite.ClasspathSuite;
  21 +import org.junit.runner.RunWith;
  22 +import org.thingsboard.server.dao.CustomSqlUnit;
  23 +import org.thingsboard.server.queue.memory.InMemoryStorage;
  24 +
  25 +import java.util.Arrays;
  26 +
  27 +@RunWith(ClasspathSuite.class)
  28 +@ClasspathSuite.ClassnameFilters({
  29 + "org.thingsboard.server.service.resource.*Test",
  30 + })
  31 +public class ServiceSqlTestSuite {
  32 +
  33 + @ClassRule
  34 + public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
  35 + Arrays.asList("sql/schema-types-hsql.sql", "sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql"),
  36 + "sql/hsql/drop-all-tables.sql",
  37 + "sql-test.properties");
  38 +
  39 + @BeforeClass
  40 + public static void cleanupInMemStorage(){
  41 + InMemoryStorage.getInstance().cleanup();
  42 + }
  43 +}
application/src/test/java/org/thingsboard/server/service/resource/BaseTbResourceServiceTest.java renamed from dao/src/test/java/org/thingsboard/server/dao/service/BaseTbResourceServiceTest.java
@@ -13,28 +13,37 @@ @@ -13,28 +13,37 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.service; 16 +package org.thingsboard.server.service.resource;
17 17
18 import com.datastax.oss.driver.api.core.uuid.Uuids; 18 import com.datastax.oss.driver.api.core.uuid.Uuids;
19 import org.junit.After; 19 import org.junit.After;
20 import org.junit.Assert; 20 import org.junit.Assert;
21 import org.junit.Before; 21 import org.junit.Before;
22 import org.junit.Test; 22 import org.junit.Test;
  23 +import org.springframework.beans.factory.annotation.Autowired;
23 import org.thingsboard.server.common.data.ResourceType; 24 import org.thingsboard.server.common.data.ResourceType;
24 import org.thingsboard.server.common.data.TbResource; 25 import org.thingsboard.server.common.data.TbResource;
25 import org.thingsboard.server.common.data.TbResourceInfo; 26 import org.thingsboard.server.common.data.TbResourceInfo;
26 import org.thingsboard.server.common.data.Tenant; 27 import org.thingsboard.server.common.data.Tenant;
  28 +import org.thingsboard.server.common.data.User;
27 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
28 import org.thingsboard.server.common.data.page.PageData; 30 import org.thingsboard.server.common.data.page.PageData;
29 import org.thingsboard.server.common.data.page.PageLink; 31 import org.thingsboard.server.common.data.page.PageLink;
  32 +import org.thingsboard.server.common.data.security.Authority;
  33 +import org.thingsboard.server.controller.AbstractControllerTest;
30 import org.thingsboard.server.dao.exception.DataValidationException; 34 import org.thingsboard.server.dao.exception.DataValidationException;
  35 +import org.thingsboard.server.dao.service.AbstractServiceTest;
  36 +import org.thingsboard.server.dao.service.DaoSqlTest;
31 37
32 import java.util.ArrayList; 38 import java.util.ArrayList;
33 import java.util.Base64; 39 import java.util.Base64;
34 import java.util.Collections; 40 import java.util.Collections;
35 import java.util.List; 41 import java.util.List;
36 42
37 -public abstract class BaseTbResourceServiceTest extends AbstractServiceTest { 43 +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  44 +
  45 +@DaoSqlTest
  46 +public class BaseTbResourceServiceTest extends AbstractControllerTest {
38 47
39 private static final String LWM2M_TEST_MODEL = "<LWM2M xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://www.openmobilealliance.org/tech/profiles/LWM2M-v1_1.xsd\">\n" + 48 private static final String LWM2M_TEST_MODEL = "<LWM2M xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://www.openmobilealliance.org/tech/profiles/LWM2M-v1_1.xsd\">\n" +
40 "<Object ObjectType=\"MODefinition\">\n" + 49 "<Object ObjectType=\"MODefinition\">\n" +
@@ -67,18 +76,38 @@ public abstract class BaseTbResourceServiceTest extends AbstractServiceTest { @@ -67,18 +76,38 @@ public abstract class BaseTbResourceServiceTest extends AbstractServiceTest {
67 76
68 private TenantId tenantId; 77 private TenantId tenantId;
69 78
  79 + @Autowired
  80 + private TbResourceService resourceService;
  81 +
  82 + private Tenant savedTenant;
  83 + private User tenantAdmin;
  84 +
70 @Before 85 @Before
71 - public void before() { 86 + public void beforeTest() throws Exception {
  87 + loginSysAdmin();
  88 +
72 Tenant tenant = new Tenant(); 89 Tenant tenant = new Tenant();
73 tenant.setTitle("My tenant"); 90 tenant.setTitle("My tenant");
74 - Tenant savedTenant = tenantService.saveTenant(tenant);  
75 - Assert.assertNotNull(savedTenant); 91 + savedTenant = doPost("/api/tenant", tenant, Tenant.class);
76 tenantId = savedTenant.getId(); 92 tenantId = savedTenant.getId();
  93 + Assert.assertNotNull(savedTenant);
  94 +
  95 + tenantAdmin = new User();
  96 + tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
  97 + tenantAdmin.setTenantId(savedTenant.getId());
  98 + tenantAdmin.setEmail("tenant2@thingsboard.org");
  99 + tenantAdmin.setFirstName("Joe");
  100 + tenantAdmin.setLastName("Downs");
  101 +
  102 + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");
77 } 103 }
78 104
79 @After 105 @After
80 - public void after() {  
81 - tenantService.deleteTenant(tenantId); 106 + public void afterTest() throws Exception {
  107 + loginSysAdmin();
  108 +
  109 + doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
  110 + .andExpect(status().isOk());
82 } 111 }
83 112
84 @Test 113 @Test
@@ -239,9 +268,10 @@ public abstract class BaseTbResourceServiceTest extends AbstractServiceTest { @@ -239,9 +268,10 @@ public abstract class BaseTbResourceServiceTest extends AbstractServiceTest {
239 268
240 @Test 269 @Test
241 public void testFindTenantResourcesByTenantId() throws Exception { 270 public void testFindTenantResourcesByTenantId() throws Exception {
  271 + loginSysAdmin();
242 Tenant tenant = new Tenant(); 272 Tenant tenant = new Tenant();
243 tenant.setTitle("Test tenant"); 273 tenant.setTitle("Test tenant");
244 - tenant = tenantService.saveTenant(tenant); 274 + tenant = doPost("/api/tenant", tenant, Tenant.class);
245 275
246 TenantId tenantId = tenant.getId(); 276 TenantId tenantId = tenant.getId();
247 277
@@ -279,14 +309,17 @@ public abstract class BaseTbResourceServiceTest extends AbstractServiceTest { @@ -279,14 +309,17 @@ public abstract class BaseTbResourceServiceTest extends AbstractServiceTest {
279 Assert.assertFalse(pageData.hasNext()); 309 Assert.assertFalse(pageData.hasNext());
280 Assert.assertTrue(pageData.getData().isEmpty()); 310 Assert.assertTrue(pageData.getData().isEmpty());
281 311
282 - tenantService.deleteTenant(tenantId); 312 + doDelete("/api/tenant/" + tenantId.getId().toString())
  313 + .andExpect(status().isOk());
283 } 314 }
284 315
285 @Test 316 @Test
286 public void testFindAllTenantResourcesByTenantId() throws Exception { 317 public void testFindAllTenantResourcesByTenantId() throws Exception {
  318 + loginSysAdmin();
  319 +
287 Tenant tenant = new Tenant(); 320 Tenant tenant = new Tenant();
288 tenant.setTitle("Test tenant"); 321 tenant.setTitle("Test tenant");
289 - tenant = tenantService.saveTenant(tenant); 322 + tenant = doPost("/api/tenant", tenant, Tenant.class);
290 323
291 TenantId tenantId = tenant.getId(); 324 TenantId tenantId = tenant.getId();
292 325
@@ -344,7 +377,8 @@ public abstract class BaseTbResourceServiceTest extends AbstractServiceTest { @@ -344,7 +377,8 @@ public abstract class BaseTbResourceServiceTest extends AbstractServiceTest {
344 Assert.assertFalse(pageData.hasNext()); 377 Assert.assertFalse(pageData.hasNext());
345 Assert.assertTrue(pageData.getData().isEmpty()); 378 Assert.assertTrue(pageData.getData().isEmpty());
346 379
347 - tenantService.deleteTenant(tenantId); 380 + doDelete("/api/tenant/" + tenantId.getId().toString())
  381 + .andExpect(status().isOk());
348 } 382 }
349 383
350 } 384 }
@@ -15,35 +15,11 @@ @@ -15,35 +15,11 @@
15 */ 15 */
16 package org.thingsboard.server.transport; 16 package org.thingsboard.server.transport;
17 17
18 -import com.fasterxml.jackson.databind.node.ObjectNode;  
19 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
20 -import org.eclipse.paho.client.mqttv3.MqttAsyncClient;  
21 -import org.eclipse.paho.client.mqttv3.MqttConnectOptions;  
22 -import org.eclipse.paho.client.mqttv3.MqttException;  
23 -import org.eclipse.paho.client.mqttv3.MqttMessage;  
24 -import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;  
25 -import org.junit.Assert;  
26 -import org.springframework.util.StringUtils;  
27 import org.thingsboard.server.common.data.Device; 19 import org.thingsboard.server.common.data.Device;
28 import org.thingsboard.server.common.data.DeviceProfile; 20 import org.thingsboard.server.common.data.DeviceProfile;
29 -import org.thingsboard.server.common.data.DeviceProfileProvisionType;  
30 -import org.thingsboard.server.common.data.DeviceProfileType;  
31 -import org.thingsboard.server.common.data.DeviceTransportType;  
32 import org.thingsboard.server.common.data.Tenant; 21 import org.thingsboard.server.common.data.Tenant;
33 -import org.thingsboard.server.common.data.TransportPayloadType;  
34 import org.thingsboard.server.common.data.User; 22 import org.thingsboard.server.common.data.User;
35 -import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration;  
36 -import org.thingsboard.server.common.data.device.profile.CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration;  
37 -import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration;  
38 -import org.thingsboard.server.common.data.device.profile.DeviceProfileData;  
39 -import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration;  
40 -import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration;  
41 -import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration;  
42 -import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;  
43 -import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;  
44 -import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;  
45 -import org.thingsboard.server.common.data.security.Authority;  
46 -import org.thingsboard.server.common.data.security.DeviceCredentials;  
47 import org.thingsboard.server.controller.AbstractControllerTest; 23 import org.thingsboard.server.controller.AbstractControllerTest;
48 import org.thingsboard.server.gen.transport.TransportProtos; 24 import org.thingsboard.server.gen.transport.TransportProtos;
49 25
@@ -51,8 +27,6 @@ import java.util.ArrayList; @@ -51,8 +27,6 @@ import java.util.ArrayList;
51 import java.util.List; 27 import java.util.List;
52 import java.util.concurrent.atomic.AtomicInteger; 28 import java.util.concurrent.atomic.AtomicInteger;
53 29
54 -import static org.junit.Assert.assertEquals;  
55 -import static org.junit.Assert.assertNotNull;  
56 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 30 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
57 31
58 @Slf4j 32 @Slf4j
@@ -105,6 +79,22 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle @@ -105,6 +79,22 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle
105 " }\n" + 79 " }\n" +
106 "}"; 80 "}";
107 81
  82 + protected static final String DEVICE_RPC_RESPONSE_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
  83 + "package rpc;\n" +
  84 + "\n" +
  85 + "message RpcResponseMsg {\n" +
  86 + " string payload = 1;\n" +
  87 + "}";
  88 +
  89 + protected static final String DEVICE_RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
  90 + "package rpc;\n" +
  91 + "\n" +
  92 + "message RpcRequestMsg {\n" +
  93 + " string method = 1;\n" +
  94 + " int32 requestId = 2;\n" +
  95 + " string params = 3;\n" +
  96 + "}";
  97 +
108 protected Tenant savedTenant; 98 protected Tenant savedTenant;
109 protected User tenantAdmin; 99 protected User tenantAdmin;
110 100
@@ -53,7 +53,7 @@ import static org.junit.Assert.assertNotNull; @@ -53,7 +53,7 @@ import static org.junit.Assert.assertNotNull;
53 public abstract class AbstractCoapIntegrationTest extends AbstractTransportIntegrationTest { 53 public abstract class AbstractCoapIntegrationTest extends AbstractTransportIntegrationTest {
54 54
55 protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { 55 protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception {
56 - this.processBeforeTest(deviceName, coapDeviceType, payloadType, null, null, DeviceProfileProvisionType.DISABLED, null, null); 56 + this.processBeforeTest(deviceName, coapDeviceType, payloadType, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
57 } 57 }
58 58
59 protected void processBeforeTest(String deviceName, 59 protected void processBeforeTest(String deviceName,
@@ -61,8 +61,11 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg @@ -61,8 +61,11 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg
61 TransportPayloadType payloadType, 61 TransportPayloadType payloadType,
62 String telemetryProtoSchema, 62 String telemetryProtoSchema,
63 String attributesProtoSchema, 63 String attributesProtoSchema,
64 - DeviceProfileProvisionType provisionType,  
65 - String provisionKey, String provisionSecret 64 + String rpcResponseProtoSchema,
  65 + String rpcRequestProtoSchema,
  66 + String provisionKey,
  67 + String provisionSecret,
  68 + DeviceProfileProvisionType provisionType
66 ) throws Exception { 69 ) throws Exception {
67 loginSysAdmin(); 70 loginSysAdmin();
68 71
@@ -85,7 +88,7 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg @@ -85,7 +88,7 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg
85 device.setType("default"); 88 device.setType("default");
86 89
87 if (coapDeviceType != null) { 90 if (coapDeviceType != null) {
88 - DeviceProfile coapDeviceProfile = createCoapDeviceProfile(payloadType, coapDeviceType, attributesProtoSchema, provisionType, provisionKey, provisionSecret, telemetryProtoSchema); 91 + DeviceProfile coapDeviceProfile = createCoapDeviceProfile(payloadType, coapDeviceType, provisionSecret, provisionType, provisionKey, attributesProtoSchema, telemetryProtoSchema, rpcResponseProtoSchema, rpcRequestProtoSchema);
89 deviceProfile = doPost("/api/deviceProfile", coapDeviceProfile, DeviceProfile.class); 92 deviceProfile = doPost("/api/deviceProfile", coapDeviceProfile, DeviceProfile.class);
90 device.setType(deviceProfile.getName()); 93 device.setType(deviceProfile.getName());
91 device.setDeviceProfileId(deviceProfile.getId()); 94 device.setDeviceProfileId(deviceProfile.getId());
@@ -103,8 +106,9 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg @@ -103,8 +106,9 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg
103 } 106 }
104 107
105 protected DeviceProfile createCoapDeviceProfile(TransportPayloadType transportPayloadType, CoapDeviceType coapDeviceType, 108 protected DeviceProfile createCoapDeviceProfile(TransportPayloadType transportPayloadType, CoapDeviceType coapDeviceType,
106 - String attributesProtoSchema, DeviceProfileProvisionType provisionType,  
107 - String provisionKey, String provisionSecret, String telemetryProtoSchema) { 109 + String provisionSecret, DeviceProfileProvisionType provisionType,
  110 + String provisionKey, String attributesProtoSchema,
  111 + String telemetryProtoSchema, String rpcResponseProtoSchema, String rpcRequestProtoSchema) {
108 DeviceProfile deviceProfile = new DeviceProfile(); 112 DeviceProfile deviceProfile = new DeviceProfile();
109 deviceProfile.setName(transportPayloadType.name()); 113 deviceProfile.setName(transportPayloadType.name());
110 deviceProfile.setType(DeviceProfileType.DEFAULT); 114 deviceProfile.setType(DeviceProfileType.DEFAULT);
@@ -127,8 +131,16 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg @@ -127,8 +131,16 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg
127 if (StringUtils.isEmpty(attributesProtoSchema)) { 131 if (StringUtils.isEmpty(attributesProtoSchema)) {
128 attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; 132 attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA;
129 } 133 }
  134 + if (StringUtils.isEmpty(rpcResponseProtoSchema)) {
  135 + rpcResponseProtoSchema = DEVICE_RPC_RESPONSE_PROTO_SCHEMA;
  136 + }
  137 + if (StringUtils.isEmpty(rpcRequestProtoSchema)) {
  138 + rpcRequestProtoSchema = DEVICE_RPC_REQUEST_PROTO_SCHEMA;
  139 + }
130 protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); 140 protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema);
131 protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); 141 protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema);
  142 + protoTransportPayloadConfiguration.setDeviceRpcResponseProtoSchema(rpcResponseProtoSchema);
  143 + protoTransportPayloadConfiguration.setDeviceRpcRequestProtoSchema(rpcRequestProtoSchema);
132 transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; 144 transportPayloadTypeConfiguration = protoTransportPayloadConfiguration;
133 } else { 145 } else {
134 transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration(); 146 transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration();
@@ -79,7 +79,7 @@ public abstract class AbstractCoapAttributesRequestProtoIntegrationTest extends @@ -79,7 +79,7 @@ public abstract class AbstractCoapAttributesRequestProtoIntegrationTest extends
79 @Test 79 @Test
80 public void testRequestAttributesValuesFromTheServer() throws Exception { 80 public void testRequestAttributesValuesFromTheServer() throws Exception {
81 super.processBeforeTest("Test Request attribute values from the server proto", CoapDeviceType.DEFAULT, 81 super.processBeforeTest("Test Request attribute values from the server proto", CoapDeviceType.DEFAULT,
82 - TransportPayloadType.PROTOBUF, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null); 82 + TransportPayloadType.PROTOBUF, null, ATTRIBUTES_SCHEMA_STR, null, null, null, null, DeviceProfileProvisionType.DISABLED);
83 processTestRequestAttributesValuesFromTheServer(); 83 processTestRequestAttributesValuesFromTheServer();
84 } 84 }
85 85
@@ -88,7 +88,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn @@ -88,7 +88,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn
88 88
89 89
90 private void processTestProvisioningDisabledDevice() throws Exception { 90 private void processTestProvisioningDisabledDevice() throws Exception {
91 - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.DISABLED, null, null); 91 + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
92 byte[] result = createCoapClientAndPublish().getPayload(); 92 byte[] result = createCoapClientAndPublish().getPayload();
93 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 93 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
94 Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); 94 Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString());
@@ -97,7 +97,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn @@ -97,7 +97,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn
97 97
98 98
99 private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { 99 private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception {
100 - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 100 + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
101 byte[] result = createCoapClientAndPublish().getPayload(); 101 byte[] result = createCoapClientAndPublish().getPayload();
102 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 102 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
103 103
@@ -113,7 +113,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn @@ -113,7 +113,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn
113 113
114 114
115 private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { 115 private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception {
116 - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 116 + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
117 String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; 117 String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\"";
118 byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); 118 byte[] result = createCoapClientAndPublish(requestCredentials).getPayload();
119 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 119 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
@@ -132,7 +132,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn @@ -132,7 +132,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn
132 132
133 133
134 private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { 134 private void processTestProvisioningCreateNewDeviceWithCert() throws Exception {
135 - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 135 + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
136 String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; 136 String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\"";
137 byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); 137 byte[] result = createCoapClientAndPublish(requestCredentials).getPayload();
138 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 138 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
@@ -156,7 +156,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn @@ -156,7 +156,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn
156 } 156 }
157 157
158 private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { 158 private void processTestProvisioningCheckPreProvisionedDevice() throws Exception {
159 - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); 159 + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES);
160 byte[] result = createCoapClientAndPublish().getPayload(); 160 byte[] result = createCoapClientAndPublish().getPayload();
161 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 161 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
162 162
@@ -167,7 +167,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn @@ -167,7 +167,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn
167 } 167 }
168 168
169 private void processTestProvisioningWithBadKeyDevice() throws Exception { 169 private void processTestProvisioningWithBadKeyDevice() throws Exception {
170 - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); 170 + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, null, null, "testProvisionKeyOrig", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES);
171 byte[] result = createCoapClientAndPublish().getPayload(); 171 byte[] result = createCoapClientAndPublish().getPayload();
172 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 172 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
173 Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); 173 Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString());
@@ -92,14 +92,14 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI @@ -92,14 +92,14 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI
92 92
93 93
94 private void processTestProvisioningDisabledDevice() throws Exception { 94 private void processTestProvisioningDisabledDevice() throws Exception {
95 - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.DISABLED, null, null); 95 + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
96 ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); 96 ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload());
97 Assert.assertNotNull(result); 97 Assert.assertNotNull(result);
98 Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString()); 98 Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString());
99 } 99 }
100 100
101 private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { 101 private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception {
102 - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 102 + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
103 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); 103 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload());
104 104
105 Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); 105 Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device");
@@ -113,7 +113,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI @@ -113,7 +113,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI
113 } 113 }
114 114
115 private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { 115 private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception {
116 - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 116 + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
117 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); 117 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build();
118 118
119 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayload()); 119 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayload());
@@ -131,7 +131,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI @@ -131,7 +131,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI
131 } 131 }
132 132
133 private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { 133 private void processTestProvisioningCreateNewDeviceWithCert() throws Exception {
134 - super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 134 + super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
135 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); 135 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build();
136 136
137 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayload()); 137 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayload());
@@ -155,7 +155,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI @@ -155,7 +155,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI
155 } 155 }
156 156
157 private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { 157 private void processTestProvisioningCheckPreProvisionedDevice() throws Exception {
158 - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); 158 + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES);
159 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); 159 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload());
160 160
161 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); 161 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId());
@@ -165,7 +165,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI @@ -165,7 +165,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI
165 } 165 }
166 166
167 private void processTestProvisioningWithBadKeyDevice() throws Exception { 167 private void processTestProvisioningWithBadKeyDevice() throws Exception {
168 - super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); 168 + super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, null, "testProvisionKeyOrig", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES);
169 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); 169 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload());
170 Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString()); 170 Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString());
171 } 171 }
@@ -124,7 +124,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC @@ -124,7 +124,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
124 return COAP_BASE_URL + token + "/" + FeatureType.RPC.name().toLowerCase() + "/" + requestId; 124 return COAP_BASE_URL + token + "/" + FeatureType.RPC.name().toLowerCase() + "/" + requestId;
125 } 125 }
126 126
127 - private class TestCoapCallback implements CoapHandler { 127 + protected class TestCoapCallback implements CoapHandler {
128 128
129 private final CoapClient client; 129 private final CoapClient client;
130 private final CountDownLatch latch; 130 private final CountDownLatch latch;
@@ -136,7 +136,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC @@ -136,7 +136,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
136 136
137 private Integer observe; 137 private Integer observe;
138 138
139 - private TestCoapCallback(CoapClient client, CountDownLatch latch, boolean isOneWayRpc) { 139 + TestCoapCallback(CoapClient client, CountDownLatch latch, boolean isOneWayRpc) {
140 this.client = client; 140 this.client = client;
141 this.latch = latch; 141 this.latch = latch;
142 this.isOneWayRpc = isOneWayRpc; 142 this.isOneWayRpc = isOneWayRpc;
@@ -144,7 +144,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC @@ -144,7 +144,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
144 144
145 @Override 145 @Override
146 public void onLoad(CoapResponse response) { 146 public void onLoad(CoapResponse response) {
147 - log.warn("coap response: {}, {}", response, response.getCode()); 147 + log.warn("coap response: {}, {}", response.getResponseText(), response.getCode());
148 assertNotNull(response.getPayload()); 148 assertNotNull(response.getPayload());
149 assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT); 149 assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT);
150 observe = response.getOptions().getObserve(); 150 observe = response.getOptions().getObserve();
@@ -36,12 +36,12 @@ public abstract class AbstractCoapServerSideRpcJsonIntegrationTest extends Abstr @@ -36,12 +36,12 @@ public abstract class AbstractCoapServerSideRpcJsonIntegrationTest extends Abstr
36 } 36 }
37 37
38 @Test 38 @Test
39 - public void testServerMqttOneWayRpc() throws Exception { 39 + public void testServerCoapOneWayRpc() throws Exception {
40 processOneWayRpcTest(); 40 processOneWayRpcTest();
41 } 41 }
42 42
43 @Test 43 @Test
44 - public void testServerMqttTwoWayRpc() throws Exception { 44 + public void testServerCoapTwoWayRpc() throws Exception {
45 processTwoWayRpcTest(); 45 processTwoWayRpcTest();
46 } 46 }
47 47
@@ -15,26 +15,62 @@ @@ -15,26 +15,62 @@
15 */ 15 */
16 package org.thingsboard.server.transport.coap.rpc; 16 package org.thingsboard.server.transport.coap.rpc;
17 17
  18 +import com.github.os72.protobuf.dynamic.DynamicSchema;
  19 +import com.google.protobuf.Descriptors;
  20 +import com.google.protobuf.DynamicMessage;
  21 +import com.google.protobuf.InvalidProtocolBufferException;
  22 +import com.squareup.wire.schema.internal.parser.ProtoFileElement;
18 import lombok.extern.slf4j.Slf4j; 23 import lombok.extern.slf4j.Slf4j;
19 import org.eclipse.californium.core.CoapClient; 24 import org.eclipse.californium.core.CoapClient;
20 import org.eclipse.californium.core.CoapHandler; 25 import org.eclipse.californium.core.CoapHandler;
  26 +import org.eclipse.californium.core.CoapObserveRelation;
21 import org.eclipse.californium.core.CoapResponse; 27 import org.eclipse.californium.core.CoapResponse;
  28 +import org.eclipse.californium.core.coap.CoAP;
22 import org.eclipse.californium.core.coap.MediaTypeRegistry; 29 import org.eclipse.californium.core.coap.MediaTypeRegistry;
  30 +import org.eclipse.californium.core.coap.Request;
23 import org.junit.After; 31 import org.junit.After;
24 import org.junit.Before; 32 import org.junit.Before;
25 import org.junit.Test; 33 import org.junit.Test;
26 import org.thingsboard.server.common.data.CoapDeviceType; 34 import org.thingsboard.server.common.data.CoapDeviceType;
  35 +import org.thingsboard.server.common.data.DeviceProfileProvisionType;
27 import org.thingsboard.server.common.data.TransportPayloadType; 36 import org.thingsboard.server.common.data.TransportPayloadType;
28 -import org.thingsboard.server.gen.transport.TransportProtos; 37 +import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
  38 +import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration;
  39 +import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration;
  40 +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
  41 +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
  42 +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
  43 +import org.thingsboard.server.common.msg.session.FeatureType;
29 44
  45 +import java.util.List;
30 import java.util.concurrent.CountDownLatch; 46 import java.util.concurrent.CountDownLatch;
  47 +import java.util.concurrent.TimeUnit;
  48 +
  49 +import static org.junit.Assert.assertEquals;
  50 +import static org.junit.Assert.assertNotNull;
  51 +import static org.junit.Assert.assertTrue;
  52 +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
31 53
32 @Slf4j 54 @Slf4j
33 public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { 55 public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest {
34 56
  57 + private static final String RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
  58 + "package rpc;\n" +
  59 + "\n" +
  60 + "message RpcRequestMsg {\n" +
  61 + " string method = 1;\n" +
  62 + " int32 requestId = 2;\n" +
  63 + " Params params = 3;\n" +
  64 + "\n" +
  65 + " message Params {\n" +
  66 + " string pin = 1;\n" +
  67 + " int32 value = 2;\n" +
  68 + " }\n" +
  69 + "}";
  70 +
35 @Before 71 @Before
36 public void beforeTest() throws Exception { 72 public void beforeTest() throws Exception {
37 - processBeforeTest("RPC test device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); 73 + processBeforeTest("RPC test device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, null, RPC_REQUEST_PROTO_SCHEMA, null, null, DeviceProfileProvisionType.DISABLED);
38 } 74 }
39 75
40 @After 76 @After
@@ -43,33 +79,91 @@ public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends Abst @@ -43,33 +79,91 @@ public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends Abst
43 } 79 }
44 80
45 @Test 81 @Test
46 - public void testServerMqttOneWayRpc() throws Exception { 82 + public void testServerCoapOneWayRpc() throws Exception {
47 processOneWayRpcTest(); 83 processOneWayRpcTest();
48 } 84 }
49 85
50 @Test 86 @Test
51 - public void testServerMqttTwoWayRpc() throws Exception { 87 + public void testServerCoapTwoWayRpc() throws Exception {
52 processTwoWayRpcTest(); 88 processTwoWayRpcTest();
53 } 89 }
54 90
  91 + protected void processTwoWayRpcTest() throws Exception {
  92 + CoapClient client = getCoapClient(FeatureType.RPC);
  93 + client.useCONs();
  94 +
  95 + CountDownLatch latch = new CountDownLatch(1);
  96 + TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, false);
  97 +
  98 + Request request = Request.newGet().setObserve();
  99 + request.setType(CoAP.Type.CON);
  100 + CoapObserveRelation observeRelation = client.observe(request, testCoapCallback);
  101 +
  102 + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
  103 + String deviceId = savedDevice.getId().getId().toString();
  104 +
  105 + String expected = "{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}";
  106 +
  107 + String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
  108 + latch.await(3, TimeUnit.SECONDS);
  109 +
  110 + assertEquals(expected, result);
  111 + assertEquals(0, testCoapCallback.getObserve().intValue());
  112 + observeRelation.proactiveCancel();
  113 + assertTrue(observeRelation.isCanceled());
  114 + }
  115 +
55 @Override 116 @Override
56 protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) { 117 protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) {
57 client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe)); 118 client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe));
58 - TransportProtos.ToDeviceRpcResponseMsg toDeviceRpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder()  
59 - .setPayload(DEVICE_RESPONSE)  
60 - .setRequestId(observe)  
61 - .build();  
62 - client.post(new CoapHandler() {  
63 - @Override  
64 - public void onLoad(CoapResponse response) {  
65 - log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText());  
66 - latch.countDown();  
67 - } 119 + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = getProtoTransportPayloadConfiguration();
  120 + ProtoFileElement rpcRequestProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(RPC_REQUEST_PROTO_SCHEMA);
  121 + DynamicSchema rpcRequestProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcRequestProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_REQUEST_PROTO_SCHEMA);
68 122
69 - @Override  
70 - public void onError() {  
71 - log.warn("Command Response Ack Error, No connect"); 123 + byte[] requestPayload = response.getPayload();
  124 + DynamicMessage.Builder rpcRequestMsg = rpcRequestProtoSchema.newMessageBuilder("RpcRequestMsg");
  125 + Descriptors.Descriptor rpcRequestMsgDescriptor = rpcRequestMsg.getDescriptorForType();
  126 + assertNotNull(rpcRequestMsgDescriptor);
  127 + try {
  128 + DynamicMessage dynamicMessage = DynamicMessage.parseFrom(rpcRequestMsgDescriptor, requestPayload);
  129 + List<Descriptors.FieldDescriptor> fields = rpcRequestMsgDescriptor.getFields();
  130 + for (Descriptors.FieldDescriptor fieldDescriptor: fields) {
  131 + assertTrue(dynamicMessage.hasField(fieldDescriptor));
72 } 132 }
73 - }, toDeviceRpcResponseMsg.toByteArray(), MediaTypeRegistry.APPLICATION_JSON); 133 + ProtoFileElement rpcResponseProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_RPC_RESPONSE_PROTO_SCHEMA);
  134 + DynamicSchema rpcResponseProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcResponseProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_RESPONSE_PROTO_SCHEMA);
  135 + DynamicMessage.Builder rpcResponseBuilder = rpcResponseProtoSchema.newMessageBuilder("RpcResponseMsg");
  136 + Descriptors.Descriptor rpcResponseMsgDescriptor = rpcResponseBuilder.getDescriptorForType();
  137 + assertNotNull(rpcResponseMsgDescriptor);
  138 + DynamicMessage rpcResponseMsg = rpcResponseBuilder
  139 + .setField(rpcResponseMsgDescriptor.findFieldByName("payload"), DEVICE_RESPONSE)
  140 + .build();
  141 + client.post(new CoapHandler() {
  142 + @Override
  143 + public void onLoad(CoapResponse response) {
  144 + log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText());
  145 + latch.countDown();
  146 + }
  147 +
  148 + @Override
  149 + public void onError() {
  150 + log.warn("Command Response Ack Error, No connect");
  151 + }
  152 + }, rpcResponseMsg.toByteArray(), MediaTypeRegistry.APPLICATION_JSON);
  153 + } catch (InvalidProtocolBufferException e) {
  154 + log.warn("Command Response Ack Error, Invalid response received: ", e);
  155 + }
  156 + }
  157 +
  158 + private ProtoTransportPayloadConfiguration getProtoTransportPayloadConfiguration() {
  159 + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
  160 + assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration);
  161 + CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration;
  162 + CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration();
  163 + assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration);
  164 + DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration;
  165 + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration();
  166 + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
  167 + return (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
74 } 168 }
75 } 169 }
@@ -114,7 +114,7 @@ public abstract class AbstractCoapTimeseriesProtoIntegrationTest extends Abstrac @@ -114,7 +114,7 @@ public abstract class AbstractCoapTimeseriesProtoIntegrationTest extends Abstrac
114 " }\n" + 114 " }\n" +
115 " }\n" + 115 " }\n" +
116 "}"; 116 "}";
117 - super.processBeforeTest("Test Post Telemetry device proto payload", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, schemaStr, null, DeviceProfileProvisionType.DISABLED, null, null); 117 + super.processBeforeTest("Test Post Telemetry device proto payload", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, schemaStr, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
118 DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); 118 DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
119 assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); 119 assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration);
120 CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; 120 CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration;
@@ -62,7 +62,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg @@ -62,7 +62,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg
62 protected DeviceProfile deviceProfile; 62 protected DeviceProfile deviceProfile;
63 63
64 protected void processBeforeTest (String deviceName, String gatewayName, TransportPayloadType payloadType, String telemetryTopic, String attributesTopic) throws Exception { 64 protected void processBeforeTest (String deviceName, String gatewayName, TransportPayloadType payloadType, String telemetryTopic, String attributesTopic) throws Exception {
65 - this.processBeforeTest(deviceName, gatewayName, payloadType, telemetryTopic, attributesTopic, null, null, DeviceProfileProvisionType.DISABLED, null, null); 65 + this.processBeforeTest(deviceName, gatewayName, payloadType, telemetryTopic, attributesTopic, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
66 } 66 }
67 67
68 protected void processBeforeTest(String deviceName, 68 protected void processBeforeTest(String deviceName,
@@ -72,9 +72,12 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg @@ -72,9 +72,12 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg
72 String attributesTopic, 72 String attributesTopic,
73 String telemetryProtoSchema, 73 String telemetryProtoSchema,
74 String attributesProtoSchema, 74 String attributesProtoSchema,
75 - DeviceProfileProvisionType provisionType,  
76 - String provisionKey, String provisionSecret  
77 - ) throws Exception { 75 + String rpcResponseProtoSchema,
  76 + String rpcRequestProtoSchema,
  77 + String provisionKey,
  78 + String provisionSecret,
  79 + DeviceProfileProvisionType provisionType
  80 + ) throws Exception {
78 loginSysAdmin(); 81 loginSysAdmin();
79 82
80 Tenant tenant = new Tenant(); 83 Tenant tenant = new Tenant();
@@ -103,7 +106,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg @@ -103,7 +106,7 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg
103 gateway.setAdditionalInfo(additionalInfo); 106 gateway.setAdditionalInfo(additionalInfo);
104 107
105 if (payloadType != null) { 108 if (payloadType != null) {
106 - DeviceProfile mqttDeviceProfile = createMqttDeviceProfile(payloadType, telemetryTopic, attributesTopic, telemetryProtoSchema, attributesProtoSchema, provisionType, provisionKey, provisionSecret); 109 + DeviceProfile mqttDeviceProfile = createMqttDeviceProfile(payloadType, telemetryTopic, attributesTopic, telemetryProtoSchema, attributesProtoSchema, rpcResponseProtoSchema, rpcRequestProtoSchema, provisionKey, provisionSecret, provisionType);
107 deviceProfile = doPost("/api/deviceProfile", mqttDeviceProfile, DeviceProfile.class); 110 deviceProfile = doPost("/api/deviceProfile", mqttDeviceProfile, DeviceProfile.class);
108 device.setType(deviceProfile.getName()); 111 device.setType(deviceProfile.getName());
109 device.setDeviceProfileId(deviceProfile.getId()); 112 device.setDeviceProfileId(deviceProfile.getId());
@@ -157,8 +160,9 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg @@ -157,8 +160,9 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg
157 protected DeviceProfile createMqttDeviceProfile(TransportPayloadType transportPayloadType, 160 protected DeviceProfile createMqttDeviceProfile(TransportPayloadType transportPayloadType,
158 String telemetryTopic, String attributesTopic, 161 String telemetryTopic, String attributesTopic,
159 String telemetryProtoSchema, String attributesProtoSchema, 162 String telemetryProtoSchema, String attributesProtoSchema,
160 - DeviceProfileProvisionType provisionType,  
161 - String provisionKey, String provisionSecret) { 163 + String rpcResponseProtoSchema, String rpcRequestProtoSchema,
  164 + String provisionKey, String provisionSecret,
  165 + DeviceProfileProvisionType provisionType) {
162 DeviceProfile deviceProfile = new DeviceProfile(); 166 DeviceProfile deviceProfile = new DeviceProfile();
163 deviceProfile.setName(transportPayloadType.name()); 167 deviceProfile.setName(transportPayloadType.name());
164 deviceProfile.setType(DeviceProfileType.DEFAULT); 168 deviceProfile.setType(DeviceProfileType.DEFAULT);
@@ -186,8 +190,16 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg @@ -186,8 +190,16 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg
186 if (StringUtils.isEmpty(attributesProtoSchema)) { 190 if (StringUtils.isEmpty(attributesProtoSchema)) {
187 attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; 191 attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA;
188 } 192 }
  193 + if (StringUtils.isEmpty(rpcResponseProtoSchema)) {
  194 + rpcResponseProtoSchema = DEVICE_RPC_RESPONSE_PROTO_SCHEMA;
  195 + }
  196 + if (StringUtils.isEmpty(rpcRequestProtoSchema)) {
  197 + rpcRequestProtoSchema = DEVICE_RPC_REQUEST_PROTO_SCHEMA;
  198 + }
189 protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); 199 protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema);
190 protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); 200 protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema);
  201 + protoTransportPayloadConfiguration.setDeviceRpcResponseProtoSchema(rpcResponseProtoSchema);
  202 + protoTransportPayloadConfiguration.setDeviceRpcRequestProtoSchema(rpcRequestProtoSchema);
191 transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; 203 transportPayloadTypeConfiguration = protoTransportPayloadConfiguration;
192 } 204 }
193 mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); 205 mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration);
@@ -83,7 +83,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends @@ -83,7 +83,7 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends
83 @Test 83 @Test
84 public void testRequestAttributesValuesFromTheServer() throws Exception { 84 public void testRequestAttributesValuesFromTheServer() throws Exception {
85 super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", 85 super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto",
86 - TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null); 86 + TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, null, null, null, null, DeviceProfileProvisionType.DISABLED);
87 processTestRequestAttributesValuesFromTheServer(); 87 processTestRequestAttributesValuesFromTheServer();
88 } 88 }
89 89
@@ -94,7 +94,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn @@ -94,7 +94,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn
94 94
95 95
96 protected void processTestProvisioningDisabledDevice() throws Exception { 96 protected void processTestProvisioningDisabledDevice() throws Exception {
97 - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); 97 + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
98 byte[] result = createMqttClientAndPublish().getPayloadBytes(); 98 byte[] result = createMqttClientAndPublish().getPayloadBytes();
99 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 99 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
100 Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); 100 Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString());
@@ -103,7 +103,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn @@ -103,7 +103,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn
103 103
104 104
105 protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { 105 protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception {
106 - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 106 + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
107 byte[] result = createMqttClientAndPublish().getPayloadBytes(); 107 byte[] result = createMqttClientAndPublish().getPayloadBytes();
108 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 108 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
109 109
@@ -119,7 +119,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn @@ -119,7 +119,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn
119 119
120 120
121 protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { 121 protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception {
122 - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 122 + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
123 String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; 123 String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\"";
124 byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); 124 byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes();
125 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 125 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
@@ -138,7 +138,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn @@ -138,7 +138,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn
138 138
139 139
140 protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { 140 protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception {
141 - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 141 + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
142 String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; 142 String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\"";
143 byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); 143 byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes();
144 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 144 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
@@ -163,7 +163,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn @@ -163,7 +163,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn
163 163
164 164
165 protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { 165 protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception {
166 - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 166 + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
167 String requestCredentials = ",\"credentialsType\": \"MQTT_BASIC\",\"clientId\": \"test_clientId\",\"username\": \"test_username\",\"password\": \"test_password\""; 167 String requestCredentials = ",\"credentialsType\": \"MQTT_BASIC\",\"clientId\": \"test_clientId\",\"username\": \"test_username\",\"password\": \"test_password\"";
168 byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes(); 168 byte[] result = createMqttClientAndPublish(requestCredentials).getPayloadBytes();
169 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 169 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
@@ -188,7 +188,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn @@ -188,7 +188,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn
188 } 188 }
189 189
190 protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { 190 protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception {
191 - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); 191 + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES);
192 byte[] result = createMqttClientAndPublish().getPayloadBytes(); 192 byte[] result = createMqttClientAndPublish().getPayloadBytes();
193 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 193 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
194 194
@@ -199,7 +199,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn @@ -199,7 +199,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn
199 } 199 }
200 200
201 protected void processTestProvisioningWithBadKeyDevice() throws Exception { 201 protected void processTestProvisioningWithBadKeyDevice() throws Exception {
202 - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); 202 + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.JSON, null, null, null, null, null, null, "testProvisionKeyOrig", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES);
203 byte[] result = createMqttClientAndPublish().getPayloadBytes(); 203 byte[] result = createMqttClientAndPublish().getPayloadBytes();
204 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); 204 JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
205 Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); 205 Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString());
@@ -101,14 +101,14 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI @@ -101,14 +101,14 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI
101 101
102 102
103 protected void processTestProvisioningDisabledDevice() throws Exception { 103 protected void processTestProvisioningDisabledDevice() throws Exception {
104 - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); 104 + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
105 ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); 105 ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes());
106 Assert.assertNotNull(result); 106 Assert.assertNotNull(result);
107 Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString()); 107 Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString());
108 } 108 }
109 109
110 protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { 110 protected void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception {
111 - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 111 + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
112 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); 112 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes());
113 113
114 Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); 114 Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device");
@@ -122,7 +122,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI @@ -122,7 +122,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI
122 } 122 }
123 123
124 protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { 124 protected void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception {
125 - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null,null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 125 + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null,null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
126 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); 126 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build();
127 127
128 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayloadBytes()); 128 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayloadBytes());
@@ -140,7 +140,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI @@ -140,7 +140,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI
140 } 140 }
141 141
142 protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception { 142 protected void processTestProvisioningCreateNewDeviceWithCert() throws Exception {
143 - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 143 + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
144 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); 144 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build();
145 145
146 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayloadBytes()); 146 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayloadBytes());
@@ -164,7 +164,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI @@ -164,7 +164,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI
164 } 164 }
165 165
166 protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception { 166 protected void processTestProvisioningCreateNewDeviceWithMqttBasic() throws Exception {
167 - super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); 167 + super.processBeforeTest("Test Provision device3", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES);
168 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateBasicMqttCredRequestMsg( 168 CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateBasicMqttCredRequestMsg(
169 ValidateBasicMqttCredRequestMsg.newBuilder() 169 ValidateBasicMqttCredRequestMsg.newBuilder()
170 .setClientId("test_clientId") 170 .setClientId("test_clientId")
@@ -195,7 +195,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI @@ -195,7 +195,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI
195 } 195 }
196 196
197 protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception { 197 protected void processTestProvisioningCheckPreProvisionedDevice() throws Exception {
198 - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); 198 + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKey", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES);
199 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); 199 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes());
200 200
201 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); 201 DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId());
@@ -205,7 +205,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI @@ -205,7 +205,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI
205 } 205 }
206 206
207 protected void processTestProvisioningWithBadKeyDevice() throws Exception { 207 protected void processTestProvisioningWithBadKeyDevice() throws Exception {
208 - super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); 208 + super.processBeforeTest("Test Provision device", "Test Provision gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, "testProvisionKeyOrig", "testProvisionSecret", DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES);
209 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes()); 209 ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createMqttClientAndPublish().getPayloadBytes());
210 Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString()); 210 Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString());
211 } 211 }
@@ -180,7 +180,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM @@ -180,7 +180,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
180 return message; 180 return message;
181 } 181 }
182 182
183 - private class TestMqttCallback implements MqttCallback { 183 + protected class TestMqttCallback implements MqttCallback {
184 184
185 private final MqttAsyncClient client; 185 private final MqttAsyncClient client;
186 private final CountDownLatch latch; 186 private final CountDownLatch latch;
@@ -15,25 +15,60 @@ @@ -15,25 +15,60 @@
15 */ 15 */
16 package org.thingsboard.server.transport.mqtt.rpc; 16 package org.thingsboard.server.transport.mqtt.rpc;
17 17
  18 +import com.github.os72.protobuf.dynamic.DynamicSchema;
  19 +import com.google.protobuf.Descriptors;
  20 +import com.google.protobuf.DynamicMessage;
18 import com.google.protobuf.InvalidProtocolBufferException; 21 import com.google.protobuf.InvalidProtocolBufferException;
  22 +import com.squareup.wire.schema.internal.parser.ProtoFileElement;
19 import lombok.extern.slf4j.Slf4j; 23 import lombok.extern.slf4j.Slf4j;
  24 +import org.eclipse.californium.core.CoapHandler;
  25 +import org.eclipse.californium.core.CoapResponse;
  26 +import org.eclipse.californium.core.coap.MediaTypeRegistry;
20 import org.eclipse.paho.client.mqttv3.MqttAsyncClient; 27 import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
21 import org.eclipse.paho.client.mqttv3.MqttException; 28 import org.eclipse.paho.client.mqttv3.MqttException;
22 import org.eclipse.paho.client.mqttv3.MqttMessage; 29 import org.eclipse.paho.client.mqttv3.MqttMessage;
  30 +import org.jetbrains.annotations.NotNull;
23 import org.junit.After; 31 import org.junit.After;
  32 +import org.junit.Assert;
24 import org.junit.Before; 33 import org.junit.Before;
25 import org.junit.Test; 34 import org.junit.Test;
  35 +import org.thingsboard.server.common.data.DeviceProfileProvisionType;
26 import org.thingsboard.server.common.data.TransportPayloadType; 36 import org.thingsboard.server.common.data.TransportPayloadType;
  37 +import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
  38 +import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
27 import org.thingsboard.server.common.data.device.profile.MqttTopics; 39 import org.thingsboard.server.common.data.device.profile.MqttTopics;
  40 +import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
  41 +import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
28 import org.thingsboard.server.gen.transport.TransportApiProtos; 42 import org.thingsboard.server.gen.transport.TransportApiProtos;
29 -import org.thingsboard.server.gen.transport.TransportProtos; 43 +
  44 +import java.util.List;
  45 +import java.util.concurrent.CountDownLatch;
  46 +import java.util.concurrent.TimeUnit;
  47 +
  48 +import static org.junit.Assert.assertNotNull;
  49 +import static org.junit.Assert.assertTrue;
  50 +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
30 51
31 @Slf4j 52 @Slf4j
32 public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends AbstractMqttServerSideRpcIntegrationTest { 53 public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends AbstractMqttServerSideRpcIntegrationTest {
33 54
  55 + private static final String RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
  56 + "package rpc;\n" +
  57 + "\n" +
  58 + "message RpcRequestMsg {\n" +
  59 + " string method = 1;\n" +
  60 + " int32 requestId = 2;\n" +
  61 + " Params params = 3;\n" +
  62 + "\n" +
  63 + " message Params {\n" +
  64 + " string pin = 1;\n" +
  65 + " int32 value = 2;\n" +
  66 + " }\n" +
  67 + "}";
  68 +
34 @Before 69 @Before
35 public void beforeTest() throws Exception { 70 public void beforeTest() throws Exception {
36 - processBeforeTest("RPC test device", "RPC test gateway", TransportPayloadType.PROTOBUF, null, null); 71 + processBeforeTest("RPC test device", "RPC test gateway", TransportPayloadType.PROTOBUF, null, null, null, null, null, RPC_REQUEST_PROTO_SCHEMA, null, null, DeviceProfileProvisionType.DISABLED);
37 } 72 }
38 73
39 @After 74 @After
@@ -83,14 +118,55 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst @@ -83,14 +118,55 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst
83 return builder.build(); 118 return builder.build();
84 } 119 }
85 120
  121 + protected void processTwoWayRpcTest() throws Exception {
  122 + MqttAsyncClient client = getMqttAsyncClient(accessToken);
  123 + client.subscribe(MqttTopics.DEVICE_RPC_REQUESTS_SUB_TOPIC, 1);
  124 +
  125 + CountDownLatch latch = new CountDownLatch(1);
  126 + TestMqttCallback callback = new TestMqttCallback(client, latch);
  127 + client.setCallback(callback);
  128 +
  129 + Thread.sleep(1000);
  130 +
  131 + String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
  132 + String deviceId = savedDevice.getId().getId().toString();
  133 +
  134 + String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
  135 + String expected = "{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}";
  136 + latch.await(3, TimeUnit.SECONDS);
  137 + Assert.assertEquals(expected, result);
  138 + }
  139 +
86 protected MqttMessage processMessageArrived(String requestTopic, MqttMessage mqttMessage) throws MqttException, InvalidProtocolBufferException { 140 protected MqttMessage processMessageArrived(String requestTopic, MqttMessage mqttMessage) throws MqttException, InvalidProtocolBufferException {
87 MqttMessage message = new MqttMessage(); 141 MqttMessage message = new MqttMessage();
88 if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC)) { 142 if (requestTopic.startsWith(MqttTopics.BASE_DEVICE_API_TOPIC)) {
89 - TransportProtos.ToDeviceRpcResponseMsg toDeviceRpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder()  
90 - .setPayload(DEVICE_RESPONSE)  
91 - .setRequestId(0) 143 + ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = getProtoTransportPayloadConfiguration();
  144 + ProtoFileElement rpcRequestProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(RPC_REQUEST_PROTO_SCHEMA);
  145 + DynamicSchema rpcRequestProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcRequestProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_REQUEST_PROTO_SCHEMA);
  146 +
  147 + byte[] requestPayload = mqttMessage.getPayload();
  148 + DynamicMessage.Builder rpcRequestMsg = rpcRequestProtoSchema.newMessageBuilder("RpcRequestMsg");
  149 + Descriptors.Descriptor rpcRequestMsgDescriptor = rpcRequestMsg.getDescriptorForType();
  150 + assertNotNull(rpcRequestMsgDescriptor);
  151 + try {
  152 + DynamicMessage dynamicMessage = DynamicMessage.parseFrom(rpcRequestMsgDescriptor, requestPayload);
  153 + List<Descriptors.FieldDescriptor> fields = rpcRequestMsgDescriptor.getFields();
  154 + for (Descriptors.FieldDescriptor fieldDescriptor: fields) {
  155 + assertTrue(dynamicMessage.hasField(fieldDescriptor));
  156 + }
  157 + ProtoFileElement transportProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_RPC_RESPONSE_PROTO_SCHEMA);
  158 + DynamicSchema rpcResponseProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_RESPONSE_PROTO_SCHEMA);
  159 +
  160 + DynamicMessage.Builder rpcResponseBuilder = rpcResponseProtoSchema.newMessageBuilder("RpcResponseMsg");
  161 + Descriptors.Descriptor rpcResponseMsgDescriptor = rpcResponseBuilder.getDescriptorForType();
  162 + assertNotNull(rpcResponseMsgDescriptor);
  163 + DynamicMessage rpcResponseMsg = rpcResponseBuilder
  164 + .setField(rpcResponseMsgDescriptor.findFieldByName("payload"), DEVICE_RESPONSE)
92 .build(); 165 .build();
93 - message.setPayload(toDeviceRpcResponseMsg.toByteArray()); 166 + message.setPayload(rpcResponseMsg.toByteArray());
  167 + } catch (InvalidProtocolBufferException e) {
  168 + log.warn("Command Response Ack Error, Invalid response received: ", e);
  169 + }
94 } else { 170 } else {
95 TransportApiProtos.GatewayDeviceRpcRequestMsg msg = TransportApiProtos.GatewayDeviceRpcRequestMsg.parseFrom(mqttMessage.getPayload()); 171 TransportApiProtos.GatewayDeviceRpcRequestMsg msg = TransportApiProtos.GatewayDeviceRpcRequestMsg.parseFrom(mqttMessage.getPayload());
96 String deviceName = msg.getDeviceName(); 172 String deviceName = msg.getDeviceName();
@@ -105,6 +181,14 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst @@ -105,6 +181,14 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst
105 return message; 181 return message;
106 } 182 }
107 183
  184 + private ProtoTransportPayloadConfiguration getProtoTransportPayloadConfiguration() {
  185 + DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
  186 + assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
  187 + MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
  188 + TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttTransportConfiguration.getTransportPayloadTypeConfiguration();
  189 + assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
  190 + return (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
  191 + }
108 192
109 193
110 } 194 }
@@ -119,7 +119,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac @@ -119,7 +119,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
119 " }\n" + 119 " }\n" +
120 " }\n" + 120 " }\n" +
121 "}"; 121 "}";
122 - super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, schemaStr, null, DeviceProfileProvisionType.DISABLED, null, null); 122 + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, schemaStr, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
123 List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); 123 List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
124 DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); 124 DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
125 assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration); 125 assertTrue(transportConfiguration instanceof MqttDeviceProfileTransportConfiguration);
@@ -172,7 +172,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac @@ -172,7 +172,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
172 172
173 @Test 173 @Test
174 public void testPushMqttTelemetryGateway() throws Exception { 174 public void testPushMqttTelemetryGateway() throws Exception {
175 - super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, null, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); 175 + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, null, null, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
176 TransportApiProtos.GatewayTelemetryMsg.Builder gatewayTelemetryMsgProtoBuilder = TransportApiProtos.GatewayTelemetryMsg.newBuilder(); 176 TransportApiProtos.GatewayTelemetryMsg.Builder gatewayTelemetryMsgProtoBuilder = TransportApiProtos.GatewayTelemetryMsg.newBuilder();
177 List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); 177 List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
178 String deviceName1 = "Device A"; 178 String deviceName1 = "Device A";
@@ -186,7 +186,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac @@ -186,7 +186,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
186 186
187 @Test 187 @Test
188 public void testGatewayConnect() throws Exception { 188 public void testGatewayConnect() throws Exception {
189 - super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, null, null, DeviceProfileProvisionType.DISABLED, null, null); 189 + super.processBeforeTest("Test Post Telemetry device proto payload", "Test Post Telemetry gateway proto payload", TransportPayloadType.PROTOBUF, POST_DATA_TELEMETRY_TOPIC, null, null, null, null, null, null, null, DeviceProfileProvisionType.DISABLED);
190 String deviceName = "Device A"; 190 String deviceName = "Device A";
191 TransportApiProtos.ConnectMsg connectMsgProto = getConnectProto(deviceName); 191 TransportApiProtos.ConnectMsg connectMsgProto = getConnectProto(deviceName);
192 MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken); 192 MqttAsyncClient client = getMqttAsyncClient(gatewayAccessToken);
@@ -102,4 +102,6 @@ public interface DeviceService { @@ -102,4 +102,6 @@ public interface DeviceService {
102 PageData<Device> findDevicesByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, PageLink pageLink); 102 PageData<Device> findDevicesByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, PageLink pageLink);
103 103
104 PageData<Device> findDevicesByTenantIdAndEdgeIdAndType(TenantId tenantId, EdgeId edgeId, String type, PageLink pageLink); 104 PageData<Device> findDevicesByTenantIdAndEdgeIdAndType(TenantId tenantId, EdgeId edgeId, String type, PageLink pageLink);
  105 +
  106 + long countByTenantId(TenantId tenantId);
105 } 107 }
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.event; @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.event;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.Event; 19 import org.thingsboard.server.common.data.Event;
  20 +import org.thingsboard.server.common.data.event.EventFilter;
20 import org.thingsboard.server.common.data.id.EntityId; 21 import org.thingsboard.server.common.data.id.EntityId;
21 import org.thingsboard.server.common.data.id.TenantId; 22 import org.thingsboard.server.common.data.id.TenantId;
22 import org.thingsboard.server.common.data.page.PageData; 23 import org.thingsboard.server.common.data.page.PageData;
@@ -41,6 +42,8 @@ public interface EventService { @@ -41,6 +42,8 @@ public interface EventService {
41 42
42 List<Event> findLatestEvents(TenantId tenantId, EntityId entityId, String eventType, int limit); 43 List<Event> findLatestEvents(TenantId tenantId, EntityId entityId, String eventType, int limit);
43 44
  45 + PageData<Event> findEventsByFilter(TenantId tenantId, EntityId entityId, EventFilter eventFilter, TimePageLink pageLink);
  46 +
44 void removeEvents(TenantId tenantId, EntityId entityId); 47 void removeEvents(TenantId tenantId, EntityId entityId);
45 48
46 } 49 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.resource;
  17 +
  18 +import org.thingsboard.server.common.data.ResourceType;
  19 +import org.thingsboard.server.common.data.TbResource;
  20 +import org.thingsboard.server.common.data.TbResourceInfo;
  21 +import org.thingsboard.server.common.data.id.TbResourceId;
  22 +import org.thingsboard.server.common.data.id.TenantId;
  23 +import org.thingsboard.server.common.data.page.PageData;
  24 +import org.thingsboard.server.common.data.page.PageLink;
  25 +
  26 +import java.util.List;
  27 +
  28 +public interface ResourceService {
  29 + TbResource saveResource(TbResource resource);
  30 +
  31 + TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId);
  32 +
  33 + TbResource findResourceById(TenantId tenantId, TbResourceId resourceId);
  34 +
  35 + TbResourceInfo findResourceInfoById(TenantId tenantId, TbResourceId resourceId);
  36 +
  37 + PageData<TbResourceInfo> findAllTenantResourcesByTenantId(TenantId tenantId, PageLink pageLink);
  38 +
  39 + PageData<TbResourceInfo> findTenantResourcesByTenantId(TenantId tenantId, PageLink pageLink);
  40 +
  41 + List<TbResource> findTenantResourcesByResourceTypeAndObjectIds(TenantId tenantId, ResourceType lwm2mModel, String[] objectIds);
  42 +
  43 + PageData<TbResource> findTenantResourcesByResourceTypeAndPageLink(TenantId tenantId, ResourceType lwm2mModel, PageLink pageLink);
  44 +
  45 + void deleteResource(TenantId tenantId, TbResourceId resourceId);
  46 +
  47 + void deleteResourcesByTenantId(TenantId tenantId);
  48 +
  49 +
  50 +}
@@ -43,7 +43,7 @@ public interface RuleChainService { @@ -43,7 +43,7 @@ public interface RuleChainService {
43 43
44 boolean setRootRuleChain(TenantId tenantId, RuleChainId ruleChainId); 44 boolean setRootRuleChain(TenantId tenantId, RuleChainId ruleChainId);
45 45
46 - RuleChainMetaData saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData); 46 + boolean saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData);
47 47
48 RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId); 48 RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId);
49 49
@@ -91,10 +91,6 @@ @@ -91,10 +91,6 @@
91 <groupId>org.apache.commons</groupId> 91 <groupId>org.apache.commons</groupId>
92 <artifactId>commons-lang3</artifactId> 92 <artifactId>commons-lang3</artifactId>
93 </dependency> 93 </dependency>
94 - <dependency>  
95 - <groupId>org.eclipse.leshan</groupId>  
96 - <artifactId>leshan-core</artifactId>  
97 - </dependency>  
98 </dependencies> 94 </dependencies>
99 95
100 <build> 96 <build>
@@ -19,14 +19,18 @@ import com.fasterxml.jackson.annotation.JsonProperty; @@ -19,14 +19,18 @@ import com.fasterxml.jackson.annotation.JsonProperty;
19 import org.thingsboard.server.common.data.id.CustomerId; 19 import org.thingsboard.server.common.data.id.CustomerId;
20 import org.thingsboard.server.common.data.id.DashboardId; 20 import org.thingsboard.server.common.data.id.DashboardId;
21 import org.thingsboard.server.common.data.id.TenantId; 21 import org.thingsboard.server.common.data.id.TenantId;
  22 +import org.thingsboard.server.common.data.validation.NoXss;
22 23
  24 +import javax.validation.Valid;
23 import java.util.HashSet; 25 import java.util.HashSet;
24 import java.util.Set; 26 import java.util.Set;
25 27
26 public class DashboardInfo extends SearchTextBased<DashboardId> implements HasName, HasTenantId { 28 public class DashboardInfo extends SearchTextBased<DashboardId> implements HasName, HasTenantId {
27 29
28 private TenantId tenantId; 30 private TenantId tenantId;
  31 + @NoXss
29 private String title; 32 private String title;
  33 + @Valid
30 private Set<ShortCustomerInfo> assignedCustomers; 34 private Set<ShortCustomerInfo> assignedCustomers;
31 35
32 public DashboardInfo() { 36 public DashboardInfo() {
@@ -19,6 +19,7 @@ import lombok.AllArgsConstructor; @@ -19,6 +19,7 @@ import lombok.AllArgsConstructor;
19 import lombok.Getter; 19 import lombok.Getter;
20 import lombok.Setter; 20 import lombok.Setter;
21 import org.thingsboard.server.common.data.id.CustomerId; 21 import org.thingsboard.server.common.data.id.CustomerId;
  22 +import org.thingsboard.server.common.data.validation.NoXss;
22 23
23 /** 24 /**
24 * Created by igor on 2/27/18. 25 * Created by igor on 2/27/18.
@@ -31,6 +32,7 @@ public class ShortCustomerInfo { @@ -31,6 +32,7 @@ public class ShortCustomerInfo {
31 private CustomerId customerId; 32 private CustomerId customerId;
32 33
33 @Getter @Setter 34 @Getter @Setter
  35 + @NoXss
34 private String title; 36 private String title;
35 37
36 @Getter @Setter 38 @Getter @Setter
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data;
  17 +
  18 +public class StringUtils {
  19 +
  20 + public static boolean isEmpty(String source) {
  21 + return source == null || source.isEmpty();
  22 + }
  23 +
  24 + public static boolean isNotEmpty(String source) {
  25 + return source != null && !source.isEmpty();
  26 + }
  27 +}
@@ -19,6 +19,7 @@ import lombok.Data; @@ -19,6 +19,7 @@ import lombok.Data;
19 import lombok.EqualsAndHashCode; 19 import lombok.EqualsAndHashCode;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 import org.thingsboard.server.common.data.id.TbResourceId; 21 import org.thingsboard.server.common.data.id.TbResourceId;
  22 +import org.thingsboard.server.common.data.validation.NoXss;
22 23
23 @Slf4j 24 @Slf4j
24 @Data 25 @Data
@@ -27,6 +28,7 @@ public class TbResource extends TbResourceInfo { @@ -27,6 +28,7 @@ public class TbResource extends TbResourceInfo {
27 28
28 private static final long serialVersionUID = 7379609705527272306L; 29 private static final long serialVersionUID = 7379609705527272306L;
29 30
  31 + @NoXss
30 private String fileName; 32 private String fileName;
31 33
32 private String data; 34 private String data;
@@ -20,6 +20,7 @@ import lombok.EqualsAndHashCode; @@ -20,6 +20,7 @@ import lombok.EqualsAndHashCode;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 import org.thingsboard.server.common.data.id.TbResourceId; 21 import org.thingsboard.server.common.data.id.TbResourceId;
22 import org.thingsboard.server.common.data.id.TenantId; 22 import org.thingsboard.server.common.data.id.TenantId;
  23 +import org.thingsboard.server.common.data.validation.NoXss;
23 24
24 @Slf4j 25 @Slf4j
25 @Data 26 @Data
@@ -27,6 +28,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -27,6 +28,7 @@ import org.thingsboard.server.common.data.id.TenantId;
27 public class TbResourceInfo extends SearchTextBased<TbResourceId> implements HasTenantId { 28 public class TbResourceInfo extends SearchTextBased<TbResourceId> implements HasTenantId {
28 29
29 private TenantId tenantId; 30 private TenantId tenantId;
  31 + @NoXss
30 private String title; 32 private String title;
31 private ResourceType resourceType; 33 private ResourceType resourceType;
32 private String resourceKey; 34 private String resourceKey;
@@ -19,11 +19,8 @@ import lombok.AllArgsConstructor; @@ -19,11 +19,8 @@ import lombok.AllArgsConstructor;
19 import lombok.Builder; 19 import lombok.Builder;
20 import lombok.Data; 20 import lombok.Data;
21 import org.thingsboard.server.common.data.id.EntityId; 21 import org.thingsboard.server.common.data.id.EntityId;
22 -import org.thingsboard.server.common.data.id.TenantId;  
23 import org.thingsboard.server.common.data.page.TimePageLink; 22 import org.thingsboard.server.common.data.page.TimePageLink;
24 23
25 -import java.util.UUID;  
26 -  
27 /** 24 /**
28 * Created by ashvayka on 11.05.17. 25 * Created by ashvayka on 11.05.17.
29 */ 26 */
@@ -37,6 +34,5 @@ public class AlarmQuery { @@ -37,6 +34,5 @@ public class AlarmQuery {
37 private AlarmSearchStatus searchStatus; 34 private AlarmSearchStatus searchStatus;
38 private AlarmStatus status; 35 private AlarmStatus status;
39 private Boolean fetchOriginator; 36 private Boolean fetchOriginator;
40 - private UUID idOffset;  
41 37
42 } 38 }
@@ -25,6 +25,7 @@ import java.util.List; @@ -25,6 +25,7 @@ import java.util.List;
25 public class DeviceProfileData implements Serializable { 25 public class DeviceProfileData implements Serializable {
26 26
27 private DeviceProfileConfiguration configuration; 27 private DeviceProfileConfiguration configuration;
  28 + @Valid
28 private DeviceProfileTransportConfiguration transportConfiguration; 29 private DeviceProfileTransportConfiguration transportConfiguration;
29 private DeviceProfileProvisionConfiguration provisionConfiguration; 30 private DeviceProfileProvisionConfiguration provisionConfiguration;
30 @Valid 31 @Valid
@@ -17,11 +17,14 @@ package org.thingsboard.server.common.data.device.profile; @@ -17,11 +17,14 @@ package org.thingsboard.server.common.data.device.profile;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import org.thingsboard.server.common.data.DeviceTransportType; 19 import org.thingsboard.server.common.data.DeviceTransportType;
  20 +import org.thingsboard.server.common.data.validation.NoXss;
20 21
21 @Data 22 @Data
22 public class MqttDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration { 23 public class MqttDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration {
23 24
  25 + @NoXss
24 private String deviceTelemetryTopic = MqttTopics.DEVICE_TELEMETRY_TOPIC; 26 private String deviceTelemetryTopic = MqttTopics.DEVICE_TELEMETRY_TOPIC;
  27 + @NoXss
25 private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC; 28 private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC;
26 private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; 29 private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration;
27 30
@@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.device.profile; 16 package org.thingsboard.server.common.data.device.profile;
17 17
18 -import com.fasterxml.jackson.annotation.JsonIgnore;  
19 import com.github.os72.protobuf.dynamic.DynamicSchema; 18 import com.github.os72.protobuf.dynamic.DynamicSchema;
20 import com.github.os72.protobuf.dynamic.EnumDefinition; 19 import com.github.os72.protobuf.dynamic.EnumDefinition;
21 import com.github.os72.protobuf.dynamic.MessageDefinition; 20 import com.github.os72.protobuf.dynamic.MessageDefinition;
@@ -46,9 +45,13 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC @@ -46,9 +45,13 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC
46 public static final Location LOCATION = new Location("", "", -1, -1); 45 public static final Location LOCATION = new Location("", "", -1, -1);
47 public static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema"; 46 public static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema";
48 public static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema"; 47 public static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema";
  48 + public static final String RPC_RESPONSE_PROTO_SCHEMA = "rpc response proto schema";
  49 + public static final String RPC_REQUEST_PROTO_SCHEMA = "rpc request proto schema";
49 50
50 private String deviceTelemetryProtoSchema; 51 private String deviceTelemetryProtoSchema;
51 private String deviceAttributesProtoSchema; 52 private String deviceAttributesProtoSchema;
  53 + private String deviceRpcRequestProtoSchema;
  54 + private String deviceRpcResponseProtoSchema;
52 55
53 @Override 56 @Override
54 public TransportPayloadType getTransportPayloadType() { 57 public TransportPayloadType getTransportPayloadType() {
@@ -63,13 +66,45 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC @@ -63,13 +66,45 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC
63 return getDescriptor(deviceAttributesProtoSchema, ATTRIBUTES_PROTO_SCHEMA); 66 return getDescriptor(deviceAttributesProtoSchema, ATTRIBUTES_PROTO_SCHEMA);
64 } 67 }
65 68
  69 + public Descriptors.Descriptor getRpcResponseDynamicMessageDescriptor(String deviceRpcResponseProtoSchema) {
  70 + return getDescriptor(deviceRpcResponseProtoSchema, RPC_RESPONSE_PROTO_SCHEMA);
  71 + }
  72 +
  73 + public DynamicMessage.Builder getRpcRequestDynamicMessageBuilder(String deviceRpcRequestProtoSchema) {
  74 + return getDynamicMessageBuilder(deviceRpcRequestProtoSchema, RPC_REQUEST_PROTO_SCHEMA);
  75 + }
  76 +
  77 + public String getDeviceRpcResponseProtoSchema() {
  78 + if (!isEmptyStr(deviceRpcResponseProtoSchema)) {
  79 + return deviceRpcResponseProtoSchema;
  80 + } else {
  81 + return "syntax =\"proto3\";\n" +
  82 + "package rpc;\n" +
  83 + "\n" +
  84 + "message RpcResponseMsg {\n" +
  85 + " string payload = 1;\n" +
  86 + "}";
  87 + }
  88 + }
  89 +
  90 + public String getDeviceRpcRequestProtoSchema() {
  91 + if (!isEmptyStr(deviceRpcRequestProtoSchema)) {
  92 + return deviceRpcRequestProtoSchema;
  93 + } else {
  94 + return "syntax =\"proto3\";\n" +
  95 + "package rpc;\n" +
  96 + "\n" +
  97 + "message RpcRequestMsg {\n" +
  98 + " string method = 1;\n" +
  99 + " int32 requestId = 2;\n" +
  100 + " string params = 3;\n" +
  101 + "}";
  102 + }
  103 + }
  104 +
66 private Descriptors.Descriptor getDescriptor(String protoSchema, String schemaName) { 105 private Descriptors.Descriptor getDescriptor(String protoSchema, String schemaName) {
67 try { 106 try {
68 - ProtoFileElement protoFileElement = getTransportProtoSchema(protoSchema);  
69 - DynamicSchema dynamicSchema = getDynamicSchema(protoFileElement, schemaName);  
70 - String lastMsgName = getMessageTypes(protoFileElement.getTypes()).stream()  
71 - .map(MessageElement::getName).reduce((previous, last) -> last).get();  
72 - DynamicMessage.Builder builder = dynamicSchema.newMessageBuilder(lastMsgName); 107 + DynamicMessage.Builder builder = getDynamicMessageBuilder(protoSchema, schemaName);
73 return builder.getDescriptorForType(); 108 return builder.getDescriptorForType();
74 } catch (Exception e) { 109 } catch (Exception e) {
75 log.warn("Failed to get Message Descriptor due to {}", e.getMessage()); 110 log.warn("Failed to get Message Descriptor due to {}", e.getMessage());
@@ -77,6 +112,14 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC @@ -77,6 +112,14 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC
77 } 112 }
78 } 113 }
79 114
  115 + public DynamicMessage.Builder getDynamicMessageBuilder(String protoSchema, String schemaName) {
  116 + ProtoFileElement protoFileElement = getTransportProtoSchema(protoSchema);
  117 + DynamicSchema dynamicSchema = getDynamicSchema(protoFileElement, schemaName);
  118 + String lastMsgName = getMessageTypes(protoFileElement.getTypes()).stream()
  119 + .map(MessageElement::getName).reduce((previous, last) -> last).get();
  120 + return dynamicSchema.newMessageBuilder(lastMsgName);
  121 + }
  122 +
80 public DynamicSchema getDynamicSchema(ProtoFileElement protoFileElement, String schemaName) { 123 public DynamicSchema getDynamicSchema(ProtoFileElement protoFileElement, String schemaName) {
81 DynamicSchema.Builder schemaBuilder = DynamicSchema.newBuilder(); 124 DynamicSchema.Builder schemaBuilder = DynamicSchema.newBuilder();
82 schemaBuilder.setName(schemaName); 125 schemaBuilder.setName(schemaName);
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.event;
  17 +
  18 +import lombok.Data;
  19 +import org.thingsboard.server.common.data.StringUtils;
  20 +
  21 +@Data
  22 +public abstract class DebugEvent implements EventFilter {
  23 +
  24 + private String msgDirectionType;
  25 + private String server;
  26 + private String dataSearch;
  27 + private String metadataSearch;
  28 + private String entityName;
  29 + private String relationType;
  30 + private String entityId;
  31 + private String msgType;
  32 + private boolean isError;
  33 + private String error;
  34 +
  35 + public void setIsError(boolean isError) {
  36 + this.isError = isError;
  37 + }
  38 +
  39 + @Override
  40 + public boolean hasFilterForJsonBody() {
  41 + return !StringUtils.isEmpty(msgDirectionType) || !StringUtils.isEmpty(server) || !StringUtils.isEmpty(dataSearch) || !StringUtils.isEmpty(metadataSearch)
  42 + || !StringUtils.isEmpty(entityName) || !StringUtils.isEmpty(relationType) || !StringUtils.isEmpty(entityId) || !StringUtils.isEmpty(msgType) || !StringUtils.isEmpty(error) || isError;
  43 + }
  44 +
  45 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.event;
  17 +
  18 +public class DebugRuleChainEventFilter extends DebugEvent {
  19 + @Override
  20 + public EventType getEventType() {
  21 + return EventType.DEBUG_RULE_CHAIN;
  22 + }
  23 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.event;
  17 +
  18 +public class DebugRuleNodeEventFilter extends DebugEvent {
  19 + @Override
  20 + public EventType getEventType() {
  21 + return EventType.DEBUG_RULE_NODE;
  22 + }
  23 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.event;
  17 +
  18 +import lombok.Data;
  19 +import org.thingsboard.server.common.data.StringUtils;
  20 +
  21 +@Data
  22 +public class ErrorEventFilter implements EventFilter {
  23 + private String server;
  24 + private String method;
  25 + private String error;
  26 +
  27 + @Override
  28 + public EventType getEventType() {
  29 + return EventType.ERROR;
  30 + }
  31 +
  32 + @Override
  33 + public boolean hasFilterForJsonBody() {
  34 + return !StringUtils.isEmpty(server) || !StringUtils.isEmpty(method) || !StringUtils.isEmpty(error);
  35 + }
  36 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.event;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  20 +import com.fasterxml.jackson.annotation.JsonSubTypes;
  21 +import com.fasterxml.jackson.annotation.JsonTypeInfo;
  22 +
  23 +@JsonTypeInfo(
  24 + use = JsonTypeInfo.Id.NAME,
  25 + include = JsonTypeInfo.As.PROPERTY,
  26 + property = "eventType")
  27 +@JsonSubTypes({
  28 + @JsonSubTypes.Type(value = DebugRuleNodeEventFilter.class, name = "DEBUG_RULE_NODE"),
  29 + @JsonSubTypes.Type(value = DebugRuleChainEventFilter.class, name = "DEBUG_RULE_CHAIN"),
  30 + @JsonSubTypes.Type(value = ErrorEventFilter.class, name = "ERROR"),
  31 + @JsonSubTypes.Type(value = LifeCycleEventFilter.class, name = "LC_EVENT"),
  32 + @JsonSubTypes.Type(value = StatisticsEventFilter.class, name = "STATS")
  33 +})
  34 +public interface EventFilter {
  35 + @JsonIgnore
  36 + EventType getEventType();
  37 +
  38 + boolean hasFilterForJsonBody();
  39 +
  40 +}
common/data/src/main/java/org/thingsboard/server/common/data/event/EventType.java renamed from ui-ngx/src/app/shared/components/time/quick-time-interval.component.scss
@@ -13,7 +13,8 @@ @@ -13,7 +13,8 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
  16 +package org.thingsboard.server.common.data.event;
16 17
17 -:host {  
18 - min-width: 364px;  
19 -} 18 +public enum EventType {
  19 + ERROR, LC_EVENT, STATS, DEBUG_RULE_NODE, DEBUG_RULE_CHAIN
  20 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.event;
  17 +
  18 +import lombok.Data;
  19 +import org.thingsboard.server.common.data.StringUtils;
  20 +
  21 +@Data
  22 +public class LifeCycleEventFilter implements EventFilter {
  23 + private String server;
  24 + private String event;
  25 + private String status;
  26 + private String error;
  27 +
  28 + @Override
  29 + public EventType getEventType() {
  30 + return EventType.LC_EVENT;
  31 + }
  32 +
  33 + @Override
  34 + public boolean hasFilterForJsonBody() {
  35 + return !StringUtils.isEmpty(server) || !StringUtils.isEmpty(event) || !StringUtils.isEmpty(status) || !StringUtils.isEmpty(error);
  36 + }
  37 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.event;
  17 +
  18 +import lombok.Data;
  19 +import org.thingsboard.server.common.data.StringUtils;
  20 +
  21 +@Data
  22 +public class StatisticsEventFilter implements EventFilter {
  23 + private String server;
  24 + private Integer messagesProcessed;
  25 + private Integer errorsOccurred;
  26 +
  27 + @Override
  28 + public EventType getEventType() {
  29 + return EventType.STATS;
  30 + }
  31 +
  32 + @Override
  33 + public boolean hasFilterForJsonBody() {
  34 + return !StringUtils.isEmpty(server) || (messagesProcessed != null && messagesProcessed > 0) || (errorsOccurred != null && errorsOccurred > 0);
  35 + }
  36 +}
@@ -15,10 +15,16 @@ @@ -15,10 +15,16 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.tenant.profile; 16 package org.thingsboard.server.common.data.tenant.profile;
17 17
  18 +import lombok.AllArgsConstructor;
  19 +import lombok.Builder;
18 import lombok.Data; 20 import lombok.Data;
  21 +import lombok.NoArgsConstructor;
19 import org.thingsboard.server.common.data.ApiUsageRecordKey; 22 import org.thingsboard.server.common.data.ApiUsageRecordKey;
20 import org.thingsboard.server.common.data.TenantProfileType; 23 import org.thingsboard.server.common.data.TenantProfileType;
21 24
  25 +@AllArgsConstructor
  26 +@NoArgsConstructor
  27 +@Builder
22 @Data 28 @Data
23 public class DefaultTenantProfileConfiguration implements TenantProfileConfiguration { 29 public class DefaultTenantProfileConfiguration implements TenantProfileConfiguration {
24 30
@@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.BaseData; @@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.BaseData;
20 import org.thingsboard.server.common.data.HasTenantId; 20 import org.thingsboard.server.common.data.HasTenantId;
21 import org.thingsboard.server.common.data.id.TenantId; 21 import org.thingsboard.server.common.data.id.TenantId;
22 import org.thingsboard.server.common.data.id.WidgetTypeId; 22 import org.thingsboard.server.common.data.id.WidgetTypeId;
  23 +import org.thingsboard.server.common.data.validation.NoXss;
23 24
24 @Data 25 @Data
25 public class BaseWidgetType extends BaseData<WidgetTypeId> implements HasTenantId { 26 public class BaseWidgetType extends BaseData<WidgetTypeId> implements HasTenantId {
@@ -27,8 +28,11 @@ public class BaseWidgetType extends BaseData<WidgetTypeId> implements HasTenantI @@ -27,8 +28,11 @@ public class BaseWidgetType extends BaseData<WidgetTypeId> implements HasTenantI
27 private static final long serialVersionUID = 8388684344603660756L; 28 private static final long serialVersionUID = 8388684344603660756L;
28 29
29 private TenantId tenantId; 30 private TenantId tenantId;
  31 + @NoXss
30 private String bundleAlias; 32 private String bundleAlias;
  33 + @NoXss
31 private String alias; 34 private String alias;
  35 + @NoXss
32 private String name; 36 private String name;
33 37
34 public BaseWidgetType() { 38 public BaseWidgetType() {
@@ -15,14 +15,15 @@ @@ -15,14 +15,15 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.widget; 16 package org.thingsboard.server.common.data.widget;
17 17
18 -import com.fasterxml.jackson.databind.JsonNode;  
19 import lombok.Data; 18 import lombok.Data;
20 import org.thingsboard.server.common.data.id.WidgetTypeId; 19 import org.thingsboard.server.common.data.id.WidgetTypeId;
  20 +import org.thingsboard.server.common.data.validation.NoXss;
21 21
22 @Data 22 @Data
23 public class WidgetTypeDetails extends WidgetType { 23 public class WidgetTypeDetails extends WidgetType {
24 24
25 private String image; 25 private String image;
  26 + @NoXss
26 private String description; 27 private String description;
27 28
28 public WidgetTypeDetails() { 29 public WidgetTypeDetails() {
@@ -17,12 +17,15 @@ package org.thingsboard.server.common.data.widget; @@ -17,12 +17,15 @@ package org.thingsboard.server.common.data.widget;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import org.thingsboard.server.common.data.id.WidgetTypeId; 19 import org.thingsboard.server.common.data.id.WidgetTypeId;
  20 +import org.thingsboard.server.common.data.validation.NoXss;
20 21
21 @Data 22 @Data
22 public class WidgetTypeInfo extends BaseWidgetType { 23 public class WidgetTypeInfo extends BaseWidgetType {
23 24
24 private String image; 25 private String image;
  26 + @NoXss
25 private String description; 27 private String description;
  28 + @NoXss
26 private String widgetType; 29 private String widgetType;
27 30
28 public WidgetTypeInfo() { 31 public WidgetTypeInfo() {
@@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.HasTenantId; @@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.HasTenantId;
19 import org.thingsboard.server.common.data.SearchTextBased; 19 import org.thingsboard.server.common.data.SearchTextBased;
20 import org.thingsboard.server.common.data.id.TenantId; 20 import org.thingsboard.server.common.data.id.TenantId;
21 import org.thingsboard.server.common.data.id.WidgetsBundleId; 21 import org.thingsboard.server.common.data.id.WidgetsBundleId;
  22 +import org.thingsboard.server.common.data.validation.NoXss;
22 23
23 import java.util.Arrays; 24 import java.util.Arrays;
24 25
@@ -27,9 +28,12 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H @@ -27,9 +28,12 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H
27 private static final long serialVersionUID = -7627368878362410489L; 28 private static final long serialVersionUID = -7627368878362410489L;
28 29
29 private TenantId tenantId; 30 private TenantId tenantId;
  31 + @NoXss
30 private String alias; 32 private String alias;
  33 + @NoXss
31 private String title; 34 private String title;
32 private String image; 35 private String image;
  36 + @NoXss
33 private String description; 37 private String description;
34 38
35 public WidgetsBundle() { 39 public WidgetsBundle() {
@@ -113,6 +113,10 @@ @@ -113,6 +113,10 @@
113 <artifactId>protobuf-java</artifactId> 113 <artifactId>protobuf-java</artifactId>
114 </dependency> 114 </dependency>
115 <dependency> 115 <dependency>
  116 + <groupId>com.google.protobuf</groupId>
  117 + <artifactId>protobuf-java-util</artifactId>
  118 + </dependency>
  119 + <dependency>
116 <groupId>org.apache.curator</groupId> 120 <groupId>org.apache.curator</groupId>
117 <artifactId>curator-recipes</artifactId> 121 <artifactId>curator-recipes</artifactId>
118 </dependency> 122 </dependency>
@@ -21,22 +21,28 @@ import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; @@ -21,22 +21,28 @@ import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
21 import org.thingsboard.server.queue.TbQueueConsumer; 21 import org.thingsboard.server.queue.TbQueueConsumer;
22 import org.thingsboard.server.queue.TbQueueMsg; 22 import org.thingsboard.server.queue.TbQueueMsg;
23 23
  24 +import javax.annotation.Nonnull;
24 import java.io.IOException; 25 import java.io.IOException;
25 import java.util.ArrayList; 26 import java.util.ArrayList;
26 import java.util.Collections; 27 import java.util.Collections;
27 import java.util.List; 28 import java.util.List;
  29 +import java.util.Queue;
28 import java.util.Set; 30 import java.util.Set;
29 -import java.util.concurrent.locks.Lock; 31 +import java.util.concurrent.ConcurrentLinkedQueue;
  32 +import java.util.concurrent.TimeUnit;
30 import java.util.concurrent.locks.ReentrantLock; 33 import java.util.concurrent.locks.ReentrantLock;
31 import java.util.stream.Collectors; 34 import java.util.stream.Collectors;
32 35
  36 +import static java.util.Collections.emptyList;
  37 +
33 @Slf4j 38 @Slf4j
34 public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> implements TbQueueConsumer<T> { 39 public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> implements TbQueueConsumer<T> {
35 40
36 private volatile boolean subscribed; 41 private volatile boolean subscribed;
37 protected volatile boolean stopped = false; 42 protected volatile boolean stopped = false;
38 protected volatile Set<TopicPartitionInfo> partitions; 43 protected volatile Set<TopicPartitionInfo> partitions;
39 - protected final Lock consumerLock = new ReentrantLock(); 44 + protected final ReentrantLock consumerLock = new ReentrantLock(); //NonfairSync
  45 + final Queue<Set<TopicPartitionInfo>> subscribeQueue = new ConcurrentLinkedQueue<>();
40 46
41 @Getter 47 @Getter
42 private final String topic; 48 private final String topic;
@@ -47,84 +53,101 @@ public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> i @@ -47,84 +53,101 @@ public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> i
47 53
48 @Override 54 @Override
49 public void subscribe() { 55 public void subscribe() {
50 - consumerLock.lock();  
51 - try {  
52 - partitions = Collections.singleton(new TopicPartitionInfo(topic, null, null, true));  
53 - subscribed = false;  
54 - } finally {  
55 - consumerLock.unlock(); 56 + log.info("enqueue topic subscribe {} ", topic);
  57 + if (stopped) {
  58 + log.error("trying subscribe, but consumer stopped for topic {}", topic);
  59 + return;
56 } 60 }
  61 + subscribeQueue.add(Collections.singleton(new TopicPartitionInfo(topic, null, null, true)));
57 } 62 }
58 63
59 @Override 64 @Override
60 public void subscribe(Set<TopicPartitionInfo> partitions) { 65 public void subscribe(Set<TopicPartitionInfo> partitions) {
  66 + log.info("enqueue topics subscribe {} ", partitions);
  67 + if (stopped) {
  68 + log.error("trying subscribe, but consumer stopped for topic {}", topic);
  69 + return;
  70 + }
  71 + subscribeQueue.add(partitions);
  72 + }
  73 +
  74 + @Override
  75 + public List<T> poll(long durationInMillis) {
  76 + List<R> records;
  77 + long startNanos = System.nanoTime();
  78 + if (stopped) {
  79 + return errorAndReturnEmpty();
  80 + }
  81 + if (!subscribed && partitions == null && subscribeQueue.isEmpty()) {
  82 + return sleepAndReturnEmpty(startNanos, durationInMillis);
  83 + }
  84 +
  85 + if (consumerLock.isLocked()) {
  86 + log.error("poll. consumerLock is locked. will wait with no timeout. it looks like a race conditions or deadlock", new RuntimeException("stacktrace"));
  87 + }
  88 +
61 consumerLock.lock(); 89 consumerLock.lock();
62 try { 90 try {
63 - this.partitions = partitions;  
64 - subscribed = false; 91 + while (!subscribeQueue.isEmpty()) {
  92 + subscribed = false;
  93 + partitions = subscribeQueue.poll();
  94 + }
  95 + if (!subscribed) {
  96 + List<String> topicNames = partitions.stream().map(TopicPartitionInfo::getFullTopicName).collect(Collectors.toList());
  97 + doSubscribe(topicNames);
  98 + subscribed = true;
  99 + }
  100 + records = partitions.isEmpty() ? emptyList() : doPoll(durationInMillis);
65 } finally { 101 } finally {
66 consumerLock.unlock(); 102 consumerLock.unlock();
67 } 103 }
  104 +
  105 + if (records.isEmpty()) { return sleepAndReturnEmpty(startNanos, durationInMillis); }
  106 +
  107 + return decodeRecords(records);
68 } 108 }
69 109
70 - @Override  
71 - public List<T> poll(long durationInMillis) {  
72 - if (!subscribed && partitions == null) {  
73 - try {  
74 - Thread.sleep(durationInMillis);  
75 - } catch (InterruptedException e) {  
76 - log.debug("Failed to await subscription", e);  
77 - }  
78 - } else {  
79 - long pollStartTs = System.currentTimeMillis();  
80 - consumerLock.lock(); 110 + @Nonnull
  111 + List<T> decodeRecords(@Nonnull List<R> records) {
  112 + List<T> result = new ArrayList<>(records.size());
  113 + records.forEach(record -> {
81 try { 114 try {
82 - if (!subscribed) {  
83 - List<String> topicNames = partitions.stream().map(TopicPartitionInfo::getFullTopicName).collect(Collectors.toList());  
84 - doSubscribe(topicNames);  
85 - subscribed = true; 115 + if (record != null) {
  116 + result.add(decode(record));
86 } 117 }
  118 + } catch (IOException e) {
  119 + log.error("Failed decode record: [{}]", record);
  120 + throw new RuntimeException("Failed to decode record: ", e);
  121 + }
  122 + });
  123 + return result;
  124 + }
87 125
88 - List<R> records;  
89 - if (partitions.isEmpty()) {  
90 - records = Collections.emptyList();  
91 - } else {  
92 - records = doPoll(durationInMillis);  
93 - }  
94 - if (!records.isEmpty()) {  
95 - List<T> result = new ArrayList<>(records.size());  
96 - records.forEach(record -> {  
97 - try {  
98 - if (record != null) {  
99 - result.add(decode(record));  
100 - }  
101 - } catch (IOException e) {  
102 - log.error("Failed decode record: [{}]", record);  
103 - throw new RuntimeException("Failed to decode record: ", e);  
104 - }  
105 - });  
106 - return result;  
107 - } else {  
108 - long pollDuration = System.currentTimeMillis() - pollStartTs;  
109 - if (pollDuration < durationInMillis) {  
110 - try {  
111 - Thread.sleep(durationInMillis - pollDuration);  
112 - } catch (InterruptedException e) {  
113 - if (!stopped) {  
114 - log.error("Failed to wait.", e);  
115 - }  
116 - }  
117 - } 126 + List<T> errorAndReturnEmpty() {
  127 + log.error("poll invoked but consumer stopped for topic" + topic, new RuntimeException("stacktrace"));
  128 + return emptyList();
  129 + }
  130 +
  131 + List<T> sleepAndReturnEmpty(final long startNanos, final long durationInMillis) {
  132 + long durationNanos = TimeUnit.MILLISECONDS.toNanos(durationInMillis);
  133 + long spentNanos = System.nanoTime() - startNanos;
  134 + if (spentNanos < durationNanos) {
  135 + try {
  136 + Thread.sleep(Math.max(TimeUnit.NANOSECONDS.toMillis(durationNanos - spentNanos), 1));
  137 + } catch (InterruptedException e) {
  138 + if (!stopped) {
  139 + log.error("Failed to wait", e);
118 } 140 }
119 - } finally {  
120 - consumerLock.unlock();  
121 } 141 }
122 } 142 }
123 - return Collections.emptyList(); 143 + return emptyList();
124 } 144 }
125 145
126 @Override 146 @Override
127 public void commit() { 147 public void commit() {
  148 + if (consumerLock.isLocked()) {
  149 + log.error("commit. consumerLock is locked. will wait with no timeout. it looks like a race conditions or deadlock", new RuntimeException("stacktrace"));
  150 + }
128 consumerLock.lock(); 151 consumerLock.lock();
129 try { 152 try {
130 doCommit(); 153 doCommit();
@@ -135,6 +158,7 @@ public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> i @@ -135,6 +158,7 @@ public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> i
135 158
136 @Override 159 @Override
137 public void unsubscribe() { 160 public void unsubscribe() {
  161 + log.info("unsubscribe topic and stop consumer {}", getTopic());
138 stopped = true; 162 stopped = true;
139 consumerLock.lock(); 163 consumerLock.lock();
140 try { 164 try {
@@ -128,9 +128,10 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi @@ -128,9 +128,10 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi
128 log.debug("Ignoring application ready event, ZK client is not started, ZK client state [{}]", client.getState()); 128 log.debug("Ignoring application ready event, ZK client is not started, ZK client state [{}]", client.getState());
129 return; 129 return;
130 } 130 }
  131 + log.info("Going to publish current server...");
131 publishCurrentServer(); 132 publishCurrentServer();
132 - TransportProtos.ServiceInfo currentService = serviceInfoProvider.getServiceInfo();  
133 - partitionService.recalculatePartitions(currentService, getOtherServers()); 133 + log.info("Going to recalculate partitions...");
  134 + recalculatePartitions();
134 } 135 }
135 136
136 public synchronized void publishCurrentServer() { 137 public synchronized void publishCurrentServer() {
@@ -285,11 +286,19 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi @@ -285,11 +286,19 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi
285 case CHILD_ADDED: 286 case CHILD_ADDED:
286 case CHILD_UPDATED: 287 case CHILD_UPDATED:
287 case CHILD_REMOVED: 288 case CHILD_REMOVED:
288 - TransportProtos.ServiceInfo currentService = serviceInfoProvider.getServiceInfo();  
289 - partitionService.recalculatePartitions(currentService, getOtherServers()); 289 + recalculatePartitions();
290 break; 290 break;
291 default: 291 default:
292 break; 292 break;
293 } 293 }
294 } 294 }
  295 +
  296 + /**
  297 + * A single entry point to recalculate partitions
  298 + * Synchronized to ensure that other servers info is up to date
  299 + * */
  300 + synchronized void recalculatePartitions() {
  301 + partitionService.recalculatePartitions(serviceInfoProvider.getServiceInfo(), getOtherServers());
  302 + }
  303 +
295 } 304 }
@@ -72,8 +72,10 @@ public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQue @@ -72,8 +72,10 @@ public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQue
72 protected void doSubscribe(List<String> topicNames) { 72 protected void doSubscribe(List<String> topicNames) {
73 if (!topicNames.isEmpty()) { 73 if (!topicNames.isEmpty()) {
74 topicNames.forEach(admin::createTopicIfNotExists); 74 topicNames.forEach(admin::createTopicIfNotExists);
  75 + log.info("subscribe topics {}", topicNames);
75 consumer.subscribe(topicNames); 76 consumer.subscribe(topicNames);
76 } else { 77 } else {
  78 + log.info("unsubscribe due to empty topic list");
77 consumer.unsubscribe(); 79 consumer.unsubscribe();
78 } 80 }
79 } 81 }
@@ -102,6 +104,7 @@ public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQue @@ -102,6 +104,7 @@ public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQue
102 104
103 @Override 105 @Override
104 protected void doUnsubscribe() { 106 protected void doUnsubscribe() {
  107 + log.info("unsubscribe topic and close consumer for topic {}", getTopic());
105 if (consumer != null) { 108 if (consumer != null) {
106 consumer.unsubscribe(); 109 consumer.unsubscribe();
107 consumer.close(); 110 consumer.close();
@@ -17,6 +17,7 @@ package org.thingsboard.server.transport.coap; @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.coap;
17 17
18 import com.google.gson.JsonParseException; 18 import com.google.gson.JsonParseException;
19 import com.google.protobuf.Descriptors; 19 import com.google.protobuf.Descriptors;
  20 +import com.google.protobuf.DynamicMessage;
20 import lombok.Data; 21 import lombok.Data;
21 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
22 import org.eclipse.californium.core.coap.CoAP; 23 import org.eclipse.californium.core.coap.CoAP;
@@ -261,7 +262,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -261,7 +262,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
261 TransportProtos.SessionInfoProto currentAttrSession = tokenToSessionIdMap.get(getTokenFromRequest(request)); 262 TransportProtos.SessionInfoProto currentAttrSession = tokenToSessionIdMap.get(getTokenFromRequest(request));
262 if (currentAttrSession == null) { 263 if (currentAttrSession == null) {
263 attributeSubscriptions.add(sessionId); 264 attributeSubscriptions.add(sessionId);
264 - registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor, getTokenFromRequest(request)); 265 + registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor,
  266 + transportConfigurationContainer.getRpcRequestDynamicMessageBuilder(), getTokenFromRequest(request));
265 transportService.process(sessionInfo, 267 transportService.process(sessionInfo,
266 TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), new CoapNoOpCallback(exchange)); 268 TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), new CoapNoOpCallback(exchange));
267 } 269 }
@@ -281,7 +283,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -281,7 +283,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
281 TransportProtos.SessionInfoProto currentRpcSession = tokenToSessionIdMap.get(getTokenFromRequest(request)); 283 TransportProtos.SessionInfoProto currentRpcSession = tokenToSessionIdMap.get(getTokenFromRequest(request));
282 if (currentRpcSession == null) { 284 if (currentRpcSession == null) {
283 rpcSubscriptions.add(sessionId); 285 rpcSubscriptions.add(sessionId);
284 - registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor, getTokenFromRequest(request)); 286 + registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor,
  287 + transportConfigurationContainer.getRpcRequestDynamicMessageBuilder(), getTokenFromRequest(request));
285 transportService.process(sessionInfo, 288 transportService.process(sessionInfo,
286 TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), 289 TransportProtos.SubscribeToRPCMsg.getDefaultInstance(),
287 new CoapNoOpCallback(exchange)); 290 new CoapNoOpCallback(exchange));
@@ -303,17 +306,19 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -303,17 +306,19 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
303 break; 306 break;
304 case TO_DEVICE_RPC_RESPONSE: 307 case TO_DEVICE_RPC_RESPONSE:
305 transportService.process(sessionInfo, 308 transportService.process(sessionInfo,
306 - coapTransportAdaptor.convertToDeviceRpcResponse(sessionId, request), 309 + coapTransportAdaptor.convertToDeviceRpcResponse(sessionId, request, transportConfigurationContainer.getRpcResponseMsgDescriptor()),
307 new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); 310 new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR));
308 break; 311 break;
309 case TO_SERVER_RPC_REQUEST: 312 case TO_SERVER_RPC_REQUEST:
310 - transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor), timeout); 313 + transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor,
  314 + transportConfigurationContainer.getRpcRequestDynamicMessageBuilder()), timeout);
311 transportService.process(sessionInfo, 315 transportService.process(sessionInfo,
312 coapTransportAdaptor.convertToServerRpcRequest(sessionId, request), 316 coapTransportAdaptor.convertToServerRpcRequest(sessionId, request),
313 new CoapNoOpCallback(exchange)); 317 new CoapNoOpCallback(exchange));
314 break; 318 break;
315 case GET_ATTRIBUTES_REQUEST: 319 case GET_ATTRIBUTES_REQUEST:
316 - transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor), timeout); 320 + transportService.registerSyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor,
  321 + transportConfigurationContainer.getRpcRequestDynamicMessageBuilder()), timeout);
317 transportService.process(sessionInfo, 322 transportService.process(sessionInfo,
318 coapTransportAdaptor.convertToGetAttributes(sessionId, request), 323 coapTransportAdaptor.convertToGetAttributes(sessionId, request),
319 new CoapNoOpCallback(exchange)); 324 new CoapNoOpCallback(exchange));
@@ -330,14 +335,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -330,14 +335,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
330 return tokenToSessionIdMap.remove(token); 335 return tokenToSessionIdMap.remove(token);
331 } 336 }
332 337
333 - private void registerAsyncCoapSession(CoapExchange exchange, TransportProtos.SessionInfoProto sessionInfo, CoapTransportAdaptor coapTransportAdaptor, String token) { 338 + private void registerAsyncCoapSession(CoapExchange exchange, TransportProtos.SessionInfoProto sessionInfo, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder, String token) {
334 tokenToSessionIdMap.putIfAbsent(token, sessionInfo); 339 tokenToSessionIdMap.putIfAbsent(token, sessionInfo);
335 - transportService.registerAsyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor)); 340 + transportService.registerAsyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor, rpcRequestDynamicMessageBuilder));
336 transportService.process(sessionInfo, getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null); 341 transportService.process(sessionInfo, getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null);
337 } 342 }
338 343
339 - private CoapSessionListener getCoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor) {  
340 - return new CoapSessionListener(exchange, coapTransportAdaptor); 344 + private CoapSessionListener getCoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) {
  345 + return new CoapSessionListener(exchange, coapTransportAdaptor, rpcRequestDynamicMessageBuilder);
341 } 346 }
342 347
343 private String getTokenFromRequest(Request request) { 348 private String getTokenFromRequest(Request request) {
@@ -423,10 +428,12 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -423,10 +428,12 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
423 428
424 private final CoapExchange exchange; 429 private final CoapExchange exchange;
425 private final CoapTransportAdaptor coapTransportAdaptor; 430 private final CoapTransportAdaptor coapTransportAdaptor;
  431 + private final DynamicMessage.Builder rpcRequestDynamicMessageBuilder;
426 432
427 - CoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor) { 433 + CoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) {
428 this.exchange = exchange; 434 this.exchange = exchange;
429 this.coapTransportAdaptor = coapTransportAdaptor; 435 this.coapTransportAdaptor = coapTransportAdaptor;
  436 + this.rpcRequestDynamicMessageBuilder = rpcRequestDynamicMessageBuilder;
430 } 437 }
431 438
432 @Override 439 @Override
@@ -457,7 +464,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -457,7 +464,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
457 @Override 464 @Override
458 public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg msg) { 465 public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg msg) {
459 try { 466 try {
460 - exchange.respond(coapTransportAdaptor.convertToPublish(isConRequest(), msg)); 467 + exchange.respond(coapTransportAdaptor.convertToPublish(isConRequest(), msg, rpcRequestDynamicMessageBuilder));
461 } catch (AdaptorException e) { 468 } catch (AdaptorException e) {
462 log.trace("Failed to reply due to error", e); 469 log.trace("Failed to reply due to error", e);
463 exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR); 470 exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR);
@@ -545,9 +552,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -545,9 +552,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
545 (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; 552 (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
546 String deviceTelemetryProtoSchema = protoTransportPayloadConfiguration.getDeviceTelemetryProtoSchema(); 553 String deviceTelemetryProtoSchema = protoTransportPayloadConfiguration.getDeviceTelemetryProtoSchema();
547 String deviceAttributesProtoSchema = protoTransportPayloadConfiguration.getDeviceAttributesProtoSchema(); 554 String deviceAttributesProtoSchema = protoTransportPayloadConfiguration.getDeviceAttributesProtoSchema();
  555 + String deviceRpcRequestProtoSchema = protoTransportPayloadConfiguration.getDeviceRpcRequestProtoSchema();
  556 + String deviceRpcResponseProtoSchema = protoTransportPayloadConfiguration.getDeviceRpcResponseProtoSchema();
548 return new TransportConfigurationContainer(false, 557 return new TransportConfigurationContainer(false,
549 protoTransportPayloadConfiguration.getTelemetryDynamicMessageDescriptor(deviceTelemetryProtoSchema), 558 protoTransportPayloadConfiguration.getTelemetryDynamicMessageDescriptor(deviceTelemetryProtoSchema),
550 - protoTransportPayloadConfiguration.getAttributesDynamicMessageDescriptor(deviceAttributesProtoSchema)); 559 + protoTransportPayloadConfiguration.getAttributesDynamicMessageDescriptor(deviceAttributesProtoSchema),
  560 + protoTransportPayloadConfiguration.getRpcResponseDynamicMessageDescriptor(deviceRpcResponseProtoSchema),
  561 + protoTransportPayloadConfiguration.getRpcRequestDynamicMessageBuilder(deviceRpcRequestProtoSchema)
  562 + );
551 } 563 }
552 } else { 564 } else {
553 throw new AdaptorException("Invalid CoapDeviceTypeConfiguration type: " + coapDeviceTypeConfiguration.getClass().getSimpleName() + "!"); 565 throw new AdaptorException("Invalid CoapDeviceTypeConfiguration type: " + coapDeviceTypeConfiguration.getClass().getSimpleName() + "!");
@@ -567,11 +579,15 @@ public class CoapTransportResource extends AbstractCoapTransportResource { @@ -567,11 +579,15 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
567 private boolean jsonPayload; 579 private boolean jsonPayload;
568 private Descriptors.Descriptor telemetryMsgDescriptor; 580 private Descriptors.Descriptor telemetryMsgDescriptor;
569 private Descriptors.Descriptor attributesMsgDescriptor; 581 private Descriptors.Descriptor attributesMsgDescriptor;
  582 + private Descriptors.Descriptor rpcResponseMsgDescriptor;
  583 + private DynamicMessage.Builder rpcRequestDynamicMessageBuilder;
570 584
571 - public TransportConfigurationContainer(boolean jsonPayload, Descriptors.Descriptor telemetryMsgDescriptor, Descriptors.Descriptor attributesMsgDescriptor) { 585 + public TransportConfigurationContainer(boolean jsonPayload, Descriptors.Descriptor telemetryMsgDescriptor, Descriptors.Descriptor attributesMsgDescriptor, Descriptors.Descriptor rpcResponseMsgDescriptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) {
572 this.jsonPayload = jsonPayload; 586 this.jsonPayload = jsonPayload;
573 this.telemetryMsgDescriptor = telemetryMsgDescriptor; 587 this.telemetryMsgDescriptor = telemetryMsgDescriptor;
574 this.attributesMsgDescriptor = attributesMsgDescriptor; 588 this.attributesMsgDescriptor = attributesMsgDescriptor;
  589 + this.rpcResponseMsgDescriptor = rpcResponseMsgDescriptor;
  590 + this.rpcRequestDynamicMessageBuilder = rpcRequestDynamicMessageBuilder;
575 } 591 }
576 592
577 public TransportConfigurationContainer(boolean jsonPayload) { 593 public TransportConfigurationContainer(boolean jsonPayload) {
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.transport.coap.adaptors; 16 package org.thingsboard.server.transport.coap.adaptors;
17 17
18 import com.google.protobuf.Descriptors; 18 import com.google.protobuf.Descriptors;
  19 +import com.google.protobuf.DynamicMessage;
19 import org.eclipse.californium.core.coap.Request; 20 import org.eclipse.californium.core.coap.Request;
20 import org.eclipse.californium.core.coap.Response; 21 import org.eclipse.californium.core.coap.Response;
21 import org.thingsboard.server.common.transport.adaptor.AdaptorException; 22 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
@@ -32,7 +33,7 @@ public interface CoapTransportAdaptor { @@ -32,7 +33,7 @@ public interface CoapTransportAdaptor {
32 33
33 TransportProtos.GetAttributeRequestMsg convertToGetAttributes(UUID sessionId, Request inbound) throws AdaptorException; 34 TransportProtos.GetAttributeRequestMsg convertToGetAttributes(UUID sessionId, Request inbound) throws AdaptorException;
34 35
35 - TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound) throws AdaptorException; 36 + TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound, Descriptors.Descriptor rpcResponseMsgDescriptor) throws AdaptorException;
36 37
37 TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(UUID sessionId, Request inbound) throws AdaptorException; 38 TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(UUID sessionId, Request inbound) throws AdaptorException;
38 39
@@ -42,7 +43,7 @@ public interface CoapTransportAdaptor { @@ -42,7 +43,7 @@ public interface CoapTransportAdaptor {
42 43
43 Response convertToPublish(boolean isConfirmable, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException; 44 Response convertToPublish(boolean isConfirmable, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
44 45
45 - Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException; 46 + Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg rpcRequest, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) throws AdaptorException;
46 47
47 Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException; 48 Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException;
48 49
@@ -20,6 +20,7 @@ import com.google.gson.JsonObject; @@ -20,6 +20,7 @@ import com.google.gson.JsonObject;
20 import com.google.gson.JsonParser; 20 import com.google.gson.JsonParser;
21 import com.google.gson.JsonSyntaxException; 21 import com.google.gson.JsonSyntaxException;
22 import com.google.protobuf.Descriptors; 22 import com.google.protobuf.Descriptors;
  23 +import com.google.protobuf.DynamicMessage;
23 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
24 import org.eclipse.californium.core.coap.CoAP; 25 import org.eclipse.californium.core.coap.CoAP;
25 import org.eclipse.californium.core.coap.Request; 26 import org.eclipse.californium.core.coap.Request;
@@ -64,7 +65,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { @@ -64,7 +65,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor {
64 } 65 }
65 66
66 @Override 67 @Override
67 - public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound) throws AdaptorException { 68 + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound, Descriptors.Descriptor rpcResponseMsgDescriptor) throws AdaptorException {
68 Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound); 69 Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound);
69 String payload = validatePayload(sessionId, inbound, false); 70 String payload = validatePayload(sessionId, inbound, false);
70 JsonObject response = new JsonParser().parse(payload).getAsJsonObject(); 71 JsonObject response = new JsonParser().parse(payload).getAsJsonObject();
@@ -95,7 +96,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor { @@ -95,7 +96,7 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor {
95 } 96 }
96 97
97 @Override 98 @Override
98 - public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg msg) throws AdaptorException { 99 + public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg msg, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) throws AdaptorException {
99 return getObserveNotification(isConfirmable, JsonConverter.toJson(msg, true)); 100 return getObserveNotification(isConfirmable, JsonConverter.toJson(msg, true));
100 } 101 }
101 102
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.transport.coap.adaptors; 16 package org.thingsboard.server.transport.coap.adaptors;
17 17
  18 +import com.google.gson.JsonElement;
18 import com.google.gson.JsonParser; 19 import com.google.gson.JsonParser;
19 import com.google.protobuf.Descriptors; 20 import com.google.protobuf.Descriptors;
20 import com.google.protobuf.DynamicMessage; 21 import com.google.protobuf.DynamicMessage;
@@ -63,16 +64,16 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor { @@ -63,16 +64,16 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor {
63 } 64 }
64 65
65 @Override 66 @Override
66 - public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound) throws AdaptorException { 67 + public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(UUID sessionId, Request inbound, Descriptors.Descriptor rpcResponseMsgDescriptor) throws AdaptorException {
67 Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound); 68 Optional<Integer> requestId = CoapTransportResource.getRequestId(inbound);
68 if (requestId.isEmpty()) { 69 if (requestId.isEmpty()) {
69 throw new AdaptorException("Request id is missing!"); 70 throw new AdaptorException("Request id is missing!");
70 } else { 71 } else {
71 try { 72 try {
72 - String payload = TransportProtos.ToDeviceRpcResponseMsg.parseFrom(inbound.getPayload()).getPayload();  
73 - return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId.get())  
74 - .setPayload(payload).build();  
75 - } catch (InvalidProtocolBufferException e) { 73 + JsonElement response = new JsonParser().parse(dynamicMsgToJson(inbound.getPayload(), rpcResponseMsgDescriptor));
  74 + return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId.orElseThrow(() -> new AdaptorException("Request id is missing!")))
  75 + .setPayload(response.toString()).build();
  76 + } catch (Exception e) {
76 throw new AdaptorException(e); 77 throw new AdaptorException(e);
77 } 78 }
78 } 79 }
@@ -112,8 +113,8 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor { @@ -112,8 +113,8 @@ public class ProtoCoapAdaptor implements CoapTransportAdaptor {
112 } 113 }
113 114
114 @Override 115 @Override
115 - public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg msg) throws AdaptorException {  
116 - return getObserveNotification(isConfirmable, msg.toByteArray()); 116 + public Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg rpcRequest, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) throws AdaptorException {
  117 + return getObserveNotification(isConfirmable, ProtoConverter.convertToRpcRequest(rpcRequest, rpcRequestDynamicMessageBuilder));
117 } 118 }
118 119
119 @Override 120 @Override
@@ -35,12 +35,11 @@ import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInf @@ -35,12 +35,11 @@ import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInf
35 import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; 35 import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore;
36 import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener; 36 import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener;
37 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer; 37 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer;
38 -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler;  
39 import org.thingsboard.server.transport.lwm2m.utils.TypeServer; 38 import org.thingsboard.server.transport.lwm2m.utils.TypeServer;
40 39
41 import java.io.IOException; 40 import java.io.IOException;
42 import java.security.GeneralSecurityException; 41 import java.security.GeneralSecurityException;
43 -import java.util.Arrays; 42 +import java.util.Collections;
44 import java.util.List; 43 import java.util.List;
45 import java.util.UUID; 44 import java.util.UUID;
46 45
@@ -70,8 +69,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { @@ -70,8 +69,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
70 69
71 @Override 70 @Override
72 public List<SecurityInfo> getAllByEndpoint(String endPoint) { 71 public List<SecurityInfo> getAllByEndpoint(String endPoint) {
73 - String endPointKey = endPoint;  
74 - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(endPointKey, TypeServer.BOOTSTRAP); 72 + ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(endPoint, TypeServer.BOOTSTRAP);
75 if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { 73 if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {
76 /** add value to store from BootstrapJson */ 74 /** add value to store from BootstrapJson */
77 this.setBootstrapConfigScurityInfo(store); 75 this.setBootstrapConfigScurityInfo(store);
@@ -87,7 +85,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { @@ -87,7 +85,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
87 } catch (InvalidConfigurationException e) { 85 } catch (InvalidConfigurationException e) {
88 log.error("", e); 86 log.error("", e);
89 } 87 }
90 - return store.getSecurityInfo() == null ? null : Arrays.asList(store.getSecurityInfo()); 88 + return store.getSecurityInfo() == null ? null : Collections.singletonList(store.getSecurityInfo());
91 } 89 }
92 } 90 }
93 return null; 91 return null;
@@ -166,13 +164,13 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { @@ -166,13 +164,13 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
166 lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); 164 lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap);
167 lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); 165 lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer);
168 String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint()); 166 String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint());
169 - context.sendParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo); 167 + context.sendParametersOnThingsboardTelemetry(context.getKvLogyToThingsboard(logMsg), sessionInfo);
170 return lwM2MBootstrapConfig; 168 return lwM2MBootstrapConfig;
171 } else { 169 } else {
172 log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint()); 170 log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint());
173 log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); 171 log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint());
174 String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); 172 String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint());
175 - context.sendParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo); 173 + context.sendParametersOnThingsboardTelemetry(context.getKvLogyToThingsboard(logMsg), sessionInfo);
176 return null; 174 return null;
177 } 175 }
178 } 176 }
@@ -23,5 +23,5 @@ public class LwM2MBootstrapServers { @@ -23,5 +23,5 @@ public class LwM2MBootstrapServers {
23 private Integer lifetime = 300; 23 private Integer lifetime = 300;
24 private Integer defaultMinPeriod = 1; 24 private Integer defaultMinPeriod = 1;
25 private boolean notifIfDisabled = true; 25 private boolean notifIfDisabled = true;
26 - private String binding = "U"; 26 + private String binding = "UQ";
27 } 27 }
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mQueuedRequest.java renamed from dao/src/test/java/org/thingsboard/server/dao/service/sql/TbResourceServiceSqlTest.java
@@ -13,11 +13,8 @@ @@ -13,11 +13,8 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.service.sql; 16 +package org.thingsboard.server.transport.lwm2m.server;
17 17
18 -import org.thingsboard.server.dao.service.BaseTbResourceServiceTest;  
19 -import org.thingsboard.server.dao.service.DaoSqlTest;  
20 -  
21 -@DaoSqlTest  
22 -public class TbResourceServiceSqlTest extends BaseTbResourceServiceTest { 18 +public interface LwM2mQueuedRequest {
  19 + void send();
23 } 20 }
@@ -26,7 +26,7 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; @@ -26,7 +26,7 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate;
26 26
27 import java.util.Collection; 27 import java.util.Collection;
28 28
29 -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId; 29 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer;
30 30
31 @Slf4j 31 @Slf4j
32 public class LwM2mServerListener { 32 public class LwM2mServerListener {
@@ -92,7 +92,7 @@ public class LwM2mServerListener { @@ -92,7 +92,7 @@ public class LwM2mServerListener {
92 public void onResponse(Observation observation, Registration registration, ObserveResponse response) { 92 public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
93 if (registration != null) { 93 if (registration != null) {
94 try { 94 try {
95 - service.onObservationResponse(registration, convertToIdVerFromObjectId(observation.getPath().toString(), registration), response); 95 + service.onObservationResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), response);
96 } catch (Exception e) { 96 } catch (Exception e) {
97 log.error("[{}] onResponse", e.toString()); 97 log.error("[{}] onResponse", e.toString());
98 98
@@ -107,7 +107,7 @@ public class LwM2mServerListener { @@ -107,7 +107,7 @@ public class LwM2mServerListener {
107 107
108 @Override 108 @Override
109 public void newObservation(Observation observation, Registration registration) { 109 public void newObservation(Observation observation, Registration registration) {
110 -// log.info("Received newObservation from [{}] endpoint [{}] ", observation.getPath(), registration.getEndpoint()); 110 + log.info("Received newObservation from [{}] endpoint [{}] ", observation.getPath(), registration.getEndpoint());
111 } 111 }
112 }; 112 };
113 113
@@ -18,6 +18,7 @@ package org.thingsboard.server.transport.lwm2m.server; @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.lwm2m.server;
18 import io.netty.util.concurrent.Future; 18 import io.netty.util.concurrent.Future;
19 import io.netty.util.concurrent.GenericFutureListener; 19 import io.netty.util.concurrent.GenericFutureListener;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
  21 +import org.jetbrains.annotations.NotNull;
21 import org.thingsboard.server.common.data.Device; 22 import org.thingsboard.server.common.data.Device;
22 import org.thingsboard.server.common.data.DeviceProfile; 23 import org.thingsboard.server.common.data.DeviceProfile;
23 import org.thingsboard.server.common.data.ResourceType; 24 import org.thingsboard.server.common.data.ResourceType;
@@ -74,12 +75,12 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s @@ -74,12 +75,12 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
74 75
75 @Override 76 @Override
76 public void onToDeviceRpcRequest(ToDeviceRpcRequestMsg toDeviceRequest) { 77 public void onToDeviceRpcRequest(ToDeviceRpcRequestMsg toDeviceRequest) {
77 - log.info("[{}] toDeviceRpcRequest", toDeviceRequest); 78 + this.service.onToDeviceRpcRequest(toDeviceRequest);
78 } 79 }
79 80
80 @Override 81 @Override
81 public void onToServerRpcResponse(ToServerRpcResponseMsg toServerResponse) { 82 public void onToServerRpcResponse(ToServerRpcResponseMsg toServerResponse) {
82 - log.info("[{}] toServerRpcResponse", toServerResponse); 83 + this.service.onToServerRpcResponse(toServerResponse);
83 } 84 }
84 85
85 @Override 86 @Override
@@ -87,13 +88,15 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s @@ -87,13 +88,15 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
87 log.info("[{}] operationComplete", future); 88 log.info("[{}] operationComplete", future);
88 } 89 }
89 90
90 - public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) { 91 + @Override
  92 + public void onResourceUpdate(@NotNull Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {
91 if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.get().getResourceType())) { 93 if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.get().getResourceType())) {
92 this.service.onResourceUpdate(resourceUpdateMsgOpt); 94 this.service.onResourceUpdate(resourceUpdateMsgOpt);
93 } 95 }
94 } 96 }
95 97
96 - public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) { 98 + @Override
  99 + public void onResourceDelete(@NotNull Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {
97 if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.get().getResourceType())) { 100 if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.get().getResourceType())) {
98 this.service.onResourceDelete(resourceDeleteMsgOpt); 101 this.service.onResourceDelete(resourceDeleteMsgOpt);
99 } 102 }
@@ -30,31 +30,33 @@ package org.thingsboard.server.transport.lwm2m.server; @@ -30,31 +30,33 @@ package org.thingsboard.server.transport.lwm2m.server;
30 * limitations under the License. 30 * limitations under the License.
31 */ 31 */
32 32
33 -import com.google.gson.JsonElement;  
34 -import com.google.gson.JsonObject;  
35 import lombok.Getter; 33 import lombok.Getter;
36 import lombok.extern.slf4j.Slf4j; 34 import lombok.extern.slf4j.Slf4j;
37 import org.eclipse.leshan.core.model.DDFFileParser; 35 import org.eclipse.leshan.core.model.DDFFileParser;
38 import org.eclipse.leshan.core.model.DefaultDDFFileValidator; 36 import org.eclipse.leshan.core.model.DefaultDDFFileValidator;
39 import org.eclipse.leshan.core.model.InvalidDDFFileException; 37 import org.eclipse.leshan.core.model.InvalidDDFFileException;
40 import org.eclipse.leshan.core.model.ObjectModel; 38 import org.eclipse.leshan.core.model.ObjectModel;
  39 +import org.eclipse.leshan.core.model.ResourceModel;
  40 +import org.eclipse.leshan.core.node.codec.CodecException;
41 import org.springframework.stereotype.Component; 41 import org.springframework.stereotype.Component;
42 import org.thingsboard.server.common.transport.TransportContext; 42 import org.thingsboard.server.common.transport.TransportContext;
43 import org.thingsboard.server.common.transport.TransportResourceCache; 43 import org.thingsboard.server.common.transport.TransportResourceCache;
44 import org.thingsboard.server.common.transport.TransportService; 44 import org.thingsboard.server.common.transport.TransportService;
45 import org.thingsboard.server.common.transport.TransportServiceCallback; 45 import org.thingsboard.server.common.transport.TransportServiceCallback;
46 -import org.thingsboard.server.common.transport.adaptor.AdaptorException;  
47 import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; 46 import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer;
  47 +import org.thingsboard.server.gen.transport.TransportProtos;
48 import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; 48 import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;
49 import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; 49 import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;
50 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; 50 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
51 -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;  
52 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 51 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
53 import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; 52 import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor;
54 53
55 import java.io.ByteArrayInputStream; 54 import java.io.ByteArrayInputStream;
56 import java.io.IOException; 55 import java.io.IOException;
  56 +import java.util.ArrayList;
  57 +import java.util.List;
57 58
  59 +import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V;
58 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; 60 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY;
59 61
60 @Slf4j 62 @Slf4j
@@ -91,7 +93,7 @@ public class LwM2mTransportContextServer extends TransportContext { @@ -91,7 +93,7 @@ public class LwM2mTransportContextServer extends TransportContext {
91 /** 93 /**
92 * send to Thingsboard Attribute || Telemetry 94 * send to Thingsboard Attribute || Telemetry
93 * 95 *
94 - * @param msg - JsonObject: [{name: value}] 96 + * @param msg - JsonObject: [{name: value}]
95 * @return - dummy 97 * @return - dummy
96 */ 98 */
97 private <T> TransportServiceCallback<Void> getPubAckCallbackSendAttrTelemetry(final T msg) { 99 private <T> TransportServiceCallback<Void> getPubAckCallbackSendAttrTelemetry(final T msg) {
@@ -108,33 +110,29 @@ public class LwM2mTransportContextServer extends TransportContext { @@ -108,33 +110,29 @@ public class LwM2mTransportContextServer extends TransportContext {
108 }; 110 };
109 } 111 }
110 112
111 - public void sendParametersOnThingsboard(JsonElement msg, String topicName, SessionInfoProto sessionInfo) {  
112 - try {  
113 - if (topicName.equals(LwM2mTransportHandler.DEVICE_ATTRIBUTES_TOPIC)) {  
114 - PostAttributeMsg postAttributeMsg = adaptor.convertToPostAttributes(msg);  
115 - TransportServiceCallback call = this.getPubAckCallbackSendAttrTelemetry(postAttributeMsg);  
116 - transportService.process(sessionInfo, postAttributeMsg, this.getPubAckCallbackSendAttrTelemetry(call));  
117 - } else if (topicName.equals(LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC)) {  
118 - PostTelemetryMsg postTelemetryMsg = adaptor.convertToPostTelemetry(msg);  
119 - TransportServiceCallback call = this.getPubAckCallbackSendAttrTelemetry(postTelemetryMsg);  
120 - transportService.process(sessionInfo, postTelemetryMsg, this.getPubAckCallbackSendAttrTelemetry(call));  
121 - }  
122 - } catch (AdaptorException e) {  
123 - log.error("[{}] Failed to process publish msg [{}]", topicName, e);  
124 - log.info("[{}] Closing current session due to invalid publish", topicName);  
125 - } 113 + public void sendParametersOnThingsboardAttribute(List<TransportProtos.KeyValueProto> result, SessionInfoProto sessionInfo) {
  114 + PostAttributeMsg.Builder request = PostAttributeMsg.newBuilder();
  115 + request.addAllKv(result);
  116 + PostAttributeMsg postAttributeMsg = request.build();
  117 + TransportServiceCallback call = this.getPubAckCallbackSendAttrTelemetry(postAttributeMsg);
  118 + transportService.process(sessionInfo, postAttributeMsg, this.getPubAckCallbackSendAttrTelemetry(call));
126 } 119 }
127 120
128 - public JsonObject getTelemetryMsgObject(String logMsg) {  
129 - JsonObject telemetries = new JsonObject();  
130 - telemetries.addProperty(LOG_LW2M_TELEMETRY, logMsg);  
131 - return telemetries; 121 + public void sendParametersOnThingsboardTelemetry(List<TransportProtos.KeyValueProto> result, SessionInfoProto sessionInfo) {
  122 + PostTelemetryMsg.Builder request = PostTelemetryMsg.newBuilder();
  123 + TransportProtos.TsKvListProto.Builder builder = TransportProtos.TsKvListProto.newBuilder();
  124 + builder.setTs(System.currentTimeMillis());
  125 + builder.addAllKv(result);
  126 + request.addTsKvList(builder.build());
  127 + PostTelemetryMsg postTelemetryMsg = request.build();
  128 + TransportServiceCallback call = this.getPubAckCallbackSendAttrTelemetry(postTelemetryMsg);
  129 + transportService.process(sessionInfo, postTelemetryMsg, this.getPubAckCallbackSendAttrTelemetry(call));
132 } 130 }
133 131
134 /** 132 /**
135 * @return - sessionInfo after access connect client 133 * @return - sessionInfo after access connect client
136 */ 134 */
137 - public SessionInfoProto getValidateSessionInfo(ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) { 135 + public SessionInfoProto getValidateSessionInfo(TransportProtos.ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) {
138 return SessionInfoProto.newBuilder() 136 return SessionInfoProto.newBuilder()
139 .setNodeId(this.getNodeId()) 137 .setNodeId(this.getNodeId())
140 .setSessionIdMSB(mostSignificantBits) 138 .setSessionIdMSB(mostSignificantBits)
@@ -159,4 +157,90 @@ public class LwM2mTransportContextServer extends TransportContext { @@ -159,4 +157,90 @@ public class LwM2mTransportContextServer extends TransportContext {
159 return null; 157 return null;
160 } 158 }
161 } 159 }
  160 +
  161 + /**
  162 + *
  163 + * @param logMsg - info about Logs
  164 + * @return- KeyValueProto for telemetry (Logs)
  165 + */
  166 + public List <TransportProtos.KeyValueProto> getKvLogyToThingsboard(String logMsg) {
  167 + List <TransportProtos.KeyValueProto> result = new ArrayList<>();
  168 + result.add(TransportProtos.KeyValueProto.newBuilder()
  169 + .setKey(LOG_LW2M_TELEMETRY)
  170 + .setType(TransportProtos.KeyValueType.STRING_V)
  171 + .setStringV(logMsg).build());
  172 + return result;
  173 + }
  174 +
  175 + /**
  176 + * @return - KeyValueProto for attribute/telemetry (change value)
  177 + * @throws CodecException -
  178 + */
  179 +
  180 + public TransportProtos.KeyValueProto getKvAttrTelemetryToThingsboard(ResourceModel.Type resourceType, String resourceName, Object value, boolean isMultiInstances) {
  181 + TransportProtos.KeyValueProto.Builder kvProto = TransportProtos.KeyValueProto.newBuilder().setKey(resourceName);
  182 + if (isMultiInstances) {
  183 + kvProto.setType(TransportProtos.KeyValueType.JSON_V)
  184 + .setJsonV((String) value);
  185 + }
  186 + else {
  187 + switch (resourceType) {
  188 + case BOOLEAN:
  189 + kvProto.setType(BOOLEAN_V).setBoolV((Boolean) value).build();
  190 + break;
  191 + case STRING:
  192 + case TIME:
  193 + case OPAQUE:
  194 + case OBJLNK:
  195 + kvProto.setType(TransportProtos.KeyValueType.STRING_V).setStringV((String) value);
  196 + break;
  197 + case INTEGER:
  198 + kvProto.setType(TransportProtos.KeyValueType.LONG_V).setLongV((Long) value);
  199 + break;
  200 + case FLOAT:
  201 + kvProto.setType(TransportProtos.KeyValueType.DOUBLE_V).setDoubleV((Double) value);
  202 + }
  203 + }
  204 + return kvProto.build();
  205 + }
  206 +
  207 + /**
  208 + *
  209 + * @param currentType -
  210 + * @param resourcePath -
  211 + * @return
  212 + */
  213 + public ResourceModel.Type getResourceModelTypeEqualsKvProtoValueType(ResourceModel.Type currentType, String resourcePath) {
  214 + switch (currentType) {
  215 + case BOOLEAN:
  216 + return ResourceModel.Type.BOOLEAN;
  217 + case STRING:
  218 + case TIME:
  219 + case OPAQUE:
  220 + case OBJLNK:
  221 + return ResourceModel.Type.STRING;
  222 + case INTEGER:
  223 + return ResourceModel.Type.INTEGER;
  224 + case FLOAT:
  225 + return ResourceModel.Type.FLOAT;
  226 + default:
  227 + }
  228 + throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType);
  229 + }
  230 +
  231 + public Object getValueFromKvProto (TransportProtos.KeyValueProto kv) {
  232 + switch (kv.getType()) {
  233 + case BOOLEAN_V:
  234 + return kv.getBoolV();
  235 + case LONG_V:
  236 + return kv.getLongV();
  237 + case DOUBLE_V:
  238 + return kv.getDoubleV();
  239 + case STRING_V:
  240 + return kv.getStringV();
  241 + case JSON_V:
  242 + return kv.getJsonV();
  243 + }
  244 + return null;
  245 + }
162 } 246 }