Bei einer Vielzahl an IoT Projekten sind die Geräte meist auf einem großen Gelände oder in einem Gebäude verstreut. Eine Kartenansicht der eigenen Geräte mit der Positionierung ist daher bei vielen Nutzern ein gern gesehenes Feature. Die meisten zur Verfügung gestellten Map Widgets basieren auf Online Karten und GPS Koordinaten. Viele der IoT Geräten besitzen aber keinen eigenen GPS Sensor, sind nicht genau genug oder sollen auf eine individuelle Kartenansicht dargestellt werden.

Das Drag’n’Drop Map Widget, konzipiert für die Cumulocity IoT Cloud Plattform, ist eine einfache Kartenansicht mit einer Drag-and-drop (deutsch: Ziehen und Ablegen) Funktionalität, um seine IoT Geräte entsprechend positionieren zu können.

Anwendung - Wie funktioniert das Widget?

Bei der Nutzung des Widgets wird davon ausgegangen, dass die IoT Geräte von Interesse in der Cloud registriert sind. Zur administrativen Verwaltung ist es für gewöhnlich gängig, dass eine gewisse Gruppenstruktur erstellt wird und die IoT Geräte und Sensoren diesen Gruppen zugewiesen werden.

Beispiel: IoT Gruppierung für ein Unternehmen
Ein Unternehmen besitzt verschiedene Standorte auf der ganzen Welt. Eine mögliche Gruppenstruktur könnte sein, seine Geräte nach Ländern und nach den einzelnen Standorten des Unternehmens zu unterteilen und zu definieren, welche Geräte an welchen Standort zum Einsatz kommen.

Wurde solch eine Zuweisung von Gruppen durchgeführt, kann als nächster Schritt unser Drag’n’Drop Map Widget genutzt werden. Dafür müssen Sie nur eine Bilddatei von Ihrem Grundstück oder Gebäudeumrisses bereithalten und es in die IoT Plattform hochladen.

edit-widget-1 Bild 1: Upload Bilddatei

Nachdem die Bilddatei erfolgreich hochgeladen wurde, folgt nun der spaßige Teil 😁
Das individuelle Platzieren der Sensoren!

Die zur Gruppe zugewiesenen Sensoren werden auf der Karte angezeigt und können per Mausklick verschoben werden. Ist man mit der Platzierung der Sensoren zufrieden, wird die Einstellung gespeichert durch das Sperren des Dashboards (🔐 oben rechts).

drag-and-drop Bild 2: Platzieren der Sensor-Icons mit Drag und Drop Funktionalität

Das war’s!🎉 Das Widget ist nun individuell konfiguriert und zeigt in Echtzeit den aktuellen Zustand der Sensoren innerhalb einer Gruppe an. Durch die Verwendung von Ampelfarben🚦sieht der Betrachter sofort, welche Sensoren Alarm schlagen und wo sich die Sensoren auf dem Grundstück befinden. Ist ein Sensor zurzeit deaktiviert oder hat seit einer vordefinierten Zeit keine Daten an die Plattform geschickt, wird das Sensoricon grau dargestellt.

Möchte der Benutzer mehr Details zu dem betroffenen Sensor wissen, muss man einfach nur auf den entsprechenden Sensor klicken und es wird die Dashboardansicht für den Sensor angezeigt. Hier hat der Benutzer die Möglichkeit alle Sensormesswerte und -zustände im Verlauf sich anzuschauen und auszuwerten.

Sobald die Alarme bestätigt wurden und der Sensor in den Normalzustand wechselt, schalten die Sensor-Icons in dem Drag’n’Drop Map Widget wieder auf die Farbe Grün.🟢

realtime-alarming Bild 3: Echtzeitalarmierung durch Farbwechsel und direkte Verlinkung zu den Sensorobjekten

Technischer Aspekt - Angular DragDropModule

Das Hauptmerkmal dieses Widget besteht an der Einfachheit seiner Nutzung. Das individuelle Positionieren der Sensoren auf einer Karte mithilfe von Drag-and-drop ist ein wesentlicher Bestandteil des Widgets. Für die Implementierung solch einer Funktionalität mit Angular verwende ich das DragDropModule.

