Dimensionale Daten aus einer benutzerdefinierten Funktion hinzufügen

Sie können vorhandenen Gerätetypen Dimensionen und Dimensionswerte hinzufügen. Wenn Sie mit Pythonvertraut sind, können Sie mithilfe von Code Dimensionsdaten zu vorhandenen Gerätetypen hinzufügen.

Sie können eine benutzerdefinierte Funktion für eine Stapeldatenmetrik auf der Basis der benutzerdefinierten Beispielfunktion entwickeln, um Dimensionen hinzuzufügen. Die Beispielfunktion verwendet die Preload -Basisklasse von IoT Functions , um Dimensionen hinzuzufügen. Bei jeder Ausführung der Funktion löschen Sie die Dimensionen und ihre Werte und erstellen Sie erneut. Wenn mehrere Gerätetypen Dimensionen gemeinsam nutzen, können Sie die angepasste Funktion auf jeden Gerätetyp anwenden, um die Dimensionen festzulegen.

Vorbereitende Schritte

Führen Sie die Schritte im Lernprogramm: Angepasste Funktion hinzufügen aus, um zu erfahren, wie Sie Ihre Umgebung einrichten und Ihre Funktion speichern, installieren, testen, registrieren und anwenden.

Wenn Sie Dimensionen für einen Einheitentyp simulieren möchten, können Sie den Beispielscript verwenden, um die Dimensionen zu einem Einheitentyp hinzuzufügen. Verwenden Sie im Script die Methoden make_dimenion und generate_dimension_data für einen Gerätetyp, um Dimensionsdaten zu simulieren.

Dimensionen mithilfe einer angepassten Funktion hinzufügen

Erstellen Sie eine angepasste Funktion, die der Datenbank eine Dimensionstabelle hinzufügt und den Dimensionen Werte zuweist. Verwenden Sie den folgenden Beispielcode als Vorlage für ihre Funktion. Sie können die angepasste Funktion erweitern, um die Dimensionswerte zuzuweisen. Sie können beispielsweise die Funktion erweitern, um Dimensionswerte aus einer .csv -Datei zu laden.

Die Beispielfunktion hat zwei Klassen. Beide Klassen fügen eine Dimensionstabelle hinzu und weisen der Dimension pro Geräte-ID Werte zu.

  • Die Klasse SampleDimensionPreload_random ordnet Zufallswerte zu.
  • Die Klasse SampleDimensionPreload_preset weist voreingestellte Werte zu.

Beispiel einer angepassten Funktion

Der folgende Code ist ein Beispiel für eine angepasste Funktion. Die Funktion verwendet die vorinstallierten Dimensionsdaten mit voreingestellten Werten zum Erstellen und Laden von Dimensionsdaten und generiert und ordnet Testdaten nach dem Zufallsprinzip zu. Die Funktion erstellt eine Dimension dimension_1und fügt ihr Zufallswerte hinzu. Die Funktion löscht die alten Werte und lädt die Dimensionstabelle neu. Die Dimensionsdatenwerte sind fest codiert, können jedoch durch Laden von Daten aus einer .csv -Datei oder über eine HTTP -Anforderung erweitert werden. In der folgenden Vorlage ist der Wert fest in preload_valuecodiert.

Geben Sie für die Variable PACKAGE_URL die URL zu Ihrem Paket an. Diese URL muss über eine Pip-Installation zugänglich sein. Verwenden Sie das folgende Format: git+https://<personal_access_token>@github.com/<user_id><path_to_repository>@<package. Wenn Ihr Code unter GitLab, gehostet wird, verwenden Sie das folgende Format: git+https://<deploy_token_username>:<deploy_token_password>@gitlab.com/<user_id><path_to_repository>@prod

import logging
import pandas as pd
import numpy as np


from iotfunctions.base import BasePreload
from iotfunctions import ui

from sqlalchemy import Column, Integer, String, Float, DateTime, Boolean, func

logger = logging.getLogger(__name__)

PACKAGE_URL = 'PACKAGE_URL'

class SampleDimensionPreload_random(BasePreload):

    dim_table_name = None

    def __init__(self, output_item ='dimension_preload_done'):

        super().__init__(dummy_items=[],output_item = output_item)


    def execute(self, df, start_ts = None,end_ts=None,entities=None):

        entity_type = self.get_entity_type()
        self.db = entity_type.db
        schema = entity_type._db_schema

        try:
            self.dim_table_name = (entity_type.get_attributes_dict()['_dimension_table_name']).upper()
        except:
            self.dim_table_name = entity_type.logical_name + '_DIMENSION'

        msg = 'Dimension table name: ' + str(self.dim_table_name)
        logging.debug(msg)

        ef = self.db.read_table(entity_type.logical_name, schema=schema, columns=[entity_type._entity_id])
        ids = set(ef[entity_type._entity_id].unique())
        msg = 'entities with device_id present:' + str(ids)
        logger.debug(msg)

        self.db.drop_table(self.dim_table_name, schema=schema)
        entity_type.make_dimension(self.dim_table_name,
                                   Column('dimension_1', String(50)), # add dimension_1
                                   **{'schema': schema})
        entity_type.register()
       
        entity_type.generate_dimension_data(entities=ids)

        return True

    @classmethod
    def build_ui(cls):
     
        inputs = []
        outputs=[]
        outputs.append(ui.UIStatusFlag(name='output_item'))
        return (inputs, outputs)


