Browse Source

Merge branch 'master' into transaction/development

pull/1301/head
Dima Landiak 8 years ago
parent
commit
f4decda92c
  1. 2
      application/pom.xml
  2. 14
      application/src/main/data/json/system/widget_bundles/maps.json
  3. 65
      application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java
  4. 1
      application/src/main/resources/thingsboard.yml
  5. 2
      common/data/pom.xml
  6. 2
      common/message/pom.xml
  7. 2
      common/pom.xml
  8. 2
      common/queue/pom.xml
  9. 2
      common/transport/coap/pom.xml
  10. 2
      common/transport/http/pom.xml
  11. 2
      common/transport/mqtt/pom.xml
  12. 2
      common/transport/pom.xml
  13. 2
      common/transport/transport-api/pom.xml
  14. 2
      dao/pom.xml
  15. 1
      docker/docker-compose.yml
  16. 2
      msa/black-box-tests/pom.xml
  17. 1
      msa/js-executor/.gitignore
  18. 4282
      msa/js-executor/package-lock.json
  19. 2
      msa/js-executor/package.json
  20. 4
      msa/js-executor/pom.xml
  21. 2
      msa/pom.xml
  22. 2
      msa/tb-node/pom.xml
  23. 4
      msa/tb/pom.xml
  24. 2
      msa/transport/coap/pom.xml
  25. 2
      msa/transport/http/pom.xml
  26. 2
      msa/transport/mqtt/pom.xml
  27. 2
      msa/transport/pom.xml
  28. 1
      msa/web-ui/.gitignore
  29. 4049
      msa/web-ui/package-lock.json
  30. 3
      msa/web-ui/package.json
  31. 4
      msa/web-ui/pom.xml
  32. 5
      msa/web-ui/server.js
  33. 4
      netty-mqtt/pom.xml
  34. 2
      pom.xml
  35. 2
      rule-engine/pom.xml
  36. 2
      rule-engine/rule-engine-api/pom.xml
  37. 2
      rule-engine/rule-engine-components/pom.xml
  38. 2
      tools/pom.xml
  39. 2
      transport/coap/pom.xml
  40. 2
      transport/http/pom.xml
  41. 2
      transport/mqtt/pom.xml
  42. 2
      transport/pom.xml
  43. 16437
      ui/package-lock.json
  44. 4
      ui/package.json
  45. 4
      ui/pom.xml
  46. 10
      ui/src/app/api/alias-controller.js
  47. 44
      ui/src/app/api/entity.service.js
  48. 2
      ui/src/app/entity/attribute/attribute-table.tpl.html
  49. 12
      ui/src/app/widget/lib/google-map.js
  50. 12
      ui/src/app/widget/lib/image-map.js
  51. 7
      ui/src/app/widget/lib/map-widget.js
  52. 126
      ui/src/app/widget/lib/map-widget2.js
  53. 12
      ui/src/app/widget/lib/openstreet-map.js
  54. 12
      ui/src/app/widget/lib/tencent-map.js
  55. 4
      ui/src/app/widget/lib/widget-utils.js

2
application/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>application</artifactId>

14
application/src/main/data/json/system/widget_bundles/maps.json

File diff suppressed because one or more lines are too long

65
application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java

