Skip to content

lib-his 库参考 ​

原文: https://finproducts.atlassian.net/wiki/spaces/JIDD3/pages/34793423262/FIN+5.3.1+lib-his 中文整理基于 FIN 5.3.1

导读: 历史学家核心功能

以下为 API 参考,保留英文以便对照源码;目录已列出(英文标题便于检索);概述已尽量中译。


目录(导读) ​

  • lib
  • meta
  • docs
  • tags
  • apps
  • funcs
  • views
  • def
  • supertypes
  • Overview
  • Sizing
  • Precision
  • Configuration
  • Writing
  • Queries
    • Read Grid
    • Query TimeZone
    • Appending N/A
  • His Grid Shape
  • His Period Shape
  • Computed Histories
    • hisFuncWritable
  • Totalized
    • Totalized Rollovers
    • Computed Totalized Points
  • Consumption Data
  • OnWrite
  • Forecast
  • covAvg(val, ts, acc)
  • discreteBoolPeriods(val, ts, acc)
  • discreteEnumPeriods(val, ts, acc)
  • discretePeriods(val, ts, acc)
  • durTrue(val, ts, acc)
  • hisClear(hisArg, span)
  • hisClip(src)
  • hisInterpolate(src)
  • hisJoin(grids, opts: {})
  • hisRead(hisRefs, dates, opts: {})
  • hisRemove(hisRec, spans)
  • hisRewrite(hisArg, fn)
  • hisRollup(src, fold, interval)
  • hisRollupAuto(src, interval: null, foldFinder: null)
  • hisRollups(src, folds, interval)
  • hisSync(timeout: null)
  • hisWrite(data, hisRec, opts: null)
  • parseDiscreteBoolPeriods(val)
  • parseDiscreteEnumPeriods(val, rec: null)
  • parseDiscretePeriods(val)

概述(中译) ​

历史学家核心功能


API 正文(英文) ​

docs ​

Overview • Sizing • Precision • Configuration • Writing • Queries • His Grid Shape • His Period Shape • Computed Histories • Totalized • Consumption Data • OnWrite • Forecast


tags ​

hisAppendNASpecifies the amount of time after a history point's hisEnd that the hisRead() function should append an NA
hisEndTimestamp of newest item in history
hisFuncAxon expression used to create a computed history
hisFuncWritableAllow writing raw data to a point that has the hisFunc tag
hisInterpolateModeExplicitly configures the interpolation mode to use for this point
hisIntervalThe interval at which sampled or consumption data is collected
hisOnWriteAxon expression to trap and map history data before writing to the historian database
hisRollupAutoMinIntervalForces hisRollupAuto() to do a rollup using this interval when none is specified and the range of the source history grid is less than 2 days
hisRollupFuncFunction name to use for hisRollupAuto()
hisRollupIntervalIndicates the roll-up interval in his grid column meta-data
hisSizeApproximate number of timestamp/value pairs stored in history
hisStartTimestamp of oldest item in history
hisTotalizedRolloverDefines the rollover value for a totalized history - see totalized
hisTsPrecisionControls the precision used to store timetamps in the historian
periodsTimeline of on/off periods encoded as Base64 via discretePeriods()

apps ​

hisViews used to visualize and analyze historical point data

funcs ​

covAvgFolding function for generating a time weighted average on change-of-value histories (where hisInterpolate() is "cov")
discreteBoolPeriodsFold timestamp/bool value pairs into an encoded Str of discrete minutely intervals
discreteEnumPeriodsFold timestamp/enum Str value pairs into an encoded Str of discrete minutely intervals
discretePeriodsFold timestamp/bool value pairs into an encoded Str of discrete minutely intervals
durTrueFold function for folding timestamp/bool value pairs into durations when true (runtime)
hisClearClear the history items in the given range
hisClipRemove the rows with leading/trailing timestamps from the actual query range
hisInterpolateInterpolate all the null value cells for each timestamp
hisJoinGiven a list of history grids, join them by the ts timestamp column
hisReadQuery history for an arbitrary range
hisRemoveRemove items from a history using a timestamp or timestamp range
hisRewriteRewrite every item of a history using the given transformation function
hisRollupRoll up a history grid over discrete intervals of time with the given fold function
hisRollupAutoAutomatically chooses the best rollup interval and the best rollup fold function for each history
hisRollupsPerform a series of rollups over discrete intervals
hisSyncBlock until any pending history writes/clears are completed
hisWriteAsynchronously write the specified timestamp/value pairs to the history
parseDiscreteBoolPeriodsParse a Base64 encoded timeline of discrete Bool periods as encoded by discreteBoolPeriods()
parseDiscreteEnumPeriodsParse a base64 encoded string timeline of discrete enum periods as encoded by discreteEnumPeriods()
parseDiscretePeriodsParse a base64 encoded string timeline of discrete periods as encoded by discretePeriods()

views ​

hisChartVisualize historical point data as a graphical chart
hisCompareVisualize historical point data from two different spans
hisCorrelateChart a linear correlation of historical point data
hisEquipVisualize historical point data of a single equipment
hisImportImport point history data into the local project database
hisTableVisualize historical point data as a table


def ​

app:his ​

Views used to visualize and analyze historical point data


meta ​

defapp:his
disKeyui::historian
iconhis
isapp
liblib:his

supertypes ​

featureFeature namespace of definitions formatted as feature:name
appUI application grouping of views

lib his ​

Overview ​

The history extension implements the SkySpark historian or time-series database which is is optimized to store and query large volumes of timestamp/value pairs which are typically associated with sensor data. The history extension is built with the following basic design:

  • Points which are historized are tagged with his to indicate that historical data is available
  • Timestamp/value pairs for the point are stored to Folio using a highly compressed binary format optimized for time-series data
  • The history extension provides a rich Axon library to query and analyze the historical data

The following value types of histories are supported:

  • Bool
  • Number (encoded as int or float)
  • Str
  • Coord

Also see hisKit which provides a rich library to perform analytics on time series data stored in the historian.

Sizing ​

Historical data tends to consume the bulk of the disk space in a typical application. Due to the compression algorithms used there is no exact formula for calculating disk space. Analysis of projects has shown an average about 1.5 bytes per timestamp sample which equates to about 51KB per year per point for 15min interval data.

Precision ​

By default the SkySpark historian stores timestamps with one second precision. If you have timestamps measured in milliseconds (or smaller) they will be floored to the nearest second during storage. You can turn on millisecond precision for timestamps by adding the hisTsPrecision tag.

Analog data is currently stored using a 32-bit floating point number. If your original data was 64-bit floating point, accuracy may be lost.

If your application requires higher precision, please let us know.

Configuration ​

