libfagorclient

This is a api library that provides a connection and understandable api layer for a certain HMIELite system.

This HMIELite system must be connected to QUERCUS CNC machine.

There are two scenarios where libfagorclient is designed to be used:

  • A custom web component that runs inside HMIELite main application. In this case, an instance of connected and authenticated libfagorclient is provided.
  • A new web application created from scratch. In this case, it is necessary to create the needed objects and do the connnection and authentication process.

Installation

⚠️️(This step is only needed if libfagorclient is used from scratch)

This libfagorclient library is distributed in two flavors.

  • umd bundle (for traditional web applications)
  • es modules (for modern web applications to be run on evergreenbrowsers)

Right now libfagorclient client is distributed using a tar.gz file. The library can be downloaded clicking here:

📦 Download libfagorclient-latest.tgz

Both bundles (umd and es module), include every dependecy needed to be able to work with the CNC Server.

Shortly the package will be available thought a private npm repository; so no manual interaction will be needed in order to install or update this library.

> File schematics

The .tgz file distributed is a npm-compatible packed file.

.
└── package
    ├── dist
    │   ├── libfagorclient.es5.js
    │   ├── libfagorclient.umd.js
    │   ├── polyfill.js
    │   └── types
    │       ├── /**
    │       │    Typing files for typescript usage
    │       │         **/*.d.ts
    │       │         ........
    │       └── **/
    ├── package.json
    └── README.md

The minimal files needed to setup a working CNC UI are these:

  • package.json: Meta file to be used by npm or yarn manager.
  • libfagorclient.es5.js: ES Module bundle; for modern frameworks and/or evergreen browsers.
  • libfagorclient.umd.js: UMD bundle, for simple jQuery-ish applications;
  • polyfill.js: This file is pretended to be used when using libfagorclient.umd.js, since it completes some funcionalities missing on legacy browsers.

> Manual setup

⚠️(This step is only needed if libfagorclient is used from scratch)

Both bundles are likely to be used just by uncompressing the file, and including them on the HTML:

<script nomodule src="./lib/polyfill.js"></script>
<script nomodule src="./lib/libfagorclient.umd.js"></script>
<script nomodule>

  // libfagorclient. object is created on global context

  var conn = new libfagorclient.CommHmiNodeServer(); // Implements the connection process with the main HMI Node Server
  var cnc = new libfagorclient.Cnc(conn); // CNC class
</script>

Or we can just import them using ES Modules (just evergreen browsers).

<script type="module">
import {
  CommHmiNodeServer,
  Cnc
} from './lib/libfagorclient.es5.js'

const conn = new CommHmiNodeServer(); // Implements the connection process with the main HMI Node Server
const cnc = new Cnc(conn); // CNC class
</script>

This is a not recomended way of working, since no package manager is used.

> Use with npm

If we are build a modern web application, most likely you would be using npm or yarn. Download the .tgz file, and place it anywhere on your computer.

Then just use npm install as if you were installing any othe dependency on your proyect.

$ npm install c:\Downloasd\libfagorclient-latest.tgz

The library 'libfagorclient' will be available from within your proyect, and you will be able to start using it:

import {
  CommHmiNodeServer,
  Cnc
} from 'libfagorclient'


const conn = new CommHmiNodeServer(); // Implements the connection process with the main HMI Node Server
const cnc = new Cnc(conn); // CNC class

> important notice

Please, be aware the dependency wont be copied to your VCS (git, snv, ...); a relative path will be added to your pacakge.json file; be sure the libfagoclient-latest.tgz file location is shared within your team:

{
  "dependencies": {
    "libfagorclient": "file:../libfagorclient/libfagorclient-0.0.1.tgz",
  }
}

> fagor altenative npm use

We could use the a remote URL but just from within Fagor Automation's LAN, since the .tgz file is not accesible from the Internet:

$ npm install http://new-hmi.gitlab.fagorautomation.net/libfagorclient/libfagorclient-latest.tgz

Basic Usage

> Connection and authentication

⚠️(This step is only needed if libfagorclient is used from scratch)

First of all, we need an instance of CommHmiNodeServer. This instance is used to connect to a HMIElite system and do the authentication process.

//This is only a example of how we can import classes and enums from libfagorclient.
import {
  CommHmiNodeServer,
  Cnc,
  CncKernelType
} from './lib/libfagorclient.es5.js'

const conn = new CommHmiNodeServer(); // Implements the connection process with the main HMI Node Server

