DataCall Property

General info

Label

Data Call

Description

User provided script which receives a table with the following entries: ExternalID, DataFrom, DataTo, History. ExternalID supplies the configured Tag Name, which is known in the external system. DataFrom and DataTo specify the acquisition time frame in POSIX miliseconds since epoch. History is a boolean, if true the call is a history call, else it is a continuous call. Additional parameters are: timeout, throttle, pointlimit. The table must be returned with an new 'data' field, containing a table {V=, Q=, T=}. The 'Q' field is optional, the 'T' field must contain a POSIX millisecond value. Additional a 'timeout' parameter will be supplied, which is the latest moment of the user script terminating. In case you experience overload, consider adjusting the 'Slicing' parameter of the HistoryTransporter object. Running a HistoryTransporter in constant overload is not considered an inmation support case. Full function signature: return function(tbl,timeout,throttle,pointlimit).

Data type

String

Default value

"return function(worktable,deephistory,timeout,pointlimit,throttle) end"

Type

Regular

Code

6580

Symbolic name

MODEL_PROP_DATACALL

Lua access code

syslib.model.properties.DataCall

Available since

1.54

Parent properties

CustomConnection

Attributes

Name Tooltip
PROP_CONFIGURABLE The property is configurable and can be changed with DataStudio and the various inmation APIs.
PROP_VISIBLE The property is visible in DataStudio and can be read by the inmation APIs.
PROP_HAS_DEFAULT The property has a default value as standard.

Contained Script Example

