Fixing the xetics lean adapter
This commit is contained in:
parent
c96a2785c9
commit
e3a2f9f921
1
modules/xetics-lean-connector/.gitignore
vendored
Normal file
1
modules/xetics-lean-connector/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
generated
|
13
modules/xetics-lean-connector/README.md
Normal file
13
modules/xetics-lean-connector/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Xetics LEAN Connector
|
||||
|
||||
A Connector for *Xetics Lean*. The Xetics API is provided via [SWAGGER](https://swagger.io/). You can read the current API [here](http://dz-062-vl-docker:8089/swagger-ui.html).
|
||||
|
||||
This Library will create a Client based on the available Swagger-Definition.
|
||||
|
||||
# Update the Client
|
||||
|
||||
1. To Update the Client-Interface, the Typescript code has to be compiled to JS code. (Use the `compile.bat` in the `root`-Directory)
|
||||
2. Generate new Interfaces by executing etc: `node .\dist\modules\ZISS-Xetics-Lean-Connector\helper\generate.code.js`
|
||||
3. Update the Functions provided in:
|
||||
- `src\xetics.client`
|
||||
- etc
|
2
modules/xetics-lean-connector/defaults/default.params.ts
Normal file
2
modules/xetics-lean-connector/defaults/default.params.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const DEFAULT_TOKEN = 'Basic YXBpdXNlcjpkR1E2amdEc0ZKN21aaHZnM0FZZg==';
|
||||
export const DEFAULT_URI = 'http://10.10.13.31/release';
|
115
modules/xetics-lean-connector/helper/generate.code.ts
Normal file
115
modules/xetics-lean-connector/helper/generate.code.ts
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @author Martin Karkowski
|
||||
* @email m.karkowski@zema.de
|
||||
* @create date 2020-02-18 16:28:19
|
||||
* @modify date 2020-11-11 12:40:41
|
||||
* @desc [description]
|
||||
*/
|
||||
|
||||
import { get } from 'http';
|
||||
import { TsFromSwagger } from 'swagger-ts-client';
|
||||
import { camelize, replaceAll } from '../../../lib/helpers/stringMethods';
|
||||
import { DEFAULT_URI } from '../defaults/default.params';
|
||||
|
||||
/**
|
||||
* Hack to Fix the Swagger Definition.
|
||||
*
|
||||
* To fix the Broken Swagger Definition. Download the Definition File.
|
||||
* Then Replace the broken chars and parse it as JSON.
|
||||
*
|
||||
*/
|
||||
get(DEFAULT_URI+'/v2/api-docs', (res) => {
|
||||
const { statusCode } = res;
|
||||
const contentType = res.headers['content-type'];
|
||||
|
||||
let error;
|
||||
if (statusCode !== 200) {
|
||||
error = new Error('Request Failed.\n' +
|
||||
`Status Code: ${statusCode}`);
|
||||
} else if (!/^application\/json/.test(contentType)) {
|
||||
error = new Error('Invalid content-type.\n' +
|
||||
`Expected application/json but received ${contentType}`);
|
||||
}
|
||||
if (error) {
|
||||
console.error(error.message);
|
||||
// Consume response data to free up memory
|
||||
res.resume();
|
||||
return;
|
||||
}
|
||||
|
||||
res.setEncoding('utf8');
|
||||
let rawData = '';
|
||||
res.on('data', (chunk) => { rawData += chunk; });
|
||||
res.on('end', () => {
|
||||
try {
|
||||
|
||||
rawData = replaceAll(rawData, '«', '<')
|
||||
rawData = replaceAll(rawData, '»', '>')
|
||||
|
||||
const settings = {
|
||||
|
||||
swaggerProvider: {
|
||||
// Function to Return all Elements
|
||||
provide: () => JSON.parse(rawData)
|
||||
},
|
||||
|
||||
type: {
|
||||
outPutPath: "./modules/xetics-lean-connector/generated/interfaces.ts",
|
||||
generatedTypes: 'interface',
|
||||
templateFile: './modules/xetics-lean-connector/helper/typeDefinitions.handlebars',
|
||||
membersOptional: true
|
||||
},
|
||||
operations: {
|
||||
outPutPath: "./modules/xetics-lean-connector/generated/clients",
|
||||
operationsNameTransformFn(name: string, httpVerb, operation) {
|
||||
let adaptedName = name;
|
||||
if (name.split('/').length > 1) {
|
||||
adaptedName = name.split('/').slice(3).join('/');
|
||||
}
|
||||
adaptedName = replaceAll(adaptedName, '-', '_');
|
||||
adaptedName = replaceAll(adaptedName, '{', 'by_');
|
||||
adaptedName = replaceAll(adaptedName, '}', '');
|
||||
// adaptedName = adaptedName.replace(/\{\w*}/g, '');
|
||||
adaptedName = replaceAll(adaptedName, '/', '_');
|
||||
|
||||
return camelize(httpVerb + '_' + adaptedName);
|
||||
},
|
||||
operationsGroupNameTransformFn(name: string, httpVerb, operation) {
|
||||
let adaptedName = operation.tags[0];
|
||||
return camelize(adaptedName, '-');
|
||||
},
|
||||
templateFile: './modules/xetics-lean-connector/helper/node-rest-client.handlebars',
|
||||
},
|
||||
templateHelpers: {
|
||||
updateURL: function (context, ...options) {
|
||||
if (context && typeof (context) === "string") {
|
||||
console.log(context)
|
||||
return replaceAll(context, '{', '${');
|
||||
}
|
||||
else {
|
||||
return ""
|
||||
}
|
||||
|
||||
},
|
||||
getDoku: function (context, ...options) {
|
||||
if (context && typeof (context) === "string") {
|
||||
return 'LINK';
|
||||
}
|
||||
else {
|
||||
return ""
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const app = new TsFromSwagger(null, settings);
|
||||
app.generateCode();
|
||||
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
}
|
||||
});
|
||||
}).on('error', (e) => {
|
||||
console.error(`Got error: ${e.message}`);
|
||||
});
|
@ -0,0 +1,85 @@
|
||||
// Import the Node-Rest-Client Library
|
||||
import { Client } from 'node-rest-client';
|
||||
import { getNopeLogger } from '../../../../lib/logger/getLogger';
|
||||
|
||||
{{#if imports.types}}
|
||||
import { {{#joinList imports.types}}{{this}}{{/joinList}} } from "{{imports.path}}"
|
||||
{{/if}}
|
||||
|
||||
{{#if tag}}
|
||||
{{#each tag}}
|
||||
{{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
export class {{operationGroup.operationsGroupName}} {
|
||||
|
||||
// Default URI which will be used to combine the Requests
|
||||
public uri = '';
|
||||
public token = '';
|
||||
public client = new Client();
|
||||
protected _logger = getNopeLogger('xetics.{{operationGroup.operationsGroupName}}');
|
||||
|
||||
|
||||
{{#each operationGroup.operations}}
|
||||
// Checkout the Original Link at {{getDoku operationName}}
|
||||
public {{operationName}}({{#joinList operationParams}} {{paramDisplayName}}?:{{paramType}} {{/joinList}}):Promise<{{responsesType}}>{
|
||||
const _this = this;
|
||||
// Define the Parameters and Path Object
|
||||
let _data: any = {};
|
||||
const _path: any = {};
|
||||
|
||||
{{#if operationParams}}
|
||||
{{!-- {{#each operationParams}}
|
||||
///////////////////////////////////////////
|
||||
// OP =>
|
||||
// Inbody: {{this.inBody}}
|
||||
// InPath: {{this.inPath}}
|
||||
// Parameter-Name: {{paramName}}
|
||||
// Display-Name: {{paramDisplayName}}
|
||||
{{/each}} --}}
|
||||
{{!-- Update Path Variable --}}
|
||||
{{#some operationParams "op=>(!op.inBody)"}}
|
||||
// Path Variables
|
||||
{{#joinList this "\n" "op=>(!op.inBody)"}}
|
||||
_path["{{paramName}}"] = {{paramDisplayName}};{{/joinList}}
|
||||
{{/some}}
|
||||
|
||||
{{!-- Update Parameter --}}
|
||||
{{#some operationParams "op=>(op.inBody && !op.inPath)"}}
|
||||
// Update Parameters
|
||||
_data = Object.assign({},{{#joinList this "\n" "op=>(op.inBody && !op.inPath)"}}{{paramDisplayName}}{{#unless @last}},{{/unless}}{{/joinList}});
|
||||
{{/some}}
|
||||
{{/if}}
|
||||
|
||||
// Define the Callback
|
||||
return new Promise<{{responsesType}}>((resolve, reject) => {
|
||||
this.client.{{httpVerb}}(this.uri+`{{updateURL url}}`{{#some operationParams "op=>(!op.inBody && !op.inPath)"}}{{#joinList this " " "op=>(!op.inBody && !op.inPath)"}}+ ({{paramDisplayName}} !== undefined ? `?{{paramDisplayName}}=${ {{paramDisplayName}} }` : ''){{/joinList}}{{/some}},{
|
||||
data: _data,
|
||||
headers: this.token ? {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': this.token
|
||||
|
||||
} : {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
path: _path,
|
||||
}, function(data, response) {
|
||||
{{!-- console.log(data,response) --}}
|
||||
if (response.statusCode !== 200) {
|
||||
_this._logger.error('rest-error: ' + response.statusCode);
|
||||
const error = new Error('Failed with '+ response.statusCode);
|
||||
reject(error);
|
||||
} else {
|
||||
if (_this._logger.isDebugEnabled()) {
|
||||
_this._logger.debug('request {{operationGroup.operationsGroupName}}.{{operationName}} sucessfull');
|
||||
}
|
||||
resolve(data as {{responsesType}});
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{{/each}}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
// Import the Node-Rest-Client Library
|
||||
const request = require('superagent');
|
||||
|
||||
{{#if imports.types}}
|
||||
import { {{#joinList imports.types}}{{this}}{{/joinList}} } from "{{imports.path}}"
|
||||
{{/if}}
|
||||
|
||||
{{#if tag}}
|
||||
{{#each tag}}
|
||||
{{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
export class {{operationGroup.operationsGroupName}} {
|
||||
|
||||
// Default URI which will be used to combine the Requests
|
||||
public uri = '';
|
||||
public token = '';
|
||||
|
||||
|
||||
|
||||
{{#each operationGroup.operations}}
|
||||
public {{operationName}}({{#joinList operationParams}} {{paramDisplayName}}:{{paramType}} {{/joinList}}):Promise<{{responsesType}}>{
|
||||
{{#if operationParams}}
|
||||
{{#some operationParams "op=>(!op.inBody && !op.inPath)"}}
|
||||
const params = {
|
||||
{{#joinList this ",\n" "op=>(!op.inBody && !op.inPath)"}}
|
||||
"{{paramName}}":{{paramDisplayName}}{{/joinList}}
|
||||
};
|
||||
{{/some}}
|
||||
{{/if}}
|
||||
|
||||
// Define the Callback
|
||||
return new Promise<{{responsesType}}>((resolve, reject) => {
|
||||
request
|
||||
.{{httpVerb}}(this.uri+'{{updateURL url}}'{{#some operationParams "op=>(!op.inBody && !op.inPath)"}}{{#joinList this " " "op=>(!op.inBody && !op.inPath)"}}+ ({{paramDisplayName}} ? '?{{paramDisplayName}}=${ {{paramDisplayName}} }' : ''){{/joinList}}{{/some}})
|
||||
{{#some operationParams "op=>(!op.inBody && !op.inPath)"}}
|
||||
.query(params)
|
||||
{{/some}}
|
||||
.set('Authorization', this.token)
|
||||
{{#filterList operationParams "op=>op.inBody" "1"}}
|
||||
.send({{paramDisplayName}})
|
||||
{{/filterList}}
|
||||
.end(function(error, res){
|
||||
if(error){
|
||||
reject(error);
|
||||
}else{
|
||||
resolve(res.body as {{responsesType}});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{{/each}}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
/*****************************AutoGenerated Code : Do not edit *******************************/
|
||||
// Type generated from Swagger definition
|
||||
|
||||
{{#if tag}}
|
||||
{{#each tag}}
|
||||
{{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
{{#each types}}
|
||||
export {{../generatedTypes}} {{swaggerTypeName}} {
|
||||
{{#each properties}}
|
||||
{{propertyName}}{{../../membersOptional}} : {{typeName}}
|
||||
{{/each}}
|
||||
}
|
||||
{{/each}}
|
400
modules/xetics-lean-connector/src/xetics.functions.ts
Normal file
400
modules/xetics-lean-connector/src/xetics.functions.ts
Normal file
@ -0,0 +1,400 @@
|
||||
/**
|
||||
* @author Martin Karkowski
|
||||
* @email m.karkowski@zema.de
|
||||
* @create date 2020-02-18 13:50:49
|
||||
* @modify date 2020-11-11 13:32:07
|
||||
* @desc [description]
|
||||
*/
|
||||
|
||||
import { map } from 'async';
|
||||
import { exportFunctionToDispatcher } from '../../../lib/decorators/dispatcherDecorators';
|
||||
import { deepClone, keepPropertiesOfObject } from '../../../lib/helpers/objectMethods';
|
||||
import { DEFAULT_TOKEN, DEFAULT_URI } from '../defaults/default.params';
|
||||
import { equipmentController } from '../generated/clients/equipmentController';
|
||||
import { jobController } from '../generated/clients/jobController';
|
||||
import { productStepController } from '../generated/clients/productStepController';
|
||||
import { trackingStationController } from '../generated/clients/trackingStationController';
|
||||
import { JobDTO, QualityParameterDTO, TraceabilityParameterDTO } from '../generated/interfaces';
|
||||
|
||||
/**
|
||||
* Function to getthe Task for a Station of the Xetics MES system.
|
||||
* @param station The Name of the Station or the ID
|
||||
* @param uri The URI of the Xetics System
|
||||
* @param token The API Token to grand access
|
||||
*/
|
||||
export const getTasksFromMES = exportFunctionToDispatcher(_getTasksFromMES, {
|
||||
id: 'getTasksFromMES'
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to get a currently active task of a Station.
|
||||
*
|
||||
* @param station The Name of the Station or the ID
|
||||
* @param uri The URI of the Xetics System
|
||||
* @param token The API Token to grand access
|
||||
*/
|
||||
export const getActiveTasksFromMES = exportFunctionToDispatcher(_getActivesTaskFromMES, {
|
||||
id: 'getActiveTasksFromMES'
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to Start a Task
|
||||
* @param station The Name or ID of the Statio, which should be used
|
||||
* @param jobId The ID of the Job
|
||||
* @param userId The User which should be used to mark the Job as Started
|
||||
* @param uri The URI of Xetics
|
||||
* @param token The API Token to access the API
|
||||
*/
|
||||
export const startTask = exportFunctionToDispatcher(_startTask, {
|
||||
id: 'startTask'
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to Mark a Task as finished.
|
||||
* @param station The Station (Name or ID)
|
||||
* @param jobId The ID of the Job
|
||||
* @param userId The User which will be used to finish the Task
|
||||
* @param qualityParameters Quality Parameters that should be returend
|
||||
* @param traceabilityParameters Additional Parameters to trace the Parameters
|
||||
* @param uri The URI of Xetics
|
||||
* @param token The API Token to access the API
|
||||
*/
|
||||
export const finishTask = exportFunctionToDispatcher(_finishTask, {
|
||||
id: 'finishTask'
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to getthe Task for a Station of the Xetics MES system.
|
||||
* @param station The Name of the Station or the ID
|
||||
* @param uri The URI of the Xetics System
|
||||
* @param token The API Token to grand access
|
||||
*/
|
||||
async function _getTasksFromMES(station: string | number, all = true, uri = DEFAULT_URI, token = DEFAULT_TOKEN) {
|
||||
|
||||
const _jobController = new jobController();
|
||||
const _trackingStationController = new trackingStationController();
|
||||
const _equipmentController = new equipmentController();
|
||||
const _productStepController = new productStepController();
|
||||
|
||||
const controllers = [
|
||||
_jobController,
|
||||
_trackingStationController,
|
||||
_equipmentController,
|
||||
_productStepController
|
||||
]
|
||||
|
||||
for (const controller of controllers){
|
||||
controller.uri = uri;
|
||||
controller.token = token;
|
||||
}
|
||||
|
||||
const propertiesToKeep = {
|
||||
'operation': () => '',
|
||||
'name': () => '',
|
||||
'id': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'lotId': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'productionOrderId': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'productionOrderName': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'productId': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'productName': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'qualityParameters': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'traceabilityParameters': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'consumptions': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'parameters': () => {
|
||||
throw Error('Item must be provided')
|
||||
}
|
||||
}
|
||||
|
||||
let stationId = -1;
|
||||
if (typeof station === 'string') {
|
||||
// Get the Equipment
|
||||
stationId = (await _equipmentController.getEquipment(undefined, undefined, station)).id;
|
||||
} else {
|
||||
stationId = station;
|
||||
}
|
||||
|
||||
// Get the Active Jobs for the Equipment
|
||||
const jobs = await _trackingStationController.getStationsByStationIdWaitingJobs(undefined, undefined, undefined, !all, undefined, undefined, stationId);
|
||||
|
||||
const jobsWithParmas: Array<JobDTO & {
|
||||
parameters: {
|
||||
[index: string]: any;
|
||||
};
|
||||
operation: string
|
||||
}> = await map(jobs, async (job: JobDTO) => {
|
||||
|
||||
const parameterList= await _jobController.getJobsByJobIdProcessParameters(job.id);
|
||||
const productStepDefinition = await _productStepController.getDtosProductstepdetailById(job.productStepId);
|
||||
|
||||
const parameters: { [index: string]: any } = {};
|
||||
|
||||
for (const parameter of parameterList) {
|
||||
parameters[parameter.name] = parameter.processValue;
|
||||
}
|
||||
|
||||
// Simplify The Object.
|
||||
return keepPropertiesOfObject(Object.assign(job, { parameters, operation: productStepDefinition.step.name }), propertiesToKeep)
|
||||
})
|
||||
|
||||
const textClass = '.ProcessParameterText';
|
||||
|
||||
const extractorDict = {
|
||||
'.ProcessParameterText': 'parameterValue',
|
||||
'.ProcessParameterFloat': 'parameterValue',
|
||||
'.SelectProcessParameter': 'selectedValues',
|
||||
'.RangeProcessParameter': 'parameterValue',
|
||||
};
|
||||
|
||||
const validClasses = Object.getOwnPropertyNames(extractorDict);
|
||||
|
||||
|
||||
for (const job of jobsWithParmas) {
|
||||
if (job.parameters) {
|
||||
const orgParams = deepClone(job.parameters);
|
||||
const params = {};
|
||||
for (const attr in orgParams) {
|
||||
const item = orgParams[attr];
|
||||
if (validClasses.includes(item['@class'])) {
|
||||
if (item['@class'] === textClass) {
|
||||
try {
|
||||
params[attr] = JSON.parse(item.value);
|
||||
} catch (e) {
|
||||
}
|
||||
} else {
|
||||
params[attr] = item[extractorDict[item['@class']]]
|
||||
}
|
||||
}
|
||||
}
|
||||
// Overwrite the Parameters
|
||||
job.parameters = params;
|
||||
}
|
||||
}
|
||||
|
||||
return jobsWithParmas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get a currently active task of a Station.
|
||||
*
|
||||
* @param station The Name of the Station or the ID
|
||||
* @param uri The URI of the Xetics System
|
||||
* @param token The API Token to grand access
|
||||
*/
|
||||
async function _getActivesTaskFromMES(station: string | number, all=true, uri = DEFAULT_URI, token = DEFAULT_TOKEN) {
|
||||
|
||||
const _jobController = new jobController();
|
||||
const _trackingStationController = new trackingStationController();
|
||||
const _equipmentController = new equipmentController();
|
||||
const _productStepController = new productStepController();
|
||||
|
||||
const controllers = [
|
||||
_jobController,
|
||||
_trackingStationController,
|
||||
_equipmentController,
|
||||
_productStepController
|
||||
]
|
||||
|
||||
for (const controller of controllers){
|
||||
controller.uri = uri;
|
||||
controller.token = token;
|
||||
}
|
||||
|
||||
const propertiesToKeep = {
|
||||
'operation': () => '',
|
||||
'name': () => '',
|
||||
'id': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'lotId': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'productionOrderId': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'productionOrderName': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'productId': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'productName': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'qualityParameters': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'traceabilityParameters': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'consumptions': () => {
|
||||
throw Error('Item must be provided')
|
||||
},
|
||||
'parameters': () => {
|
||||
throw Error('Item must be provided')
|
||||
}
|
||||
}
|
||||
|
||||
let stationId = -1;
|
||||
if (typeof station === 'string') {
|
||||
// Get the Equipment
|
||||
stationId = (await _equipmentController.getEquipment(undefined, undefined, station)).id;
|
||||
} else {
|
||||
stationId = station;
|
||||
}
|
||||
|
||||
// Get the Active Jobs for the Equipment
|
||||
const jobs = await _trackingStationController.getStationsByStationIdProcessingJobs(undefined, undefined, undefined, !all, undefined, undefined, stationId);
|
||||
|
||||
const jobsWithParmas: Array<JobDTO & {
|
||||
parameters: {
|
||||
[index: string]: any;
|
||||
};
|
||||
operation: string
|
||||
}> = await map(jobs, async (job: JobDTO) => {
|
||||
|
||||
const parameterList= await _jobController.getJobsByJobIdProcessParameters(job.id);
|
||||
const productStepDefinition = await _productStepController.getDtosProductstepdetailById((await _jobController.getJobsByJobId(job.id)).productStepId);
|
||||
|
||||
const parameters: { [index: string]: any } = {};
|
||||
|
||||
for (const parameter of parameterList) {
|
||||
parameters[parameter.name] = parameter.processValue;
|
||||
}
|
||||
|
||||
// Simplify The Object.
|
||||
return keepPropertiesOfObject(Object.assign(job, { parameters, operation: productStepDefinition.step.name }), propertiesToKeep)
|
||||
})
|
||||
|
||||
const textClass = '.ProcessParameterText';
|
||||
|
||||
const extractorDict = {
|
||||
'.ProcessParameterText': 'parameterValue',
|
||||
'.ProcessParameterFloat': 'parameterValue',
|
||||
'.SelectProcessParameter': 'selectedValues',
|
||||
'.RangeProcessParameter': 'parameterValue',
|
||||
};
|
||||
|
||||
const validClasses = Object.getOwnPropertyNames(extractorDict);
|
||||
|
||||
|
||||
for (const job of jobsWithParmas) {
|
||||
if (job.parameters) {
|
||||
const orgParams = deepClone(job.parameters);
|
||||
const params = {};
|
||||
for (const attr in orgParams) {
|
||||
const item = orgParams[attr];
|
||||
if (validClasses.includes(item['@class'])) {
|
||||
if (item['@class'] === textClass) {
|
||||
try {
|
||||
params[attr] = JSON.parse(item.value);
|
||||
} catch (e) {
|
||||
}
|
||||
} else {
|
||||
params[attr] = item[extractorDict[item['@class']]]
|
||||
}
|
||||
}
|
||||
}
|
||||
// Overwrite the Parameters
|
||||
job.parameters = params;
|
||||
}
|
||||
}
|
||||
|
||||
return jobsWithParmas;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function to Start a Task
|
||||
* @param station The Name or ID of the Statio, which should be used
|
||||
* @param jobId The ID of the Job
|
||||
* @param userId The User which should be used to mark the Job as Started
|
||||
* @param uri The URI of Xetics
|
||||
* @param token The API Token to access the API
|
||||
*/
|
||||
async function _startTask(station: string | number, jobId: number, userId: number, uri = DEFAULT_URI, token = DEFAULT_TOKEN) {
|
||||
|
||||
const _jobController = new jobController();
|
||||
const _equipmentController = new equipmentController();
|
||||
|
||||
_jobController.uri = uri;
|
||||
_equipmentController.uri = uri;
|
||||
_jobController.token = token;
|
||||
_equipmentController.token = token;
|
||||
|
||||
let stationId = -1;
|
||||
if (typeof station === 'string') {
|
||||
// Get the Equipment ID
|
||||
stationId = (await _equipmentController.getEquipment(undefined, undefined, station)).id;
|
||||
} else {
|
||||
stationId = station;
|
||||
}
|
||||
|
||||
// Get the Active Jobs for the Equipment
|
||||
const job = await _jobController.postJobsStart({
|
||||
jobId,
|
||||
stationId,
|
||||
userId,
|
||||
startTimeUTC: Date.now()
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to Mark a Task as finished.
|
||||
* @param station The Station (Name or ID)
|
||||
* @param jobId The ID of the Job
|
||||
* @param userId The User which will be used to finish the Task
|
||||
* @param qualityParameters Quality Parameters that should be returend
|
||||
* @param traceabilityParameters Additional Parameters to trace the Parameters
|
||||
* @param uri The URI of Xetics
|
||||
* @param token The API Token to access the API
|
||||
*/
|
||||
async function _finishTask(station: string | number, jobId: number, userId: number, qualityParameters: QualityParameterDTO[], traceabilityParameters: TraceabilityParameterDTO[], uri = DEFAULT_URI, token = DEFAULT_TOKEN) {
|
||||
|
||||
const _jobController = new jobController();
|
||||
const _equipmentController = new equipmentController();
|
||||
|
||||
_jobController.uri = uri;
|
||||
_equipmentController.uri = uri;
|
||||
_jobController.token = token;
|
||||
_equipmentController.token = token;
|
||||
|
||||
let stationId = -1;
|
||||
if (typeof station === 'string') {
|
||||
// Get the Equipment ID
|
||||
stationId = (await _equipmentController.getEquipment(undefined, undefined, station)).id;
|
||||
} else {
|
||||
stationId = station;
|
||||
}
|
||||
|
||||
// Get the Active Jobs for the Equipment
|
||||
const job = await _jobController.postJobsStopSingle({
|
||||
jobId,
|
||||
stationId,
|
||||
userId,
|
||||
qualityParameters,
|
||||
traceabilityParameters
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
241
modules/xetics-lean-connector/src/xetics.module.ts
Normal file
241
modules/xetics-lean-connector/src/xetics.module.ts
Normal file
@ -0,0 +1,241 @@
|
||||
/**
|
||||
* @author Martin Karkowski
|
||||
* @email m.karkowski@zema.de
|
||||
* @create date 2020-11-10 10:12:51
|
||||
* @modify date 2020-11-11 16:02:41
|
||||
* @desc [description]
|
||||
*/
|
||||
|
||||
import { injectable } from "inversify";
|
||||
import { exportMethod, exportProperty } from "../../../lib/decorators/moduleDecorators";
|
||||
import { NopeBaseModule } from "../../../lib/module/BaseModule";
|
||||
import { NopeObservable } from "../../../lib/observables/nopeObservable";
|
||||
import { INopeObservable } from "../../../lib/types/nope/nopeObservable.interface";
|
||||
import { DEFAULT_TOKEN, DEFAULT_URI } from "../defaults/default.params";
|
||||
import { JobDTO, QualityParameterDTO, TraceabilityParameterDTO } from "../generated/interfaces";
|
||||
import { finishTask, getActiveTasksFromMES, getTasksFromMES, startTask } from "./xetics.functions";
|
||||
|
||||
/**
|
||||
* Definition of the MES-Task Definition.
|
||||
*
|
||||
* @export
|
||||
* @interface MESTask
|
||||
* @extends {JobDTO}
|
||||
*/
|
||||
export interface MESTask extends JobDTO {
|
||||
parameters: {
|
||||
[index: string]: any;
|
||||
};
|
||||
operation: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface describing the Xetics Interface Client.
|
||||
*
|
||||
* @export
|
||||
* @interface IXeticsInterfaceClient
|
||||
*/
|
||||
export interface IXeticsInterfaceClient {
|
||||
/**
|
||||
* The currently active task.
|
||||
*
|
||||
* @type {INopeObservable<MESTask>}
|
||||
* @memberof IXeticsInterfaceClient
|
||||
*/
|
||||
currentTask: INopeObservable<MESTask>;
|
||||
/**
|
||||
* All available tasks for the station
|
||||
*
|
||||
* @type {INopeObservable<MESTask[]>}
|
||||
* @memberof IXeticsInterfaceClient
|
||||
*/
|
||||
availableTasks: INopeObservable<MESTask[]>;
|
||||
/**
|
||||
* Function to finish the task.
|
||||
*
|
||||
* @param {QualityParameterDTO[]} [qualityParameters]
|
||||
* @param {TraceabilityParameterDTO[]} [traceabilityParameters]
|
||||
* @return {*} {Promise<void>}
|
||||
* @memberof IXeticsInterfaceClient
|
||||
*/
|
||||
finishCurrentTask(qualityParameters?: QualityParameterDTO[], traceabilityParameters?: TraceabilityParameterDTO[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Start the current Task.
|
||||
*
|
||||
* @return {Promise<boolean>} The success of the Operation.
|
||||
* @memberof IXeticsInterfaceClient
|
||||
*/
|
||||
startCurrentTask(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Function to get the Task for a specific Product
|
||||
*
|
||||
* @param {string} id
|
||||
* @return {*} {Promise<MESTask>}
|
||||
* @memberof IXeticsInterfaceClient
|
||||
*/
|
||||
selectTaskForProduct(id: string): Promise<MESTask>;
|
||||
|
||||
/**
|
||||
* Function, to refresh the available tasks manually.
|
||||
*
|
||||
* @return {*} {Promise<MESTask[]>}
|
||||
* @memberof IXeticsInterfaceClient
|
||||
*/
|
||||
updateTasks(): Promise<MESTask[]>;
|
||||
}
|
||||
|
||||
|
||||
@injectable()
|
||||
export class XeticsInterfaceClient extends NopeBaseModule implements IXeticsInterfaceClient {
|
||||
protected _station: string;
|
||||
protected _uri: string;
|
||||
protected _token: string;
|
||||
protected _user: number;
|
||||
|
||||
/**
|
||||
* Property containing the current Task of the Client.
|
||||
*
|
||||
* @memberof XeticsInterfaceClient
|
||||
*/
|
||||
@exportProperty({
|
||||
mode: ['publish'],
|
||||
topic: 'currentTask',
|
||||
})
|
||||
public currentTask = new NopeObservable<MESTask>();
|
||||
|
||||
/**
|
||||
* List containing the available Tasks for the Client.
|
||||
* You can randomly pick one.
|
||||
*
|
||||
* @memberof XeticsInterfaceClient
|
||||
*/
|
||||
@exportProperty({
|
||||
mode: ['publish'],
|
||||
topic: 'availableTasks',
|
||||
})
|
||||
public availableTasks = new NopeObservable<MESTask[]>();
|
||||
|
||||
/**
|
||||
* Like the Constructor of the Element.
|
||||
*
|
||||
* @param {string} station A Station name, which should be used.
|
||||
* @param {number} user The User.
|
||||
* @param {*} [uri=DEFAULT_URI]
|
||||
* @param {*} [token=DEFAULT_TOKEN]
|
||||
* @memberof XeticsInterfaceClient
|
||||
*/
|
||||
async init(station: string, user: number, uri = DEFAULT_URI, token = DEFAULT_TOKEN){
|
||||
this._station = station;
|
||||
this._uri = uri;
|
||||
this._token = token;
|
||||
this._user = user;
|
||||
|
||||
this.author = {
|
||||
forename: 'Martin',
|
||||
mail: 'm.karkowski@zema.de',
|
||||
surename: 'karkowski'
|
||||
}
|
||||
this.description = 'A Module to access the Xetics MES-System. This module is used as wrapper for task extraction and manipulation'
|
||||
this.version = {
|
||||
date: new Date('12.10.2020'),
|
||||
version: 1
|
||||
}
|
||||
|
||||
await super.init();
|
||||
}
|
||||
|
||||
@exportMethod({
|
||||
paramsHasNoCallback: true
|
||||
})
|
||||
async selectTaskForProduct(id: number){
|
||||
// Iterate over the
|
||||
for (const task of this.availableTasks.getContent()){
|
||||
if (task.productId === id){
|
||||
this.currentTask.setContent(task);
|
||||
return task;
|
||||
}
|
||||
}
|
||||
|
||||
// Raise an Error.
|
||||
throw Error('No task available for the Product of ID: "'+ id + '"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Functiion to start the currently active MES task.
|
||||
*
|
||||
* @return {*}
|
||||
* @memberof XeticsInterfaceClient
|
||||
*/
|
||||
@exportMethod({
|
||||
paramsHasNoCallback: true
|
||||
})
|
||||
async startCurrentTask(){
|
||||
if (this.currentTask.getContent()){
|
||||
return startTask(this._station, this.currentTask.getContent().id, this._user, this._uri, this._token)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to mark the current task as finished.
|
||||
*
|
||||
* @param {QualityParameterDTO[]} [qualityParameters=[]] Quality Parameters, that should be stored in the MES
|
||||
* @param {TraceabilityParameterDTO[]} [traceabilityParameters=[]] Traceability Parameters.
|
||||
* @memberof XeticsInterfaceClient
|
||||
*/
|
||||
@exportMethod({
|
||||
paramsHasNoCallback: true
|
||||
})
|
||||
async finishCurrentTask(qualityParameters: QualityParameterDTO[] = [], traceabilityParameters: TraceabilityParameterDTO[] = []) {
|
||||
// Perform the Finish Operation, if there exists one.
|
||||
if (this.currentTask.getContent()) {
|
||||
// Call the Finish-Task Operation. Use the parameters of the current Task.
|
||||
// Returns the sucess of the Operation.
|
||||
const finished = await finishTask(
|
||||
this._station,
|
||||
this.currentTask.getContent().id,
|
||||
this._user, qualityParameters,
|
||||
traceabilityParameters,
|
||||
this._uri,
|
||||
this._token
|
||||
);
|
||||
|
||||
// If the T
|
||||
if (finished) {
|
||||
await this.updateTasks();
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
// The Operation wasnt sucessfull.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to internally update the currently active task.
|
||||
*
|
||||
* @return {*}
|
||||
* @memberof XeticsInterfaceClient
|
||||
*/
|
||||
@exportMethod({
|
||||
paramsHasNoCallback: true
|
||||
})
|
||||
async updateTasks(){
|
||||
// Update the available Tasks:
|
||||
this.availableTasks.setContent(await getTasksFromMES(this._station, true, this._uri, this._token));
|
||||
|
||||
// Check if there exists a current Task?
|
||||
const activeTasks = await getActiveTasksFromMES(this._station, true, this._uri, this._token);
|
||||
if (activeTasks.length > 0){
|
||||
// Assign the Active Task.
|
||||
this.currentTask.setContent(activeTasks[0])
|
||||
} else {
|
||||
// Assign the First Task of the active Task.
|
||||
this.currentTask.setContent(this.availableTasks.getContent()[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
81
modules/xetics-lean-connector/src/xetics.package.ts
Normal file
81
modules/xetics-lean-connector/src/xetics.package.ts
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @author Martin Karkowski
|
||||
* @email m.karkowski@zema.de
|
||||
* @create date 2020-11-10 16:53:43
|
||||
* @modify date 2020-11-11 16:57:30
|
||||
* @desc [description]
|
||||
*/
|
||||
|
||||
import { IPackageDescription } from "../../../lib/types/nope/nopePackage.interface";
|
||||
import { XeticsInterfaceClient } from "./xetics.module";
|
||||
|
||||
const TYPES = {
|
||||
'xeticsClient': Symbol.for('xeticsClient')
|
||||
}
|
||||
|
||||
export const DESCRIPTION: IPackageDescription<typeof TYPES> = {
|
||||
activationHandlers: [],
|
||||
autostart: {},
|
||||
defaultInstances: [
|
||||
{
|
||||
options: {
|
||||
identifier: "xetics-einlegen",
|
||||
params: [
|
||||
'Einlegen',
|
||||
0
|
||||
],
|
||||
type: XeticsInterfaceClient.prototype.constructor.name.toString()
|
||||
},
|
||||
selector: XeticsInterfaceClient.prototype.constructor.name.toString()
|
||||
},
|
||||
{
|
||||
options: {
|
||||
identifier: "xetics-schrauben",
|
||||
params: [
|
||||
'Verschrauben',
|
||||
0
|
||||
],
|
||||
type: XeticsInterfaceClient.prototype.constructor.name.toString()
|
||||
},
|
||||
selector: XeticsInterfaceClient.prototype.constructor.name.toString()
|
||||
}, {
|
||||
options: {
|
||||
identifier: "xetics-qualitaetskontrolle",
|
||||
params: [
|
||||
'Qualitaetskontrolle',
|
||||
0
|
||||
],
|
||||
type: XeticsInterfaceClient.prototype.constructor.name.toString()
|
||||
},
|
||||
selector: XeticsInterfaceClient.prototype.constructor.name.toString()
|
||||
}, {
|
||||
options: {
|
||||
identifier: "xetics-verpacken",
|
||||
params: [
|
||||
'Verpacken',
|
||||
0
|
||||
],
|
||||
type: XeticsInterfaceClient.prototype.constructor.name.toString()
|
||||
},
|
||||
selector: XeticsInterfaceClient.prototype.constructor.name.toString()
|
||||
}
|
||||
],
|
||||
nameOfPackage: 'xeticsPackage',
|
||||
providedClasses: [
|
||||
{
|
||||
description: {
|
||||
name: XeticsInterfaceClient.constructor.name,
|
||||
selector: TYPES.xeticsClient,
|
||||
type: XeticsInterfaceClient
|
||||
},
|
||||
settings: {
|
||||
allowInstanceGeneration: true,
|
||||
}
|
||||
}
|
||||
],
|
||||
providedFunctions: [],
|
||||
requiredPackages: [],
|
||||
types: TYPES
|
||||
}
|
||||
|
||||
export default DESCRIPTION;
|
45
modules/xetics-lean-connector/test/test.ts
Normal file
45
modules/xetics-lean-connector/test/test.ts
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @author Martin Karkowski
|
||||
* @email m.karkowski@zema.de
|
||||
* @create date 2020-02-18 14:06:50
|
||||
* @modify date 2020-11-11 13:07:08
|
||||
* @desc [description]
|
||||
*/
|
||||
|
||||
import { promisify } from 'util';
|
||||
import { finishTask, getActiveTasksFromMES, getTasksFromMES, startTask } from '../src/xetics.functions';
|
||||
|
||||
const sleep = promisify(setTimeout)
|
||||
|
||||
const NAME = 'Einlegen'
|
||||
|
||||
async function main(){
|
||||
|
||||
const active = await getActiveTasksFromMES(NAME);
|
||||
|
||||
if (active.length > 0){
|
||||
const finished = await finishTask(NAME, active[0].id, 1, [], []);
|
||||
console.log(finished ? 'Finished already active Task!' : 'Could not finish active Task');
|
||||
} else {
|
||||
const res = await getTasksFromMES(NAME);
|
||||
if (res.length > 0) {
|
||||
// console.log(res[0])
|
||||
console.log(NAME, 'Found Task ->', JSON.stringify(res, undefined ,4));
|
||||
// Finish the Task.
|
||||
const started = await startTask(NAME, res[0].id, 1);
|
||||
|
||||
console.log(started ? 'Started Task!' : 'Could not start the Task');
|
||||
|
||||
if (started){
|
||||
await sleep(1000)
|
||||
const finished = await finishTask(NAME, res[0].id, 1, [], []);
|
||||
|
||||
console.log(finished ? 'Finished Task!' : 'Could not finish the Task');
|
||||
}
|
||||
} else {
|
||||
console.log('NO Task available.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error)
|
Loading…
Reference in New Issue
Block a user