Once conn object is instantiated, we can connect it to remote point filling the request with aproppiate connection data:

  • host: ip or name of the machine HMIElite is installed.
  • port: Configured of the api (optional, by default 3000).
  • user (in this example we use user, this user is created for testing purposes and could be removed in future releases )
  • password
// Connect to remote endpoint
conn.connect({
  host: 'localhost',
  port: 3000
  username: 'user',
  password: 'user'
});

CommHmiNodeServer class emits online event when whole connection chain has been accomplished. At this stage, all services are operative and we can perform any operation that involves a communication with the cnc. If any link is disconnected emits offline event and automatically schedules a reconnection timeout every 5 seconds.

conn.on('online', () => {
  //Every operation must be performed in this scope.
});
conn.on('offline', () => {
  //Every operation related to disconnection must be performed in this scope.
});

Further information about connection, authentication and related events can be found in Connection section.

But conn instance only allows the execution of services related to connection, it is a generic instance that should be used in another specialized classes that are exported by libfagorclient.

For now, these are the clases exported by this library:

  • Cnc: This class exposes the Cnc kernel data model (aka model) and the services that interact with it. Cnc kernel can be simulated or real, but the class that must be instantiated is the same.
  • Plc: This class exposes the PLC data model.

> Model request

⚠️(This step is only needed if libfagorclient is used from scratch)

So, if we want to instantiate a Cnc or Plc object, we must inject conn object in the constructor of these classes.

const cnc = new Cnc(conn); // CNC class
const plc = new Plc(conn); // PLC class

Notice that Cnc constructor by default creates a Real kernel instance, if we want to create a simulated instance we must add an argument to constructor using CncKernelType enum.


const cncSimulated = new Cnc(conn, CncKernelType.SIMULATED); //Cnc simulated class

Cnc class exports a cnc data model which represents a logical view of the machine we have connected to. This implies that all physical elements of the machine such spindles and axes or logical such channels can be inspected anytime and every change on these elements will be notified in real time.

In order to avoid extra cpu usage, the cnc model is created upon request.

cnc.requestModel();

When model is ready, Cnc instance emits created event, and whenever the model is updated emits updated.

Plc class exports the plc data model with all resources values. All entities can be inspected anytime and every change on these elements should be notified in real time.

The plc Model will contain a updated representation of the resources of PLC:

  • i.n: Inputs (I1-I1024)
  • o.n: Outputs (O1-O1024).
  • li.n: Local inputs (LI1-LI16)
  • lo.n: Local outputs (LO1-LO8).
  • m.n: Marks (M1-M8192).
  • msg.n: Messages (MSG1-MSG1024).
  • err.n: Errors (ERR1-ERR1024).
  • r.n: Registers (R1-R1024).
  • TODO (clocks, counters, rkin,...)

In order to avoid extra cpu usage, the plc model is created upon request.

plc.requestModel();

When model is ready, Plc instance emits created event, and whenever the model is updated emits updated.

Once the model is created we can inspect it, for example, we can achieve every plc resource name and the value of a specific registry and mark.


plc.on('created', ()=> {

  // This command will output every plc resources name
  console.log(Object.keys(plc.getModel()));

  // This command will output R1024 register's value
  console.log(plc.getModel().r['1024']));

  // This command will output I24 input's value
  console.log(plc.getModel().i['24']));

  // This command will whole plc resources object
  console.log(Object.keys(plc.getModel())));

});

When execution cycle must be closed, we should disconnect conn instance but it is recommnended to disconnect fron plc model updates before to avoid unnecessary execution cycles in main server.

plc.disconnectFromModel();
conn.disconnect();

Be aware of removing every listener created before to avoid possible memory leak and performance degradations.

> Model usage

Once the model is created we can inspect it. For example, for cnc model we can achieve the logical ids of axes of the first channel.

let currentAxes = [];
cnc.on('created', (cncModel) => {
  cncModel.getChannel(1).axes.map(ax => {
    currentAxes.push(ax.logicId);
  });
})

We can use stored logical ids to schedule a polling timer to get axis positionment data and paint them.

// We choose a pooling in order to update cnc values
// an "updated" event is send on cnc, but this approach is easier.
pollingTimer = setInterval(() => {
  currentAxes.map((axLogicId) => {

    //We retrieve axis reference by logic id.
    const ax = cnc.getAxis(axLogicId);

    console.log(`
    name: ${ax.name}
    pos: ${ax.pos.external}
    flwe: ${ax.flew.external}
    parked: ${ax.parked}
    `)
  });

}, 60);

Further information about cnc data model can be found in Cnc Model and Services section.

