Core

Establishing a Connection to the Machine

A machine connection is established when creating a new machine variable.

var machine = new LUX.Machine()

Options can be passed to the constructor to modify connection parameters.

var options = {
  ipAddress: '192.16.0.1',
  port: 8000,
  timeout_ms: 500,
  maxRetryCount: 5,
  maxReconnectCount: 5
}

var machine = new LUX.Machine(options)
Option Description Default Value
ipAddress IP address of the machine WebSocket server IP address hosting the web interface (location.hostname)
port Port of the machine WebSocket server 8000
timeout_ms Time, in milliseconds, to wait for a machine response before trying again 250
maxRetryCount Maximum number of read or write attempts before registering an error 5
maxReconnectCount Maximum number of reconnect attempts before prompting the user 5

Any options not set in code will fall back to the default value.

Reestablishing Connection

If the machine connection is lost, the library will attempt to reconnect automatically, up to maxReconnectCount times. If the connection cannot be established, it will alert the user and give the option to try again or abort. Aborting will typically require a page refresh to reestablish the connection. This behavior can be customized by providing a function to machine.connection.onDisconnect. Here is an example implementation of the default behavior.

machine.connection.onDisconnect = function () {
	if (reconnectCount <= maxReconnectCount) {
		// Try to reconnect
		reconnectCount++
		machine.connection.reconnect()
	} else {
		// Prompt user for reconnection
		let shouldReconnect = confirm('Machine connection lost! Please check machine controller and physical connections.\nPress OK to attempt to reconnect.\nPress Cancel to end machine communication (a page reload will be required to reestablish communication)')
		if (shouldReconnect) {
			machine.connection.reconnect()
		}
	}
}

Reading Machine Variables

To read the value of a machine variable, call the readVariable(varName) method. The varName parameter is a string containing the name of the machine variable to read. For local machine variables, this must take the form of 'taskName:varName'. For global variables, no prefix is necessary. If you would like to cyclically update the value, use the initCyclicRead(varName) method, instead. This will update the value as quickly as possible. It is also possible to pass an array of variable names to either of these functions.

machine.readVariable('globalVar') // Read variable once
machine.initCyclicRead('myTask:localVar') // Read variable continually, as quickly as possible

machine.readVariable(['globalVar, myTask:localVar']) // Read multiple variables

Message Format

{
  "type": "read",
  "data": "[globalVar, myTask:localVar]"
}
{
  "type": "readresponse",
  "data": [
    {
      "globalVar": 25
    },
    {
      "myTask:localVar": {
        "elem1": "Hello",
        "elem2": 123.456
      }
    }
  ]
}

Events

Events are triggered on the document when reading machine variables. Here is an example of how to use these with jQuery.

$(document).on({
    'readcomplete': function() {
        // Called after a read has been completed.
    },
    'readsuccess': function() {
        // Called after a read was successful.
    },
    'readerror': function() {
        // Called after a read failed.
    }
})

Writing Machine variables

To write the value of a machine variable, call the writeVariable(varName, [value]) method. The varName parameter follows the same rules as for reading variables. The value parameter is optional. If no value is specified, then the current HMI value of the variable will be written to the machine.

machine.writeVariable('globalVar', 52)

machine['myTask:localVar'].elem1 = "World!"
machine['myTask:localVar'].elem2 = 654.321
machine.writeVariable('myTask:localVar')

Message Format

{
  "type": "write",
  "data": {
    "globalVar": 52,
    "myTask:localVar": {
      "elem1": "Hi!",
      "elem2": 654.321
    }
  }
}
{
  "type": "writeresponse",
  "data": {
    "globalVar": 52,
    "myTask:localVar": {
      "elem1": "Hi!",
      "elem2": 654.321
    }
  }
}

Events

Events are triggered on the document when writing machine variables as well. Here is another example.

$(document).on({
    'writecomplete': function() {
        // Called after a write has been completed.
    },
    'writesuccess': function() {
        // Called after a write was successful.
    },
    'writeerror': function() {
        // Called after a write failed.
    }
})

Binding to HMI App Data Instead of the PLC

We often augment hmi elements based on data from the PLC using databinding to the LUX Machine.

Sometimes, we want to augment hmi elements based on data local to the hmi app. The data and the elements are accessible programmatically, but implemting locking/hiding/IO/LED behavior requires custom javascript. The following capabilities allow us to extend typical Loupe UX databinding behavior to local hmi application data in a uniform way.

Instantiating the HMI object

An HMI object is established when creating a new hmi variable.

var hmi = new LUX.hmi(customCallback);

Unlike a LUX.Machine, the data is local to the hmi app rather than the PLC, so there is no connection or connection options.
Instead, one or more callback functions are passed.

Providing the Callback Function

The callback functions[s] are responsible for populating the hmi object with app data.

function customCallback(){
  hmi['datapoint'] = appData.datapoint;
}

Binding Loupe UX Elements to the HMI Object

Loupe UX elements can now bind to the hmi object by changing the data-machine-name to the new hmi object.

  <span class="lux-num-value" data-machine-name="hmi" data-var-name="datapoint"></span>