afEasyConnExt icon

afEasyConnExt

EasyConn - Write connectors in Axon
afEasyConnExt

Registered StackHub users may elect to receive email notifications whenever a new package version is released or a comment is posted on the forum.

There are 0 watchers.

v1.0.0

EasyConn provides a framework for creating your own SkySpark Connectors from Axon functions.

The EasyConn extension provides Axon support for:

  • Server Pings - Update connector records with server data
  • Connector Learn Tree - Create logical point navigation trees for the Builder App
  • Synchronising CurVals - Supply points with their latest CurVals
  • Synchronising History - Retrieve bulk history data for points
  • Writing Point Values - Write data values back to a point

This connector has been developed for SkySpark v3.1.6 or later.

EasyConn is FREE to download and evaluate for up to 100 Axon calls. Watch our video tutorial to understand how easy we make it to create and use your own connector - with Axon.

Fortified with Fantom! Robust, secure, and optimised, the EasyConn extension helps you to do more "in-house" with less reliance on bespoke Fantom knowledge!

EasyConn works great with Fantom Factory's HTTP Client for making calls to REST APIs.

Sufficient Axon knowledge will be needed to use this software extension.

Fantom Factory Logo

Contents

Usage

EasyConn connectors work by delegating standard SkySpark connector functionality, such as obtaining curVals for points, to custom Axon functions that YOU write.

  1. Create an EasyConn connector instance.
  2. Write Axon functions for each of the main EasyConn features, ping, learn, syncCur, syncHis, and write.
  3. Add tags to the EasyConn connector instance with the names of your Axon functions.
  4. Then sit back and watch points, historise, tune, and basically use the EasyConn SkySpark connector just like any other.

New EasyConn Connector

Custom Axon functions

To operate, EasyConn just needs the names of a few Axon functions to be tagged on the connector record.

Each Axon function is optional, depending on which features the connector is to implement.

Each Axon function written and supplied to the EasyConn connector must define a specific argument signature and return data as intended. These functions are described in the sections below, complete with dummy examples.

Real working Axon code for these functions can be found the Real example and Advanced example sections.

Note that all Axon functions are executed under a synthesised User with Admin permissions.

Ping func

This function is called in response to a connector ping.

Functions should make a request to the end server, to ensure that authentication works and the endpoints are accessible.

If possible, the ping function should return a Dict of server information. The tags in the Dict get stored on the connector record, to aid in debugging. Even storing a lastPingTs can be helpful to see when the last successful connection was!

Args:

  • conn - The Conn (record) being pinged.

Returns:

  • A Dict of tags to be set on the Conn record.
// Example Ping func
(conn) => do
  // ensure we have connectivity to the API end point
  res : `https://api.foobar.com/ping`.ioReadTrio

  // return tags for the Conn
  return {
    lastPingTs : now(),
    fooVer     : res.first->version,
  }
end

Learn func

The "Learn" function as used in the SkySpark Builder Application and is responsible for:

  • populating the device tree
  • supplying tags for points

Args:

  • conn - The Conn (record).
  • arg - a Str that identifies the parent node in the tree (if any).

Returns:

  • A Grid where each row either identifies a sub-node (branch) in the tree, or a point to bind.

The "Learn" function is called for every non-leaf node in the Learn tree.

The first time it is called, arg is null to designate the top-level tree object. It is then called very time a node in the Learn tree is expanded (when the arrow icon is clicked).

It is the expectation that the Learn function will call out to a REST API to obtain a list of points (and associated metadata) that can be bound in SkySpark.

Point binding

To create a point that can be bound in SkySpark, return a Grid row with the following tags.

  • dis - The display name (Str) to be shown in the tree.
  • kind - A Str of either Bool, Number, or Str to designate the kind of point value. Number points should also return a unit tag.
  • his / cur / writable - At least one of these three tags are required to bind the point, each designates what the point is able to do.
    • his allows the point to collect and sync history
    • cur allows the point to be polled for a curVal
    • writable allows the point to be written to
  • ... - All other (custom) tags returned will also set on the point record.

