Axon - lib:his

Axon - lib:his

In this page are presented some useful example about how manage histories with axon functions

Summary

There are different ways to handle histories in FIN:

  • His Computed: used to indicate that histories are generate with function;

  • His Imported: used to indicate that histories have been imported, usually from a csv file;

  • His Collected: used to indicate that histories are collect from curVal;

  • His Synchronized: used to populate histories from the device that the point originated from. (Example TODO)

There are three differents hisMode:

  • “sampled” (default)

  • “cov”

  • “consumption“

Point Type (examples)

hisMode

kind

hisTotalized

rollup fold (usually)

 

Point Type (examples)

hisMode

kind

hisTotalized

rollup fold (usually)

 

power or temp or …

“sampled”

“Number”

 

max, min, avg

read({{filterExpr}}).hisRead({{dates}}, opts: {-limit}).hisRollup({{fold}}, {{interval}}).hisInterpolate.hisClip

setpoint or …

“cov”

“Number”

 

max, min, avg

read({{filterExpr}}).hisRead({{dates}}, opts: {-limit}).hisRollup({{fold}}, {{interval}}).hisInterpolate

run or …

“cov”

“Bool”

 

 

read({{filterExpr}}).hisRead({{dates}}, opts: {-limit}).hisRollupAuto

energy or …

“consumption”

“Number”

M

sum, avg, min, max

read({{filterExpr}}).hisRead({{dates}}, opts: {-limit}).hisRollup({{fold}}, {{interval}}).hisInterpolate

Examples/Exercises

In the examples below, there are some examples about how configure and use the different history types.

It’s suggested to follow each chapter with the suggested order, since some concepts/results are reused from previous chapters.

His Computed: Generate Fake histories

Create the function you want to use to create your fake histories: Computed Histories
Examples (you can upload them using folio update of trio files):

hisMode:“sampled”

name:powerHisFunc func demoData hisFuncReady doc: Generate fake energy histories each day at fixed hours inside the dates span It's appliable to a point with kind==\"Number\" and unit:\"kW\" NOTE: THIS IS JUST AN EXAMPLE. J2 DOESN T ENSURE THAT THIS FUNC IT'S USABLE IN A REAL ENVIRONMENT src: (rec, dates, opts, yield) => do tz: rec->tz eachDay(dates) day => do (0..23).each hour => do ts:dateTime(day, time(hour.as(1h),0,0), tz) val:random(0..10).as(1kW) echo("ts:"+ts+" | val:"+val) //TryCatch handles the time change usually takes place in March try yield(ts, val) catch echo("SKIPPED!! --> ts:"+ts+" | val:"+val) end end end

hisMode:“cov”