History records use the following tags:

  • his: marker tag
  • tz: timezone of the timestamps as a city name from the Olson timezone database (see TimeZone)
  • kind: indicates expected scalar value type; must be "Number", "Bool", or "Str"
  • unit: numeric histories must define a unit tag with the unit identifier; this unit is assigned to all numbers read from the history and checked during history writes

Writing ​

The historian is designed to batch write histories to the disk. To achieve the best performance the history data should be sorted and written in "append-only mode" (always writing data with newer timestamps).

If the historian detects out-of-order data it will automatically re-sort the data to ensure items are always ordered by timestamp. However this can be expensive because it requires decompressing the history data for that chunk into memory to re-sort it. So always try to work in append-only mode. If an out-of-order write is performed, a warning with the message "[his] Out of order" is logged. You can suppress this warning by passing in {noWarn} for the options.

The historian will also attempt to detect duplicate items. If an item with the same timestamp is detected, then the old one is discarded and replaced by the new item. Note that this feature has the same performance implications as out-of-order data. Note that timestamps are floored to the closest second or millisecond based on the precision before checking for duplicate timestamps.

You can write history data using the hisWrite() Axon function or with the HTTP API. Here is a simple example which writes some CSV data into a history:

// import history data from CSV file where timestamps
// are formatted as 2010-10-02T13:00
ioReadCsv(`io/his.csv`)
  .map(row => {ts: parseDateTime(row->ts, "YYYY-MM-DD'T'hh:mm", "New_York"),
               val: parseNumber(row->val)})
  .hisWrite(hisId)

You must have the tz and kind tags properly configured on your history record before you write any items. If a conflict is detected then the system will raise an exception on write. If you happen to write a series of items incorrectly (such as using wrong timezone), you can rewrite the history using the hisRewrite() function.

Queries ​

All history queries begin with the hisRead() function. This function takes a set of recs with the his tag, a date range, and a set of options. The function returns the historical data as a grid joined by timestamp.

The input piped to the hisRead function is quite flexible:

readAll(zoneTemp).hisRead(null)      // grid of history recs
read(zoneTemp).hisRead(null)         // single history rec
hisRead(@13cb8334-b4721633, null)    // Ref
hisRead([@13cb8334-b4721633], null)  // list of Refs

If a list or grid of records is passed to hisRead, only the records which implement the his marker tag are used (the others are silently ignored).

The date/time range used with hisRead is likewise very flexible:

hisRead(src, null)                   // all the records found
hisRead(src, 2010)                   // entire year of 2010
hisRead(src, 2010-03)                // entire month of March 2010
hisRead(src, 2010-03-05)             // entire day of March 5th, 2010
hisRead(src, 2010-01-01..2010-03-01) // date range Jan 1st to Mar 31st
hisRead(src, today)                  // any of the core time funcs can be used

You may use an optional third parameter to pass in additional options to the query such as a limit on the number of rows returned.

Read Grid ​

When a read is performed, the result is returned as a grid joined by timestamp. The timestamp column is named ts, and each record passed into hisRead becomes a column named v0, v1, etc. The meta for each value column is the history record itself. Consider this example:

// let's assume two zone temps in our database:
{dis:"East Wing", zoneTemp, his, ... }
{dis:"West Wing", zoneTemp, his, ... }

// read two zone temps, and get their historical data for yesterday
r: readAll(zoneTemp).sort("dis").hisRead(yesterday)

The resulting grid might look something like:

ts      v0    v1
-----   ----  ----
00:05   72.3  74.1
00:10   72.4  74.1
00:15         74.2
00:16   72.5
00:30   72.6  74.1
...     ...   ...

Note the ts column contains full DateTimes, but to keep things simple we are only showing time of day here. Since we sorted the records by their dis tag in the example, so we know that v0 is "East Wing" and v1 is "West Wing". The meta dictionaries for the two value columns are the records passed into the hisRead function. For example:

r.col("v0")->dis  // evaluates to "East Wing"
r.col("v1")->dis  // evaluates to "West Wing"

The rows of the query grid are joined by timestamp. If samples have the exact same timestamp then they are joined into the same row. Unless your data is aligned to the second, then the join will be sparse. Value columns without a sample for a given timestamp will have null for that row. In the example above, we can see that 00:05, 00:10, and 00:30 are joined by an aligned timestamp. However 00:15 and 00:16 are sparse.

The hisRead function returns raw data - the actual samples stored into the historian. Typically unless you are charting a 24-hour period or less, then you will pipe hisRead into additional history functions to perform rollups, maps, and filters.

Query TimeZone ​

All history records are required to implement the tz tag. When performing a history query, all the values are joined by a single ts column. If the set of histories shares the exact same tz value, then the resulting ts column will be in that timezone.

If however you perform a query across multiple timezones, then the timestamp is normalized into the "Etc/Rel" timezone (see TimeZone.rel). This is a special timezone which indicates relative time of day (as opposed to absolute time). If you wish to normalize to an explicit timezone then pass it as an option to the hisRead function.

Let's take an example:

Data for tz:"New_York"
12:00 75
13:00 76
14:00 77
15:00 78

Data for tz:"Chicago"
12:00 85
13:00 86
14:00 87
15:00 88

By default if were to perform a hisRead on these two records they would be joined as follows:

// query the records
hisRead(src, date)

// resulting join
ts     v0   v1
-----  --   --
12:00  75   85
13:00  76   86
14:00  77   87
15:00  78   88

If however we wished to join these timestamps by New_York time, then the Chicago data would be one hour behind:

// query the records
hisRead(src, date, {tz:"New_York})

// resulting join
ts     v0   v1
-----  --   --
12:00  75
13:00  76   85
14:00  77   86
15:00  78   87
16:00       88

Note that the data is joined by absolute time. When its 2pm in New York, it is 1pm Chicago.

Appending N/A ​

When dealing with data that is synchronized, we frequently wish to write rules that gracefully handle lags in the data synchronization. For example, a COV point is assumed to have the same value as its last value, even if we haven't synchronized the data for 24 hours. So we may want our rules to skip running if we don't have up-to-date data yet. You can use the hisAppendNA tag to help identify this condition.

When you do a hisRead on a point that has the hisAppendNA tag, an NA value will be appended if

rec["hisEnd"] + rec["hisAppendNA"] < span.end

For example,

// history point
hisEnd: 2016-01-14 01:30 EST
hisAppendNA: 30min

// history data
ts                 val
2016-01-14 00:00     0
2016-01-14 00:30    30
2016-01-14 01:00   100
2016-01-14 01:30   130

hisRead(rec, 2016-01-14)

// result
ts                 val
2016-01-14 00:00     0
2016-01-14 00:30    30
2016-01-14 01:00   100
2016-01-14 01:30   130
2016-01-14 02:00    NA  <-- NA appended

The hisRead appended NA because

(2016-01-14 1:30 EST) + 30min < (2016-01-15 00:00 EST)

If, however, hisAppendNA had been 24hr, no NA would have been appended since the hisRead span.end is within the 24hr threshold.

His Grid Shape ​

Most functions which consume history data require grids to be shaped a specific way we call a his grid. His grids have the following restrictions:

  1. First column must be called ts and contain only ordered DateTimes with the same timezone
  2. Zero or more value columns, typically named v0, v1, etc
  3. Grid meta must define a hisStart and hisEnd tags

Results from hisRead() or the built-in history functions will automatically shape his grids properly. However if you are constructing history data yourself, then you will need to adhere to these restrictions.

His Period Shape ​

Some functions expect to work with history grids where the values are durations. This special grid shape is called a his period grid. In order to be considered a "normalized" his period grid, the following must be true

  1. The grid must meet all the conditions of the his grid shape with the constraint that values must be durations.
  2. The periods must not overlap. In the case where you have overlapping periods, you can use the hisPeriodNormalize() func to merge overlapping periods.

Computed Histories ​

A normal history record stores its samples as a set of timestamp/value pairs to disk. But on occasion it is preferable to compute a history's samples on demand using a function. Histories which generate their samples on demand are called computed histories. A computed history is configured just like a standard history with the addition of a hisFunc tag which is an Axon expression which evaluates to a function with the following parameters:

  • rec: the history record itself
  • dates: a date time range
  • opts: currently not used
  • yield the generator sink function which takes DateTime timestamp and value A computed history may also return an optional Dict of metadata that will be merged into the result his grid meta. Note that you cannot override "his" meta tags; they will take precedence.

Suppose we wish to create a computed history which simulates a fixed occupied schedule where occupancy begins at 8am and ends at 10pm. First we create a new function called "occupancyHisFunc":

(rec, dates, opts, yield) => do
  tz: rec->tz
  eachDay(dates) day => do
    yield(dateTime(day, 8:00, tz), true)
    yield(dateTime(day, 22:00, tz), false)
  end
  // Returns some metadata
  return {foo:"bar"}
end

Here we are using the eachDay() function to iterate all the days within the date time range. For each day we yield a history item of true at 8am and false at 10pm. Now we create the computed history record:

{dis:"Occupancy", his, kind:"Bool", tz:"Chicago", hisFunc:"occupancyHisFunc"}

We can test it using the standard hisRead() function:

read(dis == "Occupancy").hisRead(pastWeek)

You can use partial application to parameterize your history functions on a per record basis. Lets take the function above and add start/end time parameters:

(rec, dates, opts, yield, startTime:8:00, endTime:22:00) => do
  tz: rec->tz
  eachDay(dates) day => do
    yield(dateTime(day, startTime, tz), true)
    yield(dateTime(day, endTime, tz), false)
  end
end

We can use partial application to bind start, end times to our function:

{dis:"Occupancy Params", his, kind:"Bool", tz:"New_York",
 hisFunc:"occupancyHisFunc(_, _, _, _, 6:00, 23:00)"}

Lets consider another example. Suppose our site doesn't have a single site level electric meter, but instead has two meters for each of the wings. Let's construct a computed history which sums the demand from each meter:

(rec, dates, opts, yield) => do
   readAll(kw and wing)
     .hisRead(dates)
     .foldCols(["v0", "v1"], "val", sum)
     .each(row => yield(row->ts, row->val))
end

Lets review the code above line by line. The first line does a readAll() to read the two sub-meters which we've assumed have been marked with the wing tag. The next line performs a standard hisRead() on the two histories. The foldCols() call sums the "v0" and "v1" columns into a single "val" column. Lastly we iterate the rows via each() and yield the timestamp and summed values. Note in production this function would require that the sub-meters have data perfectly aligned by timestamp - in practice we would probably need an extra interpolation step.

hisFuncWritable ​

Normally, a computed point is not writable. However, sometimes it is desirable to store "raw" data about a point in the historian, but use a computed point as the default view of that data. You can use the hisFunc tag on a point with storage, but to enable writes you must also apply the hisFuncWritable tag to the point.

IMPORTANT: To read the underlying data for your computed history, you need to pass the {-hisFunc} option to your hisRead(). If you don't do this, your computed func will be called over-and-over again resulting in a stack overflow error. You could also use the {raw} option, but be aware that {raw} disables all transformations on your underlying data (e.g. timestamp shifting for consumption points).

(rec, dates, opts, yield) => do
  // read underlying data
  his: rec.hisRead(dates, opts.set("hisFunc", removeMarker()))

  ... do computations on underlying his data ...
end

See the computed totalized points section for a real-world example of using the hisFuncWritable tag.

Totalized ​

It is common in some logs to store an continuously incrementing stream of totalized values. For example electrical consumption is often stored like this:

ts     val
-----  --------
08:00  1000 kWh
09:00  1057 kWh
10:00  1206 kWh
11:00  1321 kWh
12:00  1404 kWh

The electrical consumption of each hour is actually the delta between each sample. For example 57kWh was used between 8am and 9am. If we tried to sum our consumption using a function like hisRollup() we would get incorrect results using the data in its totalized form.

In this case, you can add the hisTotalized marker to the history record and the hisRead() function will automatically convert the samples to compute the delta. For example the records above would be read as:

ts     val
-----  --------
08:00  null
09:00   57 kWh  // 1057 - 1000
10:00  149 kWh  // 1206 - 1057
11:00  115 kWh  // 1321 - 1206
12:00   83 kWh  // 1404 - 1321

Note that boundary records are computed as null. This means that unlike other histories we don't necessarily get the value immediately before a given history.

Totalized Rollovers ​

When using a totalized history, a rollover occurs anytime that that a sample is read which is less than the previous value (negative delta). By default a rollover will use the new value without computing a delta. If you add the hisTotalizedRollover tag then the new value will be the computed as follows:

delta = (rollover - previous) + current

Consider this example with the raw data:

ts     val
-----  ------
08:00  10 kWh
09:00  15 kWh
10:00   4 kWh
11:00   7 kWh

Without a rollover definition, we will compute the delta values as:

ts     val
-----  ------
08:00  null
09:00   5 kWh  // 15 - 10
10:00   4 kWh  // ignore last value, and use 4 as delta
11:00   3 kWh  // 7 - 4

Or if we define hisTotalizedRollover: 20 then the deltas are:

ts     val
-----  ------
08:00  null
09:00   5 kWh  // 15 - 10
10:00   9 kWh  // (20 - 15) + 4
11:00   3 kWh  // 7 - 4

Computed Totalized Points ​

Sometimes the behavior of a totalized meter is too complex for the standard rollover logic described above to work. For example, net-metered buildings, or thermal systems with heat recovery or potential reverse flow will frequently generate valid negative deltas. There are also cases where meters will generate large positive deltas that need to be handled as a special case.

In these instances, you can make use of a special feature of computed points. You can use a standard writable point to store the raw, totalized data. Then, apply the hisFunc tag to that point to use a computed history to handle all the complex logic for how you want to handle the deltas. To use a hisFunc with a writable point, you must also apply the hisFuncWritable tag to the point. See the hisFuncWritable section for details.

The following is an example of how this feature could be used to configure how negative and positive deltas are handled. See the first three comments in this forum thread for more background.

// His Point
point
his
hisFuncWritable
hisFunc: computeDeltas
hisTotalizedDeltaMin: -50
hisTotalizedDeltaMax: 1000
... other tags ...

// computeDeltas() hisFunc
(rec, dates, opts, yield) =>
  // get custom configuration from his rec
  deltaMin: rec["hisTotalizedDeltaMin"]
  if (deltaMin == null) deltaMin = 0

  deltaMax: rec["hisTotalizedDeltaMax"]
  if (deltaMax == null) deltaMax = posInf()

  // read raw totalized data - make sure you pass the {-hisFunc} option!!!
  rawData: rec.hisRead(dates, {-hisFunc, -hisTotalized})

  // compute deltas
  prev: null
  rawData.each row => do
    // handle first value (or nulls in data)
    if (prev == null) prev = row

    // compute delta
    delta: row->v0 - prev->v0

    // handle rollover
    if ((delta < deltaMin) or (delta > deltaMax)) do
      if (rec.has("hisTotalizedOnRollover")) do
        delta = rec->hisTotalizedOnRollover
      else if (rec.has("hisTotalizedRollover")) do
        delta = rec->hisTotalizedRollover + delta
      else do
        delta = row->v0
      end
    end

    // yield result
    yield(row->ts, delta)

    // reset previous row
    prev = row
  end

Consumption Data ​

Consumption data is unique in that the timestamp of the logged data value indicates the end of an interval. All functions that work with historical data in SkySpark assume that a timestamp indicates the start of an interval. Therefore, history points that model consumption data should be tagged with hisMode set to "consumption". When you do a hisRead() on a consumption point, the data will automatically be normalized so that timestamps indicate the start of an interval. For example, given this raw data:

23:45  10
00:00  20
00:15  30
00:30  40
00:45  50
01:00  60
01:15  70

When we perform a hisRead on the data above, we would get:

23:45  20
00:00  30
00:15  40
00:30  50
00:45  60
01:00  70

In addition to affecting a timestamp shift, consumption points imply:

  1. A rollup behavior (sum())
  2. An interpolation behavior (apportion)

The canonical use-case for consumption points is energy (kWh) data. Therefore you should not use hisMode=consumption simply to achieve a timestamp shift. If you just need a timestamp shift, but the rollup and interpolation behavior does not apply to your point (e.g. a rolling demand point), you should consider using hisOnWrite instead.

OnWrite ​

You can register an Axon function on a history record to receive a callback before data is written to the historian database. This feature allows:

  • data cleanup
  • timezone conversion from source data
  • kind conversion (such as mapping 1/0 to true/false)
  • unit conversion from source data

To register a write callback, create a hisOnWrite tag on the history record with a string which evaluates to an Axon function that takes a history data grid and Dict record for the point being written. The history data grid has a ts and val column. The function must return the mapped data to write to the database. The on write callback is only invoked when writing new data via hisWrite().

Here are some simple examples of on write callbacks:

// convert source data to configured timezone
(his, rec) => do
  his.map r => r.set("ts", r->ts.toTimeZone(rec->tz))
end

// convert 0 to false and anything else to true
(his) => do
  his.map r => r.set("val", r->val != 0)
end

Forecast ​

The Folio historian provides special support for forecast items. Forecast items allow management of future forecast data to be integrated seamlessly with persistent time-series data. Summary of forecast characteristics:

  • stored transiently (cleared on restart)
  • written using the {forecast} option
  • write semantics is always replacement of forecast items
  • forecast items do not effect hisSize, hisStart, or hisEnd tags
  • hisRead will append forecast items when {forecast} option is specified
  • hisRead will read only forecast items using {forecastOnly} option
  • reads automatically clip forecast to now or latest persistent timestamp

To write forecast data, use the forecast tag in your hisWrite options:

hisWrite(data, id, {forecast})

When using the forecast option, it overwrites any previous forecast data. The forecast data is stored transiently and will be cleared if the VM is restarted. Writing forecast items does not modify the hisSize, hisStart, or hisEnd tags - these tags only represent the persistent items.

The default behavior for hisRead only returns persistent items. You can force forecast items to be appended with the forecast option tag. Or you can use the forecastOnly tag to only return transient forecast items. Forecast data is automatically clipped by the current timestamp or the latest persistent item. Forecast items are not filtered by the time span.

// read today persistent data plus forecast items
hisRead(pt, today, {forecast})

// read only forecast items
hisRead(pt, today, {forecastOnly})

Note: reading forecast items will not work correctly using a null span. Always use an explicit span such as today when working with forecast data.



def ​

func:covAvg ​

covAvg(val, ts, acc) ​

Folding function for generating a time weighted average on change-of-value histories (where hisInterpolate() is "cov"). The average is calcualted by weighting each sample with its ratio of duration in the the overall interval. For example given the following time/value pairs:

00:00  10
02:00  30
12:00  70

If performing a 1day rollup with the data above, the point had a value of 10 for 2 hours, a value of 30 for ten hours, and a value of 70 for 12 hours (until end of day). The time weighted COV average would be 48.3:

10 * (2/24) + 30 * (10/24) + 70 * (12/24)

If any value in the rollup interval is na(), then the result is na().


meta ​

deffunc:covAvg
disKeyui::covAvg
foldOnNumber
isfunc
liblib:his
namecovAvg

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:discreteBoolPeriods ​

discreteBoolPeriods(val, ts, acc) ​

Fold timestamp/bool value pairs into an encoded Str of discrete minutely intervals. This rollup is similar to discretePeriods() with the same Base64 encoding. There are two significant differences:

  1. This rollup supports NA data
  2. Instead of encoding offset/duration pairs, the encoding is offset/ordinal pairs. The ordinal values map as {0: false, 1: true, 2: NA}

Also see parseDiscreteBoolPeriods() and Etc.discretePeriods.


meta ​

deffunc:discreteBoolPeriods
foldOnBool
isfunc
liblib:his
namediscreteBoolPeriods

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:discreteEnumPeriods ​

discreteEnumPeriods(val, ts, acc) ​

Fold timestamp/enum Str value pairs into an encoded Str of discrete minutely intervals. This rollup works very similar to discretePeriods() with the same Base64 encoding. The difference is that instead of offset/duration pairs, the encoding is offset/ordinal pairs. The ordinal values map the position of each string value in the point's enum tag. If a string value is not mapped by enum then a value of 0xff (255) is used for the ordinal. If a string value is NA, then a value of 0xfff (4095) is used for the ordinal.

Also see parseDiscreteEnumPeriods() and Etc.discretePeriods.


meta ​

deffunc:discreteEnumPeriods
foldOnStr
isfunc
liblib:his
namediscreteEnumPeriods

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:discretePeriods ​

discretePeriods(val, ts, acc) ​

Fold timestamp/bool value pairs into an encoded Str of discrete minutely intervals. The string encoding is based on 12-bit minutely start/duration pairs. Each 12-bit minute offset/duration is encoded using two 6-bit ASCII characters encoded by the Base64 table. Also see parseDiscretePeriods() and Etc.discretePeriods.

Here is the Fantom code which decodes a string to iterate a period where time is offset in minutes from base timestamp and dur is duration of period in minutes (assuming a minutely interval).

static Void decodePeriod(Str str, |Int time, Int dur| f)
{
  for (i := 0; i<str.size; i += 4)
  {
    time := fromBase64[str[i+0]].shiftl(6) + fromBase64[str[i+1]]
    dur  := fromBase64[str[i+2]].shiftl(6) + fromBase64[str[i+3]]
    f(time, dur)
  }
}

// base64 lookup tables
static const Str toBase64 :=
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
static const Int[] fromBase64
static
{
  list := Int[,].fill(0, 128)
  toBase64.each |ch, i| { list[ch] = i }
  fromBase64 = list
}

Note: the encoding size of 12-bits limits representations to offsets of 4095 minutes or roughly 2.8 days. Using using rollup intervals over 1day cannot be represented using this encoding and will be silently truncated past 2.8 days.


meta ​

deffunc:discretePeriods
foldOnBool
isfunc
liblib:his
namediscretePeriods

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:durTrue ​

durTrue(val, ts, acc) ​

Fold function for folding timestamp/bool value pairs into durations when true (runtime). This is a rollup function of arity 3, so it can only be used with history rollups. na() is treated like false, and terminates a true period.


meta ​

deffunc:durTrue
foldOnBool
isfunc
liblib:his
namedurTrue

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisClear ​

hisClear(hisArg, span) ​

Clear the history items in the given range. This function has similiar semantics as hisRemove() except:

  • it supports multiple history records as a target
  • it only supports a single span or null

WARNING: once the data is cleared, there is NO recovery!!!

The hisArg contains the list of histories to query using any value supported by the toRecList() function. See hisRead().

The span can be any non-null span accepted by hisRead() or null. A null value will delete all the history data for each point. Unlike hisRemove() the span cannot be a list nor a single DateTime.

The result of this function is unspecified and may change.


meta ​

admin✓
deffunc:hisClear
isfunc
liblib:his
namehisClear

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisClip ​

hisClip(src) ​

Remove the rows with leading/trailing timestamps from the actual query range. The query range is defined as inclusive of meta.hisStart and exclusive of meta.hisEnd. These meta tags are derived from the dates range passed to the hisRead() function.

Example:

hisRead(points, dates).hisClip

meta ​

deffunc:hisClip
isfunc
liblib:his
namehisClip

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisInterpolate ​

hisInterpolate(src) ​

Interpolate all the null value cells for each timestamp. See Interpolation for details.


meta ​

deffunc:hisInterpolate
isfunc
liblib:his
namehisInterpolate

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisJoin ​

hisJoin(grids, opts: {}) ​

Given a list of history grids, join them by the ts timestamp column. This function automatically renames columns to ensure each column in result has a unique name. Grid meta is merged in order of grids parameter, however all "hisX" meta tags are stripped, and new hisStart and hisEnd are computed based on a merged range.

The following options are supported:

  • tz: specifies the timezone for the ts column for the join. If omitted, and all the histories have the same timezone then that is the timezone used by ts. Otherwise histories are joined by relative time of day using "Etc/Rel". If an explicit timezone other than "Etc/Rel" is specified, then timestamps are joined by absolute time.

Example:

a: hisRead(pointA, dates)
b: hisRead(pointB, dates)
hisJoin([a, b])

meta ​

deffunc:hisJoin
isfunc
liblib:his
namehisJoin

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisRead ​

hisRead(hisRefs, dates, opts: {}) ​

Query history for an arbitrary range. The result is a grid with a column called "ts", and multiple "v0", "v1", etc columns with the values joined by timestamp.

The hisRefs contains the list of histories to query using any value supported by the toRecList() function:

  • Ref or Ref[] to his
  • Dict/Row or Dict[]/Row[] of his
  • Grid of his

Any records which don't support the his tag are silently ignored. If no records with the his tag are specified then an exception is thrown.

The dates specifies the start/ending times of the query:

  • if start is null, then we use oldest item
  • if end is null, then we use most recent item
  • if start is Date, then we use midnight of that day
  • if end is Date, then we use midnight of next after
  • otherwise start/end must be DateTimes

The following convenience values are also allowed for range:

  • Date: convenience for date..date
  • null: convenience for null..null
  • Int: if between 1900 and 2100 convenience for entire year
  • Fn: function is resolved to one of the above today vs today()

The result always includes the previous item immediately before the range, and immediately after the range. The leading/trailing values are often needed to interpret the first/last values of the result. If leading/trailing values are not desired, then pipe the result of this function to hisClip()

The following options are supported:

  • limit: used to cap the number of records generated by the query. The default is 10,000. You may use Remove.val to indicate no limit such as {-limit}.
  • tz: specifies the timezone for the ts column used to join multiple histories. If omitted, and all the histories have the same timezone then that is the timezone used by ts. Otherwise histories are joined by relative time of day using "Etc/Rel". If an explicit timezone other than "Etc/Rel" is specified, then timestamps are joined by absolute time.
  • hisTotalized: set to Remove.val to disable delta reads of of hisTotalized recs (reads raw values); in Axon you can specify this like {-hisTotalized}.
  • hisMode: set to Remove.val to force all reads to behave as though the hisMode tag was not set on the rec; in Axon you can specify this like {-hisMode}.
  • hisAppendNA: set to Remove.val to disable the append NA threshold on histories that have this tag.; in Axon you specify this like {-hisAppendNA}. See hisAppendNA for details.
  • hisFunc: set to Remove.val to disable the computed function for this point. Can only be used on writable computed points. In Axon you can specify this like {-hisFunc}.
  • raw: set to Marker.val to disable all transformations of the history read; in Axon you can specify this like {raw}. This option is equivalent to {-hisTotalized, -hisMode, -hisAppendNA, -hisFunc}.
  • forecast: include forecast items
  • forecastOnly: include only forecast items

Note that the query limit is applied to the pipeline, not the raw hisRead. So if hisRead is piped directly to a hisRollup, the limit will apply to the number of rollup rows, not raw rows. Unless configured in opts, the default limit is 10,000. This value may be overridden by applying the hisLimit tag on the HisExt record. If the limit is hit and more data is available, then grid meta has the limit and more tags defined.

Also see his.


meta ​

deffunc:hisRead
haystackApiRead time series data to historian
isfunc
liblib:his
namehisRead

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisRemove ​

hisRemove(hisRec, spans) ​

Remove items from a history using a timestamp or timestamp range. This function blocks until the remove is complete.

WARNING: once the data is removed, there is NO recovery!!!

The hisRec supports anything accepted by toRec(). Note this function only works on one record at a time.

The spans argument can be any non-null span accepted by hisRead() or a list of such spans. If a single DateTime is used then just that item is removed, otherwise any items within the span's inclusive start time and exclusive end time are removed. Note that timestamps are normalized according to the record's hisTsPrecision.

This function is best used for fine grained removal. Also see the hisClear() function for removing multiple points or the entire history.

The result of this function is unspecified and may change.

Examples:

hisRemove(pt, ts)              // remove single item
hisRemove(pt, startTs..endTs)  // remove span of items
hisRemove(pt, [ts1, ts2])      // remove list of timestamps

meta ​

admin✓
deffunc:hisRemove
isfunc
liblib:his
namehisRemove

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisRewrite ​

hisRewrite(hisArg, fn) ​

Rewrite every item of a history using the given transformation function. This function will automatically update the kind, tz, and unit tag if the mapping function returns a new timezone, new value type, or new unit. The mapping function takes (val, ts, his) and returns new items as tuple list of [ts, val] or null to omit a specific writing item.

CAUTION: This function will read and rewrite every item and there is no undo, so use it with care!

The hisArg contains the list of histories to rewrite using any value supported by the toRecList() function. See hisRead().

Return a grid with a row for each history converted. The following columns are included:

  • id: of the history record
  • dis: dis string of the history record
  • numRewritten: number of history items rewritten

Side effects:

  • rewrites every history item
  • clears context read cache

Examples:

// to convert to New_York timezone
hisRewrite(hisId) (val, ts) => [ts.toTimeZone("New_York"), val]

// convert numbers to bool if non-zero
hisRewrite(hisId) (val, ts) => [ts, val != 0]

// convert units
hisRewrite(hisId) (val, ts) => [ts, val.to("kW")]

meta ​

admin✓
deffunc:hisRewrite
isfunc
liblib:his
namehisRewrite

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisRollup ​

hisRollup(src, fold, interval) ​

Roll up a history grid over discrete intervals of time with the given fold function. The src must be a history grid created from hisRead() or some transformation of it.

Rollups are inclusive of start and exclusive of end times. For example a daily rollup includes midnight of the current day, but excludes midnight of the next day. All the items found within the interval are passed to the folding function to compute a timestamp/val pair with each timestamp aligned to the start of the interval. Use the string "*" to rollup the entire grid as one big interval.

For example a rollup interval of 1day over a one year range would calculate 365 (or 366 if leap year) items with the start time being midnight of each day. Interval rules:

  • Less 1day: use absolute time, aligned off start (example 1hr)
  • 1day: daily rollup, aligned off midnight
  • 1wk: weekly rollup, aligned off midnight on Sunday
  • 1mo: monthly rollup, aligned off midnight on 1st of month
  • 3mo: quarterly rollup, aligned off midnight on 1st of 3 month intervals
  • 1yr: yearly rollup, aligned off midnight Jan 1st
  • Anything else is an error

See core::fold for how folding functions work. History rollups also support rollup functions with arity of 3 (val, ts, acc).

This function will work with forecast data provided one of the following is true:

  1. You did the initial hisRead() with the {forecast} option
  2. The column metadata for the value has a hisEnd in the future
  3. The data comes from a computed point (hisFunc)
  4. The data does not come from a demo database

meta ​

deffunc:hisRollup
isfunc
liblib:his
namehisRollup

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisRollupAuto ​

hisRollupAuto(src, interval: null, foldFinder: null) ​

Automatically chooses the best rollup interval and the best rollup fold function for each history.

If null is passed for the interval, then the following automatic selection is made:

  • less 2days: Check each history rec to see if any specify the hisRollupAutoMinInterval tag and take the maximum value. Otherwise, no rollup is applied and the raw history grid is returned.
  • one week: 10min interval
  • one month: 1hour interval
  • over one month: daily interval

The rollup function applied to each history is determined as follows:

  1. if foldFinder parameter is specified, it is called for each history to get fold function. If it returns null we check next step
  2. if hisRollupFunc is defined on the history, then use it
  3. Select fold function based on kind:
    1. Bool: discreteBoolPeriods()
    2. Number with hisMode of "cov": covAvg()
    3. Number pick based on unit's quantity:
      • power: max
      • volume, energy: sum()
      • default: avg
    4. Str with enum tag: discreteEnumPeriods()
    5. fallback to count()

If your history has no data or is a computed history, you should explicitly specify the kind or hisRollupFunc to ensure a suitable rollup is selected.

If a rollup is applied, then the following tags are automatically applied to the resulting grid:

  • hisRollupInterval: applied to grid.meta interval used for the rollup
  • hisRollup: applied to col.meta of each value column (such as "avg")
  • hisRollupDis: applied to col.meta for each rollup, if all the columns have the same rollup, then it is applied to grid.meta also

Examples:

// over 1hr intervals
src.hisRead(pastWeek).hisRollupAuto

// over 6hr intervals
src.hisRead(pastMonth).hisRollupAuto

// explicit 1day intervals
src.hisRead(pastMonth).hisRollupAuto(1day)

// explicit fold finder, uses max for all columns
src.hisRead(pastMonth).hisRollupAuto(null, his => max)

meta ​

deffunc:hisRollupAuto
isfunc
liblib:his
namehisRollupAuto

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisRollups ​

hisRollups(src, folds, interval) ​

Perform a series of rollups over discrete intervals. This function works just like hisRollup(), but takes a list of folding functions. Instead of a single value per input history, there are a series of columns for each folding function. For example if the input has a v0 and v1 column and the folding functions are [min, max], then the resulting grid will have v0_min, v0_max, v1_min, and v1_max.


meta ​

deffunc:hisRollups
isfunc
liblib:his
namehisRollups

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisSync ​

hisSync(timeout: null) ​

Block until any pending history writes/clears are completed.


meta ​

admin✓
deffunc:hisSync
isfunc
liblib:his
namehisSync

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:hisWrite ​

hisWrite(data, hisRec, opts: null) ​

Asynchronously write the specified timestamp/value pairs to the history. The timestamps must match tz of history. If the history has a unit tag, then the items have either a null or matching unit. Return future which may be used to track when write completes - the value of the future subject to change.

Writing data with existing timestamps will replace the current data with the new data. Note that timestamp comparison happens after normalizing timestamps to closest second or millisecond.

The data may be one of the following:

  • Dict with ts and val tags; writes one pair to the history
  • List of Dicts with ts and val tags; writes the list of items to the history
  • Grid where first column is ts and second column (may be named anything) is the values

The hisRec parameter may be:

  • Ref of history to write to
  • Rec of history to write to

Options:

  • noWarn: suppress out of order warning logging
  • forecast: set to marker to write as forecast data

Side effects:

  • updates his rec tags hisSize, hisStart, etc
  • clears context read cache

See documentation for more details.


meta ​

admin✓
deffunc:hisWrite
haystackApiWrite time series data to historian
isfunc
liblib:his
namehisWrite

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:parseDiscreteBoolPeriods ​

parseDiscreteBoolPeriods(val) ​

Parse a Base64 encoded timeline of discrete Bool periods as encoded by discreteBoolPeriods(). Return a grid of minutely offsets and Bool/NA values with the columns offset and val. If val is null, then return null.


meta ​

deffunc:parseDiscreteBoolPeriods
isfunc
liblib:his
nameparseDiscreteBoolPeriods

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:parseDiscreteEnumPeriods ​

parseDiscreteEnumPeriods(val, rec: null) ​

Parse a base64 encoded string timeline of discrete enum periods as encoded by discreteEnumPeriods(). Return a grid of minutely offsets and enum ordinal values with the columns offset and ordinal. If the rec is passed with the enum tag, then an additional name column specifies the ordinal to name mapping. If val is null, then return null.


meta ​

deffunc:parseDiscreteEnumPeriods
isfunc
liblib:his
nameparseDiscreteEnumPeriods

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:parseDiscretePeriods ​

parseDiscretePeriods(val) ​

Parse a base64 encoded string timeline of discrete periods as encoded by discretePeriods(). Return a grid of minutely offsets and duration with the columns offset and dur. If val is null, then return null.


meta ​

deffunc:parseDiscretePeriods
isfunc
liblib:his
nameparseDiscretePeriods

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

hisAppendNA ​

Specifies the amount of time after a history point's hisEnd that the hisRead() function should append an NA. See Appending N/A for details.


meta ​

defhisAppendNA
isduration
liblib:his
tagOnhis-point

supertypes ​

valData value type
scalarScalar is an atomic value kind
numberInteger or floating point numbers annotated with an optional unit
durationNumber with a unit of time


def ​

hisEnd ​

Timestamp of newest item in history


meta ​

defhisEnd
isdateTime
liblib:his
tagOnhis-point
transient✓

supertypes ​

valData value type
scalarScalar is an atomic value kind
dateTimeISO 8601 timestamp followed by timezone identifier


def ​

hisFunc ​

Axon expression used to create a computed history.


meta ​

defhisFunc
isstr
liblib:his

supertypes ​

valData value type
scalarScalar is an atomic value kind
strUnicode string of characters


def ​

hisFuncWritable ​

Allow writing raw data to a point that has the hisFunc tag.


meta ​

defhisFuncWritable
ismarker
liblib:his

supertypes ​

markerMarker labels a dict with typing information


def ​

hisInterpolateMode ​

Explicitly configures the interpolation mode to use for this point. See interpolation.


meta ​

defhisInterpolateMode
enumSee below
isstr
liblib:his
tagOnhis-point

enum ​

linear
cov
consumption

supertypes ​

valData value type
scalarScalar is an atomic value kind
strUnicode string of characters


def ​

hisInterval ​

The interval at which sampled or consumption data is collected.


meta ​

defhisInterval
isduration
liblib:his

supertypes ​

valData value type
scalarScalar is an atomic value kind
numberInteger or floating point numbers annotated with an optional unit
durationNumber with a unit of time


def ​

hisOnWrite ​

Axon expression to trap and map history data before writing to the historian database. The string must evaluate to a function which takes a history grid and optional record and returns a mapped grid. See onWrite.


meta ​

defhisOnWrite
isstr
liblib:his

supertypes ​

valData value type
scalarScalar is an atomic value kind
strUnicode string of characters


def ​

hisRollupAutoMinInterval ​

Forces hisRollupAuto() to do a rollup using this interval when none is specified and the range of the source history grid is less than 2 days. This tag is primarly intended to be used on high frequency histories such as secondly collections to ensure that querying a single day doesn't result in an overwhelming amount of data.


meta ​

defhisRollupAutoMinInterval
isduration
liblib:his
tagOnhis-point

supertypes ​

valData value type
scalarScalar is an atomic value kind
numberInteger or floating point numbers annotated with an optional unit
durationNumber with a unit of time


def ​

hisRollupFunc ​

Function name to use for hisRollupAuto()


meta ​

defhisRollupFunc
isstr
liblib:his

supertypes ​

valData value type
scalarScalar is an atomic value kind
strUnicode string of characters


def ​

hisRollupInterval ​

Indicates the roll-up interval in his grid column meta-data.


meta ​

defhisRollupInterval
isduration
liblib:his

supertypes ​

valData value type
scalarScalar is an atomic value kind
numberInteger or floating point numbers annotated with an optional unit
durationNumber with a unit of time


def ​

hisSize ​

Approximate number of timestamp/value pairs stored in history


meta ​

defhisSize
isint
liblib:his
tagOnhis-point
transient✓

supertypes ​

valData value type
scalarScalar is an atomic value kind
numberInteger or floating point numbers annotated with an optional unit
intUnitless integer number


def ​

hisStart ​

Timestamp of oldest item in history


meta ​

defhisStart
isdateTime
liblib:his
tagOnhis-point
transient✓

supertypes ​

valData value type
scalarScalar is an atomic value kind
dateTimeISO 8601 timestamp followed by timezone identifier


def ​

hisTotalizedRollover ​

Defines the rollover value for a totalized history - see totalized.


meta ​

defhisTotalizedRollover
isnumber
liblib:his

supertypes ​

valData value type
scalarScalar is an atomic value kind
numberInteger or floating point numbers annotated with an optional unit


def ​

hisTsPrecision ​

Controls the precision used to store timetamps in the historian. Supported values are 1sec and 1ms, any other value will raise an exception on hisWrite(). If omitted, then the default of 1sec is used.


meta ​

defhisTsPrecision
isduration
liblib:his

supertypes ​

valData value type
scalarScalar is an atomic value kind
numberInteger or floating point numbers annotated with an optional unit
durationNumber with a unit of time


def ​

periods ​

Timeline of on/off periods encoded as Base64 via discretePeriods().


meta ​

defperiods
isstr
liblib:his

supertypes ​

valData value type
scalarScalar is an atomic value kind
strUnicode string of characters


def ​

view:hisChart ​

Visualize historical point data as a graphical chart


meta ​

appNamehis
defview:hisChart
disKeyui::chart
iconview
isview
liblib:his
order100

supertypes ​

featureFeature namespace of definitions formatted as feature:name
viewFresco UI view

src ​

view:    { inherit:"chart" }
points:  { var input kind:"Ref<anyPoint>[]" navCluster navSelAny share }
span:    { var input kind:"Span" defVal:Span("today") share }
opts:    { var input kind:"Dict" disKey:"ui::options" templateName:"hisDataOpts" defVal:{} share }
details: { action:"uiMisc::HisDataDetails.invoke" disKey:"ui::details"  }
menu:    { action:"uiContextMenu" selInput:"points" }
data:    { expr:"hisDataView({{points}}, {{span}}, {{opts}})" }


def ​

view:hisCompare ​

Visualize historical point data from two different spans


meta ​

appNamehis
defview:hisCompare
disKeyui::compare
iconview
isview
liblib:his
order180

supertypes ​

featureFeature namespace of definitions formatted as feature:name
viewFresco UI view

src ​

view:    { inherit:"chart"}
points:  { var input kind:"Ref<anyPoint>[]" navCluster navSelAny share }
span1:   { var input kind:"Span" defVal:Span("today") share }
span2:   { var input kind:"Span" defVal:Span("yesterday") share }
opts:    { var input kind:"Dict" disKey:"ui::options" templateName:"hisDataOpts" defVal:{} share }
details: { action:"uiMisc::HisDataDetails.invoke" disKey:"ui::details"  }
menu:    { action:"uiContextMenu" selInput:"points" }
data:    { expr:"hisCompareView({{points}}, {{span1}}, {{span2}}, {{opts}})" }


def ​

view:hisCorrelate ​

Chart a linear correlation of historical point data


meta ​

appNamehis
defview:hisCorrelate
disKeyui::correlate
iconview
isview
liblib:his
order190

supertypes ​

featureFeature namespace of definitions formatted as feature:name
viewFresco UI view

src ​

view:   { inherit:"tile"}
uiViewBar: { var kind:"Dict" defVal:{} showVarLabels:T }
layout: { var kind:"Str" defVal:"grid 1x5; 0 0 1 2; 0 2 1 3" }
xaxis:  { var input kind:"Ref<anyPoint>" navCluster disKey:"ui::xAxis" }
yaxis:  { var input kind:"Ref<anyPoint>" navCluster disKey:"ui::yAxis" }
span:   { var input kind:"Span" defVal:Span("today") share dis:"" }
filter: Trio:
  var
  input
  kind:"Dict"
  disKey:"ui::filter"
  templateName:"hisCorrelateFilter"
  defVal: Trio:
    days:"all"
opts: Trio:
  var
  input
  kind:"Dict"
  disKey:"ui::options"
  templateName:"hisCorrelateOpts"
  defVal: Trio:
    rollup: {fold:"auto" interval:"auto"}
reg: Trio:
  view:   { inherit:"chart" }
  xaxis:  { var binding:"../xaxis" }
  yaxis:  { var binding:"../yaxis" }
  span:   { var binding:"../span" }
  filter: { var binding:"../filter" }
  opts:   { var binding:"../opts" }
  data: { expr:"hisCorrelate({{xaxis}}, {{yaxis}}, {{span}}, {{filter}}, {{opts}}).first->reg" }
his: Trio:
  view:   { inherit:"chart" }
  xaxis:  { var binding:"../xaxis" }
  yaxis:  { var binding:"../yaxis" }
  span:   { var binding:"../span" }
  filter: { var binding:"../filter" }
  opts:   { var binding:"../opts" }
  data:   { expr:"hisCorrelate({{xaxis}}, {{yaxis}}, {{span}}, {{filter}}, {{opts}}).first->his" }


def ​

view:hisEquip ​

Visualize historical point data of a single equipment


meta ​

appNamehis
defview:hisEquip
disKeyui::equip
iconview
isview
liblib:his
order200

supertypes ​

featureFeature namespace of definitions formatted as feature:name
viewFresco UI view

src ​

view:   { inherit:"chart" }
equip:  { var input kind:"Ref<equip>" navCluster share }
span:   { var input kind:"Span" defVal:Span("today") share }
opts:   { var input kind:"Dict" disKey:"ui::options" templateName:"hisEquipOpts" defVal:{showWeather:T} }
menu:   { action:"uiContextMenu" selInput:"equip" }
data:   { expr:"hisEquip({{equip}}, {{span}}, {{opts}})" }


def ​

view:hisImport ​

Import point history data into the local project database


meta ​

admin✓
appNamehis
defview:hisImport
disKeyui::import
iconview
isview
liblib:his
order801

supertypes ​

featureFeature namespace of definitions formatted as feature:name
viewFresco UI view

src ​

point:  { var input kind:"Ref<anyPoint>" saveWithDis defVal:@null }
view:   { uiType:"uiMisc::HisImportView" }
menu:   { action:"uiContextMenu" selInput:"point" }
data:   { expr:"hisImportView({{point}})" }


def ​

view:hisTable ​

Visualize historical point data as a table


meta ​

appNamehis
defview:hisTable
disKeyui::table
iconview
isview
liblib:his
order111

supertypes ​

featureFeature namespace of definitions formatted as feature:name
viewFresco UI view

src ​

view:    { inherit:"table"}
points:  { var input kind:"Ref<anyPoint>[]" navCluster navSelAny share }
span:    { var input kind:"Span" defVal:Span("today") share }
opts:    { var input kind:"Dict" disKey:"ui::options" templateName:"hisDataOpts" defVal:{} share }
details: { action:"uiMisc::HisDataDetails.invoke" disKey:"ui::details"  }
menu:    { action:"uiContextMenu" selInput:"points" }
data:    { expr:"hisDataView({{points}}, {{span}}, {{opts}})" }