UNPKG

@mindconnect/mindconnect-nodejs

Version:

NodeJS Library for Siemens Insights Hub Connectivity - TypeScript SDK for Insights Hub and Industrial IoT - Command Line Interface - Insights Hub Development Proxy (Siemens Insights Hub was formerly known as MindSphere)

251 lines 13.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const console_1 = require("console"); const fs = require("fs"); const sdk_1 = require("../../api/sdk"); const utils_1 = require("../../api/utils"); const command_utils_1 = require("./command-utils"); const ora = require("ora-classic"); let color = (0, command_utils_1.getColor)("magenta"); const yellow = (0, command_utils_1.getColor)("yellow"); exports.default = (program) => { program .command("prepare-bulk") .alias("pb") .option("-d, --dir <directoryname>", "config file with agent configuration", "bulkupload") .option("-w, --twintype <mode>", "twintype of asset [performance|simulation]") .option("-i, --assetid <assetid>", "mindsphere asset id ") .option("-t, --typeid <typeid>", "typeid e.g. castidev.Engine ") .option("-s, --size <size>", "entries per file ", "100") .option("-f, --files <files>", "generated files ", "2") .option("-o, --offset <days>", "offset in days from current date ", "0") .option("-y, --retry <number>", "retry attempts before giving up", "3") .option("-k, --passkey <passkey>", "passkey") .option("-v, --verbose", "verbose output") .description(color("creates a template directory for timeseries (bulk) upload *")) .action((options) => { (() => __awaiter(void 0, void 0, void 0, function* () { try { checkRequiredParamaters(options); const sdk = (0, command_utils_1.getSdk)(options); color = (0, command_utils_1.adjustColor)(color, options); (0, command_utils_1.homeDirLog)(options.verbose, color); (0, command_utils_1.proxyLog)(options.verbose, color); const path = makeCsvAndJsonDir(options); const { root, asset, aspects } = yield getAssetAndAspects(sdk, options); checkTwinTypeOfAsset(asset, options); const spinner = ora("generating data..."); !options.verbose && spinner.start(); for (const aspect of aspects) { createAspectDirs(path, aspect, options); // * The variables are stored in different spots depenendet if they come from the type or from the asset. const variables = aspect.variables || aspect.aspectType.variables || []; // * The csv generation generates data for every day for performance assets and every hour for simulation assets yield generateCsv({ name: aspect.name, variables: variables, options: options, path: path, mode: options.twintype, }, spinner); } options.typeid ? writeNewAssetJson(options, root, path, options.twintype) : fs.writeFileSync(`${path}/asset.json`, JSON.stringify(asset, null, 2)); !options.verbose && spinner.succeed("done."); (0, command_utils_1.directoryReadyLog)({ path: `${path}`, jobCommand: "check-bulk", runCommand: "run-bulk", }); options.twintype === sdk_1.AssetManagementModels.TwinType.Performance && options.offset < 7 && console.log(`\n${yellow("Warning!")} The data has to be older then 7 days for bulk upload of performance assets.\n`); } catch (err) { (0, command_utils_1.errorLog)(err, options.verbose); } }))(); }) .on("--help", () => { (0, console_1.log)("\n Examples:\n"); (0, console_1.log)(` mdsp prepare-bulk --typeid castidev.Engine \t this creates a directory called ${color("bulkimport")} for new asset of type castidev.Engine`); (0, console_1.log)(` mdsp pb --dir asset1 -i 123456...abc \t\t this creates a directory called ${color("asset1")} for existing asset`); (0, console_1.log)(` mdsp pb -of 3 -t castidev.Engine \t\t start data creation template 3 days before now`); (0, console_1.log)(`\n\tuse --mode ${color("performance")} for standard data generation or --mode ${color("simulation")} for high frequency data generation `); (0, console_1.log)(`\tThe typeid must be derived from ${color("core.basicdevice")} and asset ${color("twintype")} must be ${color("simulation")} for high frequency data upload\n`); }); }; function getAssetAndAspects(sdk, options) { return __awaiter(this, void 0, void 0, function* () { const assetMgmt = sdk.GetAssetManagementClient(); let aspects = []; let asset; if (options.assetid) { asset = yield assetMgmt.GetAsset(options.assetid); const embAspects = yield assetMgmt.GetAspects(options.assetid); if (embAspects._embedded && embAspects._embedded.aspects) { aspects = embAspects._embedded.aspects.filter((x) => { return x.category === sdk_1.AssetManagementModels.AspectResource.CategoryEnum.Dynamic; }); } } if (options.typeid) { const assetType = yield assetMgmt.GetAssetType(options.typeid, { exploded: true, }); if (assetType.aspects) { aspects = assetType.aspects.filter((x) => { return x.aspectType && x.aspectType.category === "dynamic"; }); } aspects = aspects || []; } const root = yield assetMgmt.GetRootAsset(); return { root, asset, aspects }; }); } function checkRequiredParamaters(options) { options.twintype !== "performance" && options.twintype !== "simulation" && (0, utils_1.throwError)("you have to specify the twin type performance or simulation"); !options.typeid && !options.assetid && (0, utils_1.throwError)("You have to specify either a typeid or assetid"); !!options.typeid === !!options.assetid && (0, utils_1.throwError)("You can't specify typeid and assetid at the same time"); (0, command_utils_1.verboseLog)(`creating directory template for: ${color(options.typeid || options.assetid)}`, options.verbose); options.assetid && (0, utils_1.checkAssetId)(options.assetid); (0, command_utils_1.verboseLog)(`creating directory: ${color(options.dir)}`, options.verbose); fs.existsSync(options.dir) && (0, utils_1.throwError)(`the directory ${color(options.dir)} already exists`); } const generateRandom = (() => { const variables = []; return (timestamp, type, variableName) => { !variables.includes(variableName) && variables.push(variableName); let result; // multiply the sine curves with factor to have every variable visible const factor = variables.indexOf(variableName) + 1; switch (type) { case sdk_1.AssetManagementModels.VariableDefinition.DataTypeEnum.DOUBLE: result = (Math.sin(timestamp.getTime()) * factor * 10).toFixed(2) + 20; break; case sdk_1.AssetManagementModels.VariableDefinition.DataTypeEnum.INT: case sdk_1.AssetManagementModels.VariableDefinition.DataTypeEnum.LONG: result = Math.floor(Math.sin(timestamp.getTime()) * factor * 20) + 40; break; case sdk_1.AssetManagementModels.VariableDefinition.DataTypeEnum.BOOLEAN: result = true; break; case sdk_1.AssetManagementModels.VariableDefinition.DataTypeEnum.STRING: case sdk_1.AssetManagementModels.VariableDefinition.DataTypeEnum.BIGSTRING: result = `${type}_${Math.random()}`; break; default: throw new Error(`invalid type ${type}`); } return result; }; })(); function generateCsv(_a, spinner_1) { return __awaiter(this, arguments, void 0, function* ({ name, variables, options, path, mode, }, spinner) { (0, command_utils_1.verboseLog)(`Generating ${options.size} entries for ${name}`, options.verbose, spinner); (0, command_utils_1.verboseLog)(`Asset TwinType: ${mode}`, options.verbose, spinner); const startDate = new Date(); startDate.setUTCDate(startDate.getUTCDate() - parseInt(options.offset)); for (let file = options.files; file > 0; file--) { const date = new Date(startDate); if (mode === sdk_1.AssetManagementModels.TwinType.Performance) { // * generate one file per day date.setUTCDate(date.getUTCDate() - (file - 1)); date.setUTCHours(0, 0, 0, 0); } else { // * generate one file per hour date.setUTCHours(file - 1, 0, 0, 0); } const fileName = `${path}/csv/${name}/${file}.csv`; (0, command_utils_1.verboseLog)(`generating: ${color(fileName)}`, options.verbose, spinner); const stream = fs.createWriteStream(fileName, { highWaterMark: 12 * 16384, }); let headers = `_time, `; variables.forEach((variable) => { headers += variable.name + ", "; if (variable.qualityCode) headers += variable.name + "_qc, "; }); stream.write(headers.trimRight().slice(0, -1) + "\n"); variables.forEach((variable) => { headers += variable.name + ", "; if (variable.qualityCode) headers += variable.name + "_qc, "; }); for (let index = options.size; index > 0; index--) { const currentDate = mode === sdk_1.AssetManagementModels.TwinType.Performance ? (0, command_utils_1.subtractSecond)(date, (86400 / options.size) * index) : (0, command_utils_1.subtractSecond)(date, (3600 / options.size) * index); let line = currentDate.toISOString() + ", "; variables.forEach((variable) => { line += generateRandom(currentDate, variable.dataType, `${variable.name}`) + ", "; if (variable.qualityCode) line += "0, "; }); const result = stream.write(line.trimRight().slice(0, -1) + "\n"); if (!result) { yield new Promise((resolve) => stream.once("drain", resolve)); } } stream.end(); } }); } function writeNewAssetJson(options, root, path, twintype) { const asset = { name: `${twintype}Asset`, twinType: twintype === "performance" ? sdk_1.AssetManagementModels.TwinType.Performance : sdk_1.AssetManagementModels.TwinType.Simulation, typeId: options.typeid, parentId: root.assetId, location: { country: "Germany", postalCode: "91052", region: "Bayern", streetAddress: "Schuhstr. 60", locality: "Erlangen", latitude: 49.59099, longitude: 11.00783, }, }; const newAssetJson = `${path}/asset.json`; (0, command_utils_1.verboseLog)(`Writing ${color(newAssetJson)}`, options.verbose); fs.writeFileSync(`${path}/asset.json`, JSON.stringify(asset, null, 2)); } function createAspectDirs(path, element, options) { const csvDir = `${path}/csv/${element.name}`; (0, command_utils_1.verboseLog)(`creating directory: ${color(csvDir)}`, options.verbose); fs.mkdirSync(csvDir); const jsonDir = `${path}/json/${element.name}`; (0, command_utils_1.verboseLog)(`creating directory: ${color(jsonDir)}`, options.verbose); fs.mkdirSync(jsonDir); } function makeCsvAndJsonDir(options) { const path = options.dir; fs.mkdirSync(path); fs.mkdirSync(`${path}/csv/`); fs.mkdirSync(`${path}/json/`); return path; } function checkTwinTypeOfAsset(asset, options) { asset && asset.twinType !== options.twintype && (0, utils_1.throwError)(`You can't use the twintype mode ${color(options.twintype)} for ${asset.twinType} asset`); } //# sourceMappingURL=iot-prepare-bulk-dir.js.map