class SampleDimensionPreload_preset(BasePreload):

    dim_table_name = None

    def __init__(self, output_item='dimension_preload_done'):

        super().__init__(dummy_items=[], output_item=output_item)

    def execute(self, df, start_ts=None, end_ts=None, entities=None):
       
        entity_type = self.get_entity_type()
        self.db = entity_type.db
        schema = entity_type._db_schema
        try:
            self.dim_table_name = (entity_type.get_attributes_dict()['_dimension_table_name']).upper()
        except:
            self.dim_table_name = entity_type.logical_name + '_DIMENSION'

        msg = 'Dimension table name: ' + str(self.dim_table_name)
        logging.debug(msg)
        ef = self.db.read_table(entity_type.logical_name, schema=schema, columns=[entity_type._entity_id])
        ids = set(ef[entity_type._entity_id].unique())
        msg = 'entities with device_id present:' + str(ids)
        logger.debug(msg)

        self.db.drop_table(self.dim_table_name, schema=schema)
        entity_type.make_dimension(self.dim_table_name,
                                   Column('dimension_1', String(50)),  # add dimension_1
                                   **{'schema': schema})
        entity_type.register()
       
        preload_data = {}
        preload_values = np.repeat('preload_value', len(ids))
        preload_data['dimension_1'] = preload_values
        preload_data[entity_type._entity_id] = list(ids)
        df = pd.DataFrame(preload_data)
        msg = 'Setting columns for dimensional table\n'
        required_cols = self.db.get_column_names(table=self.dim_table_name, schema=schema)
        missing_cols = list(set(required_cols) - set(df.columns))
        msg = msg + 'required_cols ' + str(required_cols) + '\n'
        msg = msg + 'missing_cols ' + str(missing_cols) + '\n'
        logger.debug(msg)

        self.write_frame(df=df, table_name=self.dim_table_name, if_exists='append')

        kwargs = {
            'dimension_table': self.dim_table_name,
            'schema': schema,
        }
        entity_type.trace_append(created_by=self,
                                 msg='Wrote dimension to table',
                                 log_method=logger.debug,
                                 **kwargs)

        return True

    @classmethod
    def build_ui(cls):
        
        inputs = []
        outputs = []
        outputs.append(ui.UIStatusFlag(name='output_item'))
        return (inputs, outputs)

Wenn Sie die angepasste Funktion in Ihrer lokalen Umgebung testen, können Sie ein Script ähnlich dem folgenden Beispiel verwenden, um die Klasse SampleDimensionPreload_random zu testen. Wenn Sie voreingestellte Werte verwenden möchten, ersetzen Sie den Klassennamen SampleDimensionPreload_random durch die Klasse SampleDimensionPreload_preset .

Bevor Sie das Script verwenden, rufen Sie die Datenbankberechtigungsnachweise ab.

  1. Laden Sie die credentials_as.json -Dateiherunter.
  2. Ersetzen Sie die Variablen durch Ihre Daten und speichern Sie die Datei anschließend auf Ihrer lokalen Workstation.
Hinweis : Speichern Sie die Berechtigungsnachweisdatei nicht in einem externen Repository.
Das folgende Script kann verwendet werden, um die folgenden Aufgaben auszuführen:
  • Erstellen Sie ein Datenbankobjekt für den Zugriff auf die Datenbank. Übertragen Sie die Berechtigungsnachweisdatei nicht mit Push in Ihr externes Repository. Stellen Sie den Wert schema ein, wenn Sie nicht den Standardwert verwenden.
  • Registrieren Sie die angepasste Funktion. Sie müssen unregister_functions verwenden, wenn Sie die Methodensignatur oder erforderliche Eingaben ändern.
  • Fügen Sie einen Gerätetyp hinzu. Dieses Beispiel setzt voraus, dass das Gerät, dem Sie Dimensionen hinzufügen, vorhanden ist. Das Script fügt die angepasste Funktion zu diesem Gerätetyp hinzu, um sie lokal zu testen. Aktualisieren Sie den Namen des Gerätetyps auf den Namen Ihres Gerätetyps.
  • Rufen Sie den Namen der Dimensionstabelle ab und fügen Sie der Tabelle Dimensionswerte hinzu.
  • Testen Sie die Ausführung von Metrikberechnungen, die für den Gerätetyp lokal definiert sind. Ein lokaler Test aktualisiert weder das Serverjobprotokoll noch schreibt er Metrikdaten in den Data Lake. Stattdessen werden die Messdaten im .csv -Format in das lokale Dateisystem geschrieben.
  • Gerätedaten anzeigen.
import json
import logging
from ai.function_dimension import (SampleDimensionPreload_random,
                                   SampleDimensionPreload_preset)