Für die Definition meiner zu verschiebenden Sensor-Icons, muss den Objekten die cdkDrag Klasse zugewiesen werden. Damit sichergestellt wird, dass die Sensoren nur innerhalb des Widgets verschoben werden können, wird mit dem cdkDragBoundary eine CSS-Klasse angebunden.

In [cdkDragFreeDragPosition] wird die initiale Position des Sensors definiert. Beim ersten Nutzen des Widgets liegt der Sensor zentriert zum Widget. Ansonsten wird die letzte Position aufgerufen, wo der Sensor zuletzt verschoben wurde. Jedes neue Verschieben eines Sensors wird mit (cdkDragEnded) verfolgt. In [cdkDragDisabled] wird dynamisch bestimmt, wann die Funktionalität für Drag-and-drop aktiviert wird.

<!-- List of sensor child assets -->
<div  *ngFor="let child of childAssets; let i = index" >
    <!-- Load sensor with cdkDrag and update positions -->
    <a #icon
        class="icon"
        cdkDrag 
        cdkDragBoundary=".overlay"
        [cdkDragFreeDragPosition]="dragPositions.get(child.id)"
        [cdkDragDisabled]="isFrozen"
        (cdkDragEnded)="drop($event,child)">
            <!-- Change color for different status -->
            <i class="dlt-c8y-icon-wifi"
                [ngStyle]="{color: childIsUnavailable[i] ? '#1e292f' : childIsCritical[i] ? '#E0000E' : childIsMajor[i] ? '#FF801F' : '#008800'}"></i>
            <!-- Display sensor name -->
            <p class="crop">{{child.name}}</p>
    </a>
</div>  

Code 1: HTML zum Anzeigen der Sensoren und Einbindung von cdkDrag

Werfen wir noch einen genaueren Blick auf den Methodenaufruf drop($event,child). Um zu garantieren, dass auch bei unterschiedlicher Bildschirmauflösung die Positionen der Sensoren auf der Karte gleich bleiben, ist eine Umrechnung notwendig. Die Klasse cdkDrag liefert nur die absolute (x, y)-Position des Sensors in Relation zu dem Widget. Es muss somit ebenfalls die relative Position noch ermittelt werden, um eine exakte Positionierung auf der Karte, bei unterschiedlicher Bildschirmauflösung, zu garantieren.

// Update Position of every sensor after drag and drop
function drop(event:any, device:IManagedObject){
    const newPos = event.source.getFreeDragPosition(); // get new position
    this.dragPositions.set(device.id, newPos); // update new position of sensor with id

    // Get size of map widget
    this.max_height = this.widget.nativeElement.offsetHeight;
    this.max_width = this.widget.nativeElement.offsetWidth;
    // Calculate relative position of sensor and update in c8y inventory storage
    this.updateChildAssetRelativePosition(device.id);
}

Code 2: Methodenaufruf bei jeder Positionsänderung eines Sensors

Nachdem die absolute Position und die aktuelle Größe des Widgets ermittelt wurde, wird die relative Position in updateChildAssetRelativePosition berechnet und in der Plattform gespeichert. Wird demnach das Widget im Browser geladen, dann wird immer zuerst die relative Position herangezogen und äquivalent die absolute Position dann ermittelt.

// Function to calculate relative position of sensor
function updateChildAssetRelativePosition(id:string){
    // Get absolute position from cdkDrag
    const absPos :any = this.dragPositions.get(id);

    // Calculate relative position using size of widget (max width and height)
    const newPos = {
        x: (absPos.x ) / (this.max_width / 100.0),
        y: (absPos.y ) / (this.max_height / 100.0)
    };
    //  Update relative position in c8y inventory storage
    this.asset.c8y_DevicesImagePositions.set(id, newPos);
}

Code 3: Umrechnung der absoluten Position (in Pixel) zur relativen Position (in %)

Drag’n’Drop Map Widget auch für Sie!

Wenn Sie an der Nutzung des Drag’n’Drop Map Widgets interessiert sind, kontaktieren Sie uns einfach unter info@nola-ventures.com.

Oder testen Sie JETZT die Demo-Version! Auf unserem GitHub repo finden Sie die Anwendung zum herunterladen, sowie eine Anleitung zur Installation auf ihrem Cumulocity IoT Tenant.

demo-github-repo Bild 4: Cumulocity Drag’n’Drop Map Widget Demo repository

Happy drag’n’drop 😊