return function(worktable,deephistory,timeout,pointlimit,throttle)
    -- load some built-in libraries
    -- this is required to reflect on throttling
    local SOCKET=require'socket'
    -- some string functions we always need
    local STR=require('esi-string')
    -- some datetime function we always need
    local DT=require('esi-datetime')
    --  convenience inmation API call aliasing (makes them faster too)
    local CT=inmation.currenttime
    local GT=inmation.gettime
    local LOG=inmation.log
    -- save the entry time
    local now=CT()
    -- the data call can happen for continuous (near-time) history or
    -- backlog history fetches
    local logtopic
    if deephistory then
        logtopic="Custom Deep History Script Call"
        -- '4' is Debug, '3' is Information, '2' is Warning, '1' is Error
		LOG(4,logtopic,("Entry at %s"):format(GT(now)))
    else
        logtopic="Custom Continuous History Script Call"
		LOG(4,logtopic,("Entry at %s"):format(GT(now)))
    end
    -- this should never happen, but good practice to check
    if "table"~=type(worktable) then
        -- error message and out we go
        LOG(1,logtopic,("The given worktable is of wrong type (%s)"):format(type(worktable)))
        return worktable
    end
    -- overall point counter
    local cnt=0
    -- work through the worktable safely
    for n=1,#worktable do
        -- record pointer for convenience
        local r=worktable[n]
        -- prepare the table of VQT points to return
        r.points={}
        if deephistory then
            -- deep history...
            local base=r.from
            -- set the stepping to a multplicator of 5 minutes
            -- all returned rows will have a distinct data frequency
            local step=n*5*60*1000
            -- initialize the first simulated timestamp
            local ts=base+step
            -- make sure we have a good 'r.to'-Value
            if not DT:VALID(r.to) then
                -- now, since we are inside the worktable record,
                -- we can report individual errors per row, so that
                -- they are displayed in the HistoryTransporter
                -- StateTable property
                r.err=("Invalid 'r.to' parameter (%s)")
            else
                repeat
                    cnt=cnt+1
                    -- simulated VQT record
                    table.insert(r.points,
                    {
                        V=n*1000+cnt,       -- simulated value
                        Q=0,                -- good quality
                        T=ts                -- POSIX ms (UTC)
                    })
                    -- don't forget to increase the timestamp
                    -- to avoid an endless loop!
                    ts=ts+step
                until ts>=r.to
                -- Done for this worktable entry
                LOG(4,"Custom (Deep) History Data Simulation",
                    ("id=%s recid=%s from=%s to=%s produced %d simulated points for deep history")
                        :format(r.id,STR:STRING(r.recid),GT(r.from),GT(r.to),#r.points))
            end
        else
            -- near-time history, we generate two VQT's, one close to 'from', one close to 'to'
            table.insert(r.points,
            {
                V=n,
                Q=0,
                T=r.from+n
            })
            table.insert(r.points,
            {
                V=1000+n,
                Q=0,
                T=r.to-n
            })
            cnt=cnt+2
            LOG(4,"Custom (Continuous) History Data Simulation",
                ("index=%s id=%s recid=%s from=%s to=%s simulated %d points for near-time history")
                    :format(STR:STRING(r.idx),STR:STRING(r.id),STR:STRING(r.recid),GT(r.from),GT(r.to),#r.points))
        end
        -- always reflect on the passed 'throttle' value!
        if 0<throttle and 1>=throttle then SOCKET.sleep(throttle) end
        -- always respect the timeout!
        if inmation.currenttime()>=timeout then break end
    end
    -- Done
    LOG(4,logtopic,("Simulated a total of %d VQT points for %d worktable entries in %d ms")
        :format(cnt,#worktable,CT()-now))
    -- hand back the results
	return worktable
end

Contained Script Return Example

{
  "statistics" : {
    "ms_call" : 4,
    "recs_missingreturn" : 0,
    "points_notgood" : 0,
    "ms_userscript" : 4,
    "recs_returned" : 3,
    "recs_in" : 3,
    "points_oot" : 0,
    "points_malformed" : 0,
    "points_returned" : 1,
    "recs_nodata" : 2
  },
  "result" : [{
      "ExternalID" : "T1",
      "StateRow" : 1,
      "RETURN" : {
        "Q" : 2151546880,
        "ERROR" : "Item T1 was not found in the external server"
      },
      "DataTo" : 1553817600000,
      "DataFrom" : 1553731200000
    }, {
      "ExternalID" : "T2",
      "StateRow" : 2,
      "RETURN" : [],
      "DataTo" : 1553904000000,
      "DataFrom" : 1553817600000
    }, {
      "ExternalID" : "T3",
      "StateRow" : 3,
      "RETURN" : [{
          "T_iso" : "2019-03-29T00:03:03.000Z",
          "T" : 1553817783000,
          "Q" : 0,
          "V" : 155.38177830000001
          "V" : 155.3897991
        }, {
          "T_iso" : "2019-03-29T22:47:42.000Z",
          "T" : 1553899662000,
          "Q" : 0,
          "V" : 155.3899662
        }, {
          "T_iso" : "2019-03-29T23:15:33.000Z",
          "T" : 1553901333000,
          "Q" : 0,
          "V" : 155.3901333
        }, {
          "T_iso" : "2019-03-29T23:43:24.000Z",
          "T" : 1553903004000,
          "Q" : 0,
          "V" : 155.3903004
        }],
      "DataTo" : 1553904000000,
      "DataFrom" : 1553817600000
    }]
}

Examples

Read from or write to the DataCall property.

  • Lua

  • C#

-- Read from the DataCall
local script = syslib.getvalue("<OBJECT FULL PATH>.TransporterConfiguration.AlternativeInterfaceParameter.CustomConnection.DataCall")

-- Write to the DataCall
local script = [[
    return function(tbl, historycall, timeout, pointlimit, throttle) end
]]
syslib.setvalue("<OBJECT FULL PATH>.TransporterConfiguration.AlternativeInterfaceParameter.CustomConnection.DataCall", script)
TcpConfig tcpcfg = new TcpConfig() { HostNameOrIp = "localhost", Port = 6512 };
SecurityCredentials sc = new SecurityCredentials() { ProfileName = "<username>", Password = "<password>" };
StatelessInterface sli = new StatelessInterface(tcpcfg);

// Read from the DataCall
Result result = sli.ReadValue(sc, new ReadItem("<OBJECT FULL PATH>.TransporterConfiguration.AlternativeInterfaceParameter.CustomConnection.DataCall"));
// Write to the DataCall
string script = @"
    return function(tbl, historycall, timeout, pointlimit, throttle) end";
Result result = sli.WriteValue(sc, new WriteItem(script, "<OBJECT FULL PATH>.TransporterConfiguration.AlternativeInterfaceParameter.CustomConnection.DataCall"));