from iotfunctions.db import Database
from iotfunctions.enginelog import EngineLogging

EngineLogging.configure_console_logging(logging.DEBUG)

schema = 'bluadmin' 
with open('./scripts/credentials_as.json', encoding='utf-8') as F:
    credentials = json.loads(F.read())
db = Database(credentials = credentials)

db.unregister_functions(['SampleDimensionPreload_random'])
db.register_functions([SampleDimensionPreload_random])

entity_name = 'entity_dimension_test_random'
entity_type = db.get_entity_type(name=entity_name)

try:
    dim_table_name = (entity_type.get_attributes_dict()['_dimension_table_name']).lower()
except:
    dim_table_name = entity_name + '_dimension'

entity_type._functions.extend([SampleDimensionPreload_random()])

entity_type.exec_local_pipeline(**{'_production_mode': False})

print ("Reading new dimension table")
print(dim_table_name)
df = db.read_dimension(dimension=dim_table_name, schema=schema)
print(df.head())

print("Finished reading the device dimension table")

Das folgende Script fügt einem Gerätetyp Dimensionen hinzu und simuliert die Werte durch Hinzufügen von Zufallswerten. Das Script erstellt die Dimensionen, indem es sie als Spalten hinzufügt. Der Dimensionstyp kann Integer, INTEGER, Float, FLOAT, String, VARCHAR, DateTime, oder Timestamp sein.

Bevor Sie das Script verwenden, rufen Sie die Datenbankberechtigungsnachweise ab.

  1. Laden Sie die credentials_as.json -Dateiherunter.
  2. Ersetzen Sie die Variablen durch Ihre Daten und speichern Sie die Datei anschließend auf Ihrer lokalen Workstation.
Hinweis : Speichern Sie die Berechtigungsnachweisdatei nicht in einem externen Repository.

Legen Sie im Script den Wert schema fest, wenn Sie nicht den Standardwert verwenden. Wenn Sie eine dieser Dimensionen verwenden, werden Werte aus einem vordefinierten Satz ausgewählt. Jeder andere Dimensionsname generiert Zufallswerte.

Um die Ausführung von Metrikberechnungen lokal zu testen, verwenden Sie die Funktion # entity_type.exec_local_pipeline(**{'_production_mode': False}) . Ein lokaler Test aktualisiert weder das Serverjobprotokoll noch schreibt er Metrikdaten in den Data Lake. Stattdessen werden die Messdaten im .csv -Format in das lokale Dateisystem geschrieben.

Abbildung 1. Beispielscript

import json
import logging
from iotfunctions.db import Database
from iotfunctions.enginelog import EngineLogging

from sqlalchemy import Column, String, Integer, Float

EngineLogging.configure_console_logging(logging.DEBUG)

schema = 'bluadmin'
with open('./scripts/credentials_as.json', encoding='utf-8') as F:
    credentials = json.loads(F.read())
db = Database(credentials = credentials)

entity_name = 'entity_dimension_simulate'
entity_type = db.get_entity_type(name=entity_name)

try:
    dim_table_name = (entity_type.get_attributes_dict()['_dimension_table_name']).lower()
except:
    dim_table_name = entity_name + '_dimension'

# db.drop_table(dim_table_name, schema=schema)

Dimension name:Values
['company', 'company_id', 'company_code']: ['ABC', 'COMPANY', 'JDI']
['plant', 'plant_id', 'plant_code']: ['Zhongshun', 'Holtsburg', 'Midway']
['plant', 'plant_id', 'plant_code']: ['US', 'CA', 'UK', 'DE']
['firmware', 'firmware_version']: ['1.0', '1.12', '1.13', '2.1']
['manufacturer']: ['Rentech', 'GHI Industries']
['zone']: ['27A', '27B', '27C']
['status', 'status_code']: ['inactive', 'active']
['operator', 'operator_id', 'person', 'employee']: ['Fred', 'Joe', 'Mary', 'Steve', 'Henry', 'Jane', 'Hillary', 'Justin', 'Rod']

db.drop_table(dim_table_name, schema=schema)
entity_type.make_dimension(dim_table_name,
                           Column('company', String(50)),
                           Column('status', String(50)),
                           Column('operator', String(50)),
                           **{'schema': schema})

entity_type.register()

# entity_type.exec_local_pipeline(**{'_production_mode': False})

ef = db.read_table(entity_type.logical_name, schema=schema, columns=[entity_type._entity_id])
ids = set(ef[entity_type._entity_id].unique())
entity_type.generate_dimension_data(entities=ids)

Dimensionsdaten simulieren

Sie können Dimensionen für einen Gerätetyp simulieren. Mit einem Python-Script ähnlich dem Folgenden können Sie Dimensionen und die zugehörigen Werte hinzufügen. Zufallswerte werden aus einem Wertebereich entnommen. Das Script umfasst die folgenden Schritte:

  1. Verbinden mit.
  2. Erstellen Sie ein Datenbankobjekt in der Datenbank.
  3. Fügen Sie neue Datenbankspalten für die Dimensionen und Zufallswerte hinzu.