From c00279c447bf0a0ce8e6241a13878fb3e9c442a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Milo=C5=A1evi=C4=87?= Date: Tue, 11 Feb 2020 10:18:51 +0100 Subject: [PATCH 01/39] NOISSUE - Add publishing mqtt to service subtopic (#50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add mqtt publish to service Signed-off-by: Ivan Milošević * Remove trailing / from createTopic Signed-off-by: Ivan Milošević --- src/app/common/services/mqtt/mqtt.manager.service.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/app/common/services/mqtt/mqtt.manager.service.ts b/src/app/common/services/mqtt/mqtt.manager.service.ts index bbe02570..22a40b6e 100644 --- a/src/app/common/services/mqtt/mqtt.manager.service.ts +++ b/src/app/common/services/mqtt/mqtt.manager.service.ts @@ -65,7 +65,7 @@ export class MqttManagerService { } createTopic(channel: string) { - return `channels/${channel}/messages/`; + return `channels/${channel}/messages`; } createPayload(baseName: string, name: string, valueString: string) { @@ -73,13 +73,19 @@ export class MqttManagerService { } publish(channel: string, bn: string, n: string, vs: string) { - const topic = this.createTopic(channel) + 'req'; + const topic = `${this.createTopic(channel)}/req`; + const payload = this.createPayload(bn, n, vs); + this.mqttService.publish(topic, payload).subscribe(); + } + + publishToService(channel: string, svc: string, bn: string, n: string, vs: string) { + const topic = `${this.createTopic(channel)}/services/${svc}`; const payload = this.createPayload(bn, n, vs); this.mqttService.publish(topic, payload).subscribe(); } subscribe(channel: string) { - const topic = this.createTopic(channel) + 'res'; + const topic = `${this.createTopic(channel)}/res`; const topicSub = this.mqttService.observe(topic).subscribe( (message: IMqttMessage) => { const pl = message.payload.toString(); From 26352d354263719d881d64b1f5982d89cd2ebda2 Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Wed, 12 Feb 2020 10:36:21 +0100 Subject: [PATCH 02/39] NOISSUE - Add store and search bar for browsed opc-ua server data (#53) * NOISSUE - Add store and search bar for browsed opc-ua server data Signed-off-by: Manuel Imperiale * Fix reviews Signed-off-by: Manuel Imperiale * Fix reviews Signed-off-by: Manuel Imperiale --- .../auth/auth.token.interceptor.service.ts | 1 + src/app/common/common.module.ts | 2 + src/app/common/store/opcua.store.ts | 21 ++++ .../pages/things/opcua/opcua.component.html | 99 +++++++++---------- .../pages/things/opcua/opcua.component.scss | 12 +-- src/app/pages/things/opcua/opcua.component.ts | 38 ++++++- 6 files changed, 110 insertions(+), 63 deletions(-) create mode 100644 src/app/common/store/opcua.store.ts diff --git a/src/app/auth/auth.token.interceptor.service.ts b/src/app/auth/auth.token.interceptor.service.ts index a76943b5..a1c96ece 100644 --- a/src/app/auth/auth.token.interceptor.service.ts +++ b/src/app/auth/auth.token.interceptor.service.ts @@ -50,6 +50,7 @@ export class TokenInterceptor implements HttpInterceptor { !request.url.startsWith(environment.writerChannelsUrl) && !request.url.startsWith(environment.readerChannelsUrl) && !request.url.startsWith(environment.bootstrapUrl) && + !request.url.startsWith(environment.browseUrl) && (err.status === 403 || err.status === 504)) { localStorage.removeItem('auth_app_token'); this.router.navigateByUrl('/auth/login'); diff --git a/src/app/common/common.module.ts b/src/app/common/common.module.ts index aabfc045..3d3acee0 100644 --- a/src/app/common/common.module.ts +++ b/src/app/common/common.module.ts @@ -5,6 +5,7 @@ import { ChannelsService } from './services/channels/channels.service'; import { GatewaysService } from './services/gateways/gateways.service'; import { LoraService } from './services/lora/lora.service'; import { OpcuaService } from './services/opcua/opcua.service'; +import { OpcuaStore } from 'app/common/store/opcua.store'; import { MessagesService } from './services/messages/messages.service'; import { MqttManagerService } from './services/mqtt/mqtt.manager.service'; import { NotificationsService } from './services/notifications/notifications.service'; @@ -23,6 +24,7 @@ import { HTTP_INTERCEPTORS } from '@angular/common/http'; GatewaysService, LoraService, OpcuaService, + OpcuaStore, MessagesService, MqttManagerService, NotificationsService, diff --git a/src/app/common/store/opcua.store.ts b/src/app/common/store/opcua.store.ts new file mode 100644 index 00000000..82d91e9e --- /dev/null +++ b/src/app/common/store/opcua.store.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; + +@Injectable() +export class OpcuaStore { + browsedNodes = { + uri: '', + nodes: [], + }; + + constructor( + ) { } + + setBrowsedNodes(browse: any) { + this.browsedNodes.uri = browse.uri; + this.browsedNodes.nodes = browse.nodes; + } + + getBrowsedNodes() { + return this.browsedNodes; + } +} diff --git a/src/app/pages/things/opcua/opcua.component.html b/src/app/pages/things/opcua/opcua.component.html index d35ad268..6256ecef 100644 --- a/src/app/pages/things/opcua/opcua.component.html +++ b/src/app/pages/things/opcua/opcua.component.html @@ -1,20 +1,11 @@ - +
-
- ServerURI -
-
- -
-
- NodeID -
-
- -
- + OPC-UA Server URI: +
+
+
+
+ + + + +
+ Node ID +
+
+ Data Type +
+
+ Description +
+
+ BrowseName +
+
+ +
+
+
- - -
- Node ID -
-
- Data Type -
-
- Description -
-
- BrowseName -
-
-
-
- -
- {{ node.NodeID }} -
-
- {{ node.DataType }} -
-
- {{ node.Description }} -
-
- {{ node.BrowseName }} -
-
- -
-
-
+ + No browsed server + + +
+ {{ node.NodeID }} +
+
+ {{ node.DataType }} +
+
+ {{ node.Description }} +
+
+ {{ node.BrowseName }} +
+
+ +
+
- +
{{ opcuaNodes.length }}   OPC-UA Server Subscription diff --git a/src/app/pages/things/opcua/opcua.component.scss b/src/app/pages/things/opcua/opcua.component.scss index b2760d0f..a3fdc27b 100644 --- a/src/app/pages/things/opcua/opcua.component.scss +++ b/src/app/pages/things/opcua/opcua.component.scss @@ -1,11 +1,7 @@ -nb-card-header { - text-align: center; -} - -i { - font-size: 8px; -} - button { width: 100%; } + +.col-2, .col-4 { + word-wrap: break-word; +} diff --git a/src/app/pages/things/opcua/opcua.component.ts b/src/app/pages/things/opcua/opcua.component.ts index 98770fea..b72c982b 100644 --- a/src/app/pages/things/opcua/opcua.component.ts +++ b/src/app/pages/things/opcua/opcua.component.ts @@ -8,6 +8,7 @@ import { NotificationsService } from 'app/common/services/notifications/notifica import { ConfirmationComponent } from 'app/shared/confirmation/confirmation.component'; import { DetailsComponent } from 'app/shared/details/details.component'; import { MessagesService } from 'app/common/services/messages/messages.service'; +import { OpcuaStore } from 'app/common/store/opcua.store'; const defFreq: number = 100; @@ -39,13 +40,19 @@ export class OpcuaComponent implements OnInit { title: 'Name', addable: true, filter: false, + valuePrepareFunction: (cell, row) => { + if (cell.length > 20) { + return `${cell.substring(0, 19)}...`; + } + return cell; + }, }, serverURI: { title: 'Server URI', editable: false, addable: true, filter: false, - valuePrepareFunction: (cell) => { + valuePrepareFunction: (cell, row) => { if (cell.length > 30) { return `${cell.substring(10, 39)}...`; } @@ -57,7 +64,7 @@ export class OpcuaComponent implements OnInit { editable: true, addable: true, filter: false, - valuePrepareFunction: (cell) => { + valuePrepareFunction: (cell, row) => { if (cell.length > 20) { return `${cell.substring(0, 19)}...`; } @@ -69,7 +76,7 @@ export class OpcuaComponent implements OnInit { editable: false, addable: false, filter: false, - valuePrepareFunction: cell => { + valuePrepareFunction: (cell, row) => { if (cell > 0) { return cell; } @@ -112,9 +119,12 @@ export class OpcuaComponent implements OnInit { opcuaNodes = []; browseServerURI = ''; - browseNamespace = ''; - browseIdentifier = ''; + // Standard root OPC-UA server NodeID (ns=0;i=84) + browseNamespace = '0'; + browseIdentifier = 'i=84'; + browsedNodes = []; + browseSearch = []; checkedNodes = []; offset = 0; @@ -127,10 +137,14 @@ export class OpcuaComponent implements OnInit { private opcuaService: OpcuaService, private messagesService: MessagesService, private notificationsService: NotificationsService, + private opcuaStore: OpcuaStore, private dialogService: NbDialogService, ) { } ngOnInit() { + const browseStore = this.opcuaStore.getBrowsedNodes(); + this.browseServerURI = browseStore.uri; + this.browsedNodes = browseStore.nodes; this.getOpcuaNodes(); } @@ -214,6 +228,11 @@ export class OpcuaComponent implements OnInit { this.opcuaService.browseServerNodes(this.browseServerURI, this.browseNamespace, this.browseIdentifier).subscribe( (resp: any) => { this.browsedNodes = resp.nodes; + const browsedNodes = { + uri: this.browseServerURI, + nodes: this.browsedNodes, + }; + this.opcuaStore.setBrowsedNodes(browsedNodes); }, err => { }, @@ -260,6 +279,15 @@ export class OpcuaComponent implements OnInit { } } + searchBrowse(input) { + const browseStore = this.opcuaStore.getBrowsedNodes(); + this.browsedNodes = browseStore.nodes.filter( node => + (node.NodeID.includes(input) || + node.Description.includes(input) || + node.DataType.includes(input) || + node.BrowseName.includes(input))); + } + onClickSave() { } From e5f28181e1ba30b06a5e1ca31a1f1401034cb658 Mon Sep 17 00:00:00 2001 From: Darko Draskovic Date: Wed, 12 Feb 2020 13:38:23 +0100 Subject: [PATCH 03/39] Enable edit twin name in twins table (#54) Signed-off-by: Darko Draskovic --- src/app/pages/admin/twins/twins.component.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/pages/admin/twins/twins.component.ts b/src/app/pages/admin/twins/twins.component.ts index acdd023c..69143df7 100644 --- a/src/app/pages/admin/twins/twins.component.ts +++ b/src/app/pages/admin/twins/twins.component.ts @@ -104,6 +104,8 @@ export class TwinsComponent implements OnInit { onEditConfirm(event): void { // close edditable row event.confirm.resolve(); + + this.twinsService.editTwin(event.newData).subscribe(); } onDeleteConfirm(event): void { From 725602b2a6f5279746bfceaa910962cf0daeb044 Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Thu, 13 Feb 2020 11:53:52 +0100 Subject: [PATCH 04/39] NOISSUE - Add Twins to docker-compose and nginx conf (#55) * NOISSUE - Add Twins to docker-compose and nginx conf Signed-off-by: Manuel Imperiale * NOISSUE - Polish style Signed-off-by: Manuel Imperiale * Fix reviews Signed-off-by: Manuel Imperiale --- .env | 17 ++ docker/docker-compose.yml | 41 +++++ docker/nginx/entrypoint.sh | 1 + docker/nginx/nginx-key.conf | 6 + docker/nginx/nginx-x509.conf | 5 + .../common/interfaces/mainflux.interface.ts | 1 + .../services/gateways/gateways.service.ts | 4 +- .../services/messages/messages.service.ts | 2 +- src/app/pages/admin/admin.module.ts | 2 + .../details/twins.details.component.html | 169 +++++++++++++----- .../details/twins.details.component.scss | 6 +- .../pages/admin/twins/twins.component.html | 39 ++-- .../pages/admin/twins/twins.component.scss | 7 + src/app/pages/admin/twins/twins.component.ts | 44 ++++- .../things/channels/channels.component.ts | 29 ++- .../pages/things/devices/devices.component.ts | 21 ++- .../things/gateways/gateways.component.html | 74 ++++---- .../things/gateways/gateways.component.scss | 4 + .../things/gateways/gateways.component.ts | 66 ++++--- src/app/pages/things/lora/lora.component.ts | 32 ++-- src/app/pages/things/opcua/opcua.component.ts | 31 ++-- 21 files changed, 403 insertions(+), 198 deletions(-) diff --git a/.env b/.env index 69c917c7..c5fe69e7 100644 --- a/.env +++ b/.env @@ -193,3 +193,20 @@ MF_POSTGRES_READER_DB_SSL_MODE=disable MF_POSTGRES_READER_DB_SSL_CERT="" MF_POSTGRES_READER_DB_SSL_KEY="" MF_POSTGRES_READER_DB_SSL_ROOT_CERT="" + +# Twins +MF_TWINS_LOG_LEVEL=debug +MF_TWINS_HTTP_PORT=9021 +MF_TWINS_SERVER_CERT="" +MF_TWINS_SERVER_KEY="" +MF_TWINS_DB_NAME=mainflux-twins +MF_TWINS_DB_HOST=twins-db +MF_TWINS_DB_PORT=27018 +MF_TWINS_SINGLE_USER_EMAIL="" +MF_TWINS_SINGLE_USER_TOKEN="" +MF_TWINS_CLIENT_TLS="" +MF_TWINS_CA_CERTS="" +MF_TWINS_MQTT_URL=tcp://mqtt-adapter:1883 +MF_TWINS_THING_ID=8041bbca-34d0-435f-86c1-21798555b59a +MF_TWINS_THING_KEY=65c0244b-b4ad-4286-a9de-74a19de20b45 +MF_TWINS_CHANNEL_ID=b3cfd2cc-ad49-4ed8-82b7-cb80e544acdb diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 0748e5e3..0fb7f9f7 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -18,6 +18,8 @@ volumes: mainflux-grafana-volume: mainflux-opcua-adapter-volume: mainflux-opcua-redis-volume: + mainflux-twins-db-volume: + mainflux-twins-db-configdb-volume: services: nginx: @@ -451,3 +453,42 @@ services: MF_JAEGER_URL: ${MF_JAEGER_URL} networks: - mainflux-base-net + + twins-db: + image: mongo:3.6-jessie + command: mongod --port ${MF_TWINS_DB_PORT} + container_name: mainflux-twins-db + restart: on-failure + environment: + MONGO_INITDB_DATABASE: ${MF_TWINS_DB_NAME} + ports: + - ${MF_TWINS_DB_PORT}:${MF_TWINS_DB_PORT} + networks: + mainflux-base-net: + volumes: + - mainflux-twins-db-volume:/data/db + - mainflux-twins-db-configdb-volume:/data/configdb + + twins: + image: mainflux/twins:latest + container_name: mainflux-twins + depends_on: + - twins-db + - nats + restart: on-failure + environment: + MF_TWINS_LOG_LEVEL: ${MF_TWINS_LOG_LEVEL} + MF_TWINS_HTTP_PORT: ${MF_TWINS_HTTP_PORT} + MF_TWINS_DB_NAME: ${MF_TWINS_DB_NAME} + MF_TWINS_DB_HOST: ${MF_TWINS_DB_HOST} + MF_TWINS_DB_PORT: ${MF_TWINS_DB_PORT} + MF_TWINS_THING_ID: ${MF_TWINS_THING_ID} + MF_TWINS_THING_KEY: ${MF_TWINS_THING_KEY} + MF_TWINS_CHANNEL_ID: ${MF_TWINS_CHANNEL_ID} + MF_NATS_URL: ${MF_NATS_URL} + MF_AUTHN_URL: authn:${MF_AUTHN_GRPC_PORT} + MF_TWINS_MQTT_URL: ${MF_TWINS_MQTT_URL} + ports: + - ${MF_TWINS_HTTP_PORT}:${MF_TWINS_HTTP_PORT} + networks: + mainflux-base-net: diff --git a/docker/nginx/entrypoint.sh b/docker/nginx/entrypoint.sh index 4ee5f268..77f64da0 100755 --- a/docker/nginx/entrypoint.sh +++ b/docker/nginx/entrypoint.sh @@ -18,6 +18,7 @@ envsubst ' ${MF_UI_PORT} ${MF_INFLUX_READER_PORT} ${MF_BOOTSTRAP_PORT} + ${MF_TWINS_HTTP_PORT} ${MF_OPCUA_ADAPTER_HTTP_PORT}' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf exec nginx -g "daemon off;" diff --git a/docker/nginx/nginx-key.conf b/docker/nginx/nginx-key.conf index e6b0ae9c..41ebdaac 100644 --- a/docker/nginx/nginx-key.conf +++ b/docker/nginx/nginx-key.conf @@ -116,6 +116,12 @@ http { proxy_pass http://opcua-adapter:${MF_OPCUA_ADAPTER_HTTP_PORT}; } + # Proxy pass to mainflux-twins + location ~ ^/(twins|states) { + include snippets/proxy-headers.conf; + proxy_pass http://twins:${MF_TWINS_HTTP_PORT}; + } + location / { include snippets/proxy-headers.conf; proxy_pass http://ui:${MF_UI_PORT}; diff --git a/docker/nginx/nginx-x509.conf b/docker/nginx/nginx-x509.conf index 3c3670fb..c67f547a 100644 --- a/docker/nginx/nginx-x509.conf +++ b/docker/nginx/nginx-x509.conf @@ -126,6 +126,11 @@ http { proxy_pass http://opcua-adapter:${MF_OPCUA_ADAPTER_HTTP_PORT}; } + location ~ ^/(twins|states) { + include snippets/proxy-headers.conf; + proxy_pass http://twins:${MF_TWINS_HTTP_PORT}; + } + location / { include snippets/proxy-headers.conf; proxy_pass http://ui:${MF_UI_PORT}; diff --git a/src/app/common/interfaces/mainflux.interface.ts b/src/app/common/interfaces/mainflux.interface.ts index 46897f97..33b6e96a 100644 --- a/src/app/common/interfaces/mainflux.interface.ts +++ b/src/app/common/interfaces/mainflux.interface.ts @@ -37,6 +37,7 @@ export interface Twin { id?: string; revision?: number; created?: Date; + updated?: Date; definitions?: Definition[]; definition?: any; // for request metadata?: any; diff --git a/src/app/common/services/gateways/gateways.service.ts b/src/app/common/services/gateways/gateways.service.ts index d74d763e..eb134132 100644 --- a/src/app/common/services/gateways/gateways.service.ts +++ b/src/app/common/services/gateways/gateways.service.ts @@ -28,11 +28,11 @@ export class GatewaysService { private notificationsService: NotificationsService, ) { } - getGateways(offset?: number, limit?: number) { + getGateways(offset?: number, limit?: number, name?: string) { offset = offset || 0; limit = limit || defLimit; - return this.thingsService.getThings(offset, limit, this.typeGateway); + return this.thingsService.getThings(offset, limit, this.typeGateway, '', name); } getCtrlChannels(offset: number, limit: number) { diff --git a/src/app/common/services/messages/messages.service.ts b/src/app/common/services/messages/messages.service.ts index e5b98784..76e82b3d 100644 --- a/src/app/common/services/messages/messages.service.ts +++ b/src/app/common/services/messages/messages.service.ts @@ -6,7 +6,7 @@ import { environment } from 'environments/environment'; import { ThingsService } from 'app/common/services/things/things.service'; import { NotificationsService } from 'app/common/services/notifications/notifications.service'; -const defLimit: number = 500; +const defLimit: number = 100; @Injectable() export class MessagesService { diff --git a/src/app/pages/admin/admin.module.ts b/src/app/pages/admin/admin.module.ts index 4afd794d..f7e8a8e2 100644 --- a/src/app/pages/admin/admin.module.ts +++ b/src/app/pages/admin/admin.module.ts @@ -8,6 +8,7 @@ import { NbSelectModule, NbInputModule, NbCheckboxModule, + NbListModule, } from '@nebular/theme'; @@ -40,6 +41,7 @@ import { ConfirmationComponent } from 'app/shared/confirmation/confirmation.comp NbSelectModule, NbCheckboxModule, PagesModule, + NbListModule, ], declarations: [ TracingComponent, diff --git a/src/app/pages/admin/twins/details/twins.details.component.html b/src/app/pages/admin/twins/details/twins.details.component.html index 788e2fa1..7ff1d873 100644 --- a/src/app/pages/admin/twins/details/twins.details.component.html +++ b/src/app/pages/admin/twins/details/twins.details.component.html @@ -2,27 +2,55 @@
- Info + Twin Info
-
Name:
{{twin.name}}
-
- -
-
Owner:
{{ twin.owner }}
+
+ Name: +
+
+ {{ twin.name }} +
+
+ Owner: +
+
+ {{ twin.owner }} +
-
ID:
{{ twin.id }}
+
+ ID: +
+
+ {{ twin.id }} +
-
Created:
{{ twin.created }}
+
+ Created: +
+
+ {{ twin.created }} +
+
+ Updated: +
+
+ {{ twin.updated }} +
-
Revision:
{{ twin.revision }}
+
+ Revision: +
+
+ {{ twin.revision }} +
@@ -35,7 +63,7 @@ State {{ stateTime | date: 'long' }} - @@ -55,23 +83,43 @@ Definition {{def.created | date: 'long'}} - -
- {{attr.name}} -
    -
  • Channel - {{ defChans[attr.channel] }} - {{ attr.channel }}
  • -
  • Subtopic - {{ attr.subtopic }}
  • -
  • Persisted - {{ attr.persist_state }}
  • -
-
+ +
+ Name +
+
+ Channel +
+
+ Subtopic +
+
+ Persisted +
+
+
+
+ +
+ {{ attr.name }} +
+
+ {{ attr.channel }} - {{ defChans[attr.channel] }} +
+
+ {{ attr.subtopic }} +
+
+ {{ attr.persist_state }} +
+
+
+
@@ -79,61 +127,90 @@
- + Add definition - -
-
- {{ attr.name }} -
    -
  • Channel - {{ attr.channel }}
  • -
  • Subtopic - {{ attr.subtopic }}
  • -
  • Persisted - {{ attr.persist_state }}
  • -
+ +
+ Name +
+
+ Channel +
+
+ Subtopic +
+
+ Persisted +
+
+
+
+ +
+ {{ attr.name }} +
+
+ {{ attr.channel }} +
+
+ {{ attr.subtopic }} +
+
+ {{ attr.persist_state }}
-
+
-
Name:
+
+ Name: +
+
-
Channel:
- +
+ Channel: +
+
+ {{channel.name}}
+
-
Subtopic:
+
+
+ Subtopic: +
+
- -
Persisted:
+
+ Persisted: +
+
- -
diff --git a/src/app/pages/admin/twins/details/twins.details.component.scss b/src/app/pages/admin/twins/details/twins.details.component.scss index 57273207..c6e525da 100644 --- a/src/app/pages/admin/twins/details/twins.details.component.scss +++ b/src/app/pages/admin/twins/details/twins.details.component.scss @@ -2,8 +2,8 @@ nb-icon { vertical-align: middle; } -.col-2 { - font-weight: bold; +.row { + margin-bottom: 10px; } .pickable:hover { @@ -11,7 +11,7 @@ nb-icon { } nb-select { - min-width: 300px; + min-width: 400px; } button { diff --git a/src/app/pages/admin/twins/twins.component.html b/src/app/pages/admin/twins/twins.component.html index a9fe02c3..93744c4e 100644 --- a/src/app/pages/admin/twins/twins.component.html +++ b/src/app/pages/admin/twins/twins.component.html @@ -1,21 +1,36 @@ -
-
- - + + +
+
{{ twinsNumber }}   Twins - - -
-
- - +
+
+ +
+
+ +
+
+ +
+
+ + (deleteConfirm)="onDeleteConfirm($event)"> diff --git a/src/app/pages/admin/twins/twins.component.scss b/src/app/pages/admin/twins/twins.component.scss index e69de29b..e90dce65 100644 --- a/src/app/pages/admin/twins/twins.component.scss +++ b/src/app/pages/admin/twins/twins.component.scss @@ -0,0 +1,7 @@ +nb-card-header { + text-align: center; +} + +button { + width: 100%; +} diff --git a/src/app/pages/admin/twins/twins.component.ts b/src/app/pages/admin/twins/twins.component.ts index 69143df7..8e730cda 100644 --- a/src/app/pages/admin/twins/twins.component.ts +++ b/src/app/pages/admin/twins/twins.component.ts @@ -10,7 +10,6 @@ import { DetailsComponent } from 'app/shared/details/details.component'; import { TwinsService } from 'app/common/services/twins/twins.service'; import { Twin } from 'app/common/interfaces/mainflux.interface'; - @Component({ selector: 'ngx-twins', templateUrl: './twins.component.html', @@ -35,23 +34,42 @@ export class TwinsComponent implements OnInit { confirmDelete: true, }, columns: { + details: { + type: 'custom', + renderComponent: DetailsComponent, + valuePrepareFunction: (cell, row) => { + return row; + }, + editable: false, + addable: false, + filter: false, + }, name: { title: 'Name', editable: true, addable: true, + filter: false, }, - id: { - title: 'ID', + created: { + title: 'Created', editable: false, addable: false, + filter: false, + valuePrepareFunction: (cell, row) => { + return new Date(cell).toLocaleString(); + }, }, - details: { - title: 'Details', - type: 'custom', - renderComponent: DetailsComponent, + updated: { + title: 'Updated', + editable: false, + addable: false, + filter: false, valuePrepareFunction: (cell, row) => { - return row; + return new Date(cell).toLocaleString(); }, + }, + revision: { + title: 'Revision', editable: false, addable: false, filter: false, @@ -68,6 +86,8 @@ export class TwinsComponent implements OnInit { twinsNumber = 0; + searchTime = 0; + constructor( private dialogService: NbDialogService, private twinsService: TwinsService, @@ -124,6 +144,12 @@ export class TwinsComponent implements OnInit { ); } - onSelection(event): void { + onSaveFile() { + } + + onFileSelected(files: FileList) { + } + + searchThing(input) { } } diff --git a/src/app/pages/things/channels/channels.component.ts b/src/app/pages/things/channels/channels.component.ts index b682c340..58261387 100644 --- a/src/app/pages/things/channels/channels.component.ts +++ b/src/app/pages/things/channels/channels.component.ts @@ -9,7 +9,7 @@ import { NotificationsService } from 'app/common/services/notifications/notifica import { ConfirmationComponent } from 'app/shared/confirmation/confirmation.component'; import { DetailsComponent } from 'app/shared/details/details.component'; -const defFreq: number = 100; +const defSearchBardMs: number = 100; @Component({ selector: 'ngx-smart-table', @@ -36,18 +36,7 @@ export class ChannelsComponent implements OnInit { confirmDelete: true, }, columns: { - name: { - title: 'Name', - filter: false, - }, - id: { - title: 'ID', - editable: false, - addable: false, - filter: false, - }, details: { - title: 'Details', type: 'custom', renderComponent: DetailsComponent, valuePrepareFunction: (cell, row) => { @@ -57,6 +46,16 @@ export class ChannelsComponent implements OnInit { addable: false, filter: false, }, + name: { + title: 'Name', + filter: false, + }, + id: { + title: 'ID', + editable: false, + addable: false, + filter: false, + }, }, pager: { display: true, @@ -72,7 +71,7 @@ export class ChannelsComponent implements OnInit { offset = 0; limit = 100; - searchFreq = 0; + searchTime = 0; columnChar = '|'; constructor( @@ -140,9 +139,9 @@ export class ChannelsComponent implements OnInit { searchChannel(input) { const t = new Date().getTime(); - if ((t - this.searchFreq) > defFreq) { + if ((t - this.searchTime) > defSearchBardMs) { this.getChannels(input); - this.searchFreq = t; + this.searchTime = t; } } diff --git a/src/app/pages/things/devices/devices.component.ts b/src/app/pages/things/devices/devices.component.ts index 7e2864e5..3f7a7190 100644 --- a/src/app/pages/things/devices/devices.component.ts +++ b/src/app/pages/things/devices/devices.component.ts @@ -38,18 +38,7 @@ export class DevicesComponent implements OnInit { confirmDelete: true, }, columns: { - name: { - title: 'Name', - filter: false, - }, - id: { - title: 'ID', - editable: false, - addable: false, - filter: false, - }, details: { - title: 'Details', type: 'custom', renderComponent: DetailsComponent, valuePrepareFunction: (cell, row) => { @@ -59,6 +48,16 @@ export class DevicesComponent implements OnInit { addable: false, filter: false, }, + name: { + title: 'Name', + filter: false, + }, + id: { + title: 'ID', + editable: false, + addable: false, + filter: false, + }, }, pager: { display: true, diff --git a/src/app/pages/things/gateways/gateways.component.html b/src/app/pages/things/gateways/gateways.component.html index 2b930e2d..83f80a0d 100644 --- a/src/app/pages/things/gateways/gateways.component.html +++ b/src/app/pages/things/gateways/gateways.component.html @@ -1,40 +1,36 @@ -
-
- - + + +
+
{{ total }}   Gateways - - -
- -
- - - {{ gwCtrlChanNumber }}   Control Channels - - -
- -
- - - {{ gwDataChanNumber }}   Data Channels - - -
-
- -
-
- - - - - - -
-
+
+
+ +
+
+ +
+
+ +
+
+ + + + + + diff --git a/src/app/pages/things/gateways/gateways.component.scss b/src/app/pages/things/gateways/gateways.component.scss index 1c5c5a2c..e90dce65 100644 --- a/src/app/pages/things/gateways/gateways.component.scss +++ b/src/app/pages/things/gateways/gateways.component.scss @@ -1,3 +1,7 @@ nb-card-header { text-align: center; } + +button { + width: 100%; +} diff --git a/src/app/pages/things/gateways/gateways.component.ts b/src/app/pages/things/gateways/gateways.component.ts index 954fa57d..63c76954 100644 --- a/src/app/pages/things/gateways/gateways.component.ts +++ b/src/app/pages/things/gateways/gateways.component.ts @@ -11,16 +11,14 @@ import { MessagesService } from 'app/common/services/messages/messages.service'; import { DetailsComponent } from 'app/shared/details/details.component'; import { ConfirmationComponent } from 'app/shared/confirmation/confirmation.component'; +const defSearchBardMs: number = 100; + @Component({ selector: 'ngx-gateways-component', templateUrl: './gateways.component.html', styleUrls: ['./gateways.component.scss'], }) export class GatewaysComponent implements OnInit { - offset = 0; - limit = 20; - total = 0; - settings = { add: { addButtonContent: '', @@ -39,13 +37,21 @@ export class GatewaysComponent implements OnInit { confirmDelete: true, }, columns: { + details: { + type: 'custom', + renderComponent: DetailsComponent, + valuePrepareFunction: (cell, row) => { + row.type = 'gateways'; + return row; + }, + editable: 'false', + addable: false, + filter: false, + }, name: { title: 'Name', type: 'string', - placeholder: 'Search name', - filter: { - placeholder: 'Search name', - }, + filter: false, }, mac: { title: 'MAC', @@ -53,11 +59,7 @@ export class GatewaysComponent implements OnInit { type: 'text', editable: true, addable: true, - filter: { - config: { - placeholder: 'Search MAC', - }, - }, + filter: false, }, messages: { title: 'Messages', @@ -76,7 +78,7 @@ export class GatewaysComponent implements OnInit { width: '20%', title: 'Last Seen', type: 'text', - editable: 'false', + editable: false, addable: false, filter: false, valuePrepareFunction: (cell, row) => { @@ -86,18 +88,6 @@ export class GatewaysComponent implements OnInit { return 'undefined'; }, }, - details: { - title: 'Details', - type: 'custom', - renderComponent: DetailsComponent, - valuePrepareFunction: (cell, row) => { - row.type = 'gateways'; - return row; - }, - editable: 'false', - addable: false, - filter: false, - }, }, pager: { display: true, @@ -112,6 +102,12 @@ export class GatewaysComponent implements OnInit { gwCtrlChanNumber = 0; prefixLength = 3; + offset = 0; + limit = 20; + total = 0; + + searchTime = 0; + constructor( private gatewaysService: GatewaysService, private messagesService: MessagesService, @@ -138,10 +134,10 @@ export class GatewaysComponent implements OnInit { ); } - getGateways(): void { + getGateways(name?: string): void { this.gateways = []; - this.gatewaysService.getGateways(this.offset, this.limit).subscribe( + this.gatewaysService.getGateways(this.offset, this.limit, name).subscribe( (resp: any) => { this.total = resp.total; @@ -242,4 +238,18 @@ export class GatewaysComponent implements OnInit { }, ); } + + searchLora(input) { + const t = new Date().getTime(); + if ((t - this.searchTime) > defSearchBardMs) { + this.getGateways(input); + this.searchTime = t; + } + } + + onClickSave() { + } + + onFileSelected(files: FileList) { + } } diff --git a/src/app/pages/things/lora/lora.component.ts b/src/app/pages/things/lora/lora.component.ts index d335750c..cb6d7965 100644 --- a/src/app/pages/things/lora/lora.component.ts +++ b/src/app/pages/things/lora/lora.component.ts @@ -9,7 +9,7 @@ import { ConfirmationComponent } from 'app/shared/confirmation/confirmation.comp import { DetailsComponent } from 'app/shared/details/details.component'; import { MessagesService } from 'app/common/services/messages/messages.service'; -const defFreq: number = 100; +const defSearchBardMs: number = 100; @Component({ selector: 'ngx-lora-component', @@ -35,6 +35,18 @@ export class LoraComponent implements OnInit { confirmDelete: true, }, columns: { + details: { + title: 'Details', + type: 'custom', + renderComponent: DetailsComponent, + valuePrepareFunction: (cell, row) => { + row.type = 'lora'; + return row; + }, + editable: false, + addable: false, + filter: false, + }, name: { title: 'Name', filter: false, @@ -76,18 +88,6 @@ export class LoraComponent implements OnInit { return ' undefined '; }, }, - details: { - title: 'Details', - type: 'custom', - renderComponent: DetailsComponent, - valuePrepareFunction: (cell, row) => { - row.type = 'lora'; - return row; - }, - editable: false, - addable: false, - filter: false, - }, }, pager: { display: true, @@ -104,7 +104,7 @@ export class LoraComponent implements OnInit { offset = 0; limit = 20; - searchFreq = 0; + searchTime = 0; constructor( private loraService: LoraService, @@ -199,9 +199,9 @@ export class LoraComponent implements OnInit { searchLora(input) { const t = new Date().getTime(); - if ((t - this.searchFreq) > defFreq) { + if ((t - this.searchTime) > defSearchBardMs) { this.getLoraDevices(input); - this.searchFreq = t; + this.searchTime = t; } } diff --git a/src/app/pages/things/opcua/opcua.component.ts b/src/app/pages/things/opcua/opcua.component.ts index b72c982b..e8b30200 100644 --- a/src/app/pages/things/opcua/opcua.component.ts +++ b/src/app/pages/things/opcua/opcua.component.ts @@ -10,7 +10,7 @@ import { DetailsComponent } from 'app/shared/details/details.component'; import { MessagesService } from 'app/common/services/messages/messages.service'; import { OpcuaStore } from 'app/common/store/opcua.store'; -const defFreq: number = 100; +const defSearchBardMs: number = 100; @Component({ selector: 'ngx-opcua-component', @@ -36,6 +36,17 @@ export class OpcuaComponent implements OnInit { confirmDelete: true, }, columns: { + details: { + type: 'custom', + renderComponent: DetailsComponent, + valuePrepareFunction: (cell, row) => { + row.type = 'opcua'; + return row; + }, + editable: false, + addable: false, + filter: false, + }, name: { title: 'Name', addable: true, @@ -95,18 +106,6 @@ export class OpcuaComponent implements OnInit { return ' undefined '; }, }, - details: { - title: 'Details', - type: 'custom', - renderComponent: DetailsComponent, - valuePrepareFunction: (cell, row) => { - row.type = 'opcua'; - return row; - }, - editable: false, - addable: false, - filter: false, - }, }, pager: { display: true, @@ -130,7 +129,7 @@ export class OpcuaComponent implements OnInit { offset = 0; limit = 20; - searchFreq = 0; + searchTime = 0; columnChar = '|'; constructor( @@ -273,9 +272,9 @@ export class OpcuaComponent implements OnInit { searchNode(input) { const t = new Date().getTime(); - if ((t - this.searchFreq) > defFreq) { + if ((t - this.searchTime) > defSearchBardMs) { this.getOpcuaNodes(input); - this.searchFreq = t; + this.searchTime = t; } } From c8a2bb2e0c4616584fa9dc804bc38e22bbd281fa Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Fri, 14 Feb 2020 16:10:12 +0100 Subject: [PATCH 05/39] NOISSUE - Polish Twins lists (#56) * NOISSUE - Polish Twins lists Signed-off-by: Manuel Imperiale * Fix reviews Signed-off-by: Manuel Imperiale * Fix nb-list Signed-off-by: Manuel Imperiale --- src/app/pages/admin/admin.module.ts | 3 - .../twins.attributes.component.html | 14 - .../twins.attributes.component.scss | 3 - .../attributes/twins.attributes.component.ts | 14 - .../twins.definitions.component.html | 70 ++- .../twins.definitions.component.scss | 4 +- .../twins.definitions.component.ts | 32 -- .../details/twins.details.component.html | 397 +++++++++--------- .../details/twins.details.component.scss | 5 +- .../pages/things/opcua/opcua.component.html | 80 ++-- .../pages/things/opcua/opcua.component.scss | 2 +- 11 files changed, 290 insertions(+), 334 deletions(-) delete mode 100644 src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.html delete mode 100644 src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.scss delete mode 100644 src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.ts diff --git a/src/app/pages/admin/admin.module.ts b/src/app/pages/admin/admin.module.ts index f7e8a8e2..4b094c23 100644 --- a/src/app/pages/admin/admin.module.ts +++ b/src/app/pages/admin/admin.module.ts @@ -21,7 +21,6 @@ import { TwinsDetailsComponent } from './twins/details/twins.details.component'; import { TwinsStatesComponent } from './twins/states/twins.states.component'; import { TwinsPayloadComponent } from './twins/states/payload/twins.payload.component'; import { TwinsDefinitionsComponent } from './twins/definitions/twins.definitions.component'; -import { TwinsAttributesComponent } from './twins/definitions/attributes/twins.attributes.component'; import { DetailsComponent } from 'app/shared/details/details.component'; import { GrafanaComponent } from './grafana/grafana.component'; import { LoraServerComponent } from './loraserver/loraserver.component'; @@ -50,7 +49,6 @@ import { ConfirmationComponent } from 'app/shared/confirmation/confirmation.comp TwinsStatesComponent, TwinsPayloadComponent, TwinsDefinitionsComponent, - TwinsAttributesComponent, GrafanaComponent, LoraServerComponent, ], @@ -58,7 +56,6 @@ import { ConfirmationComponent } from 'app/shared/confirmation/confirmation.comp ConfirmationComponent, DetailsComponent, TwinsPayloadComponent, - TwinsAttributesComponent, ], }) export class AdminModule { } diff --git a/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.html b/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.html deleted file mode 100644 index 0ba3d4e7..00000000 --- a/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.html +++ /dev/null @@ -1,14 +0,0 @@ -
- {{value.created | date: 'long'}} -
- {{attr.name}} -
    -
  • Channel - {{ attr.channel }}
  • -
  • Subtopic - {{ attr.subtopic }}
  • -
  • Persisted - {{ attr.persist_state }}
  • -
-
-
diff --git a/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.scss b/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.scss deleted file mode 100644 index d7a0355f..00000000 --- a/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.col { - text-align: right; -} diff --git a/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.ts b/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.ts deleted file mode 100644 index 515e24da..00000000 --- a/src/app/pages/admin/twins/definitions/attributes/twins.attributes.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'ngx-twins-attributes-component', - templateUrl: './twins.attributes.component.html', - styleUrls: ['./twins.attributes.component.scss'], -}) -export class TwinsAttributesComponent { - // Depends on valuePrepareFunction - value: any; - - constructor( - ) { } -} diff --git a/src/app/pages/admin/twins/definitions/twins.definitions.component.html b/src/app/pages/admin/twins/definitions/twins.definitions.component.html index 3201f18b..eaaf000e 100644 --- a/src/app/pages/admin/twins/definitions/twins.definitions.component.html +++ b/src/app/pages/admin/twins/definitions/twins.definitions.component.html @@ -1,20 +1,52 @@ -
-
- - -
-
{{ definitions.length }} {{ twin.name }} definitions
-
-
- - - - - + + + {{ definitions.length }} {{ twin.name }} definitions + - - - -
-
+ + + +
+ Created +
+
+
+
+ Name +
+
+ Channels +
+
+ Subtopic +
+
+ Persisted +
+
+
+
+ +
+ {{def.created | date: 'short'}} +
+
+
+
+ {{ attr.name }} +
+
+ {{ attr.channel }} +
+
+ {{ attr.subtopic }} +
+
+ {{ attr.persist_state }} +
+
+
+
+
+
+ diff --git a/src/app/pages/admin/twins/definitions/twins.definitions.component.scss b/src/app/pages/admin/twins/definitions/twins.definitions.component.scss index feecb8c2..e8aca93a 100644 --- a/src/app/pages/admin/twins/definitions/twins.definitions.component.scss +++ b/src/app/pages/admin/twins/definitions/twins.definitions.component.scss @@ -1,3 +1,3 @@ -.col-10 { - text-align: right; +nb-list-item { + word-wrap: break-word; } diff --git a/src/app/pages/admin/twins/definitions/twins.definitions.component.ts b/src/app/pages/admin/twins/definitions/twins.definitions.component.ts index 75407a22..ca08a04e 100644 --- a/src/app/pages/admin/twins/definitions/twins.definitions.component.ts +++ b/src/app/pages/admin/twins/definitions/twins.definitions.component.ts @@ -2,8 +2,6 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { TwinsService } from 'app/common/services/twins/twins.service'; -import { LocalDataSource } from 'ng2-smart-table'; -import { TwinsAttributesComponent } from './attributes/twins.attributes.component'; import { Twin, Definition } from 'app/common/interfaces/mainflux.interface'; @Component({ @@ -12,37 +10,8 @@ import { Twin, Definition } from 'app/common/interfaces/mainflux.interface'; styleUrls: ['./twins.definitions.component.scss'], }) export class TwinsDefinitionsComponent implements OnInit { - settings = { - actions: { - add: false, - edit: false, - delete: false, - }, - columns: { - id: { - title: 'ID', - width: '3%', - filter: false, - }, - attributes: { - title: 'Attributes', - type: 'custom', - renderComponent: TwinsAttributesComponent, - valuePrepareFunction: (cell, row) => { - return row; - }, - filter: false, - }, - }, - pager: { - display: true, - perPage: 10, - }, - }; - twin: Twin = {}; definitions: Definition[] = []; - source: LocalDataSource = new LocalDataSource(); constructor( private route: ActivatedRoute, @@ -59,7 +28,6 @@ export class TwinsDefinitionsComponent implements OnInit { (resp: Twin) => { this.twin = resp; this.definitions = this.twin.definitions; - this.source.load(this.definitions); }, ); } diff --git a/src/app/pages/admin/twins/details/twins.details.component.html b/src/app/pages/admin/twins/details/twins.details.component.html index 7ff1d873..140adc19 100644 --- a/src/app/pages/admin/twins/details/twins.details.component.html +++ b/src/app/pages/admin/twins/details/twins.details.component.html @@ -1,216 +1,203 @@ -
-
- - - Twin Info - - -
-
- Name: -
-
- {{ twin.name }} -
-
- Owner: -
-
- {{ twin.owner }} -
-
- -
-
- ID: -
-
- {{ twin.id }} -
-
+ + + Twin Info + + +
+
+ Name: +
+
+ {{ twin.name }} +
+
+ Owner: +
+
+ {{ twin.owner }} +
+
-
-
- Created: -
-
- {{ twin.created }} -
-
- Updated: -
-
- {{ twin.updated }} -
-
+
+
+ ID: +
+
+ {{ twin.id }} +
+
-
-
- Revision: -
-
- {{ twin.revision }} -
-
-
+
+
+ Created: +
+
+ {{ twin.created }} +
+
+ Updated: +
+
+ {{ twin.updated }} +
+
-
-
-
+
+
+ Revision: +
+
+ {{ twin.revision }} +
+
+ + -
-
- - - State {{ stateTime | date: 'long' }} - - - -
-
{{attr.key}}
-
{{attr.value.value}}
-
{{attr.value.time | date: 'long'}}
-
-
-
-
-
+ + + State {{ stateTime | date: 'long' }} + + + +
+
{{attr.key}}
+
{{attr.value.value}}
+
{{attr.value.time | date: 'long'}}
+
+
+
-
-
- - - Definition {{def.created | date: 'long'}} - - - - -
- Name -
-
- Channel -
-
- Subtopic -
-
- Persisted -
-
-
-
- -
- {{ attr.name }} -
-
- {{ attr.channel }} - {{ defChans[attr.channel] }} -
-
- {{ attr.subtopic }} -
-
- {{ attr.persist_state }} -
-
-
-
-
-
-
-
+ + + Definition {{def.created | date: 'long'}} + + + + + +
+ Name +
+
+ Channel +
+
+ Subtopic +
+
+ Persisted +
+
+
+
+ +
+ {{ attr.name }} +
+
+ {{ attr.channel }} - {{ defChans[attr.channel] }} +
+
+ {{ attr.subtopic }} +
+
+ {{ attr.persist_state }} +
+
+
+
+
+
+
-
-
- - - Add definition - - + + + Add definition + + - - -
- Name -
-
- Channel -
-
- Subtopic -
-
- Persisted -
-
-
-
- -
- {{ attr.name }} -
-
- {{ attr.channel }} -
-
- {{ attr.subtopic }} -
-
- {{ attr.persist_state }} -
-
- -
-
-
+ + + +
+ Name +
+
+ Channel +
+
+ Subtopic +
+
+ Persisted +
+
+
+
+ +
+ {{ attr.name }} +
+
+ {{ attr.channel }} +
+
+ {{ attr.subtopic }} +
+
+ {{ attr.persist_state }} +
+
+ +
+
+
+
- -
-
- Name: -
-
- -
+ +
+
+ Name: +
+
+ +
-
- Channel: -
-
- - - {{channel.name}} - - -
-
+
+ Channel: +
+
+ + + {{channel.name}} + + +
+
-
-
- Subtopic: -
-
- -
-
- Persisted: -
-
- -
-
+
+
+ Subtopic: +
+
+ +
+
+ Persisted: +
+
+ +
+
- -
-
-
-
+ + + diff --git a/src/app/pages/admin/twins/details/twins.details.component.scss b/src/app/pages/admin/twins/details/twins.details.component.scss index c6e525da..19b4b54c 100644 --- a/src/app/pages/admin/twins/details/twins.details.component.scss +++ b/src/app/pages/admin/twins/details/twins.details.component.scss @@ -19,7 +19,6 @@ button { margin-left: 10px; } -textarea { - width: 100%; - height: 100%; +nb-list-item { + word-wrap: break-word; } diff --git a/src/app/pages/things/opcua/opcua.component.html b/src/app/pages/things/opcua/opcua.component.html index 6256ecef..90b2482b 100644 --- a/src/app/pages/things/opcua/opcua.component.html +++ b/src/app/pages/things/opcua/opcua.component.html @@ -25,46 +25,50 @@ - -
- Node ID -
-
- Data Type -
-
- Description -
-
- BrowseName -
-
- -
-
+ + +
+ Node ID +
+
+ Data Type +
+
+ Description +
+
+ BrowseName +
+
+ +
+
+
- - No browsed server - - -
- {{ node.NodeID }} -
-
- {{ node.DataType }} -
-
- {{ node.Description }} -
-
- {{ node.BrowseName }} -
-
- -
-
+ + + No browsed server + + +
+ {{ node.NodeID }} +
+
+ {{ node.DataType }} +
+
+ {{ node.Description }} +
+
+ {{ node.BrowseName }} +
+
+ +
+
+
diff --git a/src/app/pages/things/opcua/opcua.component.scss b/src/app/pages/things/opcua/opcua.component.scss index a3fdc27b..e67ea3fb 100644 --- a/src/app/pages/things/opcua/opcua.component.scss +++ b/src/app/pages/things/opcua/opcua.component.scss @@ -2,6 +2,6 @@ button { width: 100%; } -.col-2, .col-4 { +nb-list-item { word-wrap: break-word; } From a013c785fa2213c26b6e55ab12cd59ae720c57df Mon Sep 17 00:00:00 2001 From: Darko Draskovic Date: Tue, 18 Feb 2020 22:15:13 +0100 Subject: [PATCH 06/39] Add SenML value types to current state message composer (#59) Signed-off-by: Darko Draskovic --- .../twins/details/twins.details.component.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/app/pages/admin/twins/details/twins.details.component.ts b/src/app/pages/admin/twins/details/twins.details.component.ts index 73b46b01..407ed235 100644 --- a/src/app/pages/admin/twins/details/twins.details.component.ts +++ b/src/app/pages/admin/twins/details/twins.details.component.ts @@ -114,13 +114,27 @@ export class TwinsDetailsComponent implements OnInit, OnDestroy { if (!msgs.messages) { return; } + + const value = this.findValue(msgs.messages[0]); + if (!value) return; + this.state[name] = this.state[name] || {}; - this.state[name].value = msgs.messages[0] && msgs.messages[0].value; + this.state[name].value = value; this.state[name].time = msgs.messages[0].time * 1000; }, ); } + findValue(message: any): any { + let value: any; + if (message.value) value = message.value; + if (message.string_value) value = message.string_value; + if (message.date_value) value = message.date_value; + if (message.bool_value) value = message.bool_value; + if (message.sum) value = message.sum; + return value; + } + showStates() { const route = this.router.routerState.snapshot.url.replace('details', 'states'); this.router.navigate([route]); From dfbe85c20244ee8c0649723a7ba21e6696f18b65 Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Thu, 20 Feb 2020 14:49:37 +0100 Subject: [PATCH 07/39] UI-48 - Fix login sequence and add LoginComponent (#60) Signed-off-by: Manuel Imperiale --- src/app/app-routing.module.ts | 6 +- src/app/app.module.ts | 2 + .../auth/auth.token.interceptor.service.ts | 10 +- .../common/services/users/users.service.ts | 8 +- .../pages/dashboard/dashboard.component.ts | 77 +++++++------ src/app/pages/login/login.component.html | 106 ++++++++++++++++++ src/app/pages/login/login.component.ts | 20 ++++ 7 files changed, 182 insertions(+), 47 deletions(-) create mode 100644 src/app/pages/login/login.component.html create mode 100644 src/app/pages/login/login.component.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 47809b8d..f1568fed 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -2,10 +2,10 @@ import { ExtraOptions, RouterModule, Routes } from '@angular/router'; import { NgModule } from '@angular/core'; import { NbAuthComponent, - NbLoginComponent, NbRequestPasswordComponent, } from '@nebular/auth'; +import { LoginComponent } from 'app/pages/login/login.component'; import { LogoutComponent } from 'app/pages/logout/logout.component'; import { ResetPasswordComponent } from 'app/pages/reset/reset.password.component'; import { RegisterComponent } from 'app/pages/register/register.component'; @@ -21,11 +21,11 @@ const routes: Routes = [ children: [ { path: '', - component: NbLoginComponent, + component: LoginComponent, }, { path: 'login', - component: NbLoginComponent, + component: LoginComponent, }, { path: 'register', diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b3cca466..4c10535e 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -27,6 +27,7 @@ import { NbButtonModule, } from '@nebular/theme'; +import { LoginComponent } from './pages/login/login.component'; import { LogoutComponent } from './pages/logout/logout.component'; import { ResetPasswordComponent } from './pages/reset/reset.password.component'; import { RegisterComponent } from './pages/register/register.component'; @@ -46,6 +47,7 @@ export const MQTT_SERVICE_OPTIONS: IMqttServiceOptions = { @NgModule({ declarations: [ AppComponent, + LoginComponent, LogoutComponent, ResetPasswordComponent, RegisterComponent, diff --git a/src/app/auth/auth.token.interceptor.service.ts b/src/app/auth/auth.token.interceptor.service.ts index a1c96ece..8373763b 100644 --- a/src/app/auth/auth.token.interceptor.service.ts +++ b/src/app/auth/auth.token.interceptor.service.ts @@ -33,7 +33,8 @@ export class TokenInterceptor implements HttpInterceptor { if (token && token.getValue() && !request.url.startsWith(environment.writerChannelsUrl) && !request.url.startsWith(environment.readerChannelsUrl) && - !request.url.startsWith(environment.bootstrapUrl) + !request.url.startsWith(environment.bootstrapUrl) && + !request.url.startsWith(environment.browseUrl) ) { request = request.clone({ setHeaders: { @@ -45,12 +46,9 @@ export class TokenInterceptor implements HttpInterceptor { resp => { }, err => { - // Forbidden - 403 / Gateway Timeout - 504 + // Status 403 - Forbiden + // Status 504 - Gateway Timeout if (err instanceof HttpErrorResponse && - !request.url.startsWith(environment.writerChannelsUrl) && - !request.url.startsWith(environment.readerChannelsUrl) && - !request.url.startsWith(environment.bootstrapUrl) && - !request.url.startsWith(environment.browseUrl) && (err.status === 403 || err.status === 504)) { localStorage.removeItem('auth_app_token'); this.router.navigateByUrl('/auth/login'); diff --git a/src/app/common/services/users/users.service.ts b/src/app/common/services/users/users.service.ts index 36fc649d..ef575f65 100644 --- a/src/app/common/services/users/users.service.ts +++ b/src/app/common/services/users/users.service.ts @@ -1,6 +1,8 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; +import 'rxjs/add/observable/empty'; +import { Router } from '@angular/router'; import { environment } from 'environments/environment'; import { User } from 'app/common/interfaces/mainflux.interface'; @@ -12,6 +14,7 @@ export class UsersService { constructor( private http: HttpClient, + private router: Router, private notificationsService: NotificationsService, ) { } @@ -24,9 +27,8 @@ export class UsersService { ) .catch( err => { - this.notificationsService.error('Failed to fetch User', - `Error: ${err.status} - ${err.statusText}`); - return Observable.throw(err); + this.router.navigateByUrl('/auth/login'); + return Observable.empty(); }, ); } diff --git a/src/app/pages/dashboard/dashboard.component.ts b/src/app/pages/dashboard/dashboard.component.ts index d2a5fc8b..4d28dfd8 100644 --- a/src/app/pages/dashboard/dashboard.component.ts +++ b/src/app/pages/dashboard/dashboard.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { VersionsService } from 'app/common/services/versions/versions.service'; +import { UsersService } from 'app/common/services/users/users.service'; import { ThingsService } from 'app/common/services/things/things.service'; import { LoraService } from 'app/common/services/lora/lora.service'; import { ChannelsService } from 'app/common/services/channels/channels.service'; @@ -32,51 +33,57 @@ export class DashboardComponent implements OnInit { private thingsService: ThingsService, private loraService: LoraService, private channelsService: ChannelsService, + private usersService: UsersService, private router: Router, ) { } ngOnInit() { - this.thingsService.getThings(this.offset, this.limit).subscribe( - (resp: any) => { - this.thingsNumber = resp.total; - }, - ); + // If Token is valid + this.usersService.getUser().subscribe( + respUser => { + this.thingsService.getThings(this.offset, this.limit).subscribe( + (resp: any) => { + this.thingsNumber = resp.total; + }, + ); - this.loraService.getDevices(this.offset, this.limit).subscribe( - (resp: any) => { - this.loraDevNumber = resp.total; - }, - ); + this.loraService.getDevices(this.offset, this.limit).subscribe( + (resp: any) => { + this.loraDevNumber = resp.total; + }, + ); - this.gatewaysService.getGateways(this.offset, this.limit).subscribe( - (resp: any) => { - this.gatewaysNumber = resp.total; - this.gateways = resp.things; - }, - ); + this.gatewaysService.getGateways(this.offset, this.limit).subscribe( + (resp: any) => { + this.gatewaysNumber = resp.total; + this.gateways = resp.things; + }, + ); - this.channelsService.getChannels(this.offset, this.limit).subscribe( - (resp: any) => { - this.totalChanNumber = resp.total; - }, - ); + this.channelsService.getChannels(this.offset, this.limit).subscribe( + (resp: any) => { + this.totalChanNumber = resp.total; + }, + ); - this.versionsService.getUsersVersion().subscribe( - (resp: any) => { - this.version = resp.version; + this.versionsService.getUsersVersion().subscribe( + (resp: any) => { + this.version = resp.version; + }, + ); + + for (let i = 0; i < 61; i++) { + const vGas = 125 + 5 * Math.random(); + const vPress = 1 + 0.1 * Math.random(); + const vTemp = 25 + 1 * Math.random(); + const vHum = 45 + 20 * Math.random(); + this.messages.push({time: i, value: vTemp, publisher: 'mock', name: 'temperature'}); + this.messages.push({time: i, value: vHum, publisher: 'mock2', name: 'humidity'}); + this.messages.push({time: i, value: vPress, publisher: 'mock3', name: 'pressure'}); + this.messages.push({time: i, value: vGas, publisher: 'mock4', name: 'gas'}); + } }, ); - - for (let i = 0; i < 61; i++) { - const vGas = 125 + 5 * Math.random(); - const vPress = 1 + 0.1 * Math.random(); - const vTemp = 25 + 1 * Math.random(); - const vHum = 45 + 20 * Math.random(); - this.messages.push({time: i, value: vTemp, publisher: 'mock', name: 'temperature'}); - this.messages.push({time: i, value: vHum, publisher: 'mock2', name: 'humidity'}); - this.messages.push({time: i, value: vPress, publisher: 'mock3', name: 'pressure'}); - this.messages.push({time: i, value: vGas, publisher: 'mock4', name: 'gas'}); - } } toThingsList() { diff --git a/src/app/pages/login/login.component.html b/src/app/pages/login/login.component.html new file mode 100644 index 00000000..92d717a7 --- /dev/null +++ b/src/app/pages/login/login.component.html @@ -0,0 +1,106 @@ +

Sign In

+

Hello! Sign in with your username or email.

+ + +

Oh snap!

+
    +
  • {{ error }}
  • +
+
+ + +

Hooray!

+
    +
  • {{ message }}
  • +
+
+ +
+ +
+ + + +

+ Email is required! +

+

+ Email should be the real one! +

+
+
+ +
+ + + +

+ Password is required! +

+

+ Password should contains + from {{ getConfigValue('forms.validation.password.minLength') }} + to {{ getConfigValue('forms.validation.password.maxLength') }} + characters +

+
+
+ +
+ Remember me + Forgot Password? +
+ + +
+ + + +
+ Don't have an account? Sign Up +
diff --git a/src/app/pages/login/login.component.ts b/src/app/pages/login/login.component.ts new file mode 100644 index 00000000..39667e54 --- /dev/null +++ b/src/app/pages/login/login.component.ts @@ -0,0 +1,20 @@ +import { Component, ChangeDetectorRef, Inject } from '@angular/core'; + +import { NbAuthService, NB_AUTH_OPTIONS, NbLoginComponent } from '@nebular/auth'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'ngx-login', + templateUrl: 'login.component.html', +}) +export class LoginComponent extends NbLoginComponent { + + constructor( + @Inject(NB_AUTH_OPTIONS) protected options: {}, + protected authService: NbAuthService, + protected cd: ChangeDetectorRef, + protected router: Router, + ) { + super(authService, options, cd, router); + } +} From f4ac2f306661bf4b741c769a4ac16506cabd857d Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Thu, 20 Feb 2020 15:40:34 +0100 Subject: [PATCH 08/39] Update README.md (#61) Signed-off-by: Manuel Imperiale --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4bd49e66..616b9c8c 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,22 @@ ![details][details] ## Install - +Build Docker image: ``` -cd ui -npm install -npm start +make ui ``` -Make UI Docker: +Run docker-compose: ``` -make docker_ui +make run ``` +Run angular-cli: +``` +cd ui +npm install +npm start + [dashboard]: https://github.com/mainflux/docs/blob/master/docs/img/ui/dashboard.png [things]: https://github.com/mainflux/docs/blob/master/docs/img/ui/things.png [details]: https://github.com/mainflux/docs/blob/master/docs/img/ui/details.png From a0a2e0e8eba68b016e023235335c1943713f183a Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Thu, 20 Feb 2020 16:45:56 +0100 Subject: [PATCH 09/39] Update README.md (#62) Signed-off-by: Manuel Imperiale --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 616b9c8c..b6835c3c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,5 @@ # Mainflux IoT Admin UI based on Angular 8+ and Nebular -![dashboard][dashboard] - -![things][things] - -![details][details] - ## Install Build Docker image: ``` @@ -22,6 +16,16 @@ Run angular-cli: cd ui npm install npm start +``` + +## +![dashboard][dashboard] + +## +![things][things] + +## +![details][details] [dashboard]: https://github.com/mainflux/docs/blob/master/docs/img/ui/dashboard.png [things]: https://github.com/mainflux/docs/blob/master/docs/img/ui/things.png From adb484d696ce5443e2acc6bc9041daaf23f3f7ac Mon Sep 17 00:00:00 2001 From: Mirko Teodorovic Date: Thu, 20 Feb 2020 18:34:19 +0100 Subject: [PATCH 10/39] NOISSUE - Export config (#52) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Export service configuration Signed-off-by: Ivan Milošević * export config struct Signed-off-by: Mirko Teodorovic * change init for config Signed-off-by: Mirko Teodorovic * add default export file Signed-off-by: Mirko Teodorovic * add default export file Signed-off-by: Mirko Teodorovic * revert to master Signed-off-by: Mirko Teodorovic * small fix Signed-off-by: Mirko Teodorovic * small fix Signed-off-by: Mirko Teodorovic * fix export config logic Signed-off-by: Mirko Teodorovic Co-authored-by: Ivan Milošević --- .../common/interfaces/bootstrap.interface.ts | 36 ++++++++++++- .../services/bootstrap/bootstrap.service.ts | 54 +++++-------------- .../config/gateways.config.component.ts | 27 +++++----- src/environments/environment.prod.ts | 1 + src/environments/environment.ts | 1 + 5 files changed, 63 insertions(+), 56 deletions(-) diff --git a/src/app/common/interfaces/bootstrap.interface.ts b/src/app/common/interfaces/bootstrap.interface.ts index 8d6fc7f1..6c606eed 100644 --- a/src/app/common/interfaces/bootstrap.interface.ts +++ b/src/app/common/interfaces/bootstrap.interface.ts @@ -14,7 +14,41 @@ export interface ConfigContent { mqtt_url: string; edgex_url: string; nats_url: string; - export_config?: any; + export_config: ExportConfig; +} + +export interface ExportConfig { + file?: string; + exp: ExpConf + mqtt: MqttConfig; + routes: Array; +} +export interface ExpConf { + log_level?: string; + nats?: string; + port?: string; + cache_db?:string; + cache_pass?:string; + cache_url?:string; +} +export interface Route{ + mqtt_topic?: string; + nats_topic?:string; + subtopic?:string; + type?:string; +} +export interface MqttConfig { + host?: string; + ca_path?: string; + cert_path?: string; + priv_key_path?: string; + channel?: string; + qos?: number; + mtls?: boolean; + password?: string; + username?: string; + skip_tls_ver?: boolean; + retain?: boolean; } export interface ConfigUpdate { diff --git a/src/app/common/services/bootstrap/bootstrap.service.ts b/src/app/common/services/bootstrap/bootstrap.service.ts index a0fc609a..65438691 100644 --- a/src/app/common/services/bootstrap/bootstrap.service.ts +++ b/src/app/common/services/bootstrap/bootstrap.service.ts @@ -7,52 +7,24 @@ import 'rxjs/add/operator/map'; import { environment } from 'environments/environment'; import { Gateway } from 'app/common/interfaces/gateway.interface'; -import { Config, ConfigContent, ConfigUpdate } from 'app/common/interfaces/bootstrap.interface'; +import { Config, Route, ConfigContent, ConfigUpdate } from 'app/common/interfaces/bootstrap.interface'; import { NotificationsService } from 'app/common/services/notifications/notifications.service'; import { ThingsService } from 'app/common/services/things/things.service'; @Injectable() export class BootstrapService { content: ConfigContent = { - 'log_level': 'debug', - 'http_port': '9000', - 'mqtt_url': 'localhost:1883', - 'edgex_url': 'http://localhost:48090/api/v1/', - 'nats_url': 'localhost:4222', - 'export_config': { - 'exp': { - 'log_level': 'debug', - 'nats': 'nats://localhost:4222', - 'port': '8170', - }, - 'mqtt': { - 'ca_path': 'ca.crt', - 'cert_path': 'thing.crt', - 'channel': '', - 'host': 'tcp://localhost:1883', - 'mtls': false, - 'password': '', - 'priv_key_path': 'thing.key', - 'qos': 0, - 'retain': false, - 'skip_tls_ver': false, - 'username': '', - }, - 'routes': [ - { - 'mqtt_topic': '', - 'nats_topic': 'adc.samples', - 'subtopic': '', - 'type': 'plain', - }, - { - 'mqtt_topic': '', - 'nats_topic': 'telegraf', - 'subtopic': '', - 'type': 'plain', - }, - ], - }, + log_level: 'debug', + http_port: '9000', + mqtt_url: 'localhost:1883', + edgex_url: 'http://localhost:48090/api/v1/', + nats_url: 'localhost:4222', + export_config: { + file:`${environment.exportConfigFile}`, + exp: {port:"8170",}, + mqtt: {}, + routes: [{},{}], + } }; constructor( @@ -68,6 +40,8 @@ export class BootstrapService { this.content.export_config.routes[0].mqtt_topic = `channels/${gw.metadata.exportChannelID}/messages`; this.content.export_config.routes[1].mqtt_topic = `channels/${gw.metadata.exportChannelID}/messages`; this.content.export_config.mqtt.password = gw.key; + this.content.export_config.exp.nats = this.content.nats_url + const config: Config = { thing_id: gw.id, diff --git a/src/app/pages/things/gateways/details/config/gateways.config.component.ts b/src/app/pages/things/gateways/details/config/gateways.config.component.ts index 4d7615ad..3bbc955f 100644 --- a/src/app/pages/things/gateways/details/config/gateways.config.component.ts +++ b/src/app/pages/things/gateways/details/config/gateways.config.component.ts @@ -1,8 +1,8 @@ import { Component, Input, OnInit, OnChanges } from '@angular/core'; import { Gateway } from 'app/common/interfaces/gateway.interface'; -import { Config, ConfigContent, ConfigUpdate } from 'app/common/interfaces/bootstrap.interface'; +import { Config, ConfigContent, Route, ConfigUpdate } from 'app/common/interfaces/bootstrap.interface'; import { NotificationsService } from 'app/common/services/notifications/notifications.service'; - +import { environment } from 'environments/environment'; import { BootstrapService } from 'app/common/services/bootstrap/bootstrap.service'; @Component({ @@ -19,16 +19,21 @@ export class GatewaysConfigComponent implements OnInit, OnChanges { mqtt_url: '', edgex_url: '', nats_url: '', - export_config: '', + export_config: { + file:`${environment.exportConfigFile}`, + mqtt : {}, + exp: {}, + routes:Array(2), + } }; constructor( private bootstrapService: BootstrapService, private notificationsService: NotificationsService, - ) { - } + ) {} ngOnInit() { + } ngOnChanges() { @@ -39,16 +44,7 @@ export class GatewaysConfigComponent implements OnInit, OnChanges { this.bootstrapService.getConfig(this.gateway).subscribe( resp => { const cfg = resp; - const content = JSON.parse(cfg.content); - - this.content = { - log_level: content.log_level, - http_port: content.http_port, - mqtt_url: content.mqtt_url, - edgex_url: content.edgex_url, - nats_url: content.nats_url, - export_config: content.export_config, - }; + this.content = JSON.parse(cfg.content); }, err => { this.notificationsService.error( @@ -60,6 +56,7 @@ export class GatewaysConfigComponent implements OnInit, OnChanges { submit() { this.content.export_config.mqtt.host = `tcp://${this.content.mqtt_url}`; + this.content.export_config.exp.nats = `nats://${this.content.nats_url}`; const configUpdate: ConfigUpdate = { content: JSON.stringify(this.content), name: this.gateway.name, diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 9b127b34..96df35d3 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -28,4 +28,5 @@ export const environment = { loraServer: 'http://lora.mainflux.io/#/', mqttWsUrl: 'ws://localhost:80/mqtt', + exportConfigFile: 'export.toml', }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index f5998fb9..182bc7fe 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -33,4 +33,5 @@ export const environment = { loraServer: 'http://lora.mainflux.io/#/', mqttWsUrl: 'ws://localhost:80/mqtt', + exportConfigFile: 'export.toml', }; From 6cd96a3c02d16d464a158cbb5563552aa62636ce Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Thu, 27 Feb 2020 01:03:51 +0100 Subject: [PATCH 11/39] NOISSUE - Add namespace and identifier to opc-ua browser (#63) * NOISSUE - Add namespace and identifier to opc-ua browser Signed-off-by: Manuel Imperiale * Mv default nodeID to placeholder Signed-off-by: Manuel Imperiale * Fix reviews Signed-off-by: Manuel Imperiale --- src/app/pages/things/lora/lora.component.ts | 2 +- src/app/pages/things/opcua/opcua.component.html | 8 +++++++- src/app/pages/things/opcua/opcua.component.scss | 5 +++++ src/app/pages/things/opcua/opcua.component.ts | 4 ++-- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/app/pages/things/lora/lora.component.ts b/src/app/pages/things/lora/lora.component.ts index cb6d7965..c0e7a46f 100644 --- a/src/app/pages/things/lora/lora.component.ts +++ b/src/app/pages/things/lora/lora.component.ts @@ -36,7 +36,7 @@ export class LoraComponent implements OnInit { }, columns: { details: { - title: 'Details', + title: '', type: 'custom', renderComponent: DetailsComponent, valuePrepareFunction: (cell, row) => { diff --git a/src/app/pages/things/opcua/opcua.component.html b/src/app/pages/things/opcua/opcua.component.html index 90b2482b..f99890d4 100644 --- a/src/app/pages/things/opcua/opcua.component.html +++ b/src/app/pages/things/opcua/opcua.component.html @@ -4,9 +4,15 @@
OPC-UA Server URI:
-
+
+
+ +
+
+ +
+
+
+ Definition {{def.created | date: 'long'}} +
+
+ delta (ms): {{this.defDelta / 1e6}} +
+
+ +
+
@@ -116,10 +125,21 @@ - Add definition - +
+
+ Add definition +
+ +
+ delta (ms): +
+ +
+ +
+
diff --git a/src/app/pages/admin/twins/details/twins.details.component.ts b/src/app/pages/admin/twins/details/twins.details.component.ts index 407ed235..0453cb8d 100644 --- a/src/app/pages/admin/twins/details/twins.details.component.ts +++ b/src/app/pages/admin/twins/details/twins.details.component.ts @@ -6,6 +6,7 @@ import { TwinsService } from 'app/common/services/twins/twins.service'; import { NotificationsService } from 'app/common/services/notifications/notifications.service'; import { MessagesService } from 'app/common/services/messages/messages.service'; import { Thing, Channel, Attribute, Definition, Twin } from 'app/common/interfaces/mainflux.interface'; +import { isNumber } from 'util'; const stateInterval: number = 5 * 1000; @@ -22,6 +23,7 @@ export class TwinsDetailsComponent implements OnInit, OnDestroy { def: Definition; defChans: {}; defAttrs: Attribute[] = []; + defDelta: number = 1e6; twinName: string; channels: Channel[] = []; @@ -64,6 +66,8 @@ export class TwinsDetailsComponent implements OnInit, OnDestroy { this.twin = resp; this.def = this.twin.definitions[this.twin.definitions.length - 1]; + + this.defDelta = this.def.delta; this.defAttrs = this.def.attributes; this.defAttrs.forEach(attr => { this.channelsService.getChannel(attr.channel).subscribe( @@ -184,6 +188,7 @@ export class TwinsDetailsComponent implements OnInit, OnDestroy { id: this.twin.id, definition: { attributes: this.editAttrs, + delta: this.defDelta, }, }; this.twinsService.editTwin(twin).subscribe( @@ -193,6 +198,11 @@ export class TwinsDetailsComponent implements OnInit, OnDestroy { ); } + delta($event) { + const val = +$event.srcElement.value; + this.defDelta = isNumber(val) ? val * 1e6 : this.defDelta; + } + ngOnDestroy() { window.clearInterval(this.stateIntervalID); } diff --git a/src/app/pages/admin/twins/states/twins.states.component.ts b/src/app/pages/admin/twins/states/twins.states.component.ts index 5383ce78..c8e402f1 100644 --- a/src/app/pages/admin/twins/states/twins.states.component.ts +++ b/src/app/pages/admin/twins/states/twins.states.component.ts @@ -145,4 +145,5 @@ export class TwinsStatesComponent implements OnInit, OnDestroy { ngOnDestroy() { window.clearInterval(this.intervalID); } + } From 5920f85119d45465419452093fcdd9cb8ffe7f48 Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Mon, 23 Mar 2020 10:09:09 +0100 Subject: [PATCH 18/39] UI-32 - Verify if MAC exist for Gateways creation and edit (#71) Signed-off-by: Manuel Imperiale --- src/app/common/interfaces/gateway.interface.ts | 1 + .../pages/things/gateways/gateways.component.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/app/common/interfaces/gateway.interface.ts b/src/app/common/interfaces/gateway.interface.ts index a60036e7..13a0391c 100644 --- a/src/app/common/interfaces/gateway.interface.ts +++ b/src/app/common/interfaces/gateway.interface.ts @@ -14,4 +14,5 @@ export interface Gateway { key?: string; name?: string; metadata?: GatewayMetadata; + mac?: string; } diff --git a/src/app/pages/things/gateways/gateways.component.ts b/src/app/pages/things/gateways/gateways.component.ts index 2a31612a..7a4f8c80 100644 --- a/src/app/pages/things/gateways/gateways.component.ts +++ b/src/app/pages/things/gateways/gateways.component.ts @@ -166,6 +166,12 @@ export class GatewaysComponent implements OnInit { validate(row: any): boolean { + const gws = this.gateways.map(g => g.mac); + if (gws.includes(row.mac)) { + this.notificationsService.warn( + 'MAC already exist.', ''); + return false; + } if (row.name === '' || row.name.length > 32) { this.notificationsService.warn( 'Name is required and must be maximum 32 characters long.', ''); @@ -204,6 +210,15 @@ export class GatewaysComponent implements OnInit { } onEditConfirm(event): void { + // Check if the row have been modified + const macs = this.gateways.map(g => g.mac); + const names = this.gateways.map(g => g.name); + if (macs.includes(event.newData.mac) && names.includes(event.newData.name)) { + // close edditable row + event.confirm.resolve(); + return; + } + // Formulaire Validator if (!this.validate(event.newData)) { return; From 444cd80e2eacd16cd3eb3ded7df20107c84664e9 Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Mon, 23 Mar 2020 10:51:23 +0100 Subject: [PATCH 19/39] UI-49 - Fix responsive buttons (#70) Signed-off-by: Manuel Imperiale --- .../twins.definitions.component.html | 24 ++--- .../details/twins.details.component.html | 88 +++++++++---------- .../payload/twins.payload.component.html | 2 +- .../twins/states/twins.states.component.html | 4 +- .../twins/states/twins.states.component.scss | 2 +- .../pages/admin/twins/twins.component.html | 8 +- .../things/channels/channels.component.html | 8 +- .../details/channels.details.component.html | 8 +- .../details/channels.details.component.scss | 2 +- .../details/devices.details.component.html | 10 +-- .../details/devices.details.component.scss | 2 +- .../things/devices/devices.component.html | 8 +- .../config/gateways.config.component.html | 10 +-- .../details/info/gateways.info.component.html | 16 ++-- .../details/info/gateways.info.component.scss | 2 +- .../things/gateways/gateways.component.html | 8 +- .../lora/details/lora.details.component.html | 6 +- .../lora/details/lora.details.component.scss | 2 +- src/app/pages/things/lora/lora.component.html | 8 +- .../details/opcua.details.component.html | 6 +- .../details/opcua.details.component.scss | 2 +- .../pages/things/opcua/opcua.component.html | 43 +++++---- 22 files changed, 133 insertions(+), 136 deletions(-) diff --git a/src/app/pages/admin/twins/definitions/twins.definitions.component.html b/src/app/pages/admin/twins/definitions/twins.definitions.component.html index eaaf000e..2679361d 100644 --- a/src/app/pages/admin/twins/definitions/twins.definitions.component.html +++ b/src/app/pages/admin/twins/definitions/twins.definitions.component.html @@ -6,42 +6,42 @@ -
+
Created
-
+
-
+
Name
-
+
Channels
-
+
Subtopic
-
+
Persisted
-
+
{{def.created | date: 'short'}}
-
+
-
+
{{ attr.name }}
-
+
{{ attr.channel }}
-
+
{{ attr.subtopic }}
-
+
{{ attr.persist_state }}
diff --git a/src/app/pages/admin/twins/details/twins.details.component.html b/src/app/pages/admin/twins/details/twins.details.component.html index dcc15ed6..c3082a37 100644 --- a/src/app/pages/admin/twins/details/twins.details.component.html +++ b/src/app/pages/admin/twins/details/twins.details.component.html @@ -4,49 +4,49 @@
-
+
Name:
-
+
{{ twin.name }}
-
+
Owner:
-
+
{{ twin.owner }}
-
+
ID:
-
+
{{ twin.id }}
-
+
Created:
-
+
{{ twin.created }}
-
+
Updated:
-
+
{{ twin.updated }}
-
+
Revision:
-
+
{{ twin.revision }}
@@ -62,9 +62,9 @@
-
{{attr.key}}
-
{{attr.value.value}}
-
{{attr.value.time | date: 'long'}}
+
{{attr.key}}
+
{{attr.value.value}}
+
{{attr.value.time | date: 'long'}}
@@ -88,42 +88,42 @@ -
+
Name
-
+
Channel
-
+
Subtopic
-
+
Persisted
-
+
-
+
{{ attr.name }}
-
+
{{ attr.channel }} - {{ defChans[attr.channel] }}
-
+
{{ attr.subtopic }}
-
+
{{ attr.persist_state }}
-
+
- +
@@ -145,35 +145,35 @@ -
+
Name
-
+
Channel
-
+
Subtopic
-
+
Persisted
-
+
-
+
{{ attr.name }}
-
+
{{ attr.channel }}
-
+
{{ attr.subtopic }}
-
+
{{ attr.persist_state }}
-
+
@@ -182,17 +182,17 @@
-
+
Name:
-
+
-
+
Channel:
-
+
{{channel.name}} @@ -202,16 +202,16 @@
-
+
Subtopic:
-
+
-
+
Persisted:
-
+
diff --git a/src/app/pages/admin/twins/states/payload/twins.payload.component.html b/src/app/pages/admin/twins/states/payload/twins.payload.component.html index d105310c..980095cb 100644 --- a/src/app/pages/admin/twins/states/payload/twins.payload.component.html +++ b/src/app/pages/admin/twins/states/payload/twins.payload.component.html @@ -1,6 +1,6 @@
-
{{v.key}}
+
{{v.key}}
{{v.value}}
diff --git a/src/app/pages/admin/twins/states/twins.states.component.html b/src/app/pages/admin/twins/states/twins.states.component.html index f49cb03c..f69c748f 100644 --- a/src/app/pages/admin/twins/states/twins.states.component.html +++ b/src/app/pages/admin/twins/states/twins.states.component.html @@ -3,8 +3,8 @@
-
{{ total }} states of {{ twin.name }}
-
+
{{ total }} states of {{ twin.name }}
+
from: to:
diff --git a/src/app/pages/admin/twins/states/twins.states.component.scss b/src/app/pages/admin/twins/states/twins.states.component.scss index feecb8c2..e988af47 100644 --- a/src/app/pages/admin/twins/states/twins.states.component.scss +++ b/src/app/pages/admin/twins/states/twins.states.component.scss @@ -1,3 +1,3 @@ -.col-10 { +.col-md-10 { text-align: right; } diff --git a/src/app/pages/admin/twins/twins.component.html b/src/app/pages/admin/twins/twins.component.html index 93744c4e..5fda3543 100644 --- a/src/app/pages/admin/twins/twins.component.html +++ b/src/app/pages/admin/twins/twins.component.html @@ -1,21 +1,21 @@
-
+
{{ twinsNumber }}   Twins
-
+
-
+
-
+
-
+
-
+
{{con.name}}
-
+
diff --git a/src/app/pages/things/channels/details/channels.details.component.scss b/src/app/pages/things/channels/details/channels.details.component.scss index 710e4662..da771879 100644 --- a/src/app/pages/things/channels/details/channels.details.component.scss +++ b/src/app/pages/things/channels/details/channels.details.component.scss @@ -2,7 +2,7 @@ nb-icon { vertical-align: middle; } -.col-2 { +.col-md-2 { text-align: right; padding: 0; font-weight: bold; diff --git a/src/app/pages/things/devices/details/devices.details.component.html b/src/app/pages/things/devices/details/devices.details.component.html index 02b08402..a52dd291 100644 --- a/src/app/pages/things/devices/details/devices.details.component.html +++ b/src/app/pages/things/devices/details/devices.details.component.html @@ -6,9 +6,9 @@
-
Name:
{{ thing.name }}
-
ID:
{{ thing.id }}
-
Key:
{{ thing.key }}
+
Name:
{{ thing.name }}
+
ID:
{{ thing.id }}
+
Key:
{{ thing.key }}
@@ -62,11 +62,11 @@
-
+
{{con.name}}
-
+
diff --git a/src/app/pages/things/devices/details/devices.details.component.scss b/src/app/pages/things/devices/details/devices.details.component.scss index 710e4662..da771879 100644 --- a/src/app/pages/things/devices/details/devices.details.component.scss +++ b/src/app/pages/things/devices/details/devices.details.component.scss @@ -2,7 +2,7 @@ nb-icon { vertical-align: middle; } -.col-2 { +.col-md-2 { text-align: right; padding: 0; font-weight: bold; diff --git a/src/app/pages/things/devices/devices.component.html b/src/app/pages/things/devices/devices.component.html index f4d6ecd8..af7acdb7 100644 --- a/src/app/pages/things/devices/devices.component.html +++ b/src/app/pages/things/devices/devices.component.html @@ -1,21 +1,21 @@
-
+
{{ thingsNum }}   Devices
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/src/app/pages/things/gateways/details/xterm/gateways.xterm.component.ts b/src/app/pages/things/gateways/details/xterm/gateways.xterm.component.ts index de6fa759..78fa168e 100644 --- a/src/app/pages/things/gateways/details/xterm/gateways.xterm.component.ts +++ b/src/app/pages/things/gateways/details/xterm/gateways.xterm.component.ts @@ -43,7 +43,7 @@ export class GatewaysXtermComponent implements AfterViewInit, OnChanges, OnDestr this.terminal === undefined || this.connected === true) return; - if ( this.gateway.id && this.gateway.metadata.ctrlChannelID) { + if ( this.gateway.id && this.gateway.metadata.ctrl_channel_id) { this.mqttService.connect({ username: this.gateway.id, password: this.gateway.key }); this.stateSub = this.mqttService.state.subscribe(this.connectionHandler.bind(this)); } @@ -52,14 +52,14 @@ export class GatewaysXtermComponent implements AfterViewInit, OnChanges, OnDestr connectionHandler(state: MqttConnectionState) { if (state === MqttConnectionState.CONNECTED) { this.connected = true; - this.publish(this.gateway.metadata.ctrlChannelID, this.uuid, Term, btoa('open')); + this.publish(this.gateway.metadata.ctrl_channel_id, this.uuid, Term, btoa('open')); this.notificationsService.success('Connected to MQTT broker', ''); this.connectAgent(); } } connectAgent() { - const topic = `${this.createTopic(this.gateway.metadata.ctrlChannelID)}/res/term/${this.uuid}`; + const topic = `${this.createTopic(this.gateway.metadata.ctrl_channel_id)}/res/term/${this.uuid}`; const term = this.terminal; this.mqttService.publish(topic, 'payload'); this.chanSub = this.mqttService.observe(topic).subscribe( @@ -99,14 +99,14 @@ export class GatewaysXtermComponent implements AfterViewInit, OnChanges, OnDestr this.terminal.writeln('Welcome to Mainflux IoT Agent'); this.terminal.onData( data => { const vs = `c,${data}`; - this.publish(this.gateway.metadata.ctrlChannelID, this.uuid, 'term', btoa(vs)); + this.publish(this.gateway.metadata.ctrl_channel_id, this.uuid, 'term', btoa(vs)); }); } ngOnDestroy() { const vs = 'close'; this.connected = false; - this.publish(this.gateway.metadata.ctrlChannelID, this.uuid, 'term', btoa(vs)); + this.publish(this.gateway.metadata.ctrl_channel_id, this.uuid, 'term', btoa(vs)); this.stateSub && this.stateSub.unsubscribe(); this.chanSub && this.chanSub.unsubscribe(); this.mqttService.disconnect(); diff --git a/src/app/pages/things/gateways/gateways.component.ts b/src/app/pages/things/gateways/gateways.component.ts index df1ee05a..31a59c34 100644 --- a/src/app/pages/things/gateways/gateways.component.ts +++ b/src/app/pages/things/gateways/gateways.component.ts @@ -129,8 +129,8 @@ export class GatewaysComponent implements OnInit { resp.things.forEach(gw => { gw.mac = gw.metadata.mac; - const dataChannelID: string = gw.metadata ? gw.metadata.dataChannelID : ''; - this.messagesService.getMessages(dataChannelID, gw.key, gw.id).subscribe( + const data_channel_id: string = gw.metadata ? gw.metadata.data_channel_id : ''; + this.messagesService.getMessages(data_channel_id, gw.key, gw.id).subscribe( (msgResp: any) => { if (msgResp.messages) { gw.seen = msgResp.messages[0].time; diff --git a/src/app/shared/map/leaflet/map.leaflet.component.ts b/src/app/shared/map/leaflet/map.leaflet.component.ts index 4968da8c..d20e86e0 100644 --- a/src/app/shared/map/leaflet/map.leaflet.component.ts +++ b/src/app/shared/map/leaflet/map.leaflet.component.ts @@ -70,7 +70,7 @@ export class MapComponent implements OnChanges { refreshCoordinate(gateway: Gateway) { this.mqttService.connect({ username: gateway.id, password: gateway.key }); - const topic = 'channels/' + gateway.metadata.ctrlChannelID + '/messages/req'; + const topic = 'channels/' + gateway.metadata.ctrl_channel_id + '/messages/req'; this.mqttService.observe(topic).subscribe((message: IMqttMessage) => { }); this.mqttService.observe(topic).subscribe((message: IMqttMessage) => { @@ -83,7 +83,7 @@ export class MapComponent implements OnChanges { ngOnChanges() { if (this.gateways) { this.gateways.forEach((gw) => { - const channelID: string = gw.metadata ? gw.metadata.dataChannelID : ''; + const channelID: string = gw.metadata ? gw.metadata.data_channel_id : ''; if (gw.key !== '' && channelID !== '') { this.msgService.getMessages(channelID, gw.key, gw.id).subscribe( From f14525105ed588f7c6f835ec6d16fb22dc34606d Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Mon, 4 May 2020 22:49:06 +0200 Subject: [PATCH 32/39] NOISSUE - Use log level error for VermeMQ docker (#91) * NOISSUE - Use log level error for VermeMQ docker Signed-off-by: Manuel Imperiale * Add vermemq ENVARS Signed-off-by: Manuel Imperiale --- .env | 4 ++++ docker/docker-compose.yml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.env b/.env index 08fcfab8..8f2b38f5 100644 --- a/.env +++ b/.env @@ -92,6 +92,10 @@ MF_MQTT_BROKER_WS_PORT=8080 MF_MQTT_ADAPTER_ES_DB=0 MF_MQTT_ADAPTER_ES_PASS= +### VERMEMQ +MF_DOCKER_VERNEMQ_ALLOW_ANONYMOUS=on +MF_DOCKER_VERNEMQ_LOG__CONSOLE__LEVEL=error + ## Addons Services ### Bootstrap MF_BOOTSTRAP_LOG_LEVEL=debug diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index c7c2f046..f5290577 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -229,8 +229,8 @@ services: container_name: mainflux-vernemq restart: on-failure environment: - DOCKER_VERNEMQ_ALLOW_ANONYMOUS: "on" - DOCKER_VERNEMQ_LOG__CONSOLE__LEVEL: debug + DOCKER_VERNEMQ_ALLOW_ANONYMOUS: ${MF_DOCKER_VERNEMQ_ALLOW_ANONYMOUS} + DOCKER_VERNEMQ_LOG__CONSOLE__LEVEL: ${MF_DOCKER_VERNEMQ_LOG__CONSOLE__LEVEL} networks: - mainflux-base-net volumes: From 8df1153838de60b26fba34339d118b844644ee30 Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Wed, 6 May 2020 10:51:28 +0200 Subject: [PATCH 33/39] UI-73 - Check if ID is defined before opening the table details (#90) * UI-73 - Check if ID is defined before to open table details Signed-off-by: Manuel Imperiale * Simplify id check Signed-off-by: Manuel Imperiale --- src/app/shared/details/details.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/shared/details/details.component.ts b/src/app/shared/details/details.component.ts index e22349a8..16ff87a8 100644 --- a/src/app/shared/details/details.component.ts +++ b/src/app/shared/details/details.component.ts @@ -15,6 +15,8 @@ export class DetailsComponent { ) { } onOpenDetailsPage() { - this.router.navigate([`${this.router.routerState.snapshot.url}/details/${this.value.id}`]); + if (this.value.id) { + this.router.navigate([`${this.router.routerState.snapshot.url}/details/${this.value.id}`]); + } } } From edf531bbee8c07cc427b02c26a467b52e9fc5a81 Mon Sep 17 00:00:00 2001 From: Mirko Teodorovic Date: Wed, 6 May 2020 15:00:32 +0200 Subject: [PATCH 34/39] NOISSUE - Renaming mac, gw password (#92) * change path for export config Signed-off-by: Mirko Teodorovic * rename mac->externa_id, gw_password->external_key Signed-off-by: Mirko Teodorovic * rename mac->externa_id, gw_password->external_key Signed-off-by: Mirko Teodorovic * rename mac->externa_id, gw_password->external_key Signed-off-by: Mirko Teodorovic * var rename Signed-off-by: Mirko Teodorovic * var rename Signed-off-by: Mirko Teodorovic --- .../common/interfaces/gateway.interface.ts | 5 ++-- .../services/bootstrap/bootstrap.service.ts | 8 +++--- .../services/gateways/gateways.service.ts | 10 +++---- src/app/common/store/gateways.store.ts | 8 +++--- .../config/gateways.config.component.ts | 2 +- .../details/info/gateways.info.component.html | 4 +-- .../things/gateways/gateways.component.ts | 27 +++++++++---------- .../map/leaflet/map.leaflet.component.ts | 2 +- src/environments/environment.prod.ts | 2 +- src/environments/environment.ts | 2 +- 10 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/app/common/interfaces/gateway.interface.ts b/src/app/common/interfaces/gateway.interface.ts index 856f8587..4a0ea126 100644 --- a/src/app/common/interfaces/gateway.interface.ts +++ b/src/app/common/interfaces/gateway.interface.ts @@ -3,8 +3,8 @@ export interface GatewayMetadata { data_channel_id?: string; export_channel_id?: string; export_thing_id?: string; - gw_password?: string; - mac?: string; + external_key?: string; + external_id?: string; cfg_id?: string; type?: string; } @@ -14,5 +14,4 @@ export interface Gateway { key?: string; name?: string; metadata?: GatewayMetadata; - mac?: string; } diff --git a/src/app/common/services/bootstrap/bootstrap.service.ts b/src/app/common/services/bootstrap/bootstrap.service.ts index dccf1ae8..83fa67a6 100644 --- a/src/app/common/services/bootstrap/bootstrap.service.ts +++ b/src/app/common/services/bootstrap/bootstrap.service.ts @@ -45,8 +45,8 @@ export class BootstrapService { thing_id: gw.id, thing_key: gw.key, channels: [gw.metadata.ctrl_channel_id, gw.metadata.data_channel_id], - external_id: gw.metadata.mac, - external_key: gw.metadata.gw_password, + external_id: gw.metadata.external_id, + external_key: gw.metadata.external_key, content: JSON.stringify(this.content), state: 0, }; @@ -77,10 +77,10 @@ export class BootstrapService { getConfig(gateway: Gateway) { const headers = new HttpHeaders({ - 'Authorization': gateway.metadata.gw_password, + 'Authorization': gateway.metadata.external_key, }); - return this.http.get(`${environment.bootstrapUrl}/${gateway.metadata.mac}`, { headers: headers }); + return this.http.get(`${environment.bootstrapUrl}/${gateway.metadata.external_id}`, { headers: headers }); } updateConfig(configUpdate: ConfigUpdate, gateway: Gateway) { diff --git a/src/app/common/services/gateways/gateways.service.ts b/src/app/common/services/gateways/gateways.service.ts index b1cee473..8978cfbf 100644 --- a/src/app/common/services/gateways/gateways.service.ts +++ b/src/app/common/services/gateways/gateways.service.ts @@ -43,12 +43,12 @@ export class GatewaysService { return this.channelsService.getChannels(offset, limit, this.typeDataChan); } - addGateway(name: string, mac: string) { + addGateway(name: string, externalID: string) { const gateway: Gateway = { name: name, metadata: { type: this.typeGateway, - mac: mac, + external_id: externalID, }, }; @@ -97,7 +97,7 @@ export class GatewaysService { gateway.metadata.ctrl_channel_id = ctrlChanID; gateway.metadata.data_channel_id = dataChanID; gateway.metadata.export_channel_id = exportChanID; - gateway.metadata.gw_password = uuid(); + gateway.metadata.external_key = uuid(); gateway.id = gwID; this.thingsService.editThing(gateway).subscribe( @@ -147,8 +147,8 @@ export class GatewaysService { ); } - editGateway(name: string, mac: string, gateway: Gateway) { - gateway.metadata.mac = mac; + editGateway(name: string, externalID: string, gateway: Gateway) { + gateway.metadata.external_id = externalID; return this.thingsService.editThing(gateway).map( resp => { diff --git a/src/app/common/store/gateways.store.ts b/src/app/common/store/gateways.store.ts index b3594048..538a4131 100644 --- a/src/app/common/store/gateways.store.ts +++ b/src/app/common/store/gateways.store.ts @@ -30,9 +30,9 @@ export class GatewaysStore { } @action - addGateway(name: string, mac: string) { + addGateway(name: string, externalID: string) { this.uiState.loading = true; - this.gatewaysService.addGateway(name, mac) + this.gatewaysService.addGateway(name, externalID) .subscribe(() => { this.uiState.loading = false; this.getGateways(this.offset, this.limit); @@ -43,9 +43,9 @@ export class GatewaysStore { } @action - editGateway(name: string, mac: string, gw: Gateway) { + editGateway(name: string, externalID: string, gw: Gateway) { this.uiState.loading = true; - this.gatewaysService.editGateway(name, mac, gw) + this.gatewaysService.editGateway(name, externalID, gw) .subscribe(() => { this.uiState.loading = false; this.getGateways(this.offset, this.limit); diff --git a/src/app/pages/things/gateways/details/config/gateways.config.component.ts b/src/app/pages/things/gateways/details/config/gateways.config.component.ts index 55e68937..21e9a6b2 100644 --- a/src/app/pages/things/gateways/details/config/gateways.config.component.ts +++ b/src/app/pages/things/gateways/details/config/gateways.config.component.ts @@ -36,7 +36,7 @@ export class GatewaysConfigComponent implements OnInit, OnChanges { } ngOnChanges() { - if (!this.gateway.metadata.gw_password) { + if (!this.gateway.metadata.external_key) { return; } diff --git a/src/app/pages/things/gateways/details/info/gateways.info.component.html b/src/app/pages/things/gateways/details/info/gateways.info.component.html index 6ebad5e0..28742fb7 100644 --- a/src/app/pages/things/gateways/details/info/gateways.info.component.html +++ b/src/app/pages/things/gateways/details/info/gateways.info.component.html @@ -11,8 +11,8 @@
Name:
{{ gateway.name }}
ID:
{{ gateway.id }}
Key:
{{ gateway.key }}
-
External ID:
{{ gateway.metadata.mac }}
-
External key:
{{ gateway.metadata.gw_password }}
+
External ID:
{{ gateway.metadata.external_id }}
+
External key:
{{ gateway.metadata.external_key }}
Ctrl Chan ID:
{{ gateway.metadata.ctrl_channel_id }}
Data Chan ID:
{{ gateway.metadata.data_channel_id }}
BS Config ID:
{{ gateway.metadata.cfg_id }}
diff --git a/src/app/pages/things/gateways/gateways.component.ts b/src/app/pages/things/gateways/gateways.component.ts index 31a59c34..0e796819 100644 --- a/src/app/pages/things/gateways/gateways.component.ts +++ b/src/app/pages/things/gateways/gateways.component.ts @@ -54,9 +54,8 @@ export class GatewaysComponent implements OnInit { type: 'string', filter: false, }, - mac: { - title: 'MAC', - placeholder: 'Search MAC', + external_id: { + title: 'External ID', type: 'text', editable: true, addable: true, @@ -127,7 +126,7 @@ export class GatewaysComponent implements OnInit { this.total = resp.total; resp.things.forEach(gw => { - gw.mac = gw.metadata.mac; + gw.external_id = gw.metadata.external_id; const data_channel_id: string = gw.metadata ? gw.metadata.data_channel_id : ''; this.messagesService.getMessages(data_channel_id, gw.key, gw.id).subscribe( @@ -154,10 +153,10 @@ export class GatewaysComponent implements OnInit { validate(row: any): boolean { - const gws = this.gateways.map(g => g.mac); - if (gws.includes(row.mac)) { + const gws = this.gateways.map(g => g.metadata.external_id); + if (gws.includes(row.external_id)) { this.notificationsService.warn( - 'MAC already exist.', ''); + 'External ID already exist.', ''); return false; } if (row.name === '' || row.name.length > 32) { @@ -166,9 +165,9 @@ export class GatewaysComponent implements OnInit { return false; } - if (row.mac === '' || row.mac.length < 8) { + if (row.external_id === '' || row.external_id.length < 8) { this.notificationsService.warn( - 'MAC is required and must be at least 8 characters long.', ''); + 'External ID is required and must be at least 8 characters long.', ''); return false; } @@ -185,7 +184,7 @@ export class GatewaysComponent implements OnInit { // close edditable row event.confirm.resolve(); - this.gatewaysService.addGateway(event.newData.name, event.newData.mac).subscribe( + this.gatewaysService.addGateway(event.newData.name, event.newData.external_id).subscribe( resp => { setTimeout( () => { @@ -198,9 +197,9 @@ export class GatewaysComponent implements OnInit { onEditConfirm(event): void { // Check if the row have been modified - const macs = this.gateways.map(g => g.mac); + const extIDs = this.gateways.map(g => g.metadata.external_id); const names = this.gateways.map(g => g.name); - if (macs.includes(event.newData.mac) && names.includes(event.newData.name)) { + if (extIDs.includes(event.newData.external_id) && names.includes(event.newData.name)) { // close edditable row event.confirm.resolve(); return; @@ -215,10 +214,10 @@ export class GatewaysComponent implements OnInit { event.confirm.resolve(); const name = event.newData.name; - const mac = event.newData.mac; + const external_id = event.newData.external_id; const gw = event.newData; - this.gatewaysService.editGateway(name, mac, gw).subscribe( + this.gatewaysService.editGateway(name, external_id, gw).subscribe( resp => { this.getGateways(); }, diff --git a/src/app/shared/map/leaflet/map.leaflet.component.ts b/src/app/shared/map/leaflet/map.leaflet.component.ts index d20e86e0..d33273f6 100644 --- a/src/app/shared/map/leaflet/map.leaflet.component.ts +++ b/src/app/shared/map/leaflet/map.leaflet.component.ts @@ -55,7 +55,7 @@ export class MapComponent implements OnChanges { const msg = `
${ gw.name }
ID: ${ gw.id }
-
MAC: ${ gw.metadata.mac }
+
External ID: ${ gw.metadata.external_id }
`; const marker: L.Marker = L.marker( [lon, lat], { diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 96df35d3..f49926ce 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -28,5 +28,5 @@ export const environment = { loraServer: 'http://lora.mainflux.io/#/', mqttWsUrl: 'ws://localhost:80/mqtt', - exportConfigFile: 'export.toml', + exportConfigFile: '/configs/export/config.toml', }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 8bcd7641..b67a3f80 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -33,5 +33,5 @@ export const environment = { loraServer: 'http://lora.mainflux.io/#/', mqttWsUrl: 'ws://localhost/mqtt', - exportConfigFile: 'export.toml', + exportConfigFile: '/configs/export/config.toml', }; From fd0fb2a8068bd94ec1f3b7f28adf840e9987d79d Mon Sep 17 00:00:00 2001 From: Mirko Teodorovic Date: Wed, 10 Jun 2020 10:40:13 +0200 Subject: [PATCH 35/39] update vars and docker-compose (#97) Signed-off-by: Mirko Teodorovic --- .env | 16 +++++----- docker/docker-compose.yml | 15 +++++---- docker/nginx/entrypoint.sh | 4 +-- docker/nginx/nginx-key.conf | 4 +-- docker/nginx/nginx-x509.conf | 4 +-- .../nginx/snippets/mqtt-upstream-cluster.conf | 8 ++--- .../nginx/snippets/mqtt-upstream-single.conf | 4 +-- docker/ssl/authorization.js | 32 ++++++------------- 8 files changed, 38 insertions(+), 49 deletions(-) diff --git a/.env b/.env index 8f2b38f5..6aa6a93f 100644 --- a/.env +++ b/.env @@ -32,7 +32,7 @@ MF_AUTHN_LOG_LEVEL=debug MF_AUTHN_HTTP_PORT=8189 MF_AUTHN_GRPC_PORT=8181 MF_AUTHN_GRPC_URL=authn:8181 -MF_AUTHN_GRPC_TIMEOUT=1 +MF_AUTHN_GRPC_TIMEOUT=1s MF_AUTHN_DB_PORT=5432 MF_AUTHN_DB_USER=mainflux MF_AUTHN_DB_PASS=mainflux @@ -66,7 +66,7 @@ MF_THINGS_HTTP_PORT=8182 MF_THINGS_AUTH_HTTP_PORT=8989 MF_THINGS_AUTH_GRPC_PORT=8183 MF_THINGS_AUTH_GRPC_URL=things:8183 -MF_THINGS_AUTH_GRPC_TIMEOUT=1 +MF_THINGS_AUTH_GRPC_TIMEOUT=1s MF_THINGS_DB_PORT=5432 MF_THINGS_DB_USER=mainflux MF_THINGS_DB_PASS=mainflux @@ -76,16 +76,12 @@ MF_THINGS_ES_URL=localhost:6379 MF_THINGS_ES_PASS= MF_THINGS_ES_DB=0 -### WS -MF_WS_ADAPTER_LOG_LEVEL=debug -MF_WS_ADAPTER_PORT=8186 - ### HTTP MF_HTTP_ADAPTER_PORT=8185 ### MQTT MF_MQTT_ADAPTER_LOG_LEVEL=debug -MF_MQTT_ADAPTER_PORT=1883 +MF_MQTT_ADAPTER_MQTT_PORT=1883 MF_MQTT_BROKER_PORT=1883 MF_MQTT_ADAPTER_WS_PORT=8080 MF_MQTT_BROKER_WS_PORT=8080 @@ -136,6 +132,7 @@ MF_INFLUX_WRITER_DB_USER=mainflux MF_INFLUX_WRITER_DB_PASS=mainflux MF_INFLUX_WRITER_DB=mainflux MF_INFLUX_WRITER_GRAFANA_PORT=3001 +MF_INFLUX_WRITER_CONTENT_TYPE=application/senml+json ### InfluxDB Reader MF_INFLUX_READER_LOG_LEVEL=debug @@ -162,4 +159,7 @@ MF_TWINS_SINGLE_USER_TOKEN="" MF_TWINS_CLIENT_TLS="" MF_TWINS_CA_CERTS="" MF_TWINS_MQTT_URL=tcp://mqtt-adapter:1883 -MF_TWINS_CHANNEL_ID= +MF_TWINS_CHANNEL_ID="" +MF_TWINS_CACHE_URL=localhost:6379 +MF_TWINS_CACHE_PASS="" +MF_TWINS_CACHE_DB=0 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index f5290577..a02ebf0c 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -11,7 +11,7 @@ volumes: mainflux-authn-db-volume: mainflux-users-db-volume: mainflux-things-db-volume: - mainflux-things-redis-volume: + mainflux-auth-redis-volume: mainflux-es-redis-volume: mainflux-influxdb-volume: mainflux-bootstrap-db-volume: @@ -174,14 +174,14 @@ services: volumes: - mainflux-things-db-volume:/var/lib/postgresql/data - things-redis: + auth-redis: image: redis:5.0-alpine - container_name: mainflux-things-redis + container_name: mainflux-auth-redis restart: on-failure networks: - mainflux-base-net volumes: - - mainflux-things-redis-volume:/data + - mainflux-auth-redis-volume:/data things: image: mainflux/things:latest @@ -197,7 +197,7 @@ services: MF_THINGS_DB_USER: ${MF_THINGS_DB_USER} MF_THINGS_DB_PASS: ${MF_THINGS_DB_PASS} MF_THINGS_DB: ${MF_THINGS_DB} - MF_THINGS_CACHE_URL: things-redis:${MF_REDIS_TCP_PORT} + MF_THINGS_CACHE_URL: auth-redis:${MF_REDIS_TCP_PORT} MF_THINGS_ES_URL: es-redis:${MF_REDIS_TCP_PORT} MF_THINGS_HTTP_PORT: ${MF_THINGS_HTTP_PORT} MF_THINGS_AUTH_HTTP_PORT: ${MF_THINGS_AUTH_HTTP_PORT} @@ -225,7 +225,7 @@ services: - mainflux-base-net vernemq: - image: mainflux/vernemq:1.10.1-alpine + image: mainflux/vernemq:latest container_name: mainflux-vernemq restart: on-failure environment: @@ -247,7 +247,7 @@ services: restart: on-failure environment: MF_MQTT_ADAPTER_LOG_LEVEL: ${MF_MQTT_ADAPTER_LOG_LEVEL} - MF_MQTT_ADAPTER_PORT: ${MF_MQTT_ADAPTER_PORT} + MF_MQTT_ADAPTER_MQTT_PORT: ${MF_MQTT_ADAPTER_MQTT_PORT} MF_MQTT_ADAPTER_WS_PORT: ${MF_MQTT_ADAPTER_WS_PORT} MF_MQTT_ADAPTER_ES_URL: es-redis:${MF_REDIS_TCP_PORT} MF_NATS_URL: ${MF_NATS_URL} @@ -258,6 +258,7 @@ services: MF_JAEGER_URL: ${MF_JAEGER_URL} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} + MF_AUTH_CACHE_URL: auth-redis:${MF_REDIS_TCP_PORT} networks: - mainflux-base-net diff --git a/docker/nginx/entrypoint.sh b/docker/nginx/entrypoint.sh index cbea7b41..b5d15cab 100755 --- a/docker/nginx/entrypoint.sh +++ b/docker/nginx/entrypoint.sh @@ -2,10 +2,10 @@ if [ -z "$MF_MQTT_CLUSTER" ] then - envsubst '${MF_MQTT_ADAPTER_PORT}' < /etc/nginx/snippets/mqtt-upstream-single.conf > /etc/nginx/snippets/mqtt-upstream.conf + envsubst '${MF_MQTT_ADAPTER_MQTT_PORT}' < /etc/nginx/snippets/mqtt-upstream-single.conf > /etc/nginx/snippets/mqtt-upstream.conf envsubst '${MF_MQTT_ADAPTER_WS_PORT}' < /etc/nginx/snippets/mqtt-ws-upstream-single.conf > /etc/nginx/snippets/mqtt-ws-upstream.conf else - envsubst '${MF_MQTT_ADAPTER_PORT}' < /etc/nginx/snippets/mqtt-upstream-cluster.conf > /etc/nginx/snippets/mqtt-upstream.conf + envsubst '${MF_MQTT_ADAPTER_MQTT_PORT}' < /etc/nginx/snippets/mqtt-upstream-cluster.conf > /etc/nginx/snippets/mqtt-upstream.conf envsubst '${MF_MQTT_ADAPTER_WS_PORT}' < /etc/nginx/snippets/mqtt-ws-upstream-cluster.conf > /etc/nginx/snippets/mqtt-ws-upstream.conf fi diff --git a/docker/nginx/nginx-key.conf b/docker/nginx/nginx-key.conf index 9e1fc3ba..7a84e47f 100644 --- a/docker/nginx/nginx-key.conf +++ b/docker/nginx/nginx-key.conf @@ -79,10 +79,10 @@ http { } # Proxy pass to mainflux-mqtt-adapter over WS - location /mqtt/ { + location /mqtt { include snippets/proxy-headers.conf; include snippets/ws-upgrade.conf; - proxy_pass http://mqtt_ws_cluster/; + proxy_pass http://mqtt_ws_cluster; } # Proxy pass to mainflux-influxdb-reader diff --git a/docker/nginx/nginx-x509.conf b/docker/nginx/nginx-x509.conf index 83e23310..bcd83f48 100644 --- a/docker/nginx/nginx-x509.conf +++ b/docker/nginx/nginx-x509.conf @@ -87,11 +87,11 @@ http { } # Proxy pass to mainflux-mqtt-adapter over WS - location /mqtt/ { + location /mqtt { include snippets/verify-ssl-client.conf; include snippets/proxy-headers.conf; include snippets/ws-upgrade.conf; - proxy_pass http://mqtt_ws_cluster/; + proxy_pass http://mqtt_ws_cluster; } # Proxy pass to mainflux-influxdb-reader diff --git a/docker/nginx/snippets/mqtt-upstream-cluster.conf b/docker/nginx/snippets/mqtt-upstream-cluster.conf index 31657294..204219f1 100644 --- a/docker/nginx/snippets/mqtt-upstream-cluster.conf +++ b/docker/nginx/snippets/mqtt-upstream-cluster.conf @@ -3,7 +3,7 @@ upstream mqtt_cluster { least_conn; - server mqtt-adapter-1:${MF_MQTT_ADAPTER_PORT}; - server mqtt-adapter-2:${MF_MQTT_ADAPTER_PORT}; - server mqtt-adapter-3:${MF_MQTT_ADAPTER_PORT}; -} \ No newline at end of file + server mqtt-adapter-1:${MF_MQTT_ADAPTER_MQTT_PORT}; + server mqtt-adapter-2:${MF_MQTT_ADAPTER_MQTT_PORT}; + server mqtt-adapter-3:${MF_MQTT_ADAPTER_MQTT_PORT}; +} diff --git a/docker/nginx/snippets/mqtt-upstream-single.conf b/docker/nginx/snippets/mqtt-upstream-single.conf index 67a0828b..3c5372ba 100644 --- a/docker/nginx/snippets/mqtt-upstream-single.conf +++ b/docker/nginx/snippets/mqtt-upstream-single.conf @@ -2,5 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 upstream mqtt_cluster { - server mqtt-adapter:${MF_MQTT_ADAPTER_PORT}; -} \ No newline at end of file + server mqtt-adapter:${MF_MQTT_ADAPTER_MQTT_PORT}; +} diff --git a/docker/ssl/authorization.js b/docker/ssl/authorization.js index 7e8968c2..408f2317 100644 --- a/docker/ssl/authorization.js +++ b/docker/ssl/authorization.js @@ -43,7 +43,7 @@ function authenticate(s) { function parsePackage(s, data) { // An explanation of MQTT packet structure can be found here: - // https://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html#msg-format. + // https://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html#msg-format. // CONNECT message is explained here: // https://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html#connect. @@ -54,9 +54,9 @@ function parsePackage(s, data) { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | TYPE | RSRVD | REMAINING LEN | PROTOCOL NAME LEN | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | PROTOCOL NAME | + | PROTOCOL NAME | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| - | VERSION | FLAGS | KEEP ALIVE | + | VERSION | FLAGS | KEEP ALIVE | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| | Payload (if any) ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -65,8 +65,8 @@ function parsePackage(s, data) { Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. It is encoded in the manner described here: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180836. - - Connect flags byte looks like this: + + Connect flags byte looks like this: | 7 | 6 | 5 | 4 3 | 2 | 1 | 0 | | Username Flag | Password Flag | Will Retain | Will QoS | Will Flag | Clean Session | Reserved | @@ -76,7 +76,7 @@ function parsePackage(s, data) { 3. Will Message (2 bytes length + Will Message value) if Will Flag is 1. 4. User Name (2 bytes length + User Name value) if User Name Flag is 1. 5. Password (2 bytes length + Password value) if Password Flag is 1. - + This method extracts Password field. */ @@ -95,23 +95,23 @@ function parsePackage(s, data) { // CONTROL(1) + MSG_LEN(1-4) + PROTO_NAME_LEN(2) + PROTO_NAME(4) + PROTO_VERSION(1) var flags_pos = 1 + len_size + 2 + 4 + 1; var flags = data.codePointAt(flags_pos); - + // If there are no username and password flags (11xxxxxx), return. if (flags < 192) { s.error('MQTT username or password not provided'); return ''; } - + // FLAGS(1) + KEEP_ALIVE(2) var shift = flags_pos + 1 + 2; - + // Number of bytes to encode length. var len_bytes_num = 2; // If Wil Flag is present, Will Topic and Will Message need to be skipped as well. var shift_flags = 196 <= flags ? 5 : 3; var len_msb, len_lsb, len; - + for (var i = 0; i < shift_flags; i++) { len_msb = data.codePointAt(shift).toString(16); len_lsb = data.codePointAt(shift + 1).toString(16); @@ -138,18 +138,6 @@ function setKey(r) { return ''; } - if (r.uri.startsWith('/ws') && (!auth || !auth.length)) { - var a; - for (a in r.args) { - if (a == 'authorization' && r.args[a] === clientKey) { - return clientKey; - } - } - - r.error('Authorization param does not match certificate'); - return ''; - } - return clientKey; } From 5c7973e475d683afd4e98d3e67ff87d7fc130cb7 Mon Sep 17 00:00:00 2001 From: PricelessRabbit Date: Sat, 4 Jul 2020 11:35:24 +0200 Subject: [PATCH 36/39] Fixed typo in ssl Makefile (#99) --- docker/ssl/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/ssl/Makefile b/docker/ssl/Makefile index 9cf19bd2..6119e068 100644 --- a/docker/ssl/Makefile +++ b/docker/ssl/Makefile @@ -6,7 +6,7 @@ EA = info@mainflux.com CN = localhost CRT_FILE_NAME = thing -all: clean_certs ca server_crt +all: clean_certs ca server_cert # CA name and key is "ca". ca: From 034c9f391dffb8fb2bd883c6160c227625e3c7f2 Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Wed, 15 Jul 2020 11:52:11 +0200 Subject: [PATCH 37/39] NOISSUE - Add clean command to Makefile (#103) Signed-off-by: Manuel Imperiale --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 595a2854..35173fb8 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,9 @@ ui: run: docker-compose -f docker/docker-compose.yml up +clean: + docker-compose -f docker/docker-compose.yml down --rmi all -v --remove-orphans + release: $(eval version = $(shell git describe --abbrev=0 --tags)) git checkout $(version) From bf2c801087e52c452a3b864115883d48fc1edad6 Mon Sep 17 00:00:00 2001 From: Manuel Imperiale Date: Thu, 23 Jul 2020 10:51:00 +0200 Subject: [PATCH 38/39] NOISSUE - Use new endpoint query param to fetch not connected Things or Channels (#104) Signed-off-by: Manuel Imperiale --- .../services/channels/channels.service.ts | 46 +++++++++++++----- .../common/services/things/things.service.ts | 48 ++++++++++++++----- .../details/channels.details.component.ts | 24 ++++------ .../details/devices.details.component.ts | 34 ++++++------- 4 files changed, 98 insertions(+), 54 deletions(-) diff --git a/src/app/common/services/channels/channels.service.ts b/src/app/common/services/channels/channels.service.ts index 149e2cfb..de18d200 100644 --- a/src/app/common/services/channels/channels.service.ts +++ b/src/app/common/services/channels/channels.service.ts @@ -185,17 +185,41 @@ export class ChannelsService { connectedThings(chanID: string) { return this.http.get(`${environment.channelsUrl}/${chanID}/things`) - .map( - resp => { - return resp; - }, - ) - .catch( - err => { - this.notificationsService.error('Failed to fetch connected Things to the Channel', - `Error: ${err.status} - ${err.statusText}`); - return Observable.throw(err); + .map( + resp => { + return resp; }, - ); + ) + .catch( + err => { + this.notificationsService.error('Failed to fetch connected Things to the Channel', + `Error: ${err.status} - ${err.statusText}`); + return Observable.throw(err); + }, + ); + } + + disconnectedThings(chanID: string, offset?: number, limit?: number) { + offset = offset || 0; + limit = limit || defLimit; + + const params = new HttpParams() + .set('offset', offset.toString()) + .set('limit', limit.toString()) + .set('connected', 'false'); + + return this.http.get(`${environment.channelsUrl}/${chanID}/things`, { params }) + .map( + resp => { + return resp; + }, + ) + .catch( + err => { + this.notificationsService.error('Failed to fetch not connected Things to the Channel', + `Error: ${err.status} - ${err.statusText}`); + return Observable.throw(err); + }, + ); } } diff --git a/src/app/common/services/things/things.service.ts b/src/app/common/services/things/things.service.ts index c94bff35..deca32c3 100644 --- a/src/app/common/services/things/things.service.ts +++ b/src/app/common/services/things/things.service.ts @@ -133,17 +133,41 @@ export class ThingsService { connectedChannels(thingID: string) { return this.http.get(`${environment.thingsUrl}/${thingID}/channels/`) - .map( - resp => { - return resp; - }, - ) - .catch( - err => { - this.notificationsService.error('Failed to fetch connected Chanels to the Thing', - `Error: ${err.status} - ${err.statusText}`); - return Observable.throw(err); - }, - ); + .map( + resp => { + return resp; + }, + ) + .catch( + err => { + this.notificationsService.error('Failed to fetch connected Chanels to the Thing', + `Error: ${err.status} - ${err.statusText}`); + return Observable.throw(err); + }, + ); + } + + disconnectedChannels(thingID: string, offset?: number, limit?: number) { + offset = offset || 0; + limit = limit || defLimit; + + const params = new HttpParams() + .set('offset', offset.toString()) + .set('limit', limit.toString()) + .set('connected', 'false'); + + return this.http.get(`${environment.thingsUrl}/${thingID}/channels`, { params }) + .map( + resp => { + return resp; + }, + ) + .catch( + err => { + this.notificationsService.error('Failed to fetch not connected Channels to the Thing', + `Error: ${err.status} - ${err.statusText}`); + return Observable.throw(err); + }, + ); } } diff --git a/src/app/pages/things/channels/details/channels.details.component.ts b/src/app/pages/things/channels/details/channels.details.component.ts index e455d539..7f52a50f 100644 --- a/src/app/pages/things/channels/details/channels.details.component.ts +++ b/src/app/pages/things/channels/details/channels.details.component.ts @@ -88,28 +88,22 @@ export class ChannelsDetailsComponent implements OnInit { } findDisconnectedThings() { - this.things = []; - this.channelsService.connectedThings(this.channel.id).subscribe( (respConns: any) => { this.connections = respConns.things; - this.thingsService.getThings(this.offset, this.limit).subscribe( - (respThings: any) => { - respThings.things.forEach(thing => { - // Filter get Things resp and keep only disconnected ones. - if (!(this.connections.filter(c => c.id === thing.id).length > 0)) { - this.things.push(thing); - } - }); - - this.getchannelMessages(); - }, - ); + + this.getChannelMessages(); + }, + ); + + this.channelsService.disconnectedThings(this.channel.id).subscribe( + (respDisconns: any) => { + this.things = respDisconns.things; }, ); } - getchannelMessages() { + getChannelMessages() { if (this.connections.length) { this.messagesService.getMessages(this.channel.id, this.connections[0].key).subscribe( (respMsg: any) => { diff --git a/src/app/pages/things/devices/details/devices.details.component.ts b/src/app/pages/things/devices/details/devices.details.component.ts index 61f50bd9..ca47207a 100644 --- a/src/app/pages/things/devices/details/devices.details.component.ts +++ b/src/app/pages/things/devices/details/devices.details.component.ts @@ -87,28 +87,30 @@ export class DevicesDetailsComponent implements OnInit { ); } + getChannelMessages() { + this.connections.forEach(chan => { + this.messagesService.getMessages(chan.id, this.thing.key, this.thing.id).subscribe( + (respMsg: any) => { + this.messages = respMsg.messages || this.messages; + }, + ); + }); + } + findDisconnectedChans() { - this.channels = []; this.messages = []; this.thingsService.connectedChannels(this.thing.id).subscribe( (respConns: any) => { this.connections = respConns.channels; - this.channelsService.getChannels(this.offset, this.limit).subscribe( - (respChans: any) => { - respChans.channels.forEach(chan => { - if (!(this.connections.filter(c => c.id === chan.id).length > 0)) { - this.channels.push(chan); - } else { - this.messagesService.getMessages(chan.id, this.thing.key, this.thing.id).subscribe( - (respMsg: any) => { - this.messages = respMsg.messages || this.messages; - }, - ); - } - }); - }, - ); + + this.getChannelMessages(); + }, + ); + + this.thingsService.disconnectedChannels(this.thing.id).subscribe( + (respDisconn: any) => { + this.channels = respDisconn.channels; }, ); } From d31d6f7b1e7b430c098cd335d9b159e0949cb856 Mon Sep 17 00:00:00 2001 From: Mirko Teodorovic Date: Wed, 29 Jul 2020 16:43:15 +0200 Subject: [PATCH 39/39] add provision service Signed-off-by: Mirko Teodorovic --- .env | 24 ++++++++++++ docker/configs/config.toml | 78 ++++++++++++++++++++++++++++++++++++++ docker/docker-compose.yml | 37 ++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 docker/configs/config.toml diff --git a/.env b/.env index 6aa6a93f..a8367d68 100644 --- a/.env +++ b/.env @@ -102,6 +102,30 @@ MF_BOOTSTRAP_DB_PASS=mainflux MF_BOOTSTRAP_DB=bootstrap MF_BOOTSTRAP_DB_SSL_MODE=disable + +### Provision +MF_PROVISION_CONFIG_FILE=/configs/config.toml +MF_PROVISION_LOG_LEVEL=debug +MF_PROVISION_HTTP_PORT=8190 +MF_PROVISION_ENV_CLIENTS_TLS=false +MF_PROVISION_SERVER_CERT= +MF_PROVISION_SERVER_KEY= +MF_PROVISION_MQTT_URL=tcp://localhost +MF_PROVISION_USERS_LOCATION=http://localhost:8180 +MF_PROVISION_THINGS_LOCATION=http://things:8182 +MF_PROVISION_USER= +MF_PROVISION_PASS= +MF_PROVISION_API_KEY= +MF_PROVISION_CERTS_SVC_URL=http://certs:8204 +MF_PROVISION_X509_PROVISIONING=false +MF_PROVISION_BS_SVC_URL=http://bootstrap:8202/things +MF_PROVISION_BS_SVC_WHITELIST_URL=http://bootstrap:8202/things/state +MF_PROVISION_BS_CONFIG_PROVISIONING=true +MF_PROVISION_BS_AUTO_WHITELIST=true +MF_PROVISION_BS_CONTENT= +MF_PROVISION_CERTS_RSA_BITS=4096 +MF_PROVISION_CERTS_HOURS_VALID=2400h + ### LoRa MF_LORA_ADAPTER_LOG_LEVEL=debug MF_LORA_ADAPTER_MESSAGES_URL=tcp://lora.mqtt.mainflux.io:1883 diff --git a/docker/configs/config.toml b/docker/configs/config.toml new file mode 100644 index 00000000..c5749658 --- /dev/null +++ b/docker/configs/config.toml @@ -0,0 +1,78 @@ +[bootstrap] + [bootstrap.content] + [bootstrap.content.agent.edgex] + url = "http://localhost:48090/api/v1/" + + [bootstrap.content.agent.log] + level = "info" + + [bootstrap.content.agent.mqtt] + mtls = false + qos = 0 + retain = false + skip_tls_ver = true + url = "localhost:1883" + + [bootstrap.content.agent.server] + nats_url = "localhost:4222" + port = "9000" + + [bootstrap.content.agent.heartbeat] + interval = "30s" + + [bootstrap.content.agent.terminal] + session_timeout = "30s" + + + [bootstrap.content.export.exp] + log_level = "debug" + nats = "nats://localhost:4222" + port = "8172" + cache_url = "localhost:6379" + cache_pass = "" + cache_db = "0" + + [bootstrap.content.export.mqtt] + ca_path = "ca.crt" + cert_path = "thing.crt" + channel = "" + host = "tcp://localhost:1883" + mtls = false + password = "" + priv_key_path = "thing.key" + qos = 0 + retain = false + skip_tls_ver = false + username = "" + + [[bootstrap.content.export.routes]] + mqtt_topic = "" + nats_topic = "channels" + subtopic = "" + type = "mfx" + workers = 10 + + [[bootstrap.content.export.routes]] + mqtt_topic = "" + nats_topic = "export" + subtopic = "" + type = "default" + workers = 10 + +[[things]] + name = "thing" + + [things.metadata] + external_id = "xxxxxx" + +[[channels]] + name = "control-channel" + + [channels.metadata] + type = "control" + +[[channels]] + name = "data-channel" + + [channels.metadata] + type = "data" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index a02ebf0c..001028a6 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -473,6 +473,43 @@ services: networks: - mainflux-base-net + # Provision + provision: + image: mainflux/provision:latest + container_name: mainflux-provision + restart: on-failure + networks: + - mainflux-base-net + ports: + - ${MF_PROVISION_HTTP_PORT}:${MF_PROVISION_HTTP_PORT} + environment: + MF_PROVISION_LOG_LEVEL: ${MF_PROVISION_LOG_LEVEL} + MF_PROVISION_HTTP_PORT: ${MF_PROVISION_HTTP_PORT} + MF_PROVISION_CONFIG_FILE: ${MF_PROVISION_CONFIG_FILE} + MF_PROVISION_LOG_LEVEL: ${MF_PROVISION_LOG_LEVEL} + MF_PROVISION_ENV_CLIENTS_TLS: ${MF_PROVISION_ENV_CLIENTS_TLS} + MF_PROVISION_SERVER_CERT: ${MF_PROVISION_SERVER_CERT} + MF_PROVISION_SERVER_KEY: ${MF_PROVISION_SERVER_KEY} + MF_PROVISION_MQTT_URL: ${MF_PROVISION_MQTT_URL} + MF_PROVISION_USERS_LOCATION: ${MF_PROVISION_USERS_LOCATION} + MF_PROVISION_THINGS_LOCATION: ${MF_PROVISION_THINGS_LOCATION} + MF_PROVISION_USER: ${MF_PROVISION_USER} + MF_PROVISION_PASS: ${MF_PROVISION_PASS} + MF_PROVISION_API_KEY: ${MF_PROVISION_API_KEY} + MF_PROVISION_CERTS_SVC_URL: ${MF_PROVISION_CERTS_SVC_URL} + MF_PROVISION_X509_PROVISIONING: ${MF_PROVISION_X509_PROVISIONING} + MF_PROVISION_BS_SVC_URL: ${MF_PROVISION_BS_SVC_URL} + MF_PROVISION_BS_SVC_WHITELIST_URL: ${MF_PROVISION_BS_SVC_WHITELIST_URL} + MF_PROVISION_BS_CONFIG_PROVISIONING: ${MF_PROVISION_BS_CONFIG_PROVISIONING} + MF_PROVISION_BS_AUTO_WHITELIST: ${MF_PROVISION_BS_AUTO_WHITELIST} + MF_PROVISION_BS_CONTENT: ${MF_PROVISION_BS_CONTENT} + MF_PROVISION_CERTS_RSA_BITS: ${MF_PROVISION_CERTS_RSA_BITS} + MF_PROVISION_CERTS_HOURS_VALID: ${MF_PROVISION_CERTS_HOURS_VALID} + volumes: + - ./configs:/configs + - ../ssl/certs/ca.key:/etc/ssl/certs/ca.key + - ../ssl/certs/ca.crt:/etc/ssl/certs/ca.crt + ## TWINS twins-db: image: mongo:bionic