If a point contains the cur tag, there must also be a Sync Cur function to retrieve the point's curVal.

If a point contains the his tag, there should also be a Sync His function to retrieve the point's historical data.

If a point contains the writable tag, there should also be a Writable function to set a value on the actual point.

Because these other functions need to identify individual points and how they relate to data found in REST APIs, it is important that other custom identifying tags are also set on points.

Tree nodes

Because an external system / REST API may return hundreds of points to display in the Learn tree, it is possible to categorise and group them under expandable tree nodes.

To create an expandable node, return a row with the following tags.

  • dis - The display name (Str) to be shown in the tree.
  • learn - The arg argument (Str) passed to be passed when the node is expanded.
  • ... - Other tags may be returned for informational purposes.
// Example Learn func
(conn, arg : null) => do

  // at the top level, return expandable nodes
  if (arg == null)
    return [
      { learn: "/node1", dis: "Node 1" },
      { learn: "/node2", dis: "Node 2" },
    ].toGrid()

  // return points under node 1
  if (arg == "/node1")
    return [{
      "dis"  : "My first point",
      "kind" : "Number",
      cur,
      // set custom identifying tags
      "myId" : "pointId_onServer",
    }].toGrid()

  // return points under node 2
  if (arg == "/node2") do
    ...
  end
end

Sync Cur func

This function is called when points are polled to update their curVals. It should retrieve the curVal for each point in the given List.

Args:

  • conn - The Conn (record).
  • points - A List of point records that require new curVals.

Returns:

  • A Grid containing a column of point Refs (pointRef) and a column of new current values (val).

It is expected that the function communicates with an external system / REST API to obtain the curVals.

To help identify the point on the external system, the point record will contain all the tags returned by the Learn function when the point was bound.

// Example Sync Cur func
(conn, points) => do
  curVals : points.map() (point) => do
    ...
    // get the curVal for each point
    curUrl : "https://api.foobar.com/curVal/" + point->myId
    curVal : curUrl.parseUri.ioReadStr.parseNumber
    ...
    return { pointRef: point->id, val: curVal }
  end

  // return a grid of curVals
  return curVals.toGrid
end

By adding the cur tag to a point, the point is automatically polled for a curVal whenever it is watched. Points are watched when it has a hisCollectInterval tag or when the point is viewed in the Monitor App or the Connector App.

EasyConn uses the buckets polling mode so, to change the default polling frequency of 10 seconds, set the pollTime tag on a connector tuning record.

Sync His func

This function is called to return time-series history for a given his point.

Args:

  • conn - The Conn (record).
  • point - The his point (record) to be synced.
  • span - The Span of time requested to by synced.

Returns:

  • A history Grid with a ts column of DateTims and a val column of point values.

It is expected that the function communicates with an external system / REST API to obtain the time-series data.

To help identify the point on the external system, the point record will contain all the tags returned by the Learn function when the point was bound.

// Example Sync His Func
(conn, point, span) => do

  // get the history data
  hisUrl : "https://api.foobar.com/history/" + point->myId + "/" + span
  hisVal : hisUrl.parseUri.ioReadJson

  hisList : hisVal.map() (row) => do
    return { ts:row->ts, val:row->val }
  end

  return hisList.toGrid()
end

Write func

This function should set the given point value on the actual point in the external system.

Args:

  • conn - The Conn (record).
  • point - The associated point (record).
  • val - The value to be written.
  • level - The priority level (Number) that the point is to be written at.

Returns:

  • Nothing. Any returned value is ignored.

It is expected that the function communicates with an external system / REST API to set the point value.

The level argument is only applicable should the external system utilise a BACnet 16-level priority array (or similar!).

// Example Write Func
(conn, point, val, level) => do

  // write the value to the endpoint
  writeUrl : "https://api.foobar.com/write/" + point->myId + "/" + val
  writeUrl.parseUri.ioReadStr
end

HTTP REST APIs

If you are looking to sync data with HTTP REST APIs, then let Fantom Factory's HTTP Client help!