But what about the interaction with Cnc? Cnc class exposes some services to allow us to operate with the cnc and also emits some real time events to warn every relevant change in cnc kernel state.

In this example, we are going to enter block mode in the first channel (the cnc by default is launched in program mode, so that the press of a start will launch the selected program execution). Once block mode is activated, we can set a execution block that will be executed when start is pressed.

Related to this process, Cnc emits two differents events:

  • CncModeEvent: This event is fired when cnc operation mode has been changed, it can have these values:
    • PRG_SELEC
    • BLK_SELEC
  • CncStateEvent: This event is fired when cnc kernel state has been changed, it can have these values:
    • NO_READY
    • READY
    • EXEC
    • ERROR
    • STOP

We must wait until cnc operation mode is set to BLK_SELEC to program a executing block. In this example we will program 'G0X100' block.

Further information about cncEvents can be found in Cnc Events section.

//we retrieve first channel 
const channel = cnc.getChannel('1');
console.log(`About to execute [cnc.getChannel('1').cncServices.enterBlockMode()]`);
channel.cncServices.enterBlockMode().then(console.log);

// EVENTS
// When Cnc emits CncStateEvent, we print it.
cnc.on('CncStateEvent', event => {
  if ( event.data.state === 'EXEC') {
    console.warn('EXEC');
  } else if ( event.data.state === 'STOP') {
    console.warn('STOP');
  } else if ( event.data.state === 'NO_READY') {
    console.warn('NO_READY');
  } else if ( event.data.state === 'ERROR') {
    console.warn('ERROR');
  } else {
    console.warn('READY');
  }
});

// When Cnc emits CncModeEvent, we program 'G0X100' block.
cnc.on('CncModeEvent', event => {
  console.log(`Cnc operation mode has changed: ${event.data.mode}`);
  if(event.data.mode === 'BLK_SELEC') {
    console.log(`About to execute [cnc.getChannel('1').cncServices.setBlock('G0X100')]`);
      channel.cncServices.setBlock('G0X100').then(console.log);
  } 
});

> Reactive Model Properties

We have implemented a reactive-event system for some model properties. It allows developer to dynamically create events on runtime, based on changes for some propeties across the CNC models (channels, spindles, axes and most of the models contained on them).

The system implements debouncing on the emision to prevent an event-flood on highly changeable values. (default value is 60ms)

const axis = cnc.getAxis('X');

const listenerForAxis = axis.createListener(['diameters', 'inUse' 'ppos', 'pos', 'flwe', 'parked']);
console.log("Creating dynamic listener for axis X's properties: diameters', 'inUse' 'ppos', 'pos', 'flwe', 'parked");


listenerForAxis.start((axis, propsChanges) => {
  console.log(`The properties ${propsChanges.join(', ')} have changed on `, axis);
}, {debounceTime: 100});

// The emission can be stopped anytime
listenerForAxis.stop()

// And it should be deleted when no longer needed (to avoid memory-leaks)
axis.deleteListener(listenerForAxis);

Reactive properties are documented under the @Listenable() decorator on the following objects:

Any property placed above the @Listenable() decorator might be used to create a reactive event based on changes.

> Freeing resources

When a web application or integrated customized app must be destroyed, it is important to notice that all the allocated resources must be removed and freed.

These resources could be event listeners, timers or global objects. In order to allow garbage collector to collect them, all the references must be cleared or disconnected.

cnc.disconnectFromModel();
cnc.removeAllListeners('CncModeEvent');
cnc.removeAllListeners('CncStateEvent');
conn.disconnect();

Sample App

We have set up a simple sample application to show how build a new web application using a fresh instance of libfagorclient:

  • jQuery based
  • ESM Modules compatible (will only run on Chrome)
  • Establishes a connection to remote cnc
  • Query cnc state to display it in the first renderization.
  • View Channel #1 Axis main values within dynamic list.
  • View Channel #1 Spindle main values within dynamic list.
  • Enter/Leave Block Mode, reacting to cnc mode and states changes.
  • Set Block Mode
  • View cnc mode and state reports.
  • Minimal simulated jog keyboard
  • cnc and conn objects are exported globally in lfc object, so that they can be used in dev console to try out functionalities explained in this documentation.

sample app capture

Try Sample App

📃 Full Sample code

Typings

The library is set up to be able to work with typescript. Every type used within the library is exported directly from 'libfagorclient'.

Example:

import {
    Cnc,
    CommHmiNodeServer,
    Diagnosis,
    LiveStream,
    Plc,
    enums as LFCEnums,
    interfaces as LFCInterfaces,
} from 'libfagorclient';

results matching ""

    No results matching ""