=head1 Channel Filters

Channel Filters can be applied to Channel Access channels by a client, using
a JSON Field Modifier to select the filter and any parameters.
The following filters are available in this release:

=over

=item * L<TimeStamp|/"TimeStamp Filter ts">

=item * L<Deadband|/"Deadband Filter dbnd">

=item * L<Array|/"Array Filter arr">

=item * L<Synchronize|/"Synchronize Filter sync">

=item * L<Decimation|/"Decimation Filter dec">

=back

=head2 Using Filters

Channel filters can be added to any Channel Access channel name.
There can be more than one filter applied to the same channel, in which case the
order that they are specified will control the order in which they are applied
to the resulting data-stream.
The filter specification must appear after the field name, or if the default
(VAL) field is used after a dot C<.> appended to the record name.
With the exception of the array short-hand which is described below, all filters
must appear inside a pair of braces C< {} > after the dot expressed as a JSON
(L<JavaScript Object Notation|http://www.json.org/>) object, which allows filter
parameters to be included as needed.

Each filter is given as a name/value pair. The filter name (given in parentheses
in the titles below) is a string, and must be enclosed inside double-quotes C<">
characters as per the JSON specification.
Parameters to that filter are provided as the value part of the name/value pair,
and will normally appear as a child JSON object consisting of name/value pairs
inside a nested pair of braces C< {} >.

=head4 Example Filter

Given a record called C<test:channel> the following would apply a filter C<f> to
the VAL field of that record, giving the filter two numeric parameters named
C<lo> and C<hi>:

 test:channel.{"f":{"lo":0,"hi":10}}

Note that due to the required presence of the double-quote characters in the
JSON strings in the name string, it will usually be necessary to enclose a
filtered name within single-quotes C<< ' ... ' >> when typing it as an
argument to a Unix shell command.

=head2 Filter Reference

=cut

registrar(tsInitialize)

=head3 TimeStamp Filter C<"ts">

This filter is used to set the timestamp of the value fetched through
the channel to the time the value was fetched (or an update was sent),
rather than the time the record last
processed which could have been days or even weeks ago for some records, or set
to the EPICS epoch if the record has never processed.

=head4 Parameters

None, use an empty pair of braces.

=head4 Example

 Hal$ caget -a 'test:channel.{"ts":{}}'
 test:channel.{"ts":{}}   2012-08-28 22:10:31.192547 0 UDF INVALID
 Hal$ caget -a 'test:channel'
 test:channel             <undefined> 0 UDF INVALID

=cut

registrar(dbndInitialize)

=head3 Deadband Filter C<"dbnd">

This filter implements a channel-specific monitor deadband, which is applied
after any deadbands implemented by the record itself (it can only drop updates
that the unfiltered channel generates, never add additional updates).

The deadband can be specified as an absolute value change, or as a relative
percentage.

=head4 Parameters

=over

=item Mode+Deadband C<"abs">/C<"rel"> (shorthand)

Mode and deadband can be specified in one definition (shorthand).
The desired mode is given as parameter name (C<"abs"> or C<"rel">), with the
numeric size of the deadband (absolute value or numeric percentage) as value.

=item Deadband C<"d">

The size of the deadband to use.
Relative deadband values are given as a numeric percentage, but without any
trailing percent character.

=item Mode C<"m"> (optional)

A string (enclosed in double-quotes C<">), which should contain either
C<abs> or C<rel>.
The default mode is C<abs> if no mode parameter is included.

=back

=head4 Example

 Hal$ camonitor 'test:channel'
 test:channel                    2012-09-01 22:10:19.600595 1 LOLO MAJOR
 test:channel                    2012-09-01 22:10:20.600661 2 LOLO MAJOR
 test:channel                    2012-09-01 22:10:21.600819 3 LOW MINOR
 test:channel                    2012-09-01 22:10:22.600905 4 LOW MINOR
 test:channel                    2012-09-01 22:10:23.601023 5  
 test:channel                    2012-09-01 22:10:24.601136 6 HIGH MINOR
 ^C
 Hal$ camonitor 'test:channel.{"dbnd":{"abs":1.5}}'
 test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:49.613341 1 LOLO MAJOR
 test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:51.613615 3 LOW MINOR
 test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:53.613804 5  
 test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:55.614074 7 HIGH MINOR
 test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:57.614305 9 HIHI MAJOR
 ^C

=cut

registrar(arrInitialize)

=head3 Array Filter C<"arr">

This filter is used to retrieve parts of an array (subarrays and strided
subarrays).

=head4 Parameters

Note: Negative index numbers address from the end of the array, with C<-1> being the last element.

=over

=item Square bracket notation C<[start:increment:end]> (shorthand)

The common square bracket notation which can be used in place of JSON.
Any parameter may be omitted (keeping the colons) to use the default value.
If only one colon is included, this means C<[start:end]> with an increment of 1.
If only a single parameter is used C<[index]> the filter returns one element.

=item Start index C<"s">

Index of the first original array element to retrieve.

=item Increment C<"i">

Index increment between retrieved elements of the original array; must be
a positive number.

=item End index C<"e">

Index of the last original array element to retrieve.

=back

Defaults (when parameters are omitted) are:
C<s=0> (first element), C<i=1> (fetch all elements), C<e=-1>
(last element)

=head4 Example

 Hal$ caget test:channel 'test:channel.{"arr":{"s":2,"i":2,"e":8}}' test:channel.[3:5] test:channel.[3:2:-3]
 test:channel 10 0 1 2 3 4 5 6 7 8 9
 test:channel.{"arr":{"s":2,"i":2,"e":8}} 4 2 4 6 8
 test:channel.[3:5] 3 3 4 5
 test:channel.[3:2:-3] 3 3 5 7

=cut

registrar(syncInitialize)

=head3 Synchronize Filter C<"sync">

This filter is used to dynamically enable or disable monitors according
to a condition and a state variable declared by the IOC.

State variables have a boolean value and can be set by a binary output
record, an iocsh command or by other software running in the IOC calling
C<dbStateSet()>.

=head4 Parameters

=over

=item Mode+State

Mode and state can be specified in one definition (shorthand).
The desired mode is given as parameter name (C<"before"> / C<"first"> /
C<"while"> / C<"last"> / C<"after"> / C<"unless">), with the state name
(enclosed in double quotes C<">) as value.

=item Mode C<"m">

A single word from the list below, enclosed in double quotes C<">.
This controls how the state value should affect the monitor stream. 

=over

=item C<"before"> E<mdash> only the last value received before the state
changes from false to true is forwarded to the client.

=item C<"first"> E<mdash> only the first value received after the state
changes from true to false is forwarded to the client.

=item C<"while"> E<mdash> values are forwarded to the client as long as
the state is true.

=item C<"last"> E<mdash> only the last value received before the state
changes from true to false is forwarded to the client.

=item C<"after"> E<mdash> only the first value received after the state
changes from true to false is forwarded to the client.

=item C<"unless"> E<mdash> values are forwarded to the client as long
as the state is false.

=back

=item State C<"s">

The name of a state variable, enclosed in double quotes C<">.

=back

=head4 Example

Assuming there is a system state called "blue", that is being controlled by
some other facility such as a timing system, updates could be restricted to
periods only when "blue" is true by using

 Hal$ camonitor 'test:channel' 'test:channel.{"sync":{"while":"blue"}}'
 ...

=cut

registrar(decInitialize)

=head3 Decimation Filter C<"dec">

This filter is used to reduce the number or rate of monitor updates from a
channel by an integer factor C<n> that is provided as a filter argument,
discarding the other updates. A true decimation following the original meaning
of the word would be achieved by giving C<n> as 10, to only allow every tenth
update through.

=head4 Parameters

=over

=item Number C<"n">

The decimation factor, a positive integer. Giving n=1 is equivalent to a no-op
that allows all updates to be passed to the client.

=back

This filter is intentionally very simplistic. It passes on the first monitor
event that it sees after the channel connects, then discards the next N-1 events
before sending the next event. If several clients connect to a channel using the
same filter settings they may see completely different data streams since each
client gets its own instance of the filter whose event counter starts when that
client connects.

=head4 Example

To sample a 60Hz channel at 1Hz, a 10Hz channel every 6 seconds or a 1Hz channel
once every minute:

 Hal$ camonitor 'test:channel' 'test:channel.{"dec":{"n":60}}'
 ...

=cut