HTTP Client is an extension for SkySpark that provides powerful Axon functions for making HTTP requests and calling REST APIs.

HTTP Client boasts the following features:

  • support for all HTTP methods, GET, POST, PUT, DELETE, OPTIONS, etc...
  • support for custom HTTP headers
  • post Forms, JSON, and XML
  • upload files and multi-part forms
  • BASIC, BEARER, DIGEST, Project Haystack / SkySpark SCRAM, header, path, and query authentication mechanisms
  • gzip and deflate response de-compression
  • redirect following
  • session cookies
  • JSON pretty printing

Authentication

The standard suite of IO functions in SkySpark makes basic HTTP GET requests. But to make HTTP POST requests or to set HTTP authentication headers, another SkySpark library / extension is required.

Fantom Factory's HTTP Client is the only extension available that allows credentions to be saved in SkySpark's secure storage and then used securely in HTTP requests.

Production use

Once you have a connector developed with Easy Conn it will need to go live on a production SkySpark (because it was developed on a separate development / testing instance SkySpark, right!?).

To do that, the EasyConn extension will need to installed on the production SkySpark, and the custom Axon functions (that you wrote) will need to be copied over.

Note that a separate EasyConn licence will need to be purchased for the production SkySpark server.

There are many ways to copy Axon funcs from SkySpark to SkySpark, but a great and easy way is to bundle the functions up into a .pod file, and just copy / install the single .pod file over. For this, there is no easier way than to use Fantom Factory's Pod Builder.

Pod Builder compiles Axon functions, Haystack Defs, and other Folio records, into valid SkySpark extensions. That, combined with its StackHub integration, provides a simple and convenient way to distribute your amazing EasyConn connectors!

If distributing Axon connector functions to client SkySpark servers, you may not want to give the client access to your Axon source code. If so, then Fantom Factory's Axon Encryptor is the tool for you! Axon Encryptor obfuscates and protects your Intellectual Property with source code encryption for Axon!

Real example

Following below are sample Axon functions for EasyConn Learn and Sync Cur functionality.

These sample funcs may be used to create a simple connector that connects to the HTTP REST API provided by the UK's NationalGrid to obtain mixed carbon intensity values for the electrical power generation of the country of Wales (UK).

Builder screenshot

Note that the carbon intensity data is only updated every 30 minutes - so the connector can be tuned down appropriately.

This specific example, connecting to the UK's National Grid, was chosen because the data is publicly available and the REST API does NOT require any form of authentication.

To setup, create the functions easyLearn and easyCur as show below, then add the following tags to your EasyCon connector record.

afEasyConnExtLearnFn   : "easyLearn"
afEasyConnExtSyncCurFn : "easyCur"

Connector screenshot

Also see the Advanced Example for a larger / more complete example of EasyConn Axon functions.

Sample Learn func

// func
// name : easyLearn
// doc  : Sample Learn Func
(connRef, arg : null) => do

  // let the top-level be a single expandable node
  if (arg == null)
    return [{
      dis   : "Carbon Mix - Wales",
      learn : "/wales"
    }].toGrid()

  // contact the api to return and extract point data
  url        : `https://api.carbonintensity.org.uk/regional/wales`
  json       : ioReadJson(url, {safeNames})
  dataDict   : json["data"][0]
  regionDict : json["data"][0]["data"][0]

  // map the json data to points
  learnItems : regionDict->generationmix.map() (dict) => do
    return {
      "dis"    : dict->fuel.capitalize,
      "kind"   : "Number",
      "unit"   : "%",
      "ciType" : "generation",
      "ciKey"  : dict->fuel,
      cur,
    }
  end

  return learnItems.toGrid
end

Sample Sync Cur func

// func
// name : easyCur
// doc  : Sample Sync Cur Func
(conn, points) => do

  url     : `https://api.carbonintensity.org.uk/regional/regionid/17`
  json    : ioReadJson(url, {safeNames})
  mixes   : json["data"][0]["data"][0]["generationmix"]

  curVals : points.map() (point) => do
    data  : mixes.find() (mix) => mix["fuel"] == point["ciKey"]
    return {
      pointRef : point->id,
      val      : data["perc"]
    }
  end

  return curVals.toGrid()
