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)

393 lines 21.7 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()); }); }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; Object.defineProperty(exports, "__esModule", { value: true }); const console_1 = require("console"); const fs = require("fs"); const path = require("path"); const __1 = require("../.."); const utils_1 = require("../../api/utils"); const command_utils_1 = require("./command-utils"); const ora = require("ora-classic"); const cyan = (0, command_utils_1.getColor)("cyan"); let color = (0, command_utils_1.getColor)("magenta"); exports.default = (program) => { program .command("configure-agent") .alias("co") .option("-c, --config <agentconfig>", "config file with agent configuration") .option("-m, --mode [mode]", "command mode [config|map|print|delete|test|func|template]", "config") .option("-a, --agentid <agentid>", "agentid") .option("-i, --assetid <assetid>", "target assetid for mapping") .option("-t, --typeid <typeid>", "asset type for configuration") .option("-l, --language [js|python|json]", "target language for conversion function", "js") .option("-s, --timespan <timespan>", "timespan between generated timestamps (in ms)", "1000") .option("-c, --count <count>", "Number of generated records", "10") .option("-k, --passkey <passkey>", "passkey") .option("-y, --retry <number>", "retry attempts before giving up", "3") .option("-v, --verbose", "verbose output") .description(`${cyan("create data source configuration and mappings")} ${color("(optional: passkey) *")}`) .action((options) => { (() => __awaiter(void 0, void 0, void 0, function* () { try { color = (0, command_utils_1.adjustColor)(color, options); (0, command_utils_1.homeDirLog)(options.verbose, color); (0, command_utils_1.proxyLog)(options.verbose, color); checkParameters(options); let agentid = options.agentid; let agent; const sdk = !options.config ? (() => { color = (0, command_utils_1.adjustColor)(color, options); return (0, command_utils_1.getSdk)(options); })() : (() => { color = cyan; const configFile = path.resolve(options.config); (0, command_utils_1.verboseLog)(`agent configuration in: ${color(configFile)}.`, options.verbose); !fs.existsSync(configFile) && (0, utils_1.throwError)(`Can't find file ${configFile}`); const agentFolder = (0, utils_1.getAgentDir)(path.dirname(options.config)); (0, command_utils_1.verboseLog)(`Using .mc folder for agent: ${color(agentFolder)}`, options.verbose); const configuration = require(configFile); agent = new __1.MindConnectAgent(configuration, undefined, agentFolder); agentid = agent.ClientId(); return new __1.MindSphereSdk(agent); })(); options.mode === "print" && (yield print(sdk, agentid, color, options)); options.mode === "print" && process.exit(0); options.mode === "func" && (yield printFunc(sdk, agentid, color, options)); options.mode === "func" && process.exit(0); options.mode === "config" && (yield config(sdk, agentid, color, options)); options.mode === "delete" && (yield deleteMappings(sdk, agentid, color, options)); options.mode === "map" && (yield map(sdk, agentid, color, options)); options.mode === "template" && (yield template(sdk, agentid, color, options)); options.mode === "template" && process.exit(0); options.mode === "test" && (yield inject(agent, color, options)); options.mode !== "test" && (yield print(sdk, agentid, color, options)); (0, command_utils_1.agentConfigLog)({ gateway: sdk.GetGateway(), host: options.passkey ? "gateway" : "southgate", tenant: sdk.GetTenant(), agentid: agentid, color: color, }); } catch (err) { (0, command_utils_1.errorLog)(err, options.verbose); } }))(); }) .on("--help", () => { (0, console_1.log)("\n Examples:\n"); (0, console_1.log)(` mdsp configure-agent --config agent.json -assetid 1234567...89 \tconfigures agent for specified assetid`); (0, console_1.log)(` mdsp configure-agent --config agent.json --mode print \t\tprints data source configuration and mappings`); (0, console_1.log)(` mdsp configure-agent --agentid 12345..ef --typeid <tenant>.Engine \tcreates the data source configuration`); (0, console_1.log)(` mdsp configure-agent --mode map --agentid 12345..ef --assetid 1234567 creates the mappings for assetid`); (0, console_1.log)(` mdsp configure-agent --mode delete --agentid 12345..ef \t\tdeletes the mappings for agentid`); (0, console_1.log)(` mdsp configure-agent --config agent.json --mode test \t\t\tsends test data to mindsphere`); (0, console_1.log)(` mdsp configure-agent --mode template \\`); (0, console_1.log)(` \t--typeid castidev.Pump --language python \t\t\tcreate mapping template and function in python`); }); }; function template(sdk, agentid, color, options) { return __awaiter(this, void 0, void 0, function* () { const assetType = yield sdk.GetAssetManagementClient().GetAssetType(options.typeid); const dataSourceConfig = yield sdk.GetMindConnectApiClient().GenerateDataSourceConfiguration(assetType); const dataSourceMappings = yield sdk .GetMindConnectApiClient() .GenerateMappings(dataSourceConfig, options.agentid || "<externalid>", options.assetid || "<assetid>"); fs.writeFileSync(`${options.typeid}.mapping.mdsp.json`, JSON.stringify(dataSourceMappings, null, 2)); console.log(`The file ${color(`${options.typeid}.mapping.mdsp.json`)} with mapping template was created.`); printFunc(sdk, dataSourceConfig, color, options); }); } function map(sdk, agentid, color, options) { return __awaiter(this, void 0, void 0, function* () { var _a, e_1, _b, _c; const spinner = ora(color("Creating mappings...")); !options.verbose && spinner.start(""); const configuration = yield sdk.GetAgentManagementClient().GetDataSourceConfiguration(agentid); const generateMappings = yield sdk .GetMindConnectApiClient() .GenerateMappings(configuration, agentid, options.assetid); let i = 0; try { for (var _d = true, generateMappings_1 = __asyncValues(generateMappings), generateMappings_1_1; generateMappings_1_1 = yield generateMappings_1.next(), _a = generateMappings_1_1.done, !_a; _d = true) { _c = generateMappings_1_1.value; _d = false; const mapping = _c; const result = yield sdk.GetMindConnectApiClient().PostDataPointMapping(mapping, { ignoreCodes: [409] }); (0, command_utils_1.verboseLog)(`[${color(i++)}] ${mapping.dataPointId}-->${mapping.propertyName} ${mapping.propertySetName} (${mapping.entityId}) ${color(result ? "created" : "already existing")}`, options.verbose, spinner); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_d && !_a && (_b = generateMappings_1.return)) yield _b.call(generateMappings_1); } finally { if (e_1) throw e_1.error; } } spinner.stop(); }); } function deleteMappings(sdk, agentid, color, options) { return __awaiter(this, void 0, void 0, function* () { var _a, e_2, _b, _c; const filter = { agentId: agentid }; if (options.assetid) { filter.entityId = options.assetid; } const mappings = yield sdk .GetMindConnectApiClient() .GetDataPointMappings({ filter: JSON.stringify(filter), size: 2000 }); try { for (var _d = true, _e = __asyncValues(mappings.content), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; const mapping = _c; yield sdk.GetMindConnectApiClient().DeleteDataMapping(mapping.id, { ignoreCodes: [404] }); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (!_d && !_a && (_b = _e.return)) yield _b.call(_e); } finally { if (e_2) throw e_2.error; } } }); } function print(sdk, agentid, color, options) { return __awaiter(this, void 0, void 0, function* () { const configuration = yield sdk.GetAgentManagementClient().GetDataSourceConfiguration(agentid); const mappings = yield sdk .GetMindConnectApiClient() .GetDataPointMappings({ filter: JSON.stringify({ agentId: agentid }), size: 2000 }); console.log(`Configuration for ${color(agentid)} ${color(configuration.configurationId)} eTag: ${configuration.eTag}`); console.log(`Data Sources (${color(configuration.dataSources.length)}) :`); configuration.dataSources.forEach((element) => { console.log(` - ${color(element.name)} (${color(element.dataPoints.length)})`); element.dataPoints.forEach((dataPoint) => { console.log(`\t - ${color(dataPoint.id)} ${dataPoint.name} (${color(dataPoint.type)}) ${dataPoint.unit}`); }); }); console.log(`Mappings count: ${color(mappings.content.length)}`); let i = 0; mappings.content.forEach((mapping) => { console.log(`\t - [${color(i++)}] ${mapping.dataPointId}-->${mapping.propertyName} ${mapping.propertySetName} (${mapping.entityId}) `); }); (0, command_utils_1.verboseLog)(JSON.stringify(configuration, null, 2), options.verbose); (0, command_utils_1.verboseLog)(JSON.stringify(mappings, null, 2), options.verbose); }); } function printFunc(sdk, agentOrConfig, color, options) { return __awaiter(this, void 0, void 0, function* () { let configuration = agentOrConfig; if (typeof agentOrConfig === "string") { configuration = yield sdk.GetAgentManagementClient().GetDataSourceConfiguration(agentOrConfig); } switch (options.language) { case "js": yield printFuncJs(configuration, color, options); break; case "python": yield printFuncPython(configuration, color, options); break; case "json": yield printFuncJson(configuration, color, options); break; default: (0, utils_1.throwError)(`invalid language ${options.language}`); } }); } function printFuncJson(configuration, color, options) { return __awaiter(this, void 0, void 0, function* () { const result = { mappings: [], }; configuration.dataSources.forEach((element) => { if (!element.customData) { throw Error("cant create function there is no custom data avaiable, the config was not done via CLI"); } element.dataPoints.forEach((dataPoint) => { if (!dataPoint.customData) { throw Error("cant create function there is no custom data avaiable, the config was not done via CLI"); } result.mappings.push({ aspect: `${element.customData.aspect}`, variable: `${dataPoint.customData.variable}`, dataPointId: `${dataPoint.id}`, }); }); }); fs.writeFileSync(`${options.typeid}.fulltable.mdsp.json`, JSON.stringify(result, null, 2)); console.log(`The file ${color(`${options.typeid}.fulltable.mdsp.json`)} with full JSON mapping table was created.`); (0, command_utils_1.verboseLog)(result, options.verbose); }); } function printFuncJs(configuration, color, options) { return __awaiter(this, void 0, void 0, function* () { let result = ""; result += "\nfunction convertToDataPoint (rawVariable, aspect) {"; result += "\n let variable = rawVariable;"; result += "\n variable = variable.replace(' ', '_');"; result += "\n variable = variable.replace('-', '_');"; result += "\n variable = variable.replace(/[\\W_]/g, '_');"; result += "\n variable = variable.trim();"; result += "\n variable = variable.replace(/^[_]/, '');"; configuration.dataSources.forEach((element) => { if (!element.customData) { throw Error("cant create function there is no custom data avaiable, the config was not done via CLI"); } result += `\n if (aspect === '${element.customData.aspect}') { `; element.dataPoints.forEach((dataPoint) => { if (!dataPoint.customData) { throw Error("cant create function there is no custom data avaiable, the config was not done via CLI"); } if (dataPoint.id !== `DP-${dataPoint.customData.variable}`) { result += `\n if (variable === '${dataPoint.customData.variable}') return '${dataPoint.id}';`; } }); result += `\n return \`DP-\${variable}\`;`; result += `\n }`; }); result += "\n}"; fs.writeFileSync(`${options.typeid}.map.mdsp.js`, result); console.log(`The file ${color(`${options.typeid}.map.mdsp.js`)} with mapping function was created.`); (0, command_utils_1.verboseLog)(result, options.verbose); }); } function printFuncPython(configuration, color, options) { return __awaiter(this, void 0, void 0, function* () { let result = "import re\n"; result += "\ndef convertToDataPoint (rawVariable, aspect):"; result += "\n\tvariable = rawVariable"; result += "\n\tvariable = variable.replace(' ', '_')"; result += "\n\tvariable = variable.replace('-', '_')"; result += "\n\tvariable = re.sub(r'[\\W_]', '_', variable)"; result += "\n\tvariable = variable.strip()"; result += "\n\tvariable = re.sub(r'^[_]', '', variable)"; configuration.dataSources.forEach((element) => { if (!element.customData) { throw Error("cant create function there is no custom data avaiable, the config was not done via CLI"); } result += `\n\tif aspect == '${element.customData.aspect}': `; element.dataPoints.forEach((dataPoint) => { if (!dataPoint.customData) { throw Error("cant create function there is no custom data avaiable, the config was not done via CLI"); } if (dataPoint.id !== `DP-${dataPoint.customData.variable}`) { result += `\n\t\tif variable == '${dataPoint.customData.variable}': return '${dataPoint.id}'`; } }); result += `\n\t\treturn "DP-" + variable`; result += `\n`; }); result += "\n"; fs.writeFileSync(`${options.typeid}.map.mdsp.py`, result); console.log(`The file ${color(`${options.typeid}.map.mdsp.py`)} with mapping function was created.`); (0, command_utils_1.verboseLog)(result, options.verbose); }); } function config(sdk, agentid, color, options) { return __awaiter(this, void 0, void 0, function* () { let assettypeid = options.typeid; if (options.assetid) { const asset = sdk.GetAssetManagementClient().GetAsset(options.assetid); assettypeid = (yield asset).typeId; } const assetType = yield sdk.GetAssetManagementClient().GetAssetType(assettypeid, { exploded: true }); const mcapi = sdk.GetMindConnectApiClient(); const dataSourceConfiguration = mcapi.GenerateDataSourceConfiguration(assetType); const oldConfig = sdk.GetAgentManagementClient().GetDataSourceConfiguration(agentid); const etag = (yield oldConfig).eTag || "0"; yield sdk .GetAgentManagementClient() .PutDataSourceConfiguration(agentid, dataSourceConfiguration, { ifMatch: etag }); options.assetid && (yield map(sdk, agentid, color, options)); }); } function checkParameters(options) { ["map", "config", "print", "delete", "test", "func", "template"].indexOf(options.mode) < 0 && (0, utils_1.throwError)("The mode must be map | configure | print | delete | test | func | template"); options.passkey && options.mode === "test" && (0, utils_1.throwError)("test only works with agent configuration not with passkey"); options.passkey && !options.agentid && (0, utils_1.throwError)("you have to specify agentid when using passkey mode"); options.mode === "config" && !((options.assetid && !options.typeid) || (!options.assetid && options.typeid)) && (0, utils_1.throwError)("you have to specify either assetid or typeid for config mode but not both"); options.mode === "test" && !(options.timespan && options.count) && (0, utils_1.throwError)("you have to specify the timespan and the count"); options.mode === "template" && !options.typeid && (0, utils_1.throwError)("you have to specify the typeid to generate mapping templates"); (options.mode === "template" || options.mode === "func") && ["js", "json", "python"].indexOf(options.language) < 0 && (0, utils_1.throwError)("the language has to be either js, json or python"); ["map"].indexOf(options.mode) >= 0 && !options.assetid && (0, utils_1.throwError)(`you have to specify assetid for ${options.mode}`); } function inject(agent, color, options) { return __awaiter(this, void 0, void 0, function* () { const configuration = yield agent.GetDataSourceConfiguration(); const bulkData = []; const span = parseInt(options.timespan); const count = parseInt(options.count); let dataPointsCount = 0; let startTime = new Date().getTime() - span * count; for (let index = 0; index < options.count; index++) { const data = []; const timeStamp = new Date(startTime); configuration.dataSources.forEach((datasource) => { datasource.dataPoints.forEach((dp) => { data.push({ dataPointId: dp.id, qualityCode: "0", value: generateValue(dp.type.toString(), timeStamp), }); dataPointsCount++; }); }); bulkData.push({ timestamp: timeStamp.toISOString(), values: data }); startTime += parseInt(options.timespan); } (0, command_utils_1.verboseLog)(JSON.stringify(bulkData, null, 2), options.verbose); yield (0, utils_1.retry)(options.retry, () => agent.BulkPostData(bulkData)); console.log(`Injected a bulk message with ${color(count)} timestamps and total number of ${color(dataPointsCount)} datapoints.`); }); } function generateValue(type, timeStamp) { let result = 100 * Math.sin(timeStamp.getTime()); if (type === "INT" || type === "LONG") { result = Math.floor(result); } else if (type === "TIMESTAMP") { result = new Date().toISOString(); } else if (type === "BOOLEAN") { result = Math.floor(result) % 2 === 0; } else if (type === "STRING" || type === "BIG_STRING") { result = `${type}_${result}`; } return result.toString(); } //# sourceMappingURL=mc-automap.js.map