UNPKG

prisme-flow

Version:

prisme platform flow engine

318 lines (278 loc) 12.9 kB
/** * Created by prisme.io on 09/06/2017. */ 'use strict' var isaOpcUa var isaResultMessage var serverAddressSpace var isaMapping var os = require('os') var counterValue = 0 /** * Basic functions to work with OPC UA address space of node-opcua. * @module ISAAddressSpace */ module.exports = { isaOpcUa: isaOpcUa, isaResultMessage: isaResultMessage, serverAddressSpace: serverAddressSpace, isaMapping: isaMapping, counterValue: counterValue, /** * Builds a fix ISA95 information model in address space. * @function * @param {object} enterprises - enterprises as a root node object * @param {Number} namespace - id of namespace in OPC UA * @param {Number} id - unique id for the model to build more than one of that structure */ build_enterprise_structure: function (enterprises, namespace, id) { // ### Level 4 ### var enterprise = module.exports.isaOpcUa.addOrganizeFolder(enterprises, 'Enterprise' + id, namespace) var sites = module.exports.isaOpcUa.addOrganizeFolder(enterprise, 'Sites', namespace) var site = module.exports.isaOpcUa.addOrganizeFolder(sites, 'Site' + id, namespace) var areas = module.exports.isaOpcUa.addOrganizeFolder(site, 'Areas', namespace) // ### Level 3 ### var area = module.exports.isaOpcUa.addOrganizeFolder(areas, 'Area' + id, namespace) var workcenters = module.exports.isaOpcUa.addOrganizeFolder(area, 'WorkCenters', namespace) var workcenter = module.exports.isaOpcUa.addOrganizeFolder(workcenters, 'WorkCenter' + id, namespace) // ### Storage ### var storageZones = module.exports.isaOpcUa.addOrganizeFolder(workcenter, 'StorageZones', namespace) var storageZone = module.exports.isaOpcUa.addOrganizeFolder(storageZones, 'StorageZone' + id, namespace) var storageUnits = module.exports.isaOpcUa.addOrganizeFolder(storageZone, 'StorageUnits', namespace) module.exports.isaOpcUa.addOrganizeFolder(storageUnits, 'StorageUnit' + id, namespace) // ### Work Units ### var workunits = module.exports.isaOpcUa.addOrganizeFolder(workcenter, 'WorkUnits', namespace) var workunit = module.exports.isaOpcUa.addOrganizeFolder(workunits, 'WorkUnit' + id, namespace) var processcells = module.exports.isaOpcUa.addOrganizeFolder(workunit, 'ProcessCells', namespace) var processcell = module.exports.isaOpcUa.addOrganizeFolder(processcells, 'ProcessCell' + id, namespace) var units = module.exports.isaOpcUa.addOrganizeFolder(processcell, 'Units', namespace) var unit = module.exports.isaOpcUa.addOrganizeFolder(units, 'Unit' + id, namespace) var lines = module.exports.isaOpcUa.addOrganizeFolder(unit, 'ProductionLines', namespace) var line = module.exports.isaOpcUa.addOrganizeFolder(lines, 'ProductionLine' + id, namespace) var workcells = module.exports.isaOpcUa.addOrganizeFolder(line, 'WorkCells', namespace) var workcell = module.exports.isaOpcUa.addOrganizeFolder(workcells, 'WorkCell' + id, namespace) var productionunits = module.exports.isaOpcUa.addOrganizeFolder(workcell, 'ProductionUnits', namespace) module.exports.isaOpcUa.addOrganizeFolder(productionunits, 'ProductionUnit' + id, namespace) // ### Business structrue ### module.exports.isaOpcUa.addOrganizeFolder(enterprise, 'MasterRecipes', namespace) module.exports.isaOpcUa.addOrganizeFolder(enterprise, 'Recipes', namespace) module.exports.isaOpcUa.addOrganizeFolder(enterprise, 'Materials', namespace) module.exports.isaOpcUa.addOrganizeFolder(enterprise, 'MaterialLots', namespace) module.exports.isaOpcUa.addOrganizeFolder(enterprise, 'MaterialSublots', namespace) module.exports.isaOpcUa.addOrganizeFolder(processcell, 'Orders', namespace) module.exports.isaOpcUa.addOrganizeFolder(processcell, 'ControlRecipes', namespace) }, /** * Construct the address space of the OPC UA server. * @function * @returns {object} ISAResultMessage @see ISAConstants:ISAResultMessage */ construct_my_address_space: function () { if (!module.exports.serverAddressSpace) { return module.exports.isaResultMessagess.AddressSpaceNotValid } var objectsOrganizer = module.exports.serverAddressSpace.findNode('ns=0;i=85') var serverNode = module.exports.serverAddressSpace.findNode('ns=0;i=2253') var references = objectsOrganizer.findReferences('Organizes', true) if (!module.exports.findAddressSpaceReference(references, serverNode.nodeId)) { return module.exports.isaResultMessagess.ReferenceNotFound } var examples = module.exports.isaOpcUa.addOrganizeFolder(module.exports.serverAddressSpace.rootFolder.objects, 'Examples', 4) var variable2 = 10.0 module.exports.serverAddressSpace.addVariable({ componentOf: examples, nodeId: 'ns=4;s=MyVariable', browseName: new module.exports.isaOpcUa.QualifiedName({name: 'MyVariable', namespaceIndex: 4}), displayName: 'MyVariable', symbolicName: 'MyVariable', dataType: module.exports.isaOpcUa.opcua.DataType.Double, value: { get: function () { return new module.exports.isaOpcUa.opcua.Variant({ dataType: module.exports.isaOpcUa.opcua.DataType.Double, value: variable2 }) }, set: function (variant) { variable2 = parseFloat(variant.value) return module.exports.isaOpcUa.opcua.StatusCodes.Good } } }) module.exports.serverAddressSpace.addVariable({ componentOf: examples, nodeId: 'ns=4;s=FreeMemory', dataType: module.exports.isaOpcUa.opcua.DataType.Double, browseName: new module.exports.isaOpcUa.QualifiedName({name: 'FreeMemory', namespaceIndex: 4}), displayName: 'FreeMemory', symbolicName: 'FreeMemory', value: { get: function () { return new module.exports.isaOpcUa.opcua.Variant({ dataType: module.exports.isaOpcUa.opcua.DataType.Double, value: os.freemem() / os.totalmem() * 100.0 }) } } }) module.exports.serverAddressSpace.addVariable({ componentOf: examples, nodeId: 'ns=4;s=Counter', dataType: module.exports.isaOpcUa.opcua.DataType.UInt16, browseName: new module.exports.isaOpcUa.QualifiedName({name: 'Counter', namespaceIndex: 4}), displayName: 'Counter', symbolicName: 'Counter', value: { get: function () { return new module.exports.isaOpcUa.opcua.Variant({ dataType: module.exports.isaOpcUa.opcua.DataType.UInt16, value: counterValue }) } } }) var method = module.exports.serverAddressSpace.addMethod( examples, { browseName: new module.exports.isaOpcUa.QualifiedName({name: 'Bark', namespaceIndex: 4}), displayName: 'Bark', symbolicName: 'Bark', inputArguments: [ { name: 'nbBarks', description: {text: 'specifies the number of time I should bark'}, dataType: module.exports.isaOpcUa.opcua.DataType.UInt32 }, { name: 'volume', description: {text: 'specifies the sound volume [0 = quiet ,100 = loud]'}, dataType: module.exports.isaOpcUa.opcua.DataType.UInt32 } ], outputArguments: [{ name: 'Barks', description: {text: 'the generated barks'}, dataType: module.exports.isaOpcUa.opcua.DataType.String, valueRank: 1 }] }) method.bindMethod(function (inputArguments, context, callback) { var nbBarks = inputArguments[0].value var volume = inputArguments[1].value var sound_volume = new Array(volume).join('!') var barks = [] for (var i = 0; i < nbBarks; i++) { barks.push('Whaff' + sound_volume) } var callMethodResult = { statusCode: module.exports.isaOpcUa.opcua.StatusCodes.Good, outputArguments: [{ dataType: module.exports.isaOpcUa.opcua.DataType.String, arrayType: module.exports.isaOpcUa.opcua.VariantArrayType.Array, value: barks }] } callback(null, callMethodResult) }) }, /** * Find address space reference in the address space of the OPC UA server. * @function * @param {object} references - OPC UA server's references of an object * @param {String} nodeId - nodeId of OPC UA like ns=0;i85 or ns=0;s=Objects * @returns {boolean} found - true reference if found, otherwise false */ findAddressSpaceReference: function (references, nodeId) { var found = false if (!nodeId || !references) { return found } references.filter(function (r) { if (r.nodeId.toString() == nodeId.toString()) { found = true } }) return found }, /** * Add variable in the address space of the OPC UA server. * @function * @param {String} rootFolder - root reference to set componentOf * @param {object} mapping - mapping object with mapping information * @returns {object} variableNode - opc ua node of type variable */ add_opcua_variable: function (rootFolder, mapping) { var variableNode var itemDefaultSettings = module.exports.isaOpcUa.mapOpcUaDatatypeAndInitValue(mapping.typeStructure) variableNode = module.exports.serverAddressSpace.addVariable({ componentOf: rootFolder, nodeId: mapping.structureNodeId, browseName: mapping.structureName, // identifier: new module.exports.isaOpcUa.QualifiedName({name: "Examples", namespaceIndex: 4}), dataType: itemDefaultSettings.variableDatatype, value: { get: function () { var item = module.exports.isaMapping.search_mapped_to_read(mapping.structureParentNodeId, mapping.structureNodeId, mapping.typeStructure) // console.log(mapping.structureParentNodeId + " " + mapping.structureNodeId + " " + mapping.typeStructure + " get as item:" + JSON.stringify(item)); if (item && item.value) { if (item.writtenValue && item.writtenValue !== item.value) { item.value = item.writtenValue } item.value = module.exports.isaOpcUa.parseValueByDatatype(item.value, itemDefaultSettings.variableDatatype) return new module.exports.isaOpcUa.opcua.Variant({ dataType: itemDefaultSettings.variableDatatype, value: item.value }) } else { return new module.exports.isaOpcUa.opcua.Variant({ dataType: itemDefaultSettings.variableDatatype, value: itemDefaultSettings.initValue }) } }, set: function (variant) { var item = module.exports.isaMapping.search_mapped_to_read(mapping.structureParentNodeId, mapping.structureNodeId, mapping.typeStructure) // console.log(mapping.structureParentNodeId + " " + mapping.structureNodeId + " " + mapping.typeStructure + " get as item:" + JSON.stringify(item)); if (variant !== null || variant && item && item.writtenValue) { if (variant.value === null || variant.value) { item.writtenValue = module.exports.isaOpcUa.getInitValueByDatatype(variant.dataType) } else { item.writtenValue = module.exports.isaOpcUa.parseValueByDatatype(variant.value, variant.dataType) } } else { item.writtenValue = module.exports.isaOpcUa.getInitValueByDatatype(itemDefaultSettings.variableDatatype) } return module.exports.isaOpcUa.opcua.StatusCodes.Good } } }) return variableNode }, /** * Add object in the address space of the OPC UA server. * @function * @param {String} rootFolder - root reference to set organizedBy * @param {object} mapping - mapping object with mapping information * @returns {object} objectNode - node of an OPC UA object */ add_opcua_object: function (rootFolder, mapping) { var objectNode if (mapping.typeStructure) { objectNode = module.exports.serverAddressSpace.addObject({ organizedBy: rootFolder, typeDefinition: mapping.typeStructure, nodeId: mapping.structureNodeId, browseName: mapping.structureName }) } else { objectNode = module.exports.serverAddressSpace.addObject({ organizedBy: rootFolder, nodeId: mapping.structureNodeId, browseName: mapping.structureName }) } return objectNode } }