name:occupancyHisFunc func demoData hisFuncReady doc: Generate a fake occupancy history (true or false) each day at fixed hours inside the dates span. It's appliable to a point with kind==\"Bool\" NOTE: THIS IS JUST AN EXAMPLE. J2 DOESN T ENSURE THAT THIS FUNC IT'S USABLE IN A REAL ENVIRONMENT src: (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 end name:setpointHisFunc func demoData hisFuncReady doc: Generate fake setpoint histories each day at fixed hours inside the dates span It's appliable to a point with kind=="Number" and unit:"°C" NOTE: THIS IS JUST AN EXAMPLE. J2 DOESN'T ENSURE THAT THIS FUNC IT'S USABLE IN A REAL ENVIRONMENT src: (rec, dates, opts, yield) => do tz: rec->tz eachDay(dates) day => do yield(dateTime(day, 8:00, tz), 20°C) yield(dateTime(day, 22:00, tz), 16°C) end end

 

hisMode:“consumption”

name:energyHisFunc func demoData hisFuncReady doc: Generate fake energy histories each day at fixed hours inside the dates span It's appliable to a point with kind==\"Number\" and unit:\"kWh\" NOTE: THIS IS JUST AN EXAMPLE. J2 DOESN'T ENSURE THAT THIS FUNC IT'S USABLE IN A REAL ENVIRONMENT src: (rec, dates, opts, yield) => do tz: rec->tz val: 0kWh offset:() => random(0..10).as(1kWh) eachDay(dates) day => do (0..23).each hour => do ts:dateTime(day, time(hour.as(1h),0,0), tz) echo("ts:"+ts+" | val:"+val) //TryCatch handles the time change usually takes place in March try yield(ts, val) catch echo("SKIPPED!! --> ts:"+ts+" | val:"+val) val = val + offset() end end end

 

  • Create 4 points:

    • {navName:"Computed Power", kind=="Number", /* hisMode:“sampled” not required since it's the default */, ... }

    • {navName:"Computed Occupancy", kind=="Bool", hisMode:"cov", ... }

    • {navName:"Computed Setpoint", kind=="Number", hisMode:"cov", ... }

    • {navName:"Computed Energy", kind=="Number", hisMode:"consumption", hisTotalized, ... }

“unit” tag is not required since the history is created by hisFunc. Anyway, it should be better to add the proper one to the points.

 

 

 

  • For each point enabled history and set to hisType:"computed" Point Property Sheet | History and

    • hisFunc:"powerHisFunc"

    • hisFunc:"occupancyHisFunc"

    • hisFunc:"setpointHisFunc"

    • hisFunc:"energyHisFunc"

 

  • Test the results using in Folio

    • read(navName=="Computed Power").hisRead(today())

    • read(navName=="Computed Occupancy").hisRead(lastWeek())

    • read(navName=="Computed Setpoint").hisRead(pastMonth())

    • read(navName=="Computed Energy").hisRead(thisYear(), {-limit})

If a point has the hisFunc tag (i.e. it is a computed point) the function itself is completely responsible for generating the desired history output. The his read is essentially delegated to the his func.

It means that reading the histories of the Energy Point returns like the “row” his data, so an increasing value and not a “~collected” one.

Example of His configuration on a point

 

His Imported: Write\Read his to\from csv file

It could be useful to write and read points to/from a csv file. Here an example of how to do it. This requires to already have configured points as indicated in Generate Fake histories chapter.

  • Write: You can use one of these functions (in Folio) to write your CSV file in the folder ..\{{FIN_FolderName}}\var\proj\{{projName}}\io\{{fileName.csv}}

    • read(navName=="Computed Power").hisRead(thisYear(), {-limit}).addColMeta("ts", {dis:"ts"}).addColMeta("v0", {dis:"val"}).ioWriteCsv(`io/hisPower.csv`)

    • read(navName=="Computed Occupancy").hisRead(thisYear(), {-limit}).addColMeta("ts", {dis:"ts"}).addColMeta("v0", {dis:"val"}).ioWriteCsv(`io/hisOccupancy.csv`)

    • read(navName=="Computed Setpoint").hisRead(thisYear(), {-limit}).addColMeta("ts", {dis:"ts"}).addColMeta("v0", {dis:"val"}).ioWriteCsv(`io/hisSetpoint.csv`)

    • read(navName=="Computed Energy").hisRead(thisYear(), {-limit}).addColMeta("ts", {dis:"ts"}).addColMeta("v0", {dis:"val"}).ioWriteCsv(`io/hisEnergy.csv`)

Why .addColMeta("ts", {dis:"ts"}).addColMeta("v0", {dis:"val"}) ?

These funcs are used to change the names of the columns in the target csv file.

By default ioWriteCsv set as col name the dis value of the grid column return by hisRead(..)

Example before addColMeta:

  • read(navName=="Computed Power").hisRead(today()).col("ts").meta("dis").dis >>> "Timestamp"

  • read(navName=="Computed Power").hisRead(today()).col("ts").meta("dis").dis >>> "New Site Computed Points Computed Power"

Example after addColMeta:

  • read(navName=="Computed Power").hisRead(today()).addColMeta("ts", {dis:"ts"}).addColMeta("v0", {dis:"val"}).col("ts").meta("dis").dis >>> "ts"

  • read(navName=="Computed Power").hisRead(today()).addColMeta("ts", {dis:"ts"}).addColMeta("v0", {dis:"val"}).col("ts").meta("dis").dis >>> "val"

  • Create 4 new points

    • {navName:"From Csv Power", unit:"kW", kind=="Number", /* hisMode:“sampled” not required since it's the default */, ... }

    • {navName:"From Csv Occupancy", kind=="Bool", hisMode:"cov", ... }

    • {navName:"From Csv Setpoint", unit:"°C", kind=="Number", hisMode:"cov", ... }

    • {navName:"From Csv Energy", unit:"kWh", kind=="Number", hisMode:"consumption", hisTotalized, ... }

 

 

  • For each point enable the history as

  • Import the following function that will be used to read csv

    name:writeHisFromCsv func doc: Read the csv file containg histories. The csv must contains 2 columns: "ts": with data stored with format "YYYY-MM-DDThh:mm:ssz", that is the default one you have exporting DateTime values "val": contains the values as Str Inputs: - hisPoint: the point where you want to write histories to - csvUri: the URI of the csv, it should be something like `io/fileName.csv` - parseFunc: is the function used to parse the value stored in csv file as a Str. (parseNumber, parseBool, ..) - format: is the format of the DateTime value in the "ts" column. An example could be:"YYYY-MM-DDThh:mm:ssz" NOTE: THIS IS JUST AN EXAMPLE. J2 DOESN T ENSURE THAT THIS FUNC IT'S USABLE IN A REAL ENVIRONMENT src: (hisPoint, csvUri, parseFunc:parseNumber, format:"YYYY-MM-DDThh:mm:ssz") => do hisPoint= hisPoint.toRec csv:ioReadCsv(csvUri) csv.map(row => do ts:parseDateTime(row->ts, format, hisPoint->tz) val:parseFunc(row->val) return {ts:ts, val:val} end).hisWrite(hisPoint) end
Example of His configuration on a point
Example of hisEnergy.csv
Example of hisOccupancy.csv
  • Read: Populate the 4 points his with

    • read(navName=="Imported Power").writeHisFromCsv(`io/hisPower.csv`)

    • read(navName=="Imported Occupancy").writeHisFromCsv(`io/hisOccupancy.csv`, parseBool)

    • read(navName=="Imported Setpoint").writeHisFromCsv(`io/hisSetpoint.csv`)

    • read(navName=="Imported Energy").writeHisFromCsv(`io/hisEnergy.csv`)

  • Test the results using in Folio

    • read(navName=="Imported Power").hisRead(today())

    • read(navName=="Imported Occupancy").hisRead(lastWeek())

    • read(navName=="Imported Setpoint").hisRead(pastMonth())

    • read(navName=="Imported Energy").hisRead(thisYear(), {-limit})

His Collected

Usually these kind of points are sensors that you need to historicize.

There are 3 main types of collecting data like these:

  • Sampled

  • Change Of Value [COV]

  • Consumption

Based on these types, a point have different tags

Sampled

Change Of Value

Consumption

Points Examples:

  • Temperatures

  • Power

  • Instant Flow

Points Examples:

  • Occupancy

  • Set Point

  • On Off

Points Examples:

  • Energy

  • Flow-Volume

Tags usually required

  • his

  • hisMode:"sampled" //Usually it’s not required since it’s the default value

Tags usually required

  • his

  • hisMode:"cov"

Tags usually required

  • his

  • hisMode:"consumption"

  • hisTotalized

Read Raw his data in span:date..date

Here we are reading history data with hisReadopts:{raw}

  • Span: 2021-10-08

Point: Power

Notes:

Func:

read(navName=="Imported Power").hisRead(2021-10-08, {raw})

ts

val

ts

val

2021-10-07T23:00:00+02:00 Berlin

8kW

2021-10-08T00:00:00+02:00 Berlin

10kW

2021-10-08T01:00:00+02:00 Berlin

9kW

2021-10-08T02:00:00+02:00 Berlin

4kW

2021-10-08T03:00:00+02:00 Berlin

3kW

2021-10-08T04:00:00+02:00 Berlin

6kW

2021-10-08T05:00:00+02:00 Berlin

10kW

2021-10-08T06:00:00+02:00 Berlin

4kW

2021-10-08T07:00:00+02:00 Berlin

6kW

2021-10-08T08:00:00+02:00 Berlin

7kW

2021-10-08T09:00:00+02:00 Berlin

7kW

2021-10-08T10:00:00+02:00 Berlin

5kW

2021-10-08T11:00:00+02:00 Berlin

5kW

2021-10-08T12:00:00+02:00 Berlin

1kW

2021-10-08T13:00:00+02:00 Berlin

3kW

2021-10-08T14:00:00+02:00 Berlin

3kW

2021-10-08T15:00:00+02:00 Berlin

7kW

2021-10-08T16:00:00+02:00 Berlin

1kW

2021-10-08T17:00:00+02:00 Berlin

10kW

2021-10-08T18:00:00+02:00 Berlin

7kW

2021-10-08T19:00:00+02:00 Berlin

1kW

2021-10-08T20:00:00+02:00 Berlin

7kW

2021-10-08T21:00:00+02:00 Berlin

10kW

2021-10-08T22:00:00+02:00 Berlin

2kW

2021-10-08T23:00:00+02:00 Berlin

8kW

2021-10-09T00:00:00+02:00 Berlin

9kW

2021-10-09T01:00:00+02:00 Berlin

2kW

Point: Setpoint

Notes:

Func:

read(navName=="Imported Setpoint").hisRead(2021-10-08, {raw})

ts

val

ts

val

2021-10-07T22:00:00+02:00 Berlin

16°C

2021-10-08T08:00:00+02:00 Berlin

20°C

2021-10-08T22:00:00+02:00 Berlin

16°C

2021-10-09T08:00:00+02:00 Berlin

20°C

2021-10-09T22:00:00+02:00 Berlin

16°C

Point: Energy

Notes:

Func:

read(navName=="Imported Energy").hisRead(2021-10-08, {raw})

ts

val

2021-10-07T23:00:00+02:00 Berlin

33679kWh

2021-10-08T00:00:00+02:00 Berlin

33683kWh

2021-10-08T01:00:00+02:00 Berlin

33686kWh

2021-10-08T02:00:00+02:00 Berlin

33689kWh

2021-10-08T03:00:00+02:00 Berlin

33692kWh

2021-10-08T04:00:00+02:00 Berlin

33697kWh

2021-10-08T05:00:00+02:00 Berlin

33701kWh

2021-10-08T06:00:00+02:00 Berlin

33707kWh

2021-10-08T07:00:00+02:00 Berlin

33707kWh

2021-10-08T08:00:00+02:00 Berlin

33715kWh

2021-10-08T09:00:00+02:00 Berlin

33724kWh

2021-10-08T10:00:00+02:00 Berlin

33728kWh

2021-10-08T11:00:00+02:00 Berlin

33737kWh

2021-10-08T12:00:00+02:00 Berlin

33744kWh

2021-10-08T13:00:00+02:00 Berlin

33745kWh

2021-10-08T14:00:00+02:00 Berlin

33748kWh

2021-10-08T15:00:00+02:00 Berlin

33748kWh

2021-10-08T16:00:00+02:00 Berlin

33753kWh

2021-10-08T17:00:00+02:00 Berlin

33763kWh

2021-10-08T18:00:00+02:00 Berlin

33772kWh

2021-10-08T19:00:00+02:00 Berlin

33777kWh

2021-10-08T20:00:00+02:00 Berlin

33785kWh

2021-10-08T21:00:00+02:00 Berlin

33787kWh

2021-10-08T22:00:00+02:00 Berlin

33787kWh

2021-10-08T23:00:00+02:00 Berlin

33793kWh

2021-10-09T00:00:00+02:00 Berlin

33796kWh

2021-10-09T01:00:00+02:00 Berlin

33797kWh

In the hisRead documentation you can find these notes:

- if start is Date, then we use midnight of that day