Fixing the xetics lean adapter

This commit is contained in:
Martin Karkowski 2020-11-11 17:06:25 +01:00
parent c96a2785c9
commit e3a2f9f921
11 changed files with 1054 additions and 0 deletions

View File

@ -0,0 +1 @@
generated

View 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

View File

@ -0,0 +1,2 @@
export const DEFAULT_TOKEN = 'Basic YXBpdXNlcjpkR1E2amdEc0ZKN21aaHZnM0FZZg==';
export const DEFAULT_URI = 'http://10.10.13.31/release';

View 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}`);
});

View File

@ -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}}
}

View File

@ -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}}
}

View File

@ -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}}

View 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;
}

View 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;
}
}

View 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;

View 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)