end

Limitations

EasyConn exists to enable Axon programmers to develop their own connectors for SkySpark.

While EasyConn will be sufficient for many use-cases, and an excellent get out of jail free card, a heavy reliance on EasyConn for frequent polling, or a large number of points, or for high-traffic situations - may result in poor performance and system degradation.

For these situations, consider investing in or commissioning a native connector written in pure Fantom. Fantom is the native language of SkySpark and lends itself towards creating optimised code extensions.

Fantom Factory is experienced at writing optimised connectors that leverage:

  • HTTP keep-alive requests
  • secure OAUTH2 end-points
  • SOAP services

Contact Fantom Factory for details.

Tips

To make the most out of your EasyConn connector - here are some optimisation tips.

1. Make fewer API calls

Try to reduce the number of HTTP / API calls. This can be particularly important when retrieving curVals.

A 1000 points polling every 10 seconds (the SkySpark default) could mean the connector is making 6000 HTTP calls every minute!

Should your REST API supply the means to, try to make use of endpoints that return multiple curVals for a single HTTP call.

2. Tune down the polling frequency

By default SkySpark polls connectors to update the curVals on their points every 10 seconds. This can be a lot for an Axon connector, so consider adding a standard tuning record with an decreased polling frequency.

Use the pollTime tag on the connector's tuning record - see SkySpark Conn Tuning for details.

A polling frequency of half the hisCollectInterval will ensure no loss of collected data fidelity.

3. Cache authentication tokens

Session authentication tokens, like BEARER tokens used in OAUTH2, could be cached as transient tags (say, on the connector record) to prevent re-authentication before every HTTP call - thus halving the number of HTTP calls made.

Further reading

Further documentation on Points and Connectors as implemented in SkySpark.

Licensing

EasyConn is a commercial product and requires a licence to be purchased to run in production.

Licences for EasyConn are tied to a SkySpark installation / host ID. This means to use EasyConn on multiple SkySpark installations will require multiple licences; one per installation. Be sure enter your SkySpark licence ID when purchasing, see Where is my SkyArc Installation ID? for details.

Purchased licences are available from the My Licences page on StackHub and should be downloaded to the /var/lic/ directory of your SkySpark installation.

Minor updates to EasyConn may be provided free of charge, but major updates will require a new licence to be purchased.

The End-User License Agreement ("EULA") is contained with the downloaded .pod file.

For support and comments, please email -------------------------.

Evaluation mode

If EasyConn does not find a valid licence, it enters into an evaluation mode whereby a maximum of 100 Axon calls may be made; after which EasyConn will throw a licence fault.

Evaluation mode is designed for developers to try out various features of EasyConn to assess its suitability for purpose.

Disclaimer

The software is provided "AS IS" and the author disclaims all warranties with regard to this software including all implied warranties of merchantability and fitness. In no event shall the author be liable for any special, direct, indirect, or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software.

Special mentions

Special thanks go to Healthy Workers for sponsoring, supporting, and beta testing the EasyConn SkySpark connection.

Healthy Workers Logo

Published by Fantom Factory

Products & Services by Fantom Factory

Packages by Fantom Factory

Commercial packages

Free packages

Licensing options
Developer Bundle - Senior
Our main tools under one licence: Axon Encryptor, Easy Conn, Folio File Sync, HTTP Client, and Pod Builder
1 year licence
$995.00USD
EasyConn
EasyConn - Write connectors in Axon
1 year licence
$495.00USD
Package details
Version1.0.0
LicenseCommercial
Build date10 months ago
on 26th May 2023
Requirements SkySpark v3.1.6
Depends on
File nameafEasyConnExt.pod
File size157.51 kB
MD536f87e2ed50b45dc730d85941b3a8168
SHA1 5e5cd9c2041abca27e4bf84e3b67a393e424eff9
Published by
Fantom FactoryDownload now
Also available via SkyArc Install Manager
Tags
Axon
Connector
Fantom
Sky Spark