@ -40,10 +40,7 @@ import org.thingsboard.server.service.telemetry.TelemetryWebSocketMsgEndpoint;
import org.thingsboard.server.service.telemetry.TelemetryWebSocketService;
import org.thingsboard.server.service.telemetry.TelemetryWebSocketSessionRef;
import javax.websocket.RemoteEndpoint;
import javax.websocket.SendHandler;
import javax.websocket.SendResult;
import javax.websocket.Session;
import javax.websocket.*;
import java.io.IOException;
import java.net.URI;
import java.security.InvalidParameterException;
@ -75,6 +72,8 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr
private int maxSessionsPerRegularUser;
@Value("${server.ws.limits.max_sessions_per_public_user:0}")
private int maxSessionsPerPublicUser;
@Value("${server.ws.limits.max_queue_per_ws_session:1000}")
private int maxMsgQueuePerSession;
@Value("${server.ws.limits.max_updates_per_session:}")
private String perSessionUpdatesConfiguration;
@ -108,7 +107,7 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr
super.afterConnectionEstablished(session);
try {
if (session instanceof NativeWebSocketSession) {
Session nativeSession = ((NativeWebSocketSession)session).getNativeSession(Session.class);
Session nativeSession = ((NativeWebSocketSession) session).getNativeSession(Session.class);
if (nativeSession != null) {
nativeSession.getAsyncRemote().setSendTimeout(sendTimeout);
}
@ -119,7 +118,7 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr
if (!checkLimits(session, sessionRef)) {
return;
}
internalSessionMap.put(internalSessionId, new SessionMetaData(session, sessionRef));
internalSessionMap.put(internalSessionId, new SessionMetaData(session, sessionRef, maxMsgQueuePerSession));
externalSessionMap.put(externalSessionId, internalSessionId);
processInWebSocketService(sessionRef, SessionEvent.onEstablished());
log.info("[{}][{}][{}] Session is opened", sessionRef.getSecurityCtx().getTenantId(), externalSessionId, session.getId());
@ -176,31 +175,44 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr
if (!"telemetry".equalsIgnoreCase(serviceToken)) {
throw new InvalidParameterException("Can't find plugin with specified token!");
} else {
SecurityUser currentUser = (SecurityUser) ((Authentication)session.getPrincipal()).getPrincipal();
SecurityUser currentUser = (SecurityUser) ((Authentication) session.getPrincipal()).getPrincipal();
return new TelemetryWebSocketSessionRef(UUID.randomUUID().toString(), currentUser, session.getLocalAddress(), session.getRemoteAddress());
}
}
private static class SessionMetaData implements SendHandler {
private class SessionMetaData implements SendHandler {
private final WebSocketSession session;
private final RemoteEndpoint.Async asyncRemote;
private final TelemetryWebSocketSessionRef sessionRef;
private volatile boolean isSending = false;
private final Queue<String> msgQueue;
private Queue<String> msgQueue = new LinkedBlockingQueue<>();
SessionMetaData(WebSocketSession session, TelemetryWebSocketSessionRef sessionRef) {
SessionMetaData(WebSocketSession session, TelemetryWebSocketSessionRef sessionRef, int maxMsgQueuePerSession) {
super();
this.session = session;
Session nativeSession = ((NativeWebSocketSession)session).getNativeSession(Session.class);
Session nativeSession = ((NativeWebSocketSession) session).getNativeSession(Session.class);
this.asyncRemote = nativeSession.getAsyncRemote();
this.sessionRef = sessionRef;
this.msgQueue = new LinkedBlockingQueue<>(maxMsgQueuePerSession);
}
public synchronized void sendMsg(String msg) {
synchronized void sendMsg(String msg) {
if (isSending) {
msgQueue.add(msg);
try {
msgQueue.add(msg);
} catch (RuntimeException e) {
if (log.isTraceEnabled()) {
log.trace("[{}][{}] Session closed due to queue error", sessionRef.getSecurityCtx().getTenantId(), session.getId(), e);
} else {
log.info("[{}][{}] Session closed due to queue error", sessionRef.getSecurityCtx().getTenantId(), session.getId());
}
try {
close(sessionRef, CloseStatus.POLICY_VIOLATION.withReason("Max pending updates limit reached!"));
} catch (IOException ioe) {
log.trace("[{}] Session transport error", session.getId(), ioe);
}
}
} else {
isSending = true;
sendMsgInternal(msg);
@ -211,20 +223,31 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr
try {
this.asyncRemote.sendText(msg, this);
} catch (Exception e) {
log.error("[{}] Failed to send msg", session.getId(), e);
log.trace("[{}] Failed to send msg", session.getId(), e);
try {
close(this.sessionRef, CloseStatus.SESSION_NOT_RELIABLE);
} catch (IOException ioe) {
log.trace("[{}] Session transport error", session.getId(), ioe);
}
}
}
@Override
public void onResult(SendResult result) {
if (!result.isOK()) {
log.error("[{}] Failed to send msg", session.getId(), result.getException());
}
String msg = msgQueue.poll();
if (msg != null) {
sendMsgInternal(msg);
log.trace("[{}] Failed to send msg", session.getId(), result.getException());
try {
close(this.sessionRef, CloseStatus.SESSION_NOT_RELIABLE);
} catch (IOException ioe) {
log.trace("[{}] Session transport error", session.getId(), ioe);
}
} else {
isSending = false;
String msg = msgQueue.poll();
if (msg != null) {
sendMsgInternal(msg);
} else {
isSending = false;
}
}
}
}

1
application/src/main/resources/thingsboard.yml

@ -40,6 +40,7 @@ server:
max_sessions_per_customer: "${TB_SERVER_WS_TENANT_RATE_LIMITS_MAX_SESSIONS_PER_CUSTOMER:0}"
max_sessions_per_regular_user: "${TB_SERVER_WS_TENANT_RATE_LIMITS_MAX_SESSIONS_PER_REGULAR_USER:0}"
max_sessions_per_public_user: "${TB_SERVER_WS_TENANT_RATE_LIMITS_MAX_SESSIONS_PER_PUBLIC_USER:0}"
max_queue_per_ws_session: "${TB_SERVER_WS_TENANT_RATE_LIMITS_MAX_QUEUE_PER_WS_SESSION:500}"
max_subscriptions_per_tenant: "${TB_SERVER_WS_TENANT_RATE_LIMITS_MAX_SUBSCRIPTIONS_PER_TENANT:0}"
max_subscriptions_per_customer: "${TB_SERVER_WS_TENANT_RATE_LIMITS_MAX_SUBSCRIPTIONS_PER_CUSTOMER:0}"
max_subscriptions_per_regular_user: "${TB_SERVER_WS_TENANT_RATE_LIMITS_MAX_SUBSCRIPTIONS_PER_REGULAR_USER:0}"

2
common/data/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/message/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>common</artifactId>

2
common/queue/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
common/transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
common/transport/mqtt/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
common/transport/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>

2
common/transport/transport-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.common</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.common.transport</groupId>

2
dao/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>dao</artifactId>

1
docker/docker-compose.yml

@ -36,6 +36,7 @@ services:
depends_on:
- zookeeper
redis:
restart: always
image: redis:4.0
ports:
- "6379"

2
msa/black-box-tests/pom.xml

@ -21,7 +21,7 @@
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

1
msa/js-executor/.gitignore

@ -28,5 +28,4 @@ pom.xml.versionsBackup
**/target
**/.env
node_modules
package-lock.json
api/*.proto.js

4282
msa/js-executor/package-lock.json

File diff suppressed because it is too large

2
msa/js-executor/package.json

@ -1,7 +1,7 @@
{
"name": "thingsboard-js-executor",
"private": true,
"version": "2.2.0",
"version": "2.2.1",
"description": "ThingsBoard JavaScript Executor Microservice",
"main": "server.js",
"bin": "server.js",

4
msa/js-executor/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>
@ -71,7 +71,7 @@
</goals>
<configuration>
<nodeVersion>v8.11.3</nodeVersion>
<npmVersion>5.6.0</npmVersion>
<npmVersion>6.4.1</npmVersion>
</configuration>
</execution>
<execution>

2
msa/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>msa</artifactId>

2
msa/tb-node/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

4
msa/tb/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>
@ -40,7 +40,7 @@
<tb-cassandra.docker.name>tb-cassandra</tb-cassandra.docker.name>
<pkg.user>thingsboard</pkg.user>
<pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder>
<pkg.upgradeVersion>2.1.1</pkg.upgradeVersion>
<pkg.upgradeVersion>2.1.3</pkg.upgradeVersion>
</properties>
<dependencies>

2
msa/transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/mqtt/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard.msa</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>

1
msa/web-ui/.gitignore

@ -28,4 +28,3 @@ pom.xml.versionsBackup
**/target
**/.env
node_modules
package-lock.json

4049
msa/web-ui/package-lock.json

File diff suppressed because it is too large

3
msa/web-ui/package.json

@ -1,7 +1,7 @@
{
"name": "thingsboard-web-ui",
"private": true,
"version": "2.2.0",
"version": "2.2.1",
"description": "ThingsBoard Web UI Microservice",
"main": "server.js",
"bin": "server.js",
@ -12,6 +12,7 @@
"start-prod": "NODE_ENV=production nodemon server.js"
},
"dependencies": {
"compression": "^1.7.3",
"config": "^1.30.0",
"connect-history-api-fallback": "^1.5.0",
"express": "^4.16.3",

4
msa/web-ui/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>msa</artifactId>
</parent>
<groupId>org.thingsboard.msa</groupId>
@ -78,7 +78,7 @@
</goals>
<configuration>
<nodeVersion>v8.11.3</nodeVersion>
<npmVersion>5.6.0</npmVersion>
<npmVersion>6.4.1</npmVersion>
</configuration>
</execution>
<execution>

5
msa/web-ui/server.js

@ -17,6 +17,7 @@
const config = require('config'),
logger = require('./config/logger')('main'),
express = require('express'),
compression = require('compression'),
http = require('http'),
httpProxy = require('http-proxy'),
path = require('path'),
@ -54,8 +55,9 @@ var server;
const app = express();
server = http.createServer(app);
var apiProxy;
if (useApiProxy) {
const apiProxy = httpProxy.createProxyServer({
apiProxy = httpProxy.createProxyServer({
target: {
host: thingsboardHost,
port: thingsboardPort
@ -85,6 +87,7 @@ var server;
}
app.use(historyApiFallback());
app.use(compression());
const root = path.join(webDir, 'public');

4
netty-mqtt/pom.xml

@ -19,12 +19,12 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<groupId>org.thingsboard</groupId>
<artifactId>netty-mqtt</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Netty MQTT Client</name>

2
pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.thingsboard</groupId>
<artifactId>thingsboard</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Thingsboard</name>

2
rule-engine/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>rule-engine</artifactId>

2
rule-engine/rule-engine-api/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>rule-engine</artifactId>
</parent>
<groupId>org.thingsboard.rule-engine</groupId>

2
rule-engine/rule-engine-components/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>rule-engine</artifactId>
</parent>
<groupId>org.thingsboard.rule-engine</groupId>

2
tools/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<groupId>org.thingsboard</groupId>

2
transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

2
transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

2
transport/mqtt/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>transport</artifactId>
</parent>
<groupId>org.thingsboard.transport</groupId>

2
transport/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>transport</artifactId>

16437
ui/package-lock.json

File diff suppressed because it is too large

4
ui/package.json

@ -1,7 +1,7 @@
{
"name": "thingsboard",
"private": true,
"version": "2.2.0",
"version": "2.2.1",
"description": "ThingsBoard UI",
"licenses": [
{
@ -53,7 +53,7 @@
"compass-sass-mixins": "^0.12.7",
"event-source-polyfill": "0.0.9",
"flot": "git://github.com/thingsboard/flot.git#0.9-work",
"flot-curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master",
"flot.curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master",
"font-awesome": "^4.6.3",
"javascript-detect-element-resize": "^0.5.3",
"jquery": "^3.1.0",

4
ui/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.2.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<groupId>org.thingsboard</groupId>
@ -58,7 +58,7 @@
</goals>
<configuration>
<nodeVersion>v6.9.1</nodeVersion>
<npmVersion>3.10.8</npmVersion>
<npmVersion>6.4.1</npmVersion>
</configuration>
</execution>
<execution>

10
ui/src/app/api/alias-controller.js

@ -143,6 +143,11 @@ export default class AliasController {
for (var i=0;i<resolvedEntities.length;i++) {
var resolvedEntity = resolvedEntities[i];
newDatasource = angular.copy(datasource);
if (resolvedEntity.origEntity) {
newDatasource.entity = angular.copy(resolvedEntity.origEntity);
} else {
newDatasource.entity = {};
}
newDatasource.entityId = resolvedEntity.id;
newDatasource.entityType = resolvedEntity.entityType;
newDatasource.entityName = resolvedEntity.name;
@ -164,6 +169,11 @@ export default class AliasController {
} else {
var entity = aliasInfo.currentEntity;
if (entity) {
if (entity.origEntity) {
datasource.entity = angular.copy(entity.origEntity);
} else {
datasource.entity = {};
}
datasource.entityId = entity.id;
datasource.entityType = entity.entityType;
datasource.entityName = entity.name;

44
ui/src/app/api/entity.service.js

@ -344,17 +344,21 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
}
function entityToEntityInfo(entity) {
return { name: entity.name, entityType: entity.id.entityType, id: entity.id.id, entityDescription: entity.additionalInfo?entity.additionalInfo.description:"" };
return { origEntity: entity, name: entity.name, entityType: entity.id.entityType, id: entity.id.id, entityDescription: entity.additionalInfo?entity.additionalInfo.description:"" };
}
function entityRelationInfoToEntityInfo(entityRelationInfo, direction) {
var deferred = $q.defer();
var entityId = direction == types.entitySearchDirection.from ? entityRelationInfo.to : entityRelationInfo.from;
var name = direction == types.entitySearchDirection.from ? entityRelationInfo.toName : entityRelationInfo.fromName;
return {
name: name,
entityType: entityId.entityType,
id: entityId.id
};
getEntity(entityId.entityType, entityId.id, {ignoreLoading: true}).then(
function success(entity) {
deferred.resolve(entityToEntityInfo(entity));
},
function fail() {
deferred.reject();
}
);
return deferred.promise;
}
function entitiesToEntitiesInfo(entities) {
@ -368,13 +372,22 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
}
function entityRelationInfosToEntitiesInfo(entityRelations, direction) {
var entitiesInfo = [];
var deferred = $q.defer();
var entitiesInfoTaks = [];
if (entityRelations) {
for (var d = 0; d < entityRelations.length; d++) {
entitiesInfo.push(entityRelationInfoToEntityInfo(entityRelations[d], direction));
entitiesInfoTaks.push(entityRelationInfoToEntityInfo(entityRelations[d], direction));
}
}
return entitiesInfo;
$q.all(entitiesInfoTaks).then(
function success(entitiesInfo) {
deferred.resolve(entitiesInfo);
},
function fail() {
deferred.reject();
}
);
return deferred.promise;
}
@ -581,8 +594,15 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
var limit = Math.min(allRelations.length, maxItems);
allRelations.length = limit;
}
result.entities = entityRelationInfosToEntitiesInfo(allRelations, filter.direction);
deferred.resolve(result);
entityRelationInfosToEntitiesInfo(allRelations, filter.direction).then(
function success(entities) {
result.entities = entities;
deferred.resolve(result);
},
function fail() {
deferred.reject();
}
);
} else {
deferred.reject();
}

2
ui/src/app/entity/attribute/attribute-table.tpl.html

@ -126,7 +126,7 @@
</md-toolbar>
<md-table-container ng-show="mode!='widget'">
<table class="tb-attribute-table" md-table md-row-select multiple="" ng-model="selectedAttributes" md-progress="attributesDeferred.promise">
<thead fix-head md-head md-order="query.order" md-on-reorder="onReorder">
<thead ng-show="mode!='widget'" fix-head md-head md-order="query.order" md-on-reorder="onReorder">
<tr md-row>
<th md-column md-order-by="lastUpdateTs"><span translate>attribute.last-update-time</span></th>
<th md-column md-order-by="key"><span translate>attribute.key</span></th>

12
ui/src/app/widget/lib/google-map.js

@ -221,7 +221,7 @@ export default class TbGoogleMap {
/* eslint-enable no-undef */
/* eslint-disable no-undef */
createMarker(location, settings, onClickListener, markerArgs) {
createMarker(location, dsIndex, settings, onClickListener, markerArgs) {
var marker;
if (settings.showLabel) {
marker = new MarkerWithLabel({
@ -244,7 +244,7 @@ export default class TbGoogleMap {
});
if (settings.displayTooltip) {
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
this.createTooltip(marker, dsIndex, settings, markerArgs);
}
if (onClickListener) {
@ -261,13 +261,13 @@ export default class TbGoogleMap {
/* eslint-enable no-undef */
/* eslint-disable no-undef */
createTooltip(marker, pattern, replaceInfo, autoClose, markerArgs) {
createTooltip(marker, dsIndex, settings, markerArgs) {
var popup = new google.maps.InfoWindow({
content: ''
});
var map = this;
marker.addListener('click', function() {
if (autoClose) {
if (settings.autocloseTooltip) {
map.tooltips.forEach((tooltip) => {
tooltip.popup.close();
});
@ -277,8 +277,8 @@ export default class TbGoogleMap {
this.tooltips.push( {
markerArgs: markerArgs,
popup: popup,
pattern: pattern,
replaceInfo: replaceInfo
locationSettings: settings,
dsIndex: dsIndex
});
}
/* eslint-enable no-undef */

12
ui/src/app/widget/lib/image-map.js

@ -298,7 +298,7 @@ export default class TbImageMap {
onMarkerIconReady(iconInfo);
}
createMarker(position, settings, onClickListener, markerArgs) {
createMarker(position, dsIndex, settings, onClickListener, markerArgs) {
var pos = this.posFunction(position.x, position.y);
var x = pos.x * this.width;
var y = pos.y * this.height;
@ -319,7 +319,7 @@ export default class TbImageMap {
});
if (settings.displayTooltip) {
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
this.createTooltip(marker, dsIndex, settings, markerArgs);
}
if (onClickListener) {
@ -348,15 +348,15 @@ export default class TbImageMap {
}
}
createTooltip(marker, pattern, replaceInfo, autoClose, markerArgs) {
createTooltip(marker, dsIndex, settings, markerArgs) {
var popup = L.popup();
popup.setContent('');
marker.bindPopup(popup, {autoClose: autoClose, closeOnClick: false});
marker.bindPopup(popup, {autoClose: settings.autocloseTooltip, closeOnClick: false});
this.tooltips.push( {
markerArgs: markerArgs,
popup: popup,
pattern: pattern,
replaceInfo: replaceInfo
locationSettings: settings,
dsIndex: dsIndex
});
}

7
ui/src/app/widget/lib/map-widget.js

@ -403,7 +403,7 @@ export default class TbMapWidget {
if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) {
location.settings.currentImage = image;
}
location.marker = tbMap.map.createMarker(markerLocation, location.settings,
location.marker = tbMap.map.createMarker(markerLocation, location.dsIndex, location.settings,
function() {
tbMap.callbacks.onLocationClick(location);
}
@ -563,8 +563,9 @@ export default class TbMapWidget {
var tooltips = this.map.getTooltips();
for (var t=0; t < tooltips.length; t++) {
var tooltip = tooltips[t];
var text = tooltip.pattern;
var replaceInfo = tooltip.replaceInfo;
var settings = tooltip.locationSettings;
var text = settings.tooltipPattern;
var replaceInfo = settings.tooltipReplaceInfo;
for (var v = 0; v < replaceInfo.variables.length; v++) {
var variableInfo = replaceInfo.variables[v];
var txtVal = '';

126
ui/src/app/widget/lib/map-widget2.js

@ -138,6 +138,24 @@ export default class TbMapWidgetV2 {
this.locationSettings.label = this.ctx.settings.label || "${entityName}";
this.locationSettings.color = this.ctx.settings.color ? tinycolor(this.ctx.settings.color).toHexString() : "#FE7569";
this.locationSettings.useLabelFunction = this.ctx.settings.useLabelFunction === true;
if (angular.isDefined(this.ctx.settings.labelFunction) && this.ctx.settings.labelFunction.length > 0) {
try {
this.locationSettings.labelFunction = new Function('data, dsData, dsIndex', this.ctx.settings.labelFunction);
} catch (e) {
this.locationSettings.labelFunction = null;
}
}
this.locationSettings.useTooltipFunction = this.ctx.settings.useTooltipFunction === true;
if (angular.isDefined(this.ctx.settings.tooltipFunction) && this.ctx.settings.tooltipFunction.length > 0) {
try {
this.locationSettings.tooltipFunction = new Function('data, dsData, dsIndex', this.ctx.settings.tooltipFunction);
} catch (e) {
this.locationSettings.tooltipFunction = null;
}
}
this.locationSettings.useColorFunction = this.ctx.settings.useColorFunction === true;
if (angular.isDefined(this.ctx.settings.colorFunction) && this.ctx.settings.colorFunction.length > 0) {
try {
@ -192,14 +210,30 @@ export default class TbMapWidgetV2 {
var tbMap = this;
function updateLocationLabel(location) {
if (location.settings.showLabel && location.settings.labelReplaceInfo.variables.length) {
location.settings.labelText = fillPattern(location.settings.label,
location.settings.labelReplaceInfo, tbMap.subscription.data);
function updateLocationLabel(location, dataMap) {
if (location.settings.showLabel) {
if (location.settings.useLabelFunction && location.settings.labelFunction) {
try {
location.settings.label = location.settings.labelFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex);
} catch (e) {
location.settings.label = null;
}
if (location.settings.label) {
var datasources = tbMap.subscription.datasources;
location.settings.label = tbMap.utils.createLabelFromDatasource(datasources[location.dsIndex], location.settings.label);
location.settings.labelReplaceInfo = processPattern(location.settings.label, datasources, location.dsIndex);
location.settings.labelText = location.settings.label;
}
}
if (location.settings.labelReplaceInfo.variables.length) {
location.settings.labelText = fillPattern(location.settings.label,
location.settings.labelReplaceInfo, tbMap.subscription.data);
}
tbMap.map.updateMarkerLabel(location.marker, location.settings);
}
}
function calculateLocationColor(location, dataMap) {
if (location.settings.useColorFunction && location.settings.colorFunction) {
var color;
@ -249,7 +283,7 @@ export default class TbMapWidgetV2 {
}
function updateLocationStyle(location, dataMap) {
updateLocationLabel(location);
updateLocationLabel(location, dataMap);
var color = calculateLocationColor(location, dataMap);
var image = calculateLocationMarkerImage(location, dataMap);
updateLocationColor(location, color, image);
@ -263,7 +297,7 @@ export default class TbMapWidgetV2 {
if (image && (!location.settings.currentImage || !angular.equals(location.settings.currentImage, image))) {
location.settings.currentImage = image;
}
location.marker = tbMap.map.createMarker(markerLocation, location.settings,
location.marker = tbMap.map.createMarker(markerLocation, location.dsIndex, location.settings,
function (event) {
tbMap.callbacks.onLocationClick(location);
locationRowClick(event, location);
@ -425,6 +459,25 @@ export default class TbMapWidgetV2 {
}
}
function createTooltipContent(tooltip, data, datasources) {
var content;
var settings = tooltip.locationSettings;
if (settings.useTooltipFunction && settings.tooltipFunction) {
var dataMap = toLabelValueMap(data, datasources);
try {
settings.tooltipPattern = settings.tooltipFunction(dataMap.dataMap, dataMap.dsDataMap, tooltip.dsIndex);
} catch (e) {
settings.tooltipPattern = null;
}
if (settings.tooltipPattern) {
settings.tooltipPattern = tbMap.utils.createLabelFromDatasource(datasources[tooltip.dsIndex], settings.tooltipPattern);
settings.tooltipReplaceInfo = processPattern(settings.tooltipPattern, datasources, tooltip.dsIndex);
}
}
content = fillPattern(settings.tooltipPattern, settings.tooltipReplaceInfo, data);
return fillPatternWithActions(content, 'onTooltipAction', tooltip.markerArgs);
}
if (this.map && this.map.inited() && this.subscription) {
if (this.subscription.data) {
if (!this.locations) {
@ -433,10 +486,9 @@ export default class TbMapWidgetV2 {
updateLocations(this.subscription.data, this.subscription.datasources);
}
var tooltips = this.map.getTooltips();
for (var t=0; t < tooltips.length; t++) {
for (var t = 0; t < tooltips.length; t++) {
var tooltip = tooltips[t];
var text = fillPattern(tooltip.pattern, tooltip.replaceInfo, this.subscription.data);
text = fillPatternWithActions(text, 'onTooltipAction', tooltip.markerArgs);
var text = createTooltipContent(tooltip, this.subscription.data, this.subscription.datasources);
tooltip.popup.setContent(text);
}
}
@ -683,6 +735,15 @@ const commonMapSettingsSchema =
"type":"string",
"default":"${entityName}"
},
"useLabelFunction": {
"title":"Use label function",
"type":"boolean",
"default":false
},
"labelFunction":{
"title":"Label function: f(data, dsData, dsIndex)",
"type":"string"
},
"showTooltip": {
"title": "Show tooltip",
"type":"boolean",
@ -698,6 +759,15 @@ const commonMapSettingsSchema =
"type":"string",
"default":"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}"
},
"useTooltipFunction": {
"title":"Use tooltip function",
"type":"boolean",
"default":false
},
"tooltipFunction":{
"title":"Tooltip function: f(data, dsData, dsIndex)",
"type":"string"
},
"color":{
"title":"Color",
"type":"string"
@ -747,12 +817,22 @@ const commonMapSettingsSchema =
"lngKeyName",
"showLabel",
"label",
"useLabelFunction",
{
"key":"labelFunction",
"type":"javascript"
},
"showTooltip",
"autocloseTooltip",
{
"key": "tooltipPattern",
"type": "textarea"
},
"useTooltipFunction",
{
"key":"tooltipFunction",
"type":"javascript"
},
{
"key":"color",
"type":"color"
@ -851,6 +931,15 @@ const imageMapSettingsSchema =
"type":"string",
"default":"${entityName}"
},
"useLabelFunction": {
"title":"Use label function",
"type":"boolean",
"default":false
},
"labelFunction":{
"title":"Label function: f(data, dsData, dsIndex)",
"type":"string"
},
"showTooltip": {
"title": "Show tooltip",
"type":"boolean",
@ -866,6 +955,15 @@ const imageMapSettingsSchema =
"type":"string",
"default":"<b>${entityName}</b><br/><br/><b>X Pos:</b> ${xPos:2}<br/><b>Y Pos:</b> ${yPos:2}"
},
"useTooltipFunction": {
"title":"Use tooltip function",
"type":"boolean",
"default":false
},
"tooltipFunction":{
"title":"Tooltip function: f(data, dsData, dsIndex)",
"type":"string"
},
"color":{
"title":"Color",
"type":"string"
@ -934,12 +1032,22 @@ const imageMapSettingsSchema =
"yPosKeyName",
"showLabel",
"label",
"useLabelFunction",
{
"key":"labelFunction",
"type":"javascript"
},
"showTooltip",
"autocloseTooltip",
{
"key": "tooltipPattern",
"type": "textarea"
},
"useTooltipFunction",
{
"key":"tooltipFunction",
"type":"javascript"
},
{
"key":"color",
"type":"color"

12
ui/src/app/widget/lib/openstreet-map.js

@ -126,7 +126,7 @@ export default class TbOpenStreetMap {
onMarkerIconReady(iconInfo);
}
createMarker(location, settings, onClickListener, markerArgs) {
createMarker(location, dsIndex, settings, onClickListener, markerArgs) {
var marker = L.marker(location, {});
var opMap = this;
this.createMarkerIcon(marker, settings, (iconInfo) => {
@ -140,7 +140,7 @@ export default class TbOpenStreetMap {
});
if (settings.displayTooltip) {
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
this.createTooltip(marker, dsIndex, settings, markerArgs);
}
if (onClickListener) {
@ -154,15 +154,15 @@ export default class TbOpenStreetMap {
this.map.removeLayer(marker);
}
createTooltip(marker, pattern, replaceInfo, autoClose, markerArgs) {
createTooltip(marker, dsIndex, settings, markerArgs) {
var popup = L.popup();
popup.setContent('');
marker.bindPopup(popup, {autoClose: autoClose, closeOnClick: false});
marker.bindPopup(popup, {autoClose: settings.autocloseTooltip, closeOnClick: false});
this.tooltips.push( {
markerArgs: markerArgs,
popup: popup,
pattern: pattern,
replaceInfo: replaceInfo
locationSettings: settings,
dsIndex: dsIndex
});
}

12
ui/src/app/widget/lib/tencent-map.js

@ -224,7 +224,7 @@ export default class TbTencentMap {
/* eslint-enable no-undef */
/* eslint-disable no-undef */
createMarker(location, settings, onClickListener, markerArgs) {
createMarker(location, dsIndex, settings, onClickListener, markerArgs) {
var marker = new qq.maps.Marker({
position: location
});
@ -247,7 +247,7 @@ export default class TbTencentMap {
});
if (settings.displayTooltip) {
this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs);
this.createTooltip(marker, dsIndex, settings, markerArgs);
}
if (onClickListener) {
@ -268,13 +268,13 @@ export default class TbTencentMap {
/* eslint-enable no-undef */
/* eslint-disable no-undef */
createTooltip(marker, pattern, replaceInfo, autoClose, markerArgs) {
createTooltip(marker, dsIndex, settings, markerArgs) {
var popup = new qq.maps.InfoWindow({
map :this.map
});
var map = this;
qq.maps.event.addListener(marker, 'click', function() {
if (autoClose) {
if (settings.autocloseTooltip) {
map.tooltips.forEach((tooltip) => {
tooltip.popup.close();
});
@ -285,8 +285,8 @@ export default class TbTencentMap {
this.tooltips.push( {
markerArgs: markerArgs,
popup: popup,
pattern: pattern,
replaceInfo: replaceInfo
locationSettings: settings,
dsIndex: dsIndex
});
}
/* eslint-enable no-undef */

4
ui/src/app/widget/lib/widget-utils.js

@ -139,7 +139,9 @@ export function toLabelValueMap(data, datasources) {
var dataMap = {};
var dsDataMap = [];
for (var d=0;d<datasources.length;d++) {
dsDataMap[d] = {};
dsDataMap[d] = {
$datasource: datasources[d]
};
}
for (var i = 0; i < data.length; i++) {
var dataKey = data[i].dataKey;

Loading…
Cancel
Save