Compare commits
202 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 429c47a34a | |||
| 65d2cce753 | |||
| 7535e469e9 | |||
| b3f64a1392 | |||
| 6ca99ebb92 | |||
| 2dbae03028 | |||
| 09cf317521 | |||
| 8ed07fef96 | |||
| a34876e36a | |||
| 7105261c90 | |||
| a6f5d86162 | |||
| 9e8cc341ea | |||
| 6eb977ae66 | |||
| 3fb934a30b | |||
| 2d6f0f1821 | |||
| 8a661bb591 | |||
| efb2631905 | |||
| 1211d01800 | |||
| b665dac669 | |||
| 65a69a8901 | |||
| 7722fdf353 | |||
| bc9ac8422c | |||
| c3aec4e27b | |||
| 0abfeef5ed | |||
| 745119cf77 | |||
| 9f794721ab | |||
| 8f21ac8b9d | |||
| 9add9daf85 | |||
| aaacadb42d | |||
| 5961c83477 | |||
| b724b72624 | |||
| fc42cf798e | |||
| 71181afc93 | |||
| b92a3ddaa4 | |||
| 246cceae3e | |||
| 3f4df39ee0 | |||
| 837924af2e | |||
| 7b0e2b5986 | |||
| c84b24bb30 | |||
| aba40922e6 | |||
| 2c1cb03cd0 | |||
| f58c5159fc | |||
| a91ba8ef9e | |||
| ddb36536fe | |||
| 9153036ccc | |||
| 4c56116827 | |||
| 81f5e25276 | |||
| 703b2224ce | |||
| ed0b1cbf08 | |||
| 914e382dea | |||
| fd77d35b20 | |||
| 428adb270e | |||
| 3111e90de8 | |||
| 365a0b846f | |||
| 440c8fa496 | |||
| 150ac45de3 | |||
| fb6f4355f3 | |||
| 0bb17d5b09 | |||
| 00103f8207 | |||
| 522a050945 | |||
| 99a7e3b0b5 | |||
| 763c41caa3 | |||
| 9ffeffd23f | |||
| 3f6d93b22f | |||
| d650865a6f | |||
| b1c101578b | |||
| 8ab4dd1fdb | |||
| 5242540725 | |||
| a8f296ceb3 | |||
| 6633d4f21e | |||
| 8745dd03b3 | |||
| cfc3c9b998 | |||
| d57893b566 | |||
| b7ea0fe59a | |||
| 4e4554af4e | |||
| d6d5bcf771 | |||
| 6bcc036c71 | |||
| a405dd7bdb | |||
| 22e260351c | |||
| 5a5b8f809d | |||
| 9d5f06c11d | |||
| 28a23dc5a8 | |||
| dcda03c9fc | |||
| b5291d9619 | |||
| 74d381e68c | |||
| c789406f0b | |||
| a21e5b5913 | |||
| cb374fcefa | |||
| 90b2bdc162 | |||
| ea5809be9b | |||
| 0fb4612680 | |||
| 5a84b94520 | |||
| 411560ea8d | |||
| 3e9645c883 | |||
| 25b621890b | |||
| fe15b9dd09 | |||
| 64fc25c240 | |||
| c9e7bc32bd | |||
| ab4c69301f | |||
| 5b9b84f7d0 | |||
| dd65681630 | |||
| e11cc25dd7 | |||
| 05a454fa69 | |||
| b5e9aa6a60 | |||
| 4606d84185 | |||
| 97d9dc2034 | |||
| e1d50000d4 | |||
| 878cc27aa7 | |||
| 5c99282ee2 | |||
| 3b344fdb25 | |||
| 932d90ff70 | |||
| d7bf6a8910 | |||
| 9b1539f368 | |||
| 8c7506449b | |||
| 609c887c19 | |||
| 8f6cc08f85 | |||
| ae49f8ad99 | |||
| 696c251ecc | |||
| 594d8dd19f | |||
| d8ab89e96a | |||
| 9712f001c8 | |||
| 91e6392e77 | |||
| 094336b5e0 | |||
| f0efef68ea | |||
| 0912756a2e | |||
| e071e0f9e3 | |||
| 619bacc0f4 | |||
| 7fd5af9e3c | |||
| 6762c54e60 | |||
| 63947e1c3c | |||
| c019b205dd | |||
| 2f75a967de | |||
| eed64822e0 | |||
| 6249ae2c44 | |||
| 83a27341cd | |||
| 051c924992 | |||
| 261eaf5d9b | |||
| 6f18c1febf | |||
| 10cfe31653 | |||
| 22cf65022d | |||
| 98b25f6094 | |||
| b18fd4b3ae | |||
| dee908b273 | |||
| c5c7e19192 | |||
| 852510afe4 | |||
| b93f466366 | |||
| b5d4d178f5 | |||
| 348d27b7bb | |||
| bf42a5c22d | |||
| 0227872c94 | |||
| d890ce28d8 | |||
| de8fc8994b | |||
| fac07c7f3a | |||
| c06fb08168 | |||
| 5398d67e2a | |||
| 46af745a1a | |||
| a7fb12a16f | |||
| 35458045fa | |||
| 2f013af10d | |||
| f926282c54 | |||
| 4764518bd2 | |||
| 0639d45740 | |||
| 1c16a72889 | |||
| ec5d08685c | |||
| 7a4bd88d8d | |||
| 32fb16fcf0 | |||
| 04b5434b69 | |||
| 6ff53f4dcb | |||
| 3008825587 | |||
| 643fa9b40b | |||
| 3920215182 | |||
| a0cc581d3f | |||
| adc008dee6 | |||
| 40fb22ebd9 | |||
| cd9bdec84e | |||
| 3cc13e2c5a | |||
| 9f8073aaa2 | |||
| 2b7b38a3c7 | |||
| 899dc4e9be | |||
| d2e8fab2b4 | |||
| ff68b01ddf | |||
| c258018014 | |||
| 43d13175e5 | |||
| bf57c06b06 | |||
| 49f581c4bb | |||
| c55bf7ec45 | |||
| ec1f6d5eb6 | |||
| 56d96716f0 | |||
| 80073054dd | |||
| 9d0069ffe0 | |||
| 971d35f389 | |||
| 9a9bf34f83 | |||
| 86a5e037fa | |||
| 434867866b | |||
| 0f415a3e39 | |||
| 9c800f5ebf | |||
| 7f972fc877 | |||
| 1b11e49c2c | |||
| d456c815e7 | |||
| 698e901b8f | |||
| 78a8f26dd0 | |||
| 3b09ef5c21 |
+16
-11
@@ -1,12 +1,17 @@
|
|||||||
bin/
|
/cfg/
|
||||||
lib/
|
/bin/
|
||||||
doc/
|
/lib/
|
||||||
include/
|
/db/
|
||||||
db/
|
/dbd/
|
||||||
dbd/
|
/html/
|
||||||
documentation/html
|
/include/
|
||||||
documentation/*.tag
|
/templates/
|
||||||
|
/configure/*.local
|
||||||
|
/documentation/html
|
||||||
|
/documentation/*.tag
|
||||||
|
O.*/
|
||||||
|
/QtC-*
|
||||||
envPaths
|
envPaths
|
||||||
configure/*.local
|
*.orig
|
||||||
!configure/ExampleRELEASE.local
|
*.log
|
||||||
**/O.*
|
.*.swp
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# .readthedocs.yml
|
||||||
|
# Read the Docs configuration file
|
||||||
|
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||||
|
|
||||||
|
# Required
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
# Build documentation in the documentation/ directory with Sphinx
|
||||||
|
sphinx:
|
||||||
|
configuration: documentation/conf.py
|
||||||
|
|
||||||
|
# Build documentation with MkDocs
|
||||||
|
#mkdocs:
|
||||||
|
# configuration: mkdocs.yml
|
||||||
|
|
||||||
|
# Optionally build your docs in additional formats such as PDF and ePub
|
||||||
|
formats: all
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Doxyfile 1.8.6
|
# Doxyfile 1.8.10
|
||||||
|
|
||||||
# This file describes the settings to be used by the documentation system
|
# This file describes the settings to be used by the documentation system
|
||||||
# doxygen (www.doxygen.org) for a project.
|
# doxygen (www.doxygen.org) for a project.
|
||||||
@@ -32,13 +32,13 @@ DOXYFILE_ENCODING = UTF-8
|
|||||||
# title of most generated pages and in a few other places.
|
# title of most generated pages and in a few other places.
|
||||||
# The default value is: My Project.
|
# The default value is: My Project.
|
||||||
|
|
||||||
PROJECT_NAME = easyPVACPP
|
PROJECT_NAME = pvaClientCPP
|
||||||
|
|
||||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER =
|
PROJECT_NUMBER = 4.8.2-dev
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
@@ -46,10 +46,10 @@ PROJECT_NUMBER =
|
|||||||
|
|
||||||
PROJECT_BRIEF =
|
PROJECT_BRIEF =
|
||||||
|
|
||||||
# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
|
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||||
# the documentation. The maximum height of the logo should not exceed 55 pixels
|
# in the documentation. The maximum height of the logo should not exceed 55
|
||||||
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
|
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
|
||||||
# to the output directory.
|
# the logo to the output directory.
|
||||||
|
|
||||||
PROJECT_LOGO =
|
PROJECT_LOGO =
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ PROJECT_LOGO =
|
|||||||
|
|
||||||
OUTPUT_DIRECTORY =
|
OUTPUT_DIRECTORY =
|
||||||
|
|
||||||
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
|
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
|
||||||
# directories (in 2 levels) under the output directory of each output format and
|
# directories (in 2 levels) under the output directory of each output format and
|
||||||
# will distribute the generated files over these directories. Enabling this
|
# will distribute the generated files over these directories. Enabling this
|
||||||
# option can be useful when feeding doxygen a huge amount of source files, where
|
# option can be useful when feeding doxygen a huge amount of source files, where
|
||||||
@@ -70,6 +70,14 @@ OUTPUT_DIRECTORY =
|
|||||||
|
|
||||||
CREATE_SUBDIRS = NO
|
CREATE_SUBDIRS = NO
|
||||||
|
|
||||||
|
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
|
||||||
|
# characters to appear in the names of generated files. If set to NO, non-ASCII
|
||||||
|
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
|
||||||
|
# U+3044.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
ALLOW_UNICODE_NAMES = NO
|
||||||
|
|
||||||
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
||||||
# documentation generated by doxygen is written. Doxygen will use this
|
# documentation generated by doxygen is written. Doxygen will use this
|
||||||
# information to generate all constant output in the proper language.
|
# information to generate all constant output in the proper language.
|
||||||
@@ -85,14 +93,14 @@ CREATE_SUBDIRS = NO
|
|||||||
|
|
||||||
OUTPUT_LANGUAGE = English
|
OUTPUT_LANGUAGE = English
|
||||||
|
|
||||||
# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
|
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
||||||
# descriptions after the members that are listed in the file and class
|
# descriptions after the members that are listed in the file and class
|
||||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
BRIEF_MEMBER_DESC = YES
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
|
||||||
# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
|
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
|
||||||
# description of a member or function before the detailed description
|
# description of a member or function before the detailed description
|
||||||
#
|
#
|
||||||
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
|
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
|
||||||
@@ -127,7 +135,7 @@ ALWAYS_DETAILED_SEC = NO
|
|||||||
|
|
||||||
INLINE_INHERITED_MEMB = YES
|
INLINE_INHERITED_MEMB = YES
|
||||||
|
|
||||||
# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
|
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
|
||||||
# before files name in the file list and in the header files. If set to NO the
|
# before files name in the file list and in the header files. If set to NO the
|
||||||
# shortest path that makes the file name unique will be used
|
# shortest path that makes the file name unique will be used
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@@ -144,7 +152,7 @@ FULL_PATH_NAMES = YES
|
|||||||
# will be relative from the directory where doxygen is started.
|
# will be relative from the directory where doxygen is started.
|
||||||
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
||||||
|
|
||||||
STRIP_FROM_PATH =
|
STRIP_FROM_PATH = src
|
||||||
|
|
||||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
|
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
|
||||||
# path mentioned in the documentation of a class, which tells the reader which
|
# path mentioned in the documentation of a class, which tells the reader which
|
||||||
@@ -153,7 +161,7 @@ STRIP_FROM_PATH =
|
|||||||
# specify the list of include paths that are normally passed to the compiler
|
# specify the list of include paths that are normally passed to the compiler
|
||||||
# using the -I flag.
|
# using the -I flag.
|
||||||
|
|
||||||
STRIP_FROM_INC_PATH =
|
STRIP_FROM_INC_PATH = src
|
||||||
|
|
||||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
|
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
|
||||||
# less readable) file names. This can be useful is your file systems doesn't
|
# less readable) file names. This can be useful is your file systems doesn't
|
||||||
@@ -169,7 +177,7 @@ SHORT_NAMES = NO
|
|||||||
# description.)
|
# description.)
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
JAVADOC_AUTOBRIEF = YES
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
|
||||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||||
@@ -197,9 +205,9 @@ MULTILINE_CPP_IS_BRIEF = NO
|
|||||||
|
|
||||||
INHERIT_DOCS = YES
|
INHERIT_DOCS = YES
|
||||||
|
|
||||||
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
|
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
|
||||||
# new page for each member. If set to NO, the documentation of a member will be
|
# page for each member. If set to NO, the documentation of a member will be part
|
||||||
# part of the file/class/namespace that contains it.
|
# of the file/class/namespace that contains it.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
SEPARATE_MEMBER_PAGES = NO
|
SEPARATE_MEMBER_PAGES = NO
|
||||||
@@ -261,11 +269,14 @@ OPTIMIZE_OUTPUT_VHDL = NO
|
|||||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
|
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
|
||||||
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
|
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
|
||||||
# (default is Fortran), use: inc=Fortran f=C.
|
# Fortran. In the later case the parser tries to guess whether the code is fixed
|
||||||
|
# or free formatted code, this is the default for Fortran type files), VHDL. For
|
||||||
|
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
|
||||||
|
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
|
||||||
#
|
#
|
||||||
# Note For files without extension you can use no_extension as a placeholder.
|
# Note: For files without extension you can use no_extension as a placeholder.
|
||||||
#
|
#
|
||||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||||
# the files are not read by doxygen.
|
# the files are not read by doxygen.
|
||||||
@@ -284,8 +295,8 @@ MARKDOWN_SUPPORT = YES
|
|||||||
|
|
||||||
# When enabled doxygen tries to link words that correspond to documented
|
# When enabled doxygen tries to link words that correspond to documented
|
||||||
# classes, or namespaces to their corresponding documentation. Such a link can
|
# classes, or namespaces to their corresponding documentation. Such a link can
|
||||||
# be prevented in individual cases by by putting a % sign in front of the word
|
# be prevented in individual cases by putting a % sign in front of the word or
|
||||||
# or globally by setting AUTOLINK_SUPPORT to NO.
|
# globally by setting AUTOLINK_SUPPORT to NO.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
AUTOLINK_SUPPORT = YES
|
AUTOLINK_SUPPORT = YES
|
||||||
@@ -325,13 +336,20 @@ SIP_SUPPORT = NO
|
|||||||
IDL_PROPERTY_SUPPORT = YES
|
IDL_PROPERTY_SUPPORT = YES
|
||||||
|
|
||||||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
||||||
# tag is set to YES, then doxygen will reuse the documentation of the first
|
# tag is set to YES then doxygen will reuse the documentation of the first
|
||||||
# member in the group (if any) for the other members of the group. By default
|
# member in the group (if any) for the other members of the group. By default
|
||||||
# all members of a group must be documented explicitly.
|
# all members of a group must be documented explicitly.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
DISTRIBUTE_GROUP_DOC = NO
|
DISTRIBUTE_GROUP_DOC = NO
|
||||||
|
|
||||||
|
# If one adds a struct or class to a group and this option is enabled, then also
|
||||||
|
# any nested class or struct is added to the same group. By default this option
|
||||||
|
# is disabled and one has to add nested compounds explicitly via \ingroup.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
GROUP_NESTED_COMPOUNDS = NO
|
||||||
|
|
||||||
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
|
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
|
||||||
# (for instance a group of public functions) to be put as a subgroup of that
|
# (for instance a group of public functions) to be put as a subgroup of that
|
||||||
# type (e.g. under the Public Functions section). Set it to NO to prevent
|
# type (e.g. under the Public Functions section). Set it to NO to prevent
|
||||||
@@ -390,7 +408,7 @@ LOOKUP_CACHE_SIZE = 0
|
|||||||
# Build related configuration options
|
# Build related configuration options
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
|
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
|
||||||
# documentation are documented, even if no documentation was available. Private
|
# documentation are documented, even if no documentation was available. Private
|
||||||
# class members and static file members will be hidden unless the
|
# class members and static file members will be hidden unless the
|
||||||
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
|
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
|
||||||
@@ -400,35 +418,35 @@ LOOKUP_CACHE_SIZE = 0
|
|||||||
|
|
||||||
EXTRACT_ALL = YES
|
EXTRACT_ALL = YES
|
||||||
|
|
||||||
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
|
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
|
||||||
# be included in the documentation.
|
# be included in the documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
EXTRACT_PRIVATE = NO
|
EXTRACT_PRIVATE = NO
|
||||||
|
|
||||||
# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
|
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||||
# scope will be included in the documentation.
|
# scope will be included in the documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
EXTRACT_PACKAGE = NO
|
EXTRACT_PACKAGE = NO
|
||||||
|
|
||||||
# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
|
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
|
||||||
# included in the documentation.
|
# included in the documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
EXTRACT_STATIC = NO
|
EXTRACT_STATIC = NO
|
||||||
|
|
||||||
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
|
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
|
||||||
# locally in source files will be included in the documentation. If set to NO
|
# locally in source files will be included in the documentation. If set to NO,
|
||||||
# only classes defined in header files are included. Does not have any effect
|
# only classes defined in header files are included. Does not have any effect
|
||||||
# for Java sources.
|
# for Java sources.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
EXTRACT_LOCAL_CLASSES = NO
|
EXTRACT_LOCAL_CLASSES = NO
|
||||||
|
|
||||||
# This flag is only useful for Objective-C code. When set to YES local methods,
|
# This flag is only useful for Objective-C code. If set to YES, local methods,
|
||||||
# which are defined in the implementation section but not in the interface are
|
# which are defined in the implementation section but not in the interface are
|
||||||
# included in the documentation. If set to NO only methods in the interface are
|
# included in the documentation. If set to NO, only methods in the interface are
|
||||||
# included.
|
# included.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
@@ -453,21 +471,21 @@ HIDE_UNDOC_MEMBERS = NO
|
|||||||
|
|
||||||
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
|
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
|
||||||
# undocumented classes that are normally visible in the class hierarchy. If set
|
# undocumented classes that are normally visible in the class hierarchy. If set
|
||||||
# to NO these classes will be included in the various overviews. This option has
|
# to NO, these classes will be included in the various overviews. This option
|
||||||
# no effect if EXTRACT_ALL is enabled.
|
# has no effect if EXTRACT_ALL is enabled.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
HIDE_UNDOC_CLASSES = NO
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
|
||||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||||
# (class|struct|union) declarations. If set to NO these declarations will be
|
# (class|struct|union) declarations. If set to NO, these declarations will be
|
||||||
# included in the documentation.
|
# included in the documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
HIDE_FRIEND_COMPOUNDS = NO
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
|
|
||||||
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
|
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
|
||||||
# documentation blocks found inside the body of a function. If set to NO these
|
# documentation blocks found inside the body of a function. If set to NO, these
|
||||||
# blocks will be appended to the function's detailed documentation block.
|
# blocks will be appended to the function's detailed documentation block.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
@@ -481,7 +499,7 @@ HIDE_IN_BODY_DOCS = NO
|
|||||||
INTERNAL_DOCS = NO
|
INTERNAL_DOCS = NO
|
||||||
|
|
||||||
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
||||||
# names in lower-case letters. If set to YES upper-case letters are also
|
# names in lower-case letters. If set to YES, upper-case letters are also
|
||||||
# allowed. This is useful if you have classes or files whose names only differ
|
# allowed. This is useful if you have classes or files whose names only differ
|
||||||
# in case and if your file system supports case sensitive file names. Windows
|
# in case and if your file system supports case sensitive file names. Windows
|
||||||
# and Mac users are advised to set this option to NO.
|
# and Mac users are advised to set this option to NO.
|
||||||
@@ -490,12 +508,19 @@ INTERNAL_DOCS = NO
|
|||||||
CASE_SENSE_NAMES = YES
|
CASE_SENSE_NAMES = YES
|
||||||
|
|
||||||
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
|
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
|
||||||
# their full class and namespace scopes in the documentation. If set to YES the
|
# their full class and namespace scopes in the documentation. If set to YES, the
|
||||||
# scope will be hidden.
|
# scope will be hidden.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
HIDE_SCOPE_NAMES = NO
|
HIDE_SCOPE_NAMES = NO
|
||||||
|
|
||||||
|
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
|
||||||
|
# append additional text to a page's title, such as Class Reference. If set to
|
||||||
|
# YES the compound reference will be hidden.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
HIDE_COMPOUND_REFERENCE= NO
|
||||||
|
|
||||||
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
|
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
|
||||||
# the files that are included by a file in the documentation of that file.
|
# the files that are included by a file in the documentation of that file.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@@ -523,14 +548,14 @@ INLINE_INFO = YES
|
|||||||
|
|
||||||
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
|
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
|
||||||
# (detailed) documentation of file and class members alphabetically by member
|
# (detailed) documentation of file and class members alphabetically by member
|
||||||
# name. If set to NO the members will appear in declaration order.
|
# name. If set to NO, the members will appear in declaration order.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
SORT_MEMBER_DOCS = YES
|
SORT_MEMBER_DOCS = YES
|
||||||
|
|
||||||
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
|
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
|
||||||
# descriptions of file, namespace and class members alphabetically by member
|
# descriptions of file, namespace and class members alphabetically by member
|
||||||
# name. If set to NO the members will appear in declaration order. Note that
|
# name. If set to NO, the members will appear in declaration order. Note that
|
||||||
# this will also influence the order of the classes in the class list.
|
# this will also influence the order of the classes in the class list.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
@@ -575,27 +600,25 @@ SORT_BY_SCOPE_NAME = NO
|
|||||||
|
|
||||||
STRICT_PROTO_MATCHING = NO
|
STRICT_PROTO_MATCHING = NO
|
||||||
|
|
||||||
# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
|
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
|
||||||
# todo list. This list is created by putting \todo commands in the
|
# list. This list is created by putting \todo commands in the documentation.
|
||||||
# documentation.
|
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
GENERATE_TODOLIST = YES
|
GENERATE_TODOLIST = YES
|
||||||
|
|
||||||
# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
|
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
|
||||||
# test list. This list is created by putting \test commands in the
|
# list. This list is created by putting \test commands in the documentation.
|
||||||
# documentation.
|
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
GENERATE_TESTLIST = YES
|
GENERATE_TESTLIST = YES
|
||||||
|
|
||||||
# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
|
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
|
||||||
# list. This list is created by putting \bug commands in the documentation.
|
# list. This list is created by putting \bug commands in the documentation.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
GENERATE_BUGLIST = YES
|
GENERATE_BUGLIST = YES
|
||||||
|
|
||||||
# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
|
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
|
||||||
# the deprecated list. This list is created by putting \deprecated commands in
|
# the deprecated list. This list is created by putting \deprecated commands in
|
||||||
# the documentation.
|
# the documentation.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@@ -620,8 +643,8 @@ ENABLED_SECTIONS =
|
|||||||
MAX_INITIALIZER_LINES = 30
|
MAX_INITIALIZER_LINES = 30
|
||||||
|
|
||||||
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
|
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
|
||||||
# the bottom of the documentation of classes and structs. If set to YES the list
|
# the bottom of the documentation of classes and structs. If set to YES, the
|
||||||
# will mention the files that were used to generate the documentation.
|
# list will mention the files that were used to generate the documentation.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
SHOW_USED_FILES = YES
|
SHOW_USED_FILES = YES
|
||||||
@@ -669,8 +692,7 @@ LAYOUT_FILE =
|
|||||||
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
|
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
|
||||||
# For LaTeX the style of the bibliography can be controlled using
|
# For LaTeX the style of the bibliography can be controlled using
|
||||||
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
|
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
|
||||||
# search path. Do not use file names with spaces, bibtex cannot handle them. See
|
# search path. See also \cite for info how to create references.
|
||||||
# also \cite for info how to create references.
|
|
||||||
|
|
||||||
CITE_BIB_FILES =
|
CITE_BIB_FILES =
|
||||||
|
|
||||||
@@ -686,7 +708,7 @@ CITE_BIB_FILES =
|
|||||||
QUIET = NO
|
QUIET = NO
|
||||||
|
|
||||||
# The WARNINGS tag can be used to turn on/off the warning messages that are
|
# The WARNINGS tag can be used to turn on/off the warning messages that are
|
||||||
# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
|
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
|
||||||
# this implies that the warnings are on.
|
# this implies that the warnings are on.
|
||||||
#
|
#
|
||||||
# Tip: Turn warnings on while writing the documentation.
|
# Tip: Turn warnings on while writing the documentation.
|
||||||
@@ -694,7 +716,7 @@ QUIET = NO
|
|||||||
|
|
||||||
WARNINGS = YES
|
WARNINGS = YES
|
||||||
|
|
||||||
# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
|
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
|
||||||
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
|
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
|
||||||
# will automatically be disabled.
|
# will automatically be disabled.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@@ -711,8 +733,8 @@ WARN_IF_DOC_ERROR = YES
|
|||||||
|
|
||||||
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
||||||
# are documented, but have no documentation for their parameters or return
|
# are documented, but have no documentation for their parameters or return
|
||||||
# value. If set to NO doxygen will only warn about wrong or incomplete parameter
|
# value. If set to NO, doxygen will only warn about wrong or incomplete
|
||||||
# documentation, but not about the absence of documentation.
|
# parameter documentation, but not about the absence of documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
WARN_NO_PARAMDOC = NO
|
WARN_NO_PARAMDOC = NO
|
||||||
@@ -740,10 +762,11 @@ WARN_LOGFILE =
|
|||||||
# The INPUT tag is used to specify the files and/or directories that contain
|
# The INPUT tag is used to specify the files and/or directories that contain
|
||||||
# documented source files. You may enter file names like myfile.cpp or
|
# documented source files. You may enter file names like myfile.cpp or
|
||||||
# directories like /usr/src/myproject. Separate the files or directories with
|
# directories like /usr/src/myproject. Separate the files or directories with
|
||||||
# spaces.
|
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = include
|
INPUT = src \
|
||||||
|
src/pv
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
@@ -756,12 +779,17 @@ INPUT_ENCODING = UTF-8
|
|||||||
|
|
||||||
# If the value of the INPUT tag contains directories, you can use the
|
# If the value of the INPUT tag contains directories, you can use the
|
||||||
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
|
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
|
||||||
# *.h) to filter out the source-files in the directories. If left blank the
|
# *.h) to filter out the source-files in the directories.
|
||||||
# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
|
#
|
||||||
# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
|
# Note that for custom extensions or not directly supported extensions you also
|
||||||
# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
|
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
# read by doxygen.
|
||||||
# *.qsf, *.as and *.js.
|
#
|
||||||
|
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||||
|
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||||
|
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||||
|
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd,
|
||||||
|
# *.vhdl, *.ucf, *.qsf, *.as and *.js.
|
||||||
|
|
||||||
FILE_PATTERNS =
|
FILE_PATTERNS =
|
||||||
|
|
||||||
@@ -769,7 +797,7 @@ FILE_PATTERNS =
|
|||||||
# be searched for input files as well.
|
# be searched for input files as well.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
RECURSIVE = YES
|
RECURSIVE = NO
|
||||||
|
|
||||||
# The EXCLUDE tag can be used to specify files and/or directories that should be
|
# The EXCLUDE tag can be used to specify files and/or directories that should be
|
||||||
# excluded from the INPUT source files. This way you can easily exclude a
|
# excluded from the INPUT source files. This way you can easily exclude a
|
||||||
@@ -860,7 +888,7 @@ INPUT_FILTER =
|
|||||||
FILTER_PATTERNS =
|
FILTER_PATTERNS =
|
||||||
|
|
||||||
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
|
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
|
||||||
# INPUT_FILTER ) will also be used to filter the input files that are used for
|
# INPUT_FILTER) will also be used to filter the input files that are used for
|
||||||
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
|
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
@@ -920,7 +948,7 @@ REFERENCED_BY_RELATION = YES
|
|||||||
REFERENCES_RELATION = YES
|
REFERENCES_RELATION = YES
|
||||||
|
|
||||||
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
|
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
|
||||||
# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
|
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
|
||||||
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
|
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
|
||||||
# link to the documentation.
|
# link to the documentation.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@@ -997,7 +1025,7 @@ IGNORE_PREFIX =
|
|||||||
# Configuration options related to the HTML output
|
# Configuration options related to the HTML output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
|
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
GENERATE_HTML = YES
|
GENERATE_HTML = YES
|
||||||
@@ -1008,7 +1036,7 @@ GENERATE_HTML = YES
|
|||||||
# The default directory is: html.
|
# The default directory is: html.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_OUTPUT = documentation/html
|
HTML_OUTPUT = html/doxygen
|
||||||
|
|
||||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||||
# generated HTML page (for example: .htm, .php, .asp).
|
# generated HTML page (for example: .htm, .php, .asp).
|
||||||
@@ -1059,13 +1087,15 @@ HTML_FOOTER =
|
|||||||
|
|
||||||
HTML_STYLESHEET =
|
HTML_STYLESHEET =
|
||||||
|
|
||||||
# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
|
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
|
||||||
# defined cascading style sheet that is included after the standard style sheets
|
# cascading style sheets that are included after the standard style sheets
|
||||||
# created by doxygen. Using this option one can overrule certain style aspects.
|
# created by doxygen. Using this option one can overrule certain style aspects.
|
||||||
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
||||||
# standard style sheet and is therefor more robust against future updates.
|
# standard style sheet and is therefore more robust against future updates.
|
||||||
# Doxygen will copy the style sheet file to the output directory. For an example
|
# Doxygen will copy the style sheet files to the output directory.
|
||||||
# see the documentation.
|
# Note: The order of the extra style sheet files is of importance (e.g. the last
|
||||||
|
# style sheet in the list overrules the setting of the previous ones in the
|
||||||
|
# list). For an example see the documentation.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_EXTRA_STYLESHEET =
|
HTML_EXTRA_STYLESHEET =
|
||||||
@@ -1078,10 +1108,10 @@ HTML_EXTRA_STYLESHEET =
|
|||||||
# files will be copied as-is; there are no commands or markers available.
|
# files will be copied as-is; there are no commands or markers available.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_EXTRA_FILES = documentation/overview.html
|
HTML_EXTRA_FILES =
|
||||||
|
|
||||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||||
# will adjust the colors in the stylesheet and background images according to
|
# will adjust the colors in the style sheet and background images according to
|
||||||
# this color. Hue is specified as an angle on a colorwheel, see
|
# this color. Hue is specified as an angle on a colorwheel, see
|
||||||
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||||
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
||||||
@@ -1112,8 +1142,9 @@ HTML_COLORSTYLE_GAMMA = 80
|
|||||||
|
|
||||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||||
# page will contain the date and time when the page was generated. Setting this
|
# page will contain the date and time when the page was generated. Setting this
|
||||||
# to NO can help when comparing the output of multiple runs.
|
# to YES can help to show when doxygen was last run and thus if the
|
||||||
# The default value is: YES.
|
# documentation is up to date.
|
||||||
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_TIMESTAMP = YES
|
HTML_TIMESTAMP = YES
|
||||||
@@ -1209,28 +1240,29 @@ GENERATE_HTMLHELP = NO
|
|||||||
CHM_FILE =
|
CHM_FILE =
|
||||||
|
|
||||||
# The HHC_LOCATION tag can be used to specify the location (absolute path
|
# The HHC_LOCATION tag can be used to specify the location (absolute path
|
||||||
# including file name) of the HTML help compiler ( hhc.exe). If non-empty
|
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
|
||||||
# doxygen will try to run the HTML help compiler on the generated index.hhp.
|
# doxygen will try to run the HTML help compiler on the generated index.hhp.
|
||||||
# The file has to be specified with full path.
|
# The file has to be specified with full path.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
HHC_LOCATION =
|
HHC_LOCATION =
|
||||||
|
|
||||||
# The GENERATE_CHI flag controls if a separate .chi index file is generated (
|
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
||||||
# YES) or that it should be included in the master .chm file ( NO).
|
# (YES) or that it should be included in the master .chm file (NO).
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
GENERATE_CHI = NO
|
GENERATE_CHI = NO
|
||||||
|
|
||||||
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
|
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
|
||||||
# and project file content.
|
# and project file content.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
CHM_INDEX_ENCODING =
|
CHM_INDEX_ENCODING =
|
||||||
|
|
||||||
# The BINARY_TOC flag controls whether a binary table of contents is generated (
|
# The BINARY_TOC flag controls whether a binary table of contents is generated
|
||||||
# YES) or a normal table of contents ( NO) in the .chm file.
|
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
|
||||||
|
# enables the Previous and Next buttons.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
@@ -1343,7 +1375,7 @@ DISABLE_INDEX = NO
|
|||||||
# index structure (just like the one that is generated for HTML Help). For this
|
# index structure (just like the one that is generated for HTML Help). For this
|
||||||
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
||||||
# (i.e. any modern browser). Windows users are probably better off using the
|
# (i.e. any modern browser). Windows users are probably better off using the
|
||||||
# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
|
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
|
||||||
# further fine-tune the look of the index. As an example, the default style
|
# further fine-tune the look of the index. As an example, the default style
|
||||||
# sheet generated by doxygen has an example that shows how to put an image at
|
# sheet generated by doxygen has an example that shows how to put an image at
|
||||||
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
|
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
|
||||||
@@ -1371,7 +1403,7 @@ ENUM_VALUES_PER_LINE = 4
|
|||||||
|
|
||||||
TREEVIEW_WIDTH = 250
|
TREEVIEW_WIDTH = 250
|
||||||
|
|
||||||
# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
|
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
|
||||||
# external symbols imported via tag files in a separate window.
|
# external symbols imported via tag files in a separate window.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
@@ -1400,7 +1432,7 @@ FORMULA_TRANSPARENT = YES
|
|||||||
|
|
||||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||||
# http://www.mathjax.org) which uses client side Javascript for the rendering
|
# http://www.mathjax.org) which uses client side Javascript for the rendering
|
||||||
# instead of using prerendered bitmaps. Use this if you do not have LaTeX
|
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||||
# installed or if you want to formulas look prettier in the HTML output. When
|
# installed or if you want to formulas look prettier in the HTML output. When
|
||||||
# enabled you may also need to install MathJax separately and configure the path
|
# enabled you may also need to install MathJax separately and configure the path
|
||||||
# to it using the MATHJAX_RELPATH option.
|
# to it using the MATHJAX_RELPATH option.
|
||||||
@@ -1470,11 +1502,11 @@ SEARCHENGINE = NO
|
|||||||
|
|
||||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||||
# implemented using a web server instead of a web client using Javascript. There
|
# implemented using a web server instead of a web client using Javascript. There
|
||||||
# are two flavours of web server based searching depending on the
|
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||||
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
|
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||||
# searching and an index file used by the script. When EXTERNAL_SEARCH is
|
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||||
# enabled the indexing and searching needs to be provided by external tools. See
|
# and searching needs to be provided by external tools. See the section
|
||||||
# the section "External Indexing and Searching" for details.
|
# "External Indexing and Searching" for details.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||||
|
|
||||||
@@ -1486,7 +1518,7 @@ SERVER_BASED_SEARCH = NO
|
|||||||
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
|
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
|
||||||
# search results.
|
# search results.
|
||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer ( doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (doxysearch.cgi) which are based on the open source search engine library
|
||||||
# Xapian (see: http://xapian.org/).
|
# Xapian (see: http://xapian.org/).
|
||||||
#
|
#
|
||||||
@@ -1499,7 +1531,7 @@ EXTERNAL_SEARCH = NO
|
|||||||
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
|
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
|
||||||
# which will return the search results when EXTERNAL_SEARCH is enabled.
|
# which will return the search results when EXTERNAL_SEARCH is enabled.
|
||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer ( doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (doxysearch.cgi) which are based on the open source search engine library
|
||||||
# Xapian (see: http://xapian.org/). See the section "External Indexing and
|
# Xapian (see: http://xapian.org/). See the section "External Indexing and
|
||||||
# Searching" for details.
|
# Searching" for details.
|
||||||
@@ -1537,7 +1569,7 @@ EXTRA_SEARCH_MAPPINGS =
|
|||||||
# Configuration options related to the LaTeX output
|
# Configuration options related to the LaTeX output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
|
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
GENERATE_LATEX = NO
|
GENERATE_LATEX = NO
|
||||||
@@ -1568,7 +1600,7 @@ LATEX_CMD_NAME = latex
|
|||||||
|
|
||||||
MAKEINDEX_CMD_NAME = makeindex
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
|
||||||
# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
|
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
|
||||||
# documents. This may be useful for small projects and may help to save some
|
# documents. This may be useful for small projects and may help to save some
|
||||||
# trees in general.
|
# trees in general.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@@ -1586,9 +1618,12 @@ COMPACT_LATEX = NO
|
|||||||
PAPER_TYPE = a4wide
|
PAPER_TYPE = a4wide
|
||||||
|
|
||||||
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
||||||
# that should be included in the LaTeX output. To get the times font for
|
# that should be included in the LaTeX output. The package can be specified just
|
||||||
# instance you can specify
|
# by its name or with the correct syntax as to be used with the LaTeX
|
||||||
# EXTRA_PACKAGES=times
|
# \usepackage command. To get the times font for instance you can specify :
|
||||||
|
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
|
||||||
|
# To use the option intlimits with the amsmath package you can specify:
|
||||||
|
# EXTRA_PACKAGES=[intlimits]{amsmath}
|
||||||
# If left blank no extra packages will be included.
|
# If left blank no extra packages will be included.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
@@ -1602,23 +1637,36 @@ EXTRA_PACKAGES =
|
|||||||
#
|
#
|
||||||
# Note: Only use a user-defined header if you know what you are doing! The
|
# Note: Only use a user-defined header if you know what you are doing! The
|
||||||
# following commands have a special meaning inside the header: $title,
|
# following commands have a special meaning inside the header: $title,
|
||||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
|
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
||||||
# replace them by respectively the title of the page, the current date and time,
|
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
|
||||||
# only the current date, the version number of doxygen, the project name (see
|
# string, for the replacement values of the other commands the user is referred
|
||||||
# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
|
# to HTML_HEADER.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_HEADER =
|
LATEX_HEADER =
|
||||||
|
|
||||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
||||||
# generated LaTeX document. The footer should contain everything after the last
|
# generated LaTeX document. The footer should contain everything after the last
|
||||||
# chapter. If it is left blank doxygen will generate a standard footer.
|
# chapter. If it is left blank doxygen will generate a standard footer. See
|
||||||
|
# LATEX_HEADER for more information on how to generate a default footer and what
|
||||||
|
# special commands can be used inside the footer.
|
||||||
#
|
#
|
||||||
# Note: Only use a user-defined footer if you know what you are doing!
|
# Note: Only use a user-defined footer if you know what you are doing!
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_FOOTER =
|
LATEX_FOOTER =
|
||||||
|
|
||||||
|
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
|
||||||
|
# LaTeX style sheets that are included after the standard style sheets created
|
||||||
|
# by doxygen. Using this option one can overrule certain style aspects. Doxygen
|
||||||
|
# will copy the style sheet files to the output directory.
|
||||||
|
# Note: The order of the extra style sheet files is of importance (e.g. the last
|
||||||
|
# style sheet in the list overrules the setting of the previous ones in the
|
||||||
|
# list).
|
||||||
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
|
LATEX_EXTRA_STYLESHEET =
|
||||||
|
|
||||||
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
|
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||||
# other source files which should be copied to the LATEX_OUTPUT output
|
# other source files which should be copied to the LATEX_OUTPUT output
|
||||||
# directory. Note that the files will be copied as-is; there are no commands or
|
# directory. Note that the files will be copied as-is; there are no commands or
|
||||||
@@ -1636,8 +1684,8 @@ LATEX_EXTRA_FILES =
|
|||||||
|
|
||||||
PDF_HYPERLINKS = NO
|
PDF_HYPERLINKS = NO
|
||||||
|
|
||||||
# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
||||||
# the PDF file directly from the LaTeX files. Set this option to YES to get a
|
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
||||||
# higher quality PDF documentation.
|
# higher quality PDF documentation.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
@@ -1678,11 +1726,19 @@ LATEX_SOURCE_CODE = NO
|
|||||||
|
|
||||||
LATEX_BIB_STYLE = plain
|
LATEX_BIB_STYLE = plain
|
||||||
|
|
||||||
|
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
|
||||||
|
# page will contain the date and time when the page was generated. Setting this
|
||||||
|
# to NO can help when comparing the output of multiple runs.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
|
LATEX_TIMESTAMP = NO
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the RTF output
|
# Configuration options related to the RTF output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
|
# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
|
||||||
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
|
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
|
||||||
# readers/editors.
|
# readers/editors.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@@ -1697,7 +1753,7 @@ GENERATE_RTF = NO
|
|||||||
|
|
||||||
RTF_OUTPUT = rtf
|
RTF_OUTPUT = rtf
|
||||||
|
|
||||||
# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
|
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
|
||||||
# documents. This may be useful for small projects and may help to save some
|
# documents. This may be useful for small projects and may help to save some
|
||||||
# trees in general.
|
# trees in general.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@@ -1734,11 +1790,21 @@ RTF_STYLESHEET_FILE =
|
|||||||
|
|
||||||
RTF_EXTENSIONS_FILE =
|
RTF_EXTENSIONS_FILE =
|
||||||
|
|
||||||
|
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
|
||||||
|
# with syntax highlighting in the RTF output.
|
||||||
|
#
|
||||||
|
# Note that which sources are shown also depends on other settings such as
|
||||||
|
# SOURCE_BROWSER.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||||
|
|
||||||
|
RTF_SOURCE_CODE = NO
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the man page output
|
# Configuration options related to the man page output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
|
# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
|
||||||
# classes and files.
|
# classes and files.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
@@ -1762,6 +1828,13 @@ MAN_OUTPUT = man
|
|||||||
|
|
||||||
MAN_EXTENSION = .3
|
MAN_EXTENSION = .3
|
||||||
|
|
||||||
|
# The MAN_SUBDIR tag determines the name of the directory created within
|
||||||
|
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
|
||||||
|
# MAN_EXTENSION with the initial . removed.
|
||||||
|
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||||
|
|
||||||
|
MAN_SUBDIR =
|
||||||
|
|
||||||
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
|
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
|
||||||
# will generate one additional man file for each entity documented in the real
|
# will generate one additional man file for each entity documented in the real
|
||||||
# man page(s). These additional files only source the real man page, but without
|
# man page(s). These additional files only source the real man page, but without
|
||||||
@@ -1775,7 +1848,7 @@ MAN_LINKS = NO
|
|||||||
# Configuration options related to the XML output
|
# Configuration options related to the XML output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
|
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
|
||||||
# captures the structure of the code including all documentation.
|
# captures the structure of the code including all documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
@@ -1789,19 +1862,7 @@ GENERATE_XML = NO
|
|||||||
|
|
||||||
XML_OUTPUT = xml
|
XML_OUTPUT = xml
|
||||||
|
|
||||||
# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
|
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
|
||||||
# validating XML parser to check the syntax of the XML files.
|
|
||||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
|
||||||
|
|
||||||
XML_SCHEMA =
|
|
||||||
|
|
||||||
# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
|
|
||||||
# validating XML parser to check the syntax of the XML files.
|
|
||||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
|
||||||
|
|
||||||
XML_DTD =
|
|
||||||
|
|
||||||
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
|
|
||||||
# listings (including syntax highlighting and cross-referencing information) to
|
# listings (including syntax highlighting and cross-referencing information) to
|
||||||
# the XML output. Note that enabling this will significantly increase the size
|
# the XML output. Note that enabling this will significantly increase the size
|
||||||
# of the XML output.
|
# of the XML output.
|
||||||
@@ -1814,7 +1875,7 @@ XML_PROGRAMLISTING = YES
|
|||||||
# Configuration options related to the DOCBOOK output
|
# Configuration options related to the DOCBOOK output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
|
# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
|
||||||
# that can be used to generate PDF.
|
# that can be used to generate PDF.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
@@ -1828,14 +1889,23 @@ GENERATE_DOCBOOK = NO
|
|||||||
|
|
||||||
DOCBOOK_OUTPUT = docbook
|
DOCBOOK_OUTPUT = docbook
|
||||||
|
|
||||||
|
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
|
||||||
|
# program listings (including syntax highlighting and cross-referencing
|
||||||
|
# information) to the DOCBOOK output. Note that enabling this will significantly
|
||||||
|
# increase the size of the DOCBOOK output.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
||||||
|
|
||||||
|
DOCBOOK_PROGRAMLISTING = NO
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options for the AutoGen Definitions output
|
# Configuration options for the AutoGen Definitions output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
|
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
|
||||||
# Definitions (see http://autogen.sf.net) file that captures the structure of
|
# AutoGen Definitions (see http://autogen.sf.net) file that captures the
|
||||||
# the code including all documentation. Note that this feature is still
|
# structure of the code including all documentation. Note that this feature is
|
||||||
# experimental and incomplete at the moment.
|
# still experimental and incomplete at the moment.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
GENERATE_AUTOGEN_DEF = NO
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
@@ -1844,7 +1914,7 @@ GENERATE_AUTOGEN_DEF = NO
|
|||||||
# Configuration options related to the Perl module output
|
# Configuration options related to the Perl module output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
|
# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
|
||||||
# file that captures the structure of the code including all documentation.
|
# file that captures the structure of the code including all documentation.
|
||||||
#
|
#
|
||||||
# Note that this feature is still experimental and incomplete at the moment.
|
# Note that this feature is still experimental and incomplete at the moment.
|
||||||
@@ -1852,7 +1922,7 @@ GENERATE_AUTOGEN_DEF = NO
|
|||||||
|
|
||||||
GENERATE_PERLMOD = NO
|
GENERATE_PERLMOD = NO
|
||||||
|
|
||||||
# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
|
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
|
||||||
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
|
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
|
||||||
# output from the Perl module output.
|
# output from the Perl module output.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@@ -1860,9 +1930,9 @@ GENERATE_PERLMOD = NO
|
|||||||
|
|
||||||
PERLMOD_LATEX = NO
|
PERLMOD_LATEX = NO
|
||||||
|
|
||||||
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
|
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
|
||||||
# formatted so it can be parsed by a human reader. This is useful if you want to
|
# formatted so it can be parsed by a human reader. This is useful if you want to
|
||||||
# understand what is going on. On the other hand, if this tag is set to NO the
|
# understand what is going on. On the other hand, if this tag is set to NO, the
|
||||||
# size of the Perl module output will be much smaller and Perl will parse it
|
# size of the Perl module output will be much smaller and Perl will parse it
|
||||||
# just the same.
|
# just the same.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@@ -1882,14 +1952,14 @@ PERLMOD_MAKEVAR_PREFIX =
|
|||||||
# Configuration options related to the preprocessor
|
# Configuration options related to the preprocessor
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
|
# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
|
||||||
# C-preprocessor directives found in the sources and include files.
|
# C-preprocessor directives found in the sources and include files.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
ENABLE_PREPROCESSING = YES
|
ENABLE_PREPROCESSING = YES
|
||||||
|
|
||||||
# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
|
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
|
||||||
# in the source code. If set to NO only conditional compilation will be
|
# in the source code. If set to NO, only conditional compilation will be
|
||||||
# performed. Macro expansion can be done in a controlled way by setting
|
# performed. Macro expansion can be done in a controlled way by setting
|
||||||
# EXPAND_ONLY_PREDEF to YES.
|
# EXPAND_ONLY_PREDEF to YES.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@@ -1905,7 +1975,7 @@ MACRO_EXPANSION = NO
|
|||||||
|
|
||||||
EXPAND_ONLY_PREDEF = NO
|
EXPAND_ONLY_PREDEF = NO
|
||||||
|
|
||||||
# If the SEARCH_INCLUDES tag is set to YES the includes files in the
|
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
|
||||||
# INCLUDE_PATH will be searched if a #include is found.
|
# INCLUDE_PATH will be searched if a #include is found.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
@@ -1947,9 +2017,9 @@ PREDEFINED =
|
|||||||
EXPAND_AS_DEFINED =
|
EXPAND_AS_DEFINED =
|
||||||
|
|
||||||
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
||||||
# remove all refrences to function-like macros that are alone on a line, have an
|
# remove all references to function-like macros that are alone on a line, have
|
||||||
# all uppercase name, and do not end with a semicolon. Such function macros are
|
# an all uppercase name, and do not end with a semicolon. Such function macros
|
||||||
# typically used for boiler-plate code, and will confuse the parser if not
|
# are typically used for boiler-plate code, and will confuse the parser if not
|
||||||
# removed.
|
# removed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
@@ -1969,7 +2039,7 @@ SKIP_FUNCTION_MACROS = YES
|
|||||||
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
|
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
|
||||||
# section "Linking to external documentation" for more information about the use
|
# section "Linking to external documentation" for more information about the use
|
||||||
# of tag files.
|
# of tag files.
|
||||||
# Note: Each tag file must have an unique name (where the name does NOT include
|
# Note: Each tag file must have a unique name (where the name does NOT include
|
||||||
# the path). If a tag file is not located in the directory in which doxygen is
|
# the path). If a tag file is not located in the directory in which doxygen is
|
||||||
# run, you must also specify the path to the tagfile here.
|
# run, you must also specify the path to the tagfile here.
|
||||||
|
|
||||||
@@ -1981,20 +2051,21 @@ TAGFILES =
|
|||||||
|
|
||||||
GENERATE_TAGFILE =
|
GENERATE_TAGFILE =
|
||||||
|
|
||||||
# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
|
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
|
||||||
# class index. If set to NO only the inherited external classes will be listed.
|
# the class index. If set to NO, only the inherited external classes will be
|
||||||
|
# listed.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
ALLEXTERNALS = NO
|
ALLEXTERNALS = NO
|
||||||
|
|
||||||
# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
|
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
|
||||||
# the modules index. If set to NO, only the current project's groups will be
|
# in the modules index. If set to NO, only the current project's groups will be
|
||||||
# listed.
|
# listed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
EXTERNAL_GROUPS = YES
|
EXTERNAL_GROUPS = YES
|
||||||
|
|
||||||
# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
|
# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
|
||||||
# the related pages index. If set to NO, only the current project's pages will
|
# the related pages index. If set to NO, only the current project's pages will
|
||||||
# be listed.
|
# be listed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@@ -2011,7 +2082,7 @@ PERL_PATH = /usr/bin/perl
|
|||||||
# Configuration options related to the dot tool
|
# Configuration options related to the dot tool
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
|
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
|
||||||
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
|
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
|
||||||
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
|
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
|
||||||
# disabled, but it is recommended to install and use dot, since it yields more
|
# disabled, but it is recommended to install and use dot, since it yields more
|
||||||
@@ -2036,7 +2107,7 @@ MSCGEN_PATH =
|
|||||||
|
|
||||||
DIA_PATH =
|
DIA_PATH =
|
||||||
|
|
||||||
# If set to YES, the inheritance and collaboration graphs will hide inheritance
|
# If set to YES the inheritance and collaboration graphs will hide inheritance
|
||||||
# and usage relations if the target is undocumented or is not a class.
|
# and usage relations if the target is undocumented or is not a class.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
@@ -2061,7 +2132,7 @@ HAVE_DOT = NO
|
|||||||
|
|
||||||
DOT_NUM_THREADS = 0
|
DOT_NUM_THREADS = 0
|
||||||
|
|
||||||
# When you want a differently looking font n the dot files that doxygen
|
# When you want a differently looking font in the dot files that doxygen
|
||||||
# generates you can specify the font name using DOT_FONTNAME. You need to make
|
# generates you can specify the font name using DOT_FONTNAME. You need to make
|
||||||
# sure dot is able to find the font, which can be done by putting it in a
|
# sure dot is able to find the font, which can be done by putting it in a
|
||||||
# standard location or by setting the DOTFONTPATH environment variable or by
|
# standard location or by setting the DOTFONTPATH environment variable or by
|
||||||
@@ -2109,7 +2180,7 @@ COLLABORATION_GRAPH = YES
|
|||||||
|
|
||||||
GROUP_GRAPHS = YES
|
GROUP_GRAPHS = YES
|
||||||
|
|
||||||
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
|
# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
|
||||||
# collaboration diagrams in a style similar to the OMG's Unified Modeling
|
# collaboration diagrams in a style similar to the OMG's Unified Modeling
|
||||||
# Language.
|
# Language.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@@ -2161,7 +2232,8 @@ INCLUDED_BY_GRAPH = YES
|
|||||||
#
|
#
|
||||||
# Note that enabling this option will significantly increase the time of a run.
|
# Note that enabling this option will significantly increase the time of a run.
|
||||||
# So in most cases it will be better to enable call graphs for selected
|
# So in most cases it will be better to enable call graphs for selected
|
||||||
# functions only using the \callgraph command.
|
# functions only using the \callgraph command. Disabling a call graph can be
|
||||||
|
# accomplished by means of the command \hidecallgraph.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
@@ -2172,7 +2244,8 @@ CALL_GRAPH = NO
|
|||||||
#
|
#
|
||||||
# Note that enabling this option will significantly increase the time of a run.
|
# Note that enabling this option will significantly increase the time of a run.
|
||||||
# So in most cases it will be better to enable caller graphs for selected
|
# So in most cases it will be better to enable caller graphs for selected
|
||||||
# functions only using the \callergraph command.
|
# functions only using the \callergraph command. Disabling a caller graph can be
|
||||||
|
# accomplished by means of the command \hidecallergraph.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
@@ -2195,11 +2268,15 @@ GRAPHICAL_HIERARCHY = YES
|
|||||||
DIRECTORY_GRAPH = YES
|
DIRECTORY_GRAPH = YES
|
||||||
|
|
||||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||||
# generated by dot.
|
# generated by dot. For an explanation of the image formats see the section
|
||||||
|
# output formats in the documentation of the dot tool (Graphviz (see:
|
||||||
|
# http://www.graphviz.org/)).
|
||||||
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
||||||
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||||
# requirement).
|
# requirement).
|
||||||
# Possible values are: png, jpg, gif and svg.
|
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
|
||||||
|
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
|
||||||
|
# png:gdiplus:gdiplus.
|
||||||
# The default value is: png.
|
# The default value is: png.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
@@ -2242,6 +2319,19 @@ MSCFILE_DIRS =
|
|||||||
|
|
||||||
DIAFILE_DIRS =
|
DIAFILE_DIRS =
|
||||||
|
|
||||||
|
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
|
||||||
|
# path where java can find the plantuml.jar file. If left blank, it is assumed
|
||||||
|
# PlantUML is not used or called during a preprocessing step. Doxygen will
|
||||||
|
# generate a warning when it encounters a \startuml command in this case and
|
||||||
|
# will not generate output for the diagram.
|
||||||
|
|
||||||
|
PLANTUML_JAR_PATH =
|
||||||
|
|
||||||
|
# When using plantuml, the specified paths are searched for files specified by
|
||||||
|
# the !include statement in a plantuml block.
|
||||||
|
|
||||||
|
PLANTUML_INCLUDE_PATH =
|
||||||
|
|
||||||
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
|
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
|
||||||
# that will be shown in the graph. If the number of nodes in a graph becomes
|
# that will be shown in the graph. If the number of nodes in a graph becomes
|
||||||
# larger than this value, doxygen will truncate the graph, which is visualized
|
# larger than this value, doxygen will truncate the graph, which is visualized
|
||||||
@@ -2278,7 +2368,7 @@ MAX_DOT_GRAPH_DEPTH = 0
|
|||||||
|
|
||||||
DOT_TRANSPARENT = NO
|
DOT_TRANSPARENT = NO
|
||||||
|
|
||||||
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
|
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
|
||||||
# files in one run (i.e. multiple -o and -T options on the command line). This
|
# files in one run (i.e. multiple -o and -T options on the command line). This
|
||||||
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
|
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
|
||||||
# this, this feature is disabled by default.
|
# this, this feature is disabled by default.
|
||||||
@@ -2295,7 +2385,7 @@ DOT_MULTI_TARGETS = NO
|
|||||||
|
|
||||||
GENERATE_LEGEND = YES
|
GENERATE_LEGEND = YES
|
||||||
|
|
||||||
# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
|
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
|
||||||
# files that are used to generate the various graphs.
|
# files that are used to generate the various graphs.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
|
Copyright and License Terms
|
||||||
|
---------------------------
|
||||||
|
|
||||||
Copyright (c) 2008 Martin R. Kraimer
|
Copyright (c) 2006-2016 Martin R. Kraimer
|
||||||
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
|
Copyright (c) 2006-2016 UChicago Argonne LLC, as Operator of Argonne
|
||||||
National Laboratory.
|
National Laboratory.
|
||||||
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
|
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
|
||||||
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
|
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
|
||||||
Copyright (c) 2007 Control System Laboratory,
|
Copyright (c) 2007-2016 Control System Laboratory,
|
||||||
(COSYLAB) Ljubljana Slovenia
|
(COSYLAB) Ljubljana Slovenia
|
||||||
|
Copyright (c) 2010-2016 Brookhaven Science Associates, as Operator
|
||||||
|
of Brookhaven National Laboratory
|
||||||
|
Copyright (c) 2011-2016 Diamond Light Source Limited,
|
||||||
|
(DLS) Didcot, United Kingdom
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
@@ -31,48 +36,30 @@ OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
________________________________________________________________________
|
________________________________________________________________________
|
||||||
|
|
||||||
This software is in part copyrighted by the University of Chicago (UofC)
|
Additional Disclaimers
|
||||||
|
----------------------
|
||||||
|
|
||||||
In no event shall UofC be liable to any party for direct, indirect,
|
This software is copyright in part by these institutions:
|
||||||
special, incidental, or consequential damages arising out of the use of
|
|
||||||
this software, its documentation, or any derivatives thereof, even if
|
|
||||||
UofC has been advised of the possibility of such damage.
|
|
||||||
|
|
||||||
UofC specifically disclaims any warranties, including, but not limited
|
* Brookhaven Science Associates, as Operator of Brookhaven
|
||||||
to, the implied warranties of merchantability, fitness for a particular
|
National Laboratory, New York, USA
|
||||||
purpose, and non-infringement. This software is provided on an "as is"
|
* Control System Laboratory, Ljubljana, Slovenia
|
||||||
basis, and UofC has no obligation to provide maintenance, support,
|
* Deutsches Elektronen-Synchroton, Member of the Helmholtz
|
||||||
updates, enhancements, or modifications.
|
Association, Hamburg, Germany
|
||||||
|
* Diamond Light Source Limited, Didcot, United Kingdom
|
||||||
|
* Helmholtz-Zentrum Berlin fuer Materialien und Energie m.b.H.,
|
||||||
|
Berlin, Germany.
|
||||||
|
* UChicage Argonne LLC, as Operator of Argonne National Laboratory,
|
||||||
|
Illinois, USA
|
||||||
|
|
||||||
________________________________________________________________________
|
In no event shall these institutions be liable to any party for direct,
|
||||||
|
indirect, special, incidental, or consequential damages arising out of
|
||||||
|
the use of this software, its documentation, or any derivatives thereof,
|
||||||
|
even if advised of the possibility of such damage.
|
||||||
|
|
||||||
This software is in part copyrighted by the BERLINER SPEICHERRING
|
These institutions specifically disclaim any warranties, including, but
|
||||||
GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H. (BESSY), BERLIN, GERMANY.
|
not limited to, the implied warranties of merchantability, fitness for a
|
||||||
|
particular purpose, and non-infringement. This software is provided on
|
||||||
|
an "as is" basis, and these institutions have no obligation to provide
|
||||||
|
maintenance, support, updates, enhancements, or modifications.
|
||||||
|
|
||||||
In no event shall BESSY be liable to any party for direct, indirect,
|
|
||||||
special, incidental, or consequential damages arising out of the use of
|
|
||||||
this software, its documentation, or any derivatives thereof, even if
|
|
||||||
BESSY has been advised of the possibility of such damage.
|
|
||||||
|
|
||||||
BESSY specifically disclaims any warranties, including, but not limited
|
|
||||||
to, the implied warranties of merchantability, fitness for a particular
|
|
||||||
purpose, and non-infringement. This software is provided on an "as is"
|
|
||||||
basis, and BESSY has no obligation to provide maintenance, support,
|
|
||||||
updates, enhancements, or modifications.
|
|
||||||
|
|
||||||
________________________________________________________________________
|
|
||||||
|
|
||||||
This software is in part copyrighted by the Deutsches Elektronen-Synchroton,
|
|
||||||
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
|
|
||||||
|
|
||||||
In no event shall DESY be liable to any party for direct, indirect,
|
|
||||||
special, incidental, or consequential damages arising out of the use of
|
|
||||||
this software, its documentation, or any derivatives thereof, even if
|
|
||||||
DESY has been advised of the possibility of such damage.
|
|
||||||
|
|
||||||
DESY specifically disclaims any warranties, including, but not limited
|
|
||||||
to, the implied warranties of merchantability, fitness for a particular
|
|
||||||
purpose, and non-infringement. This software is provided on an "as is"
|
|
||||||
basis, and DESY has no obligation to provide maintenance, support,
|
|
||||||
updates, enhancements, or modifications.
|
|
||||||
________________________________________________________________________
|
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
#Makefile at top of application tree
|
#Makefile at top of application tree
|
||||||
TOP = .
|
TOP = .
|
||||||
include $(TOP)/configure/CONFIG
|
include $(TOP)/configure/CONFIG
|
||||||
DIRS := $(DIRS) $(filter-out $(DIRS), configure)
|
DIRS += configure
|
||||||
DIRS := $(DIRS) $(filter-out $(DIRS), src)
|
|
||||||
DIRS := $(DIRS) $(filter-out $(DIRS), example)
|
|
||||||
|
|
||||||
EMBEDDED_TOPS := $(EMBEDDED_TOPS) $(filter-out $(EMBEDDED_TOPS), example)
|
DIRS += src
|
||||||
|
src_DEPEND_DIRS = configure
|
||||||
define DIR_template
|
|
||||||
$(1)_DEPEND_DIRS = configure
|
|
||||||
endef
|
|
||||||
$(foreach dir, $(filter-out configure,$(DIRS)),$(eval $(call DIR_template,$(dir))))
|
|
||||||
|
|
||||||
define EMB_template
|
|
||||||
$(1)_DEPEND_DIRS = src
|
|
||||||
endef
|
|
||||||
$(foreach dir, $(EMBEDDED_TOPS),$(eval $(call EMB_template,$(dir))))
|
|
||||||
|
|
||||||
include $(TOP)/configure/RULES_TOP
|
include $(TOP)/configure/RULES_TOP
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +1,17 @@
|
|||||||
pvaClientCPP
|
# pvaClientCPP
|
||||||
============
|
|
||||||
|
|
||||||
pvaClient is a synchronous client interface to pvAccess,
|
The **pvaClient** API provides a synchronous client interface that was designed to be easier to use than the original basic pvAccess client API.
|
||||||
which is callback based.
|
|
||||||
pvaClient is thus easier to use than pvAccess itself.
|
|
||||||
|
|
||||||
See documentation/pvaClientCPP.html for details.
|
The pvaClientCPP module implements the pvaClient API for C++ client applications.
|
||||||
|
|
||||||
Building
|
## Links
|
||||||
--------
|
|
||||||
|
|
||||||
If a proper RELEASE.local file exists one directory level above pvaClientCPP
|
- General information about EPICS can be found at the
|
||||||
then just type:
|
[EPICS Controls website](https://epics-controls.org).
|
||||||
|
- API documentation for this module can be found in its
|
||||||
|
documentation directory, in particular the file
|
||||||
|
pvaClientCPP.html
|
||||||
|
|
||||||
make
|
## Building
|
||||||
|
|
||||||
If RELEASE.local does not exist then look at <b>configure/RELEASE</b>
|
This module is included as a submodule of a full EPICS 7 release and will be compiled during builds of that software.
|
||||||
for directions for how to build.
|
|
||||||
|
|
||||||
Examples
|
|
||||||
------------
|
|
||||||
|
|
||||||
The examples require the database in pvaClientTestCPP.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
mrk> pwd
|
|
||||||
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
|
|
||||||
mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
|
|
||||||
|
|
||||||
Status
|
|
||||||
------
|
|
||||||
|
|
||||||
* The API is for EPICS Version 4 release 4.5.0
|
|
||||||
* Everything defined in pvaClient.h is ready but see below for remaining work.
|
|
||||||
* Everything defined in pvaClientMultiChannel.h is ready but see below for remaining work.
|
|
||||||
|
|
||||||
|
|
||||||
pvaClientChannel
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Channel::getField and channelArray are not supported for release 4.5
|
|
||||||
|
|
||||||
pvaClientMultiChannel
|
|
||||||
---------------
|
|
||||||
|
|
||||||
For release 4.5 support is available for multiDouble and NTMultiChannel.
|
|
||||||
In the future additional support should be provided that at least includes NTScalarMultiChannel.
|
|
||||||
|
|
||||||
Testing with some channels not connected has not been done.
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
Release/4.1
|
|
||||||
===========
|
|
||||||
|
|
||||||
This is for EPICS V4 release 4.5
|
|
||||||
|
|
||||||
pvaClient is a synchronous API for pvAccess.
|
|
||||||
|
|
||||||
|
|
||||||
This is the first release of pvaClientCPP.
|
|
||||||
It provides an API that is similar to pvaClientJava.
|
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Version number for the PVA Client API and shared library
|
||||||
|
|
||||||
|
EPICS_PVACLIENT_MAJOR_VERSION = 4
|
||||||
|
EPICS_PVACLIENT_MINOR_VERSION = 8
|
||||||
|
EPICS_PVACLIENT_MAINTENANCE_VERSION = 2
|
||||||
|
|
||||||
|
# Development flag, set to zero for release versions
|
||||||
|
|
||||||
|
EPICS_PVACLIENT_DEVELOPMENT_FLAG = 1
|
||||||
|
|
||||||
|
# Immediately after a release the MAINTENANCE_VERSION
|
||||||
|
# will be incremented and the DEVELOPMENT_FLAG set to 1
|
||||||
@@ -20,8 +20,5 @@
|
|||||||
# INSTALL_LOCATION here.
|
# INSTALL_LOCATION here.
|
||||||
#INSTALL_LOCATION=</path/name/to/install/top>
|
#INSTALL_LOCATION=</path/name/to/install/top>
|
||||||
|
|
||||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
|
||||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
|
||||||
|
|
||||||
-include $(TOP)/../CONFIG_SITE.local
|
-include $(TOP)/../CONFIG_SITE.local
|
||||||
-include $(TOP)/configure/CONFIG_SITE.local
|
-include $(TOP)/configure/CONFIG_SITE.local
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
|
||||||
|
|
||||||
EPICS_BASE=/home/install/epics/base
|
|
||||||
V4BASE=/home/epicsv4
|
|
||||||
PVCOMMON=${V4BASE}/pvCommonCPP
|
|
||||||
PVDATA=${V4BASE}/pvDataCPP
|
|
||||||
NORMATIVETYPES=${V4BASE}/normativeTypesCPP
|
|
||||||
PVACCESS=${V4BASE}/pvAccessCPP
|
|
||||||
@@ -2,6 +2,8 @@ TOP=..
|
|||||||
|
|
||||||
include $(TOP)/configure/CONFIG
|
include $(TOP)/configure/CONFIG
|
||||||
|
|
||||||
|
CFG += CONFIG_PVACLIENT_VERSION
|
||||||
|
|
||||||
TARGETS = $(CONFIG_TARGETS)
|
TARGETS = $(CONFIG_TARGETS)
|
||||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||||
|
|
||||||
|
|||||||
+33
-19
@@ -1,30 +1,44 @@
|
|||||||
# easyPVACPP RELEASE - Location of external support modules
|
# RELEASE - Location of external support modules
|
||||||
#
|
#
|
||||||
# IF YOU CHANGE this file or any file it includes you must
|
# IF YOU CHANGE ANY PATHS in this file or make API changes to
|
||||||
# subsequently do a "gnumake rebuild" in the application's
|
# any modules it refers to, you should do a "make rebuild" in
|
||||||
# top level directory.
|
# this application's top level directory.
|
||||||
#
|
#
|
||||||
# The build process does not check dependencies against files
|
# The EPICS build process does not check dependencies against
|
||||||
# that are outside this application, thus you should also do a
|
# any files from outside the application, so it is safest to
|
||||||
# "gnumake rebuild" in the top level directory after EPICS_BASE
|
# rebuild it completely if any modules it depends on change.
|
||||||
# or any other external module pointed to below is rebuilt.
|
|
||||||
#
|
#
|
||||||
# Host- or target-specific settings can be given in files named
|
# Host- or target-specific settings can be given in files named
|
||||||
# RELEASE.$(EPICS_HOST_ARCH).Common
|
# RELEASE.$(EPICS_HOST_ARCH).Common
|
||||||
# RELEASE.Common.$(T_A)
|
# RELEASE.Common.$(T_A)
|
||||||
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
||||||
|
|
||||||
# EPICS V4 Developers: Do not edit the locations in this file!
|
|
||||||
#
|
#
|
||||||
# A RELEASE.local must exist that has the following definitions
|
# This file is parsed by both GNUmake and an EPICS Perl script,
|
||||||
# EPICS_BASE=/home/install/epics/base
|
# so it may ONLY contain definititions of paths to other support
|
||||||
# EPICS4_DIR=/home/epicsv4
|
# modules, variable definitions that are used in module paths,
|
||||||
# PVCOMMON=${EPICS4_DIR}/pvCommonCPP
|
# and include statements that pull in other RELEASE files.
|
||||||
# PVDATA=${EPICS4_DIR}/pvDataCPP
|
# Variables may be used before their values have been set.
|
||||||
# NORMATIVETYPES=${EPICSV4}/normativeTypesCPP
|
# Build variables that are NOT used in paths should be set in
|
||||||
# PVACCESS=${EPICS4_DIR}/pvAccessCPP
|
# the CONFIG_SITE file.
|
||||||
#Either create a RELEASE.local one level above the TOP for this module
|
|
||||||
#OR copy ExampleRELEASE.local to RELEASE.local and edit it.
|
|
||||||
|
|
||||||
|
# Variables and paths to dependent modules:
|
||||||
|
#MODULES = /path/to/modules
|
||||||
|
#MYMODULE = $(MODULES)/my-module
|
||||||
|
|
||||||
|
# If building the EPICS modules individually, set these:
|
||||||
|
#EPICS_PVACCESS = $(MODULES)/pvAccess
|
||||||
|
#EPICS_NORMATIVETYPES = $(MODULES)/normativeTypes
|
||||||
|
#EPICS_PVDATA = $(MODULES)/pvData
|
||||||
|
#EPICS_DATABASE = $(MODULES)/database
|
||||||
|
#EPICS_CA = $(MODULES)/ca
|
||||||
|
#EPICS_LIBCOM = $(MODULES)/libcom
|
||||||
|
#EPICS_BASE = $(MODULES)/core
|
||||||
|
|
||||||
|
# Set RULES here if you want to use build rules from elsewhere:
|
||||||
|
#RULES = $(MODULES)/build-rules
|
||||||
|
|
||||||
|
# These allow developers to override the RELEASE variable settings
|
||||||
|
# without having to modify the configure/RELEASE file itself.
|
||||||
-include $(TOP)/../RELEASE.local
|
-include $(TOP)/../RELEASE.local
|
||||||
|
-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
|
||||||
-include $(TOP)/configure/RELEASE.local
|
-include $(TOP)/configure/RELEASE.local
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
# pvaClientCPP Module
|
||||||
|
|
||||||
|
This document summarizes the changes to the module between releases.
|
||||||
|
|
||||||
|
## Release 4.8.1 (EPICS 7.0.10, Dec 2025)
|
||||||
|
|
||||||
|
* Fix error message generation code.
|
||||||
|
|
||||||
|
## Release 4.8.0 (EPICS 7.0.6 Jul 2021)
|
||||||
|
|
||||||
|
* PvaClientNTMultiData::getChannelChangeFlags is a new method. It fixes issue #66.
|
||||||
|
* Fix for issue #68. Both PvaClientArray and PvaClientField are not longer present. Neither was previously implemented.
|
||||||
|
* Several public methods are now protected. They were never meant to be called by clients.
|
||||||
|
* Issue #70 has been fixed.
|
||||||
|
* Changes was made to increase the performance of pvaMultiChannel.
|
||||||
|
* doxygen changes were made.
|
||||||
|
|
||||||
|
## Release 4.7.1 (EPICS 7.0.3.2 May 2020)
|
||||||
|
|
||||||
|
* support access to a union field that is a scalar or scalarArray
|
||||||
|
* fixed issues #62 and #63
|
||||||
|
|
||||||
|
## Release 4.7.0 (EPICS 7.0.3.1, Nov 2019)
|
||||||
|
|
||||||
|
* added JSON support for put and putGet
|
||||||
|
* Fix for
|
||||||
|
[GitHub issue #62](https://github.com/epics-base/pvaClientCPP/issues/62)
|
||||||
|
* Doxygen updates and read-the-docs integration.
|
||||||
|
|
||||||
|
|
||||||
|
## Release 4.6.0 (EPICS 7.0.3, Jul 2019)
|
||||||
|
|
||||||
|
* pvaClient now handles exceptions from the server properly (issue #54).
|
||||||
|
* MultiChannel classes now properly handle PV structures that don't have a top-level `value` field (issue #56), and are more tolerant of other missing fields (issue #57).
|
||||||
|
|
||||||
|
|
||||||
|
## Release 4.5.0 (EPICS 7.0.2.2, Apr 2019)
|
||||||
|
|
||||||
|
Changes have been made for getDouble, putDouble, getDoubleArray, putDoubleArray, getString, putString, getStringArray, and putStringArray.
|
||||||
|
|
||||||
|
1) Previously each only had support for a top level field named value.
|
||||||
|
Each now allows access to a single sub field that has the correct type.
|
||||||
|
Thus pvRequest must select a single field. For example
|
||||||
|
|
||||||
|
pva->channel("PVRdumbPowerSupply")->putDouble(1.0,"power.value" );
|
||||||
|
|
||||||
|
2) PvaChannel now has a method for each of the above.
|
||||||
|
For example instead of
|
||||||
|
|
||||||
|
PvaClientChannelPtr channel = pva->channel("PVRdouble");
|
||||||
|
PvaClientPutPtr clientPut = channel->put();
|
||||||
|
PvaClientPutDataPtr putData = clientPut->getData();
|
||||||
|
putData->putDouble(1.0); clientPut->put();
|
||||||
|
|
||||||
|
now it can be
|
||||||
|
|
||||||
|
pva->channel("PVRdouble")->putDouble(1.0 );
|
||||||
|
|
||||||
|
3) getDoubleArray and putDoubleArray work with any numeric scalar array
|
||||||
|
|
||||||
|
4) getStringArray and putStringArray work with any scalar array.
|
||||||
|
|
||||||
|
## Release 4.4 (EPICS 7.0.2, Dec 2018)
|
||||||
|
|
||||||
|
### API changes to PvaClientMonitor
|
||||||
|
|
||||||
|
The create method that had arguments for stateChangeRequester and monitorRequester no longer exists.
|
||||||
|
|
||||||
|
### API changes to PvaClientGet, ..., PvaClientMonitor
|
||||||
|
|
||||||
|
Previously the pvaClientGet, ..., pvaClientMonitor classes all implemented PvaClientChannelStateChangeRequester(). This method was never called and has been removed.
|
||||||
|
|
||||||
|
|
||||||
|
## Release 4.3 (EPICS 7.0.1, Dec 2017)
|
||||||
|
|
||||||
|
### Requires pvDataCPP-7.0 and pvAccessCPP-6.0 versions
|
||||||
|
|
||||||
|
This release will not work with older versions of these modules.
|
||||||
|
|
||||||
|
### Destroy methods removed
|
||||||
|
|
||||||
|
All the destroy() methods have been removed, implementation is RAII compliant.
|
||||||
|
|
||||||
|
### API changes to PvaClientMonitor
|
||||||
|
|
||||||
|
The second argument of method
|
||||||
|
|
||||||
|
static PvaClientMonitorPtr create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
epics::pvAccess::Channel::shared_pointer const & channel,
|
||||||
|
epics::pvData::PVStructurePtr const &pvRequest
|
||||||
|
);
|
||||||
|
|
||||||
|
is now changed to
|
||||||
|
|
||||||
|
static PvaClientMonitorPtr create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
|
epics::pvData::PVStructurePtr const &pvRequest
|
||||||
|
);
|
||||||
|
|
||||||
|
A new method is also implemented
|
||||||
|
|
||||||
|
static PvaClientMonitorPtr create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
std::string const & channelName,
|
||||||
|
std::string const & providerName,
|
||||||
|
std::string const & request,
|
||||||
|
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester,
|
||||||
|
PvaClientMonitorRequesterPtr const & monitorRequester
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
## Release 4.2 (EPICS V4.6, Aug 2016)
|
||||||
|
|
||||||
|
* The examples are moved to exampleCPP.
|
||||||
|
* Support for channelRPC is now available.
|
||||||
|
* In PvaClientMultiChannel checkConnected() now throws an exception if connect fails.
|
||||||
|
|
||||||
|
|
||||||
|
## Release 4.1 (EPICS V4.5, Oct 2015)
|
||||||
|
|
||||||
|
pvaClient is a synchronous API for pvAccess.
|
||||||
|
|
||||||
|
This is the first release of pvaClientCPP.
|
||||||
|
It provides an API that is similar to pvaClientJava.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.wy-side-nav-search {
|
||||||
|
background-color: #18334B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-side-nav-search input[type="text"] {
|
||||||
|
border-color: #18334b;
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# This file only contains a selection of the most common options. For a full
|
||||||
|
# list see the documentation:
|
||||||
|
# http://www.sphinx-doc.org/en/master/config
|
||||||
|
|
||||||
|
# -- Path setup --------------------------------------------------------------
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#
|
||||||
|
# import os
|
||||||
|
# import sys
|
||||||
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
project = 'normativeTypes (C++)'
|
||||||
|
copyright = '2019, EPICS Controls.'
|
||||||
|
author = 'EPICS'
|
||||||
|
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This pattern also affects html_static_path and html_extra_path.
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
# Intersphinx links to subprojects
|
||||||
|
intersphinx_mapping = {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
html_css_files = [
|
||||||
|
'css/custom.css',
|
||||||
|
]
|
||||||
|
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
html_theme_options = {
|
||||||
|
'logo_only': True,
|
||||||
|
}
|
||||||
|
html_logo = "images/EPICS_white_logo_v02.png"
|
||||||
|
|
||||||
|
html_extra_path = [
|
||||||
|
'../html',
|
||||||
|
'pvaClientCPP.html',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# -- Run Doxygen ------------------------------------------------------------
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,17 @@
|
|||||||
|
pvaClient (C++) Library
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
EPICS Website <https://epics-controls.org>
|
||||||
|
EPICS Documentation Home <https://docs.epics-controls.org>
|
||||||
|
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:caption: pvaClientCPP
|
||||||
|
|
||||||
|
Reference Manual <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/pvaClientCPP.html>
|
||||||
|
API Documentation <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/doxygen>
|
||||||
|
Source Code Repository on GitHub <https://github.com/epics-base/pvaClientCPP>
|
||||||
+49
-117
@@ -4,11 +4,11 @@
|
|||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||||
<title>EPICS pva</title>
|
<title>EPICS pvaClientCPP</title>
|
||||||
<link rel="stylesheet" type="text/css"
|
<link rel="stylesheet" type="text/css"
|
||||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
href="https://mrkraimer.github.io/website/css/base.css" />
|
||||||
<link rel="stylesheet" type="text/css"
|
<link rel="stylesheet" type="text/css"
|
||||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
href="https://mrkraimer.github.io/website/css/epicsv4.css" />
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
/*<![CDATA[*/
|
/*<![CDATA[*/
|
||||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
/*]]>*/</style>
|
/*]]>*/</style>
|
||||||
|
|
||||||
<!-- Script that generates the Table of Contents -->
|
<!-- Script that generates the Table of Contents -->
|
||||||
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
|
<script type="text/javascript" src="https://mrkraimer.github.io/website/css/tocgen.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -26,31 +26,13 @@
|
|||||||
|
|
||||||
<div class="head">
|
<div class="head">
|
||||||
<h1>EPICS pvaClientCPP</h1>
|
<h1>EPICS pvaClientCPP</h1>
|
||||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
<h2 class="nocount">Release 4.8 - March 2021</h2>
|
||||||
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
|
|
||||||
02-October-2015</h2>
|
|
||||||
<dl>
|
|
||||||
<dt>This version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP.html">pvaClientCPP.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Latest version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP_20151002.html">pvaClientCPP_20151002.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Previous version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP_20150803.html">pvaClientCPP_20150803.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Editors:</dt>
|
|
||||||
<dd>Marty Kraimer, BNL</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2 class="nocount">Abstract</h2>
|
<h2 class="nocount">Abstract</h2>
|
||||||
|
|
||||||
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly
|
<p>pvaClient is a software library that provides, to an EPICS client programmer, a friendly
|
||||||
client side programming interface to the data of an EPICS based control system. It is intended
|
client side programming interface to the data of an EPICS based control system. It is intended
|
||||||
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
|
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
|
||||||
scientists a way to directly develop analytical applications.</p>
|
scientists a way to directly develop analytical applications.</p>
|
||||||
|
|
||||||
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
|
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
|
||||||
@@ -59,7 +41,7 @@ pvAccess provides a callback based interface, which can be hard to use.
|
|||||||
pvaClient provides an interface that does not require callbacks even for monitors.
|
pvaClient provides an interface that does not require callbacks even for monitors.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
pvaClientChannel provides many "convenience" methods to directly get and put
|
pvaClientChannel provides many "convenience" methods to directly get and put
|
||||||
scalar and scalarArray data types.
|
scalar and scalarArray data types.
|
||||||
Additional methods provide access to the full features of pvAccess.
|
Additional methods provide access to the full features of pvAccess.
|
||||||
</p>
|
</p>
|
||||||
@@ -78,109 +60,59 @@ The data for the channels is presented via normative type NTMultiChannel.
|
|||||||
Control System</a>.</p>
|
Control System</a>.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
|
|
||||||
|
|
||||||
<p>pvaClientCPP is ready for use.</p>
|
|
||||||
|
|
||||||
</div> <!-- head -->
|
</div> <!-- head -->
|
||||||
|
|
||||||
<div id="toc">
|
<div id="contents" class="contents">
|
||||||
<h2 class="nocount">Table of Contents</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Place what you would like in the Table of Contents, inside the contents div -->
|
|
||||||
<div id="contents" class="contents">
|
|
||||||
<hr />
|
<hr />
|
||||||
|
<h2>Overview</h2>
|
||||||
<h2>Introduction</h2>
|
|
||||||
|
|
||||||
<p>pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
|
|
||||||
an interface to many of the features provided by pvData and pvAccess.</p>
|
|
||||||
|
|
||||||
<p>This document describes the layout of the source files in this project.</p>
|
|
||||||
<p>
|
<p>
|
||||||
A user overview is available via
|
Documentation for pvaClientCPP is available at:
|
||||||
<a
|
<a
|
||||||
href="./pvaClientOverview.html">pvaClientOverview.html
|
href="https://mrkraimer.github.io/website/developerGuide/pvaClient/pvaClientCPP.html">
|
||||||
|
pvaClient
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Doxygen documentation is available at
|
pvaClientCPP is one of the components of
|
||||||
<a
|
<a href="https://epics-controls.org/resources-and-support/base/epics-7/">
|
||||||
href="./html/index.html">doxygenDoc
|
EPICS-7
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<h2>Example Database</h2>
|
<p>This document is only a guide to help locate code and documentation related to pvaClientCPP
|
||||||
<p>The examples require that the database provided by project pvaClientTestCPP
|
|
||||||
is running.
|
|
||||||
For example:</p>
|
|
||||||
<pre>
|
|
||||||
mrk> pwd
|
|
||||||
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
|
|
||||||
mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
|
|
||||||
</pre>
|
|
||||||
<h2>Examples</h2>
|
|
||||||
<p>Examples are in directory <b>example/src</b>.
|
|
||||||
An example of how to run them is:</p>
|
|
||||||
<pre>
|
|
||||||
mrk> pwd
|
|
||||||
/home/epicsv4/pvaClientCPP/example
|
|
||||||
mrk> bin/linux-x86_64/examplePvaClientGet
|
|
||||||
</pre>
|
|
||||||
<p>The following is a brief description of each example.
|
|
||||||
In order to understand each example it
|
|
||||||
helps to also look at the source for the example.</p>
|
|
||||||
<h2>examplePvaClientGet</h2>
|
|
||||||
<p>This has a number of examples:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>exampleDouble</dt>
|
|
||||||
<dd>
|
|
||||||
This shows two methods for getting data from a channel that has a numeric
|
|
||||||
scalar value field.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleDoubleArray</dt>
|
|
||||||
<dd>
|
|
||||||
This shows two methods for getting data from a channel that has a
|
|
||||||
double array value field.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleCADouble</dt>
|
|
||||||
<dd>
|
|
||||||
This is like exampleDouble except it uses provider <b>ca</b>.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleCADoubleArray</dt>
|
|
||||||
<dd>
|
|
||||||
This is like exampleDoubleArray except it uses provider <b>ca</b>.
|
|
||||||
</dd>
|
|
||||||
<dt>examplePowerSupply</dt>
|
|
||||||
<dd>
|
|
||||||
This is an example of getting data from a channel that does not
|
|
||||||
have a value field.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h2>examplePvaClientMonitor</h2>
|
|
||||||
<p>This is an example of creating a monitor on a channel.
|
|
||||||
It monitors a scalar double field.
|
|
||||||
It also issues puts to the same channel so that it can make the monitors occur.
|
|
||||||
</p>
|
</p>
|
||||||
<h2>examplePvaClientPut</h2>
|
<p>
|
||||||
<p>This example gets and puts to channels exampleDouble
|
It is intended for developers that want to use pvaClientCPP.
|
||||||
and exampleDoubleArray.</p>
|
|
||||||
<h2>examplePvaClientProcess</h2>
|
|
||||||
<p>This example makes a process request to channel exampleDouble.</p>
|
|
||||||
<h2>helloWorldPutGet</h2>
|
|
||||||
<p>This is an example of issuing a channelPutGet.</p>
|
|
||||||
<h2>examplePvaClientMultiDouble</h2>
|
|
||||||
<p>This is an example of using pvaClientMultiChannel,
|
|
||||||
pvaClientMultiGetDouble, pvaClientMultiPutDouble, and pvaClientMultiMonitorDouble.
|
|
||||||
</p>
|
</p>
|
||||||
<h2>examplePvaClientNTMulti</h2>
|
<h2>Developer Guide</h2>
|
||||||
<p>This is an example of using pvaClientMultiChannel,
|
<p>A guide for developers is available at
|
||||||
pvaClientNTMultiGet, pvaClientNTMultiPut, pvaClientNTMultiMonitor, and pvaClientNTMultiData.
|
<a
|
||||||
|
href="https://mrkraimer.github.io/website/developerGuide/developerGuide.html">
|
||||||
|
developerGuide
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<h2>helloWorldRPC</h2>
|
<p>This guide provides an overview of the components that are part of an <b>EPICS V4</b> release.
|
||||||
<p>This is an example of issuing a channelRPC request.
|
Some understanding of the components and how they are related is necessary in order to
|
||||||
It does <b>not</b> use pva.</p>
|
develop code that uses pvaClientCPP.
|
||||||
|
In particular read everything related to pvaClient.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>doxygen</h2>
|
||||||
|
<p>doxygen documentation is available at
|
||||||
|
<a
|
||||||
|
href="./html/index.html">doxygen</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>exampleCPP</h2>
|
||||||
|
<p>Example code is available at
|
||||||
|
<a
|
||||||
|
href="https://github.com/epics-base/exampleCPP">
|
||||||
|
exampleCPP
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>In particular look at exampleClient.
|
||||||
|
It has many examples of using pvaClientCPP.
|
||||||
|
</p>
|
||||||
|
|
||||||
</div> <!-- class="contents" -->
|
</div> <!-- class="contents" -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,199 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
|
||||||
<title>EPICS pva</title>
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
|
||||||
<style type="text/css">
|
|
||||||
/*<![CDATA[*/
|
|
||||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
|
||||||
table { margin-left: auto; margin-right: auto }
|
|
||||||
.diagram { text-align: center; margin: 2.5em 0 }
|
|
||||||
body { margin-right: 10% }
|
|
||||||
/*]]>*/</style>
|
|
||||||
|
|
||||||
<!-- Script that generates the Table of Contents -->
|
|
||||||
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="head">
|
|
||||||
<h1>EPICS pvaClientCPP</h1>
|
|
||||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
|
||||||
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
|
|
||||||
26-June-2015</h2>
|
|
||||||
<dl>
|
|
||||||
<dt>This version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP.html">pvaClientCPP.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Latest version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP_20150626.html">pvaClientCPP_20150626.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Previous version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="easyPVA_20150609.html">easyPVA_20150609.html</a>
|
|
||||||
</dd>
|
|
||||||
<dt>Editors:</dt>
|
|
||||||
<dd>Marty Kraimer, BNL</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2 class="nocount">Abstract</h2>
|
|
||||||
|
|
||||||
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly
|
|
||||||
client side programming interface to the data of an EPICS based control system. It is intended
|
|
||||||
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
|
|
||||||
scientists a way to directly develop analytical applications.</p>
|
|
||||||
|
|
||||||
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
|
|
||||||
software support for high speed controls network communications used in EPICS version 4.
|
|
||||||
pvAccess provides a callback based interface, which can be hard to use.
|
|
||||||
pvaClient provides an interface that does not require callbacks even for monitors.
|
|
||||||
</p>
|
|
||||||
pvaClientChannel provides many "convenience" methods to directly get and put
|
|
||||||
scalar and scalarArray data types.
|
|
||||||
Additional methods provide access to the full features of pvAccess.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
pvaClientMultiChannel provides access to data from multiple channels.
|
|
||||||
It can be used directly by a client or via pvaClientMultiDouble or pvaClientNTMultiChannel.
|
|
||||||
pvaClientMultiDouble allows the client to get and put data to multiple channels.
|
|
||||||
But each channel must have a value field that is a numeric scalar.
|
|
||||||
pvaClientNTMultiChannel allows the client to get and put data to multiple channels.
|
|
||||||
Each channel must have a value field.
|
|
||||||
The data for the channels is presented via normative type NTMultiChannel.
|
|
||||||
</p>
|
|
||||||
<!-- last para of Abstract is boilerplate reference to EPICS -->
|
|
||||||
<p>For more information about EPICS generally, please refer to the home page of the <a
|
|
||||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
|
||||||
Control System</a>.</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
|
|
||||||
|
|
||||||
<p>pvaClientCPP is ready for use.</p>
|
|
||||||
|
|
||||||
</div> <!-- head -->
|
|
||||||
|
|
||||||
<div id="toc">
|
|
||||||
<h2 class="nocount">Table of Contents</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Place what you would like in the Table of Contents, inside the contents div -->
|
|
||||||
<div id="contents" class="contents">
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
|
||||||
|
|
||||||
<p>pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
|
|
||||||
an interface to many of the features provided by pvData and pvAccess.</p>
|
|
||||||
|
|
||||||
<p>This document describes the layout of the source files in this project.</p>
|
|
||||||
<p>
|
|
||||||
A user overview is available via
|
|
||||||
<a
|
|
||||||
href="./pvaClientOverview.html">pvaClientOverview.html
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Doxygen documentation is available at
|
|
||||||
<a
|
|
||||||
href="./html/index.html">doxygenDoc
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<h2>Example Database</h2>
|
|
||||||
<p>The examples require that an example pvAccess server is runnimg.
|
|
||||||
To get the test database go to:</p>
|
|
||||||
<a
|
|
||||||
href="https://github.com/epics_base/pvaClientTestCPP/blob/master/database.zip">pvaClientTestCPP/database.zip
|
|
||||||
</a>
|
|
||||||
Then select "raw file" and You will be able to download the zip file.
|
|
||||||
<p>
|
|
||||||
When unzipped this is used to create an example IOC database.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
After unzipping the file:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
cd database/configure
|
|
||||||
cp ExampleRELEASE.local RELEASE.local
|
|
||||||
edit RELEASE.local
|
|
||||||
cd ..
|
|
||||||
make
|
|
||||||
cd iocBoot/exampleDatabase
|
|
||||||
../../bin/<arch:>/exampleDatabase st.cmd
|
|
||||||
</pre>
|
|
||||||
<h2>Examples</h2>
|
|
||||||
<p>Examples are in directory <b>example/src</b>.
|
|
||||||
An example of how to run them is:</p>
|
|
||||||
<pre>
|
|
||||||
mrk> pwd
|
|
||||||
/home/epicsv4/pvaClientCPP/example
|
|
||||||
mrk> bin/linux-x86_64/examplePvaClientGet
|
|
||||||
</pre>
|
|
||||||
<p>The following is a brief description of each example.
|
|
||||||
In order to understand each example it
|
|
||||||
helps to also look at the source for the example.</p>
|
|
||||||
<h2>examplePvaClientGet</h2>
|
|
||||||
<p>This has a number of examples:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>exampleDouble</dt>
|
|
||||||
<dd>
|
|
||||||
This shows two methods for getting data from a channel that has a numeric
|
|
||||||
scalar value field.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleDoubleArray</dt>
|
|
||||||
<dd>
|
|
||||||
This shows two methods for getting data from a channel that has a
|
|
||||||
double array value field.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleCADouble</dt>
|
|
||||||
<dd>
|
|
||||||
This is like exampleDouble except it uses provider <b>ca</b>.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleCADoubleArray</dt>
|
|
||||||
<dd>
|
|
||||||
This is like exampleDoubleArray except it uses provider <b>ca</b>.
|
|
||||||
</dd>
|
|
||||||
<dt>examplePowerSupply</dt>
|
|
||||||
<dd>
|
|
||||||
This is an example of getting data from a channel that does not
|
|
||||||
have a value field.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h2>examplePvaClientMonitor</h2>
|
|
||||||
<p>This is an example of creating a monitor on a channel.
|
|
||||||
It monitors a channel that models a powerSupply, i. e. it is not a "standard" record.
|
|
||||||
It does not have a value field.
|
|
||||||
</p>
|
|
||||||
<p>After starting the example a change can be made to the powerSupply by issuing:</p>
|
|
||||||
<pre>
|
|
||||||
pvput -r "power.value,voltage.value" examplePowerSupply 6 6
|
|
||||||
</pre>
|
|
||||||
<h2>examplePvaClientPut</h2>
|
|
||||||
<p>This example gets and puts to channel exampleDouble.</p>
|
|
||||||
<h2>examplePvaClientProcess</h2>
|
|
||||||
<p>This example makes a process request to channel exampleDouble.</p>
|
|
||||||
<h2>helloWorldPutGet</h2>
|
|
||||||
<p>This is an example of issuing a channelPutGet.</p>
|
|
||||||
<h2>examplePvaClientMultiDouble</h2>
|
|
||||||
<p>This is an example of issuing gets and puts to multiple channels where each
|
|
||||||
channel has a numeric scalar value field.</p>
|
|
||||||
<h2>examplePvaClientNTMultiChannel</h2>
|
|
||||||
<p>This is an example of using NDMultiChannel to obtain data from multiple channels.
|
|
||||||
</p>
|
|
||||||
<h2>helloWorldRPC</h2>
|
|
||||||
<p>This is an example of issuing a channelRPC request.
|
|
||||||
It does <b>not</b> use pva.</p>
|
|
||||||
</div> <!-- class="contents" -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
|
||||||
<title>EPICS pva</title>
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
|
||||||
<style type="text/css">
|
|
||||||
/*<![CDATA[*/
|
|
||||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
|
||||||
table { margin-left: auto; margin-right: auto }
|
|
||||||
.diagram { text-align: center; margin: 2.5em 0 }
|
|
||||||
body { margin-right: 10% }
|
|
||||||
/*]]>*/</style>
|
|
||||||
|
|
||||||
<!-- Script that generates the Table of Contents -->
|
|
||||||
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="head">
|
|
||||||
<h1>EPICS pvaClientCPP</h1>
|
|
||||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
|
||||||
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
|
|
||||||
03-August-2015</h2>
|
|
||||||
<dl>
|
|
||||||
<dt>This version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP.html">pvaClientCPP.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Latest version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP_20150803.html">pvaClientCPP_20150803.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Previous version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP_20150626.html">pvaClientCPP_20150626.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Editors:</dt>
|
|
||||||
<dd>Marty Kraimer, BNL</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2 class="nocount">Abstract</h2>
|
|
||||||
|
|
||||||
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly
|
|
||||||
client side programming interface to the data of an EPICS based control system. It is intended
|
|
||||||
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
|
|
||||||
scientists a way to directly develop analytical applications.</p>
|
|
||||||
|
|
||||||
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
|
|
||||||
software support for high speed controls network communications used in EPICS version 4.
|
|
||||||
pvAccess provides a callback based interface, which can be hard to use.
|
|
||||||
pvaClient provides an interface that does not require callbacks even for monitors.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
pvaClientChannel provides many "convenience" methods to directly get and put
|
|
||||||
scalar and scalarArray data types.
|
|
||||||
Additional methods provide access to the full features of pvAccess.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
pvaClientMultiChannel provides access to data from multiple channels.
|
|
||||||
It can be used directly by a client or via pvaClientMultiDouble or pvaClientNTMultiChannel.
|
|
||||||
pvaClientMultiDouble allows the client to get and put data to multiple channels.
|
|
||||||
But each channel must have a value field that is a numeric scalar.
|
|
||||||
pvaClientNTMultiChannel allows the client to get and put data to multiple channels.
|
|
||||||
Each channel must have a value field.
|
|
||||||
The data for the channels is presented via normative type NTMultiChannel.
|
|
||||||
</p>
|
|
||||||
<!-- last para of Abstract is boilerplate reference to EPICS -->
|
|
||||||
<p>For more information about EPICS generally, please refer to the home page of the <a
|
|
||||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
|
||||||
Control System</a>.</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
|
|
||||||
|
|
||||||
<p>pvaClientCPP is ready for use.</p>
|
|
||||||
|
|
||||||
</div> <!-- head -->
|
|
||||||
|
|
||||||
<div id="toc">
|
|
||||||
<h2 class="nocount">Table of Contents</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Place what you would like in the Table of Contents, inside the contents div -->
|
|
||||||
<div id="contents" class="contents">
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
|
||||||
|
|
||||||
<p>pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
|
|
||||||
an interface to many of the features provided by pvData and pvAccess.</p>
|
|
||||||
|
|
||||||
<p>This document describes the layout of the source files in this project.</p>
|
|
||||||
<p>
|
|
||||||
A user overview is available via
|
|
||||||
<a
|
|
||||||
href="./pvaClientOverview.html">pvaClientOverview.html
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Doxygen documentation is available at
|
|
||||||
<a
|
|
||||||
href="./html/index.html">doxygenDoc
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<h2>Example Database</h2>
|
|
||||||
<p>The examples require that the database provided by project pvaClientTestCPP
|
|
||||||
is running.
|
|
||||||
For example:</p>
|
|
||||||
<pre>
|
|
||||||
mrk> pwd
|
|
||||||
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
|
|
||||||
mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
|
|
||||||
</pre>
|
|
||||||
<h2>Examples</h2>
|
|
||||||
<p>Examples are in directory <b>example/src</b>.
|
|
||||||
An example of how to run them is:</p>
|
|
||||||
<pre>
|
|
||||||
mrk> pwd
|
|
||||||
/home/epicsv4/pvaClientCPP/example
|
|
||||||
mrk> bin/linux-x86_64/examplePvaClientGet
|
|
||||||
</pre>
|
|
||||||
<p>The following is a brief description of each example.
|
|
||||||
In order to understand each example it
|
|
||||||
helps to also look at the source for the example.</p>
|
|
||||||
<h2>examplePvaClientGet</h2>
|
|
||||||
<p>This has a number of examples:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>exampleDouble</dt>
|
|
||||||
<dd>
|
|
||||||
This shows two methods for getting data from a channel that has a numeric
|
|
||||||
scalar value field.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleDoubleArray</dt>
|
|
||||||
<dd>
|
|
||||||
This shows two methods for getting data from a channel that has a
|
|
||||||
double array value field.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleCADouble</dt>
|
|
||||||
<dd>
|
|
||||||
This is like exampleDouble except it uses provider <b>ca</b>.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleCADoubleArray</dt>
|
|
||||||
<dd>
|
|
||||||
This is like exampleDoubleArray except it uses provider <b>ca</b>.
|
|
||||||
</dd>
|
|
||||||
<dt>examplePowerSupply</dt>
|
|
||||||
<dd>
|
|
||||||
This is an example of getting data from a channel that does not
|
|
||||||
have a value field.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h2>examplePvaClientMonitor</h2>
|
|
||||||
<p>This is an example of creating a monitor on a channel.
|
|
||||||
It monitors a scalar double field.
|
|
||||||
It also issues puts to the same channel so that it can make the monitors occur.
|
|
||||||
</p>
|
|
||||||
<h2>examplePvaClientPut</h2>
|
|
||||||
<p>This example gets and puts to channels exampleDouble
|
|
||||||
and exampleDoubleArray.</p>
|
|
||||||
<h2>examplePvaClientProcess</h2>
|
|
||||||
<p>This example makes a process request to channel exampleDouble.</p>
|
|
||||||
<h2>helloWorldPutGet</h2>
|
|
||||||
<p>This is an example of issuing a channelPutGet.</p>
|
|
||||||
<h2>examplePvaClientMultiDouble</h2>
|
|
||||||
<p>This is an example of using pvaClientMultiChannel,
|
|
||||||
pvaClientMultiGetDouble, pvaClientMultiPutDouble, and pvaClientMultiMonitorDouble.
|
|
||||||
</p>
|
|
||||||
<h2>helloWorldRPC</h2>
|
|
||||||
<p>This is an example of issuing a channelRPC request.
|
|
||||||
It does <b>not</b> use pva.</p>
|
|
||||||
</div> <!-- class="contents" -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
|
||||||
<title>EPICS pva</title>
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
|
||||||
<style type="text/css">
|
|
||||||
/*<![CDATA[*/
|
|
||||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
|
||||||
table { margin-left: auto; margin-right: auto }
|
|
||||||
.diagram { text-align: center; margin: 2.5em 0 }
|
|
||||||
body { margin-right: 10% }
|
|
||||||
/*]]>*/</style>
|
|
||||||
|
|
||||||
<!-- Script that generates the Table of Contents -->
|
|
||||||
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="head">
|
|
||||||
<h1>EPICS pvaClientCPP</h1>
|
|
||||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
|
||||||
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
|
|
||||||
02-October-2015</h2>
|
|
||||||
<dl>
|
|
||||||
<dt>This version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP.html">pvaClientCPP.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Latest version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP_20151002.html">pvaClientCPP_20151002.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Previous version:</dt>
|
|
||||||
<dd><a
|
|
||||||
href="pvaClientCPP_20150803.html">pvaClientCPP_20150803.html
|
|
||||||
</a> </dd>
|
|
||||||
<dt>Editors:</dt>
|
|
||||||
<dd>Marty Kraimer, BNL</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2 class="nocount">Abstract</h2>
|
|
||||||
|
|
||||||
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly
|
|
||||||
client side programming interface to the data of an EPICS based control system. It is intended
|
|
||||||
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
|
|
||||||
scientists a way to directly develop analytical applications.</p>
|
|
||||||
|
|
||||||
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
|
|
||||||
software support for high speed controls network communications used in EPICS version 4.
|
|
||||||
pvAccess provides a callback based interface, which can be hard to use.
|
|
||||||
pvaClient provides an interface that does not require callbacks even for monitors.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
pvaClientChannel provides many "convenience" methods to directly get and put
|
|
||||||
scalar and scalarArray data types.
|
|
||||||
Additional methods provide access to the full features of pvAccess.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
pvaClientMultiChannel provides access to data from multiple channels.
|
|
||||||
It can be used directly by a client or via pvaClientMultiDouble or pvaClientNTMultiChannel.
|
|
||||||
pvaClientMultiDouble allows the client to get and put data to multiple channels.
|
|
||||||
But each channel must have a value field that is a numeric scalar.
|
|
||||||
pvaClientNTMultiChannel allows the client to get and put data to multiple channels.
|
|
||||||
Each channel must have a value field.
|
|
||||||
The data for the channels is presented via normative type NTMultiChannel.
|
|
||||||
</p>
|
|
||||||
<!-- last para of Abstract is boilerplate reference to EPICS -->
|
|
||||||
<p>For more information about EPICS generally, please refer to the home page of the <a
|
|
||||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
|
||||||
Control System</a>.</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
|
|
||||||
|
|
||||||
<p>pvaClientCPP is ready for use.</p>
|
|
||||||
|
|
||||||
</div> <!-- head -->
|
|
||||||
|
|
||||||
<div id="toc">
|
|
||||||
<h2 class="nocount">Table of Contents</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Place what you would like in the Table of Contents, inside the contents div -->
|
|
||||||
<div id="contents" class="contents">
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
|
||||||
|
|
||||||
<p>pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
|
|
||||||
an interface to many of the features provided by pvData and pvAccess.</p>
|
|
||||||
|
|
||||||
<p>This document describes the layout of the source files in this project.</p>
|
|
||||||
<p>
|
|
||||||
A user overview is available via
|
|
||||||
<a
|
|
||||||
href="./pvaClientOverview.html">pvaClientOverview.html
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Doxygen documentation is available at
|
|
||||||
<a
|
|
||||||
href="./html/index.html">doxygenDoc
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<h2>Example Database</h2>
|
|
||||||
<p>The examples require that the database provided by project pvaClientTestCPP
|
|
||||||
is running.
|
|
||||||
For example:</p>
|
|
||||||
<pre>
|
|
||||||
mrk> pwd
|
|
||||||
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
|
|
||||||
mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
|
|
||||||
</pre>
|
|
||||||
<h2>Examples</h2>
|
|
||||||
<p>Examples are in directory <b>example/src</b>.
|
|
||||||
An example of how to run them is:</p>
|
|
||||||
<pre>
|
|
||||||
mrk> pwd
|
|
||||||
/home/epicsv4/pvaClientCPP/example
|
|
||||||
mrk> bin/linux-x86_64/examplePvaClientGet
|
|
||||||
</pre>
|
|
||||||
<p>The following is a brief description of each example.
|
|
||||||
In order to understand each example it
|
|
||||||
helps to also look at the source for the example.</p>
|
|
||||||
<h2>examplePvaClientGet</h2>
|
|
||||||
<p>This has a number of examples:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>exampleDouble</dt>
|
|
||||||
<dd>
|
|
||||||
This shows two methods for getting data from a channel that has a numeric
|
|
||||||
scalar value field.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleDoubleArray</dt>
|
|
||||||
<dd>
|
|
||||||
This shows two methods for getting data from a channel that has a
|
|
||||||
double array value field.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleCADouble</dt>
|
|
||||||
<dd>
|
|
||||||
This is like exampleDouble except it uses provider <b>ca</b>.
|
|
||||||
</dd>
|
|
||||||
<dt>exampleCADoubleArray</dt>
|
|
||||||
<dd>
|
|
||||||
This is like exampleDoubleArray except it uses provider <b>ca</b>.
|
|
||||||
</dd>
|
|
||||||
<dt>examplePowerSupply</dt>
|
|
||||||
<dd>
|
|
||||||
This is an example of getting data from a channel that does not
|
|
||||||
have a value field.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h2>examplePvaClientMonitor</h2>
|
|
||||||
<p>This is an example of creating a monitor on a channel.
|
|
||||||
It monitors a scalar double field.
|
|
||||||
It also issues puts to the same channel so that it can make the monitors occur.
|
|
||||||
</p>
|
|
||||||
<h2>examplePvaClientPut</h2>
|
|
||||||
<p>This example gets and puts to channels exampleDouble
|
|
||||||
and exampleDoubleArray.</p>
|
|
||||||
<h2>examplePvaClientProcess</h2>
|
|
||||||
<p>This example makes a process request to channel exampleDouble.</p>
|
|
||||||
<h2>helloWorldPutGet</h2>
|
|
||||||
<p>This is an example of issuing a channelPutGet.</p>
|
|
||||||
<h2>examplePvaClientMultiDouble</h2>
|
|
||||||
<p>This is an example of using pvaClientMultiChannel,
|
|
||||||
pvaClientMultiGetDouble, pvaClientMultiPutDouble, and pvaClientMultiMonitorDouble.
|
|
||||||
</p>
|
|
||||||
<h2>examplePvaClientNTMulti</h2>
|
|
||||||
<p>This is an example of using pvaClientMultiChannel,
|
|
||||||
pvaClientNTMultiGet, pvaClientNTMultiPut, pvaClientNTMultiMonitor, and pvaClientNTMultiData.
|
|
||||||
</p>
|
|
||||||
<h2>helloWorldRPC</h2>
|
|
||||||
<p>This is an example of issuing a channelRPC request.
|
|
||||||
It does <b>not</b> use pva.</p>
|
|
||||||
</div> <!-- class="contents" -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,328 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
|
||||||
<title>pva C++ Overview</title>
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
|
||||||
<style type="text/css">
|
|
||||||
/*<![CDATA[*/
|
|
||||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
|
||||||
table { margin-left: auto; margin-right: auto }
|
|
||||||
.diagram { text-align: center; margin: 2.5em 0 }
|
|
||||||
body { margin-right: 10% }
|
|
||||||
/*]]>*/</style>
|
|
||||||
|
|
||||||
<!-- Script that generates the Table of Contents -->
|
|
||||||
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="head">
|
|
||||||
<h1>PvaClient C++ Overview</h1>
|
|
||||||
|
|
||||||
</div> <!-- head -->
|
|
||||||
|
|
||||||
<div id="toc">
|
|
||||||
<h2 class="nocount">Table of Contents</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Place what you would like in the Table of Contents, inside the contents div -->
|
|
||||||
<div id="contents" class="contents">
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
|
||||||
|
|
||||||
<p>PvaClient is a synchronous API for accessing PVData via PVAccess.
|
|
||||||
It also provides a number of convenience methods.
|
|
||||||
It allows the client to request access without checking for failure,
|
|
||||||
but throws an exception if a request fails.
|
|
||||||
A client can also check for failues and thus prevent exceptions.</p>
|
|
||||||
|
|
||||||
<p>The PvaClient API has the following features:</p>
|
|
||||||
<ol>
|
|
||||||
<li>Provides a synchronous API rather than the callback API provided by pvAccess.</li>
|
|
||||||
<li>Makes common requests pva.</li>
|
|
||||||
<li>Provides full access to the pvAccess API for more demanding
|
|
||||||
applications</li>
|
|
||||||
<li>Allows efficient client side programs.</li>
|
|
||||||
<li>Takes care of most object resource management problems.</li>
|
|
||||||
</ol>
|
|
||||||
<p>Simple examples of using pva:</p>
|
|
||||||
<pre>
|
|
||||||
// pvaGet
|
|
||||||
PvaClientPtr pva = PvaClient::create();
|
|
||||||
double value = pva->channel("exampleDouble")->get()->getData()->getDouble();
|
|
||||||
|
|
||||||
// pvaPut
|
|
||||||
PvaClientChannelPtr channel = pva->channel("exampleDouble");
|
|
||||||
PvaClientPutPtr put = channel->put();
|
|
||||||
PvaClientPutDataPtr putData = put->getData();
|
|
||||||
putData->putDouble(3.0); put->put();
|
|
||||||
|
|
||||||
// pvaMonitor
|
|
||||||
PvaClientMonitorPtr monitor = pva->channel("examplePowerSupply")->monitor("");
|
|
||||||
PvaClientMonitorDataPtr pvaData = monitor->getData();
|
|
||||||
while(true) {
|
|
||||||
monitor->waitEvent();
|
|
||||||
cout << "changed\n";
|
|
||||||
pvaData->showChanged(cout);
|
|
||||||
cout << "overrun\n";
|
|
||||||
pvaData->showOverrun(cout);
|
|
||||||
monitor->releaseEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// pvaProcess
|
|
||||||
PvaClientChannelPtr channel = pva->channel("exampleDouble");
|
|
||||||
PvaClientProcessPtr process = channel->createProcess();
|
|
||||||
process->process();
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
<p><b>pvClientCPP/example</b> includes a number of examples.</p>
|
|
||||||
<p>pvaClient does <b>not</b> provide support for:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>ChannelArray</dt>
|
|
||||||
<dd>TBD</dd>
|
|
||||||
<dt>ChannelRPC</dt>
|
|
||||||
<dd>pvAccess itself already provides a synchronous interface.
|
|
||||||
The examples include helloWorldRPC, which is an example of using channelRP.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h2>PvaClient</h2>
|
|
||||||
<p>An instance of PvaClient is obtained via the call:</p>
|
|
||||||
<pre>
|
|
||||||
PvaClientPtr pva = PvaClient::create();
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>PvaClient has methods to create instances of <b>PvaClientChannel</b>.
|
|
||||||
The client can specify the provider name or use the default provider.
|
|
||||||
The client can manage it's own channels or can let pvaClient cache channels.
|
|
||||||
An example of using the cached method is:</p>
|
|
||||||
<pre>
|
|
||||||
PvaClientChannelPtr pvaChannel = pva->channel("exampleDouble");
|
|
||||||
</pre>
|
|
||||||
<p>This will attempt to connect to channel exampleDouble.
|
|
||||||
Since the client did not specify a timeout an exception wll be thrown if
|
|
||||||
the connection request fails.
|
|
||||||
The client will block until the connection is made or an exception is thrown.
|
|
||||||
If the request succeeds, pva caches the pvaChannel so that if the
|
|
||||||
client makes another request for the same channel the cached object is
|
|
||||||
returned to the client.
|
|
||||||
</p>
|
|
||||||
<p>An example of using a non cached method is:</p>
|
|
||||||
<pre>
|
|
||||||
PvaClientChannelPtr pvaChannel = pva->createChannel("exampleDouble");
|
|
||||||
</pre>
|
|
||||||
<p>This will create an PvaClientChannel and return it to the client.
|
|
||||||
The client must itself connect.
|
|
||||||
This is useful if the client wants to connect to multiple channels in parallel.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2>PvaClientChannel - Wrapper For Single Channel</h2>
|
|
||||||
<h3>PvaClientChannel</h3>
|
|
||||||
<p>This provides methods for connecting to a channel and for creating instances of
|
|
||||||
PvaClientField, PvaClientProcess, ..., PvaClientPutGet.</p>
|
|
||||||
<p>Connection must be made before any create method is called or
|
|
||||||
an exception is raised.
|
|
||||||
The following is a synchronous connection request:</p>
|
|
||||||
<pre>
|
|
||||||
pvaChannel->connect(5.0); // BLOCKS AND THROWS IF NO CONNECT
|
|
||||||
</pre>
|
|
||||||
<p>This blocks until then connection is made or until timout occurs.
|
|
||||||
An exception is raised if the connection request fails.
|
|
||||||
</p>
|
|
||||||
<p>The same request can be made without blocking and without exceptions.</p>
|
|
||||||
<pre>
|
|
||||||
pvaChannel->issueConnect(); // DOES NOT BLOCK
|
|
||||||
.....
|
|
||||||
Status status =pvaChannel->waitConnect(5.0); // BLOCKS DOES NOT THROW
|
|
||||||
if(!status.isOK()) {
|
|
||||||
// failure do something
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<p>Once the channel is connected other PvaClient objects can be created.
|
|
||||||
For example:</p>
|
|
||||||
<pre>
|
|
||||||
PvaClientGetPtr pvaGet = pvaChannel->get(); // DOES BLOCK
|
|
||||||
</pre>
|
|
||||||
<p>This is a caching request.
|
|
||||||
If the client already has made an identical request the client will receive the
|
|
||||||
cached object.
|
|
||||||
If a new pvaGet is created than it is connected before it is returned to the client.
|
|
||||||
</p>
|
|
||||||
<p>The client can also managed it's own objects:</p>
|
|
||||||
<pre>
|
|
||||||
PvaClientGetPtr pvaGet = pvaChannel->createGet(); // DOES NOT BLOCK
|
|
||||||
</pre>
|
|
||||||
<p>The client must connect the pvaGet.</p>
|
|
||||||
|
|
||||||
<h3>PvaClientGetData</h3>
|
|
||||||
<p>This provides the data returned by pvaGet and pvaPutGet.
|
|
||||||
It is obtained via:</p>
|
|
||||||
<pre>
|
|
||||||
PvaClientGetDataPtr pvaData = pvaGet->getData();
|
|
||||||
</pre>
|
|
||||||
<p>It provides methods to get everything returned by channelGet.
|
|
||||||
In addition there are methods that make it easier to handle a value
|
|
||||||
field that is a scalar or a scalarArray.
|
|
||||||
Also for a scalar that is a double or a scalarArray with element type double.
|
|
||||||
</p>
|
|
||||||
<p>An example is:</p>
|
|
||||||
<pre>
|
|
||||||
double value = pvaData->getDouble();
|
|
||||||
</pre>
|
|
||||||
<p>It also keeps a bitSet showing which fields have changed since the last channelGet or channelPutGet.</p>
|
|
||||||
|
|
||||||
<h3>PvaClientMonitorData</h3>
|
|
||||||
<p>To the client this looks identical to PvaClientGetData except that
|
|
||||||
it provides two BitSets: changedBitSet and overrrunBitSet.
|
|
||||||
It is used by pvaMonitor.
|
|
||||||
</p>
|
|
||||||
<h3>PvaClientPutData</h3>
|
|
||||||
<p>This is used to provided data for pvaPut and pvaPutGet.
|
|
||||||
It has many of the same methods as pvaGetData.
|
|
||||||
It does not have a bitSet.
|
|
||||||
It also has put methods like:</p>
|
|
||||||
<pre>
|
|
||||||
void pvaData->putDouble(5.0);
|
|
||||||
</pre>
|
|
||||||
<h3>PvaClientGet</h3>
|
|
||||||
<p>This provides methods to connect to channelGet and to issue get request.
|
|
||||||
To connect via a single synchronous call:</p>
|
|
||||||
<pre>
|
|
||||||
eastGet->connect(); // BLOCKS AND CAN THROW
|
|
||||||
</pre>
|
|
||||||
<p>This can also be done in two steps:</p>
|
|
||||||
<pre>
|
|
||||||
pvaGet->issueConnect(); // DOES NOT BLOCK
|
|
||||||
...
|
|
||||||
Status status = pvaGet->waitConnect(); // BLOCKS AND DOES NOT HROW
|
|
||||||
</pre>
|
|
||||||
<p>Once connected gets are issued via either:</p>
|
|
||||||
<pre>
|
|
||||||
void pvaGet->get(); // BLOCKS AND CAN THROW
|
|
||||||
</pre>
|
|
||||||
or
|
|
||||||
<pre>
|
|
||||||
pvaGet->issueGet(); // DOES NOT BLOCK
|
|
||||||
...
|
|
||||||
Status status = pvaGet->waitGet(); // BLOCKS AND DOES NOT THROW
|
|
||||||
</pre>
|
|
||||||
<h3>PvaClientPut</h3>
|
|
||||||
<p>This is similar to pvaGet except that it wraps channelPut instead of channelGet.
|
|
||||||
</p>
|
|
||||||
<p>Once connected puts are issued via either:</p>
|
|
||||||
<pre>
|
|
||||||
void pvaPut->put(); // BLOCKS AND CAN THROW
|
|
||||||
</pre>
|
|
||||||
or
|
|
||||||
<pre>
|
|
||||||
pvaPut->issuePut(); // DOES NOT BLOCK
|
|
||||||
...
|
|
||||||
Status status = pvaPut->waitPut(); // BLOCKS AND DOES NOT THROW
|
|
||||||
</pre>
|
|
||||||
<h3>PvaClientMonitor</h3>
|
|
||||||
<p>Connecting is similar to pvaGet and pvaPut.
|
|
||||||
The other methods are:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>start</dt>
|
|
||||||
<dd>Starts monitoring</dd>
|
|
||||||
<dt>stop</dt>
|
|
||||||
<dd>Stops monitoring</dd>
|
|
||||||
<dt>poll</dt>
|
|
||||||
<dd>polls for a monitorEvent.
|
|
||||||
The data is avalable via pvaMonitorData.
|
|
||||||
</dd>
|
|
||||||
<dt>releaseEvent</dt>
|
|
||||||
<dd>Release the data from the last poll.
|
|
||||||
Note that this must be called before another poll is requested.
|
|
||||||
</dd>
|
|
||||||
<dt>waitEvent</dt>
|
|
||||||
<dd>Block until a monitorEvent is available.
|
|
||||||
If true is returned a poll has already been issued.
|
|
||||||
</dd>
|
|
||||||
<dt>setRequester</dt>
|
|
||||||
<dd>A client callback is registered to receive notice of monitorEvents.</dd>
|
|
||||||
</dl>
|
|
||||||
<h3>PvaClientProcess</h3>
|
|
||||||
<p>Connecting is similar to pvaGet.
|
|
||||||
It has methods:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>process</dt>
|
|
||||||
<dd>call issueProcess and waitProcess.</dd>
|
|
||||||
<dt>issueProcess</dt>
|
|
||||||
<dd>call channelProcess->process() and return immediately.
|
|
||||||
</dd>
|
|
||||||
<dt>waitProcess</dt>
|
|
||||||
<dd>Wait for process to complete.</dd>
|
|
||||||
</dl>
|
|
||||||
<h3>PvaClientPutGet</h3>
|
|
||||||
<p>Connecting is similar to pvaGet.
|
|
||||||
It has methods:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>putGet</dt>
|
|
||||||
<dd>calls issuePutGet and waitPutGet.
|
|
||||||
throws an exception if not successfull.
|
|
||||||
</dd>
|
|
||||||
<dt>issuePutGet</dt>
|
|
||||||
<dd>
|
|
||||||
Calls channel->putGet() and returns.
|
|
||||||
</dd>
|
|
||||||
<dt>waitPutGet</dt>
|
|
||||||
<dd>
|
|
||||||
Waits until putGet completes and returns status.
|
|
||||||
</dd>
|
|
||||||
<dt>getGet,issueGetGet, and waitGetGet</dt>
|
|
||||||
<dd>Gets the data for the get part of channelPutGet.</dd>
|
|
||||||
<dt>getPut,issueGetPut,and waitGetPut</dt>
|
|
||||||
<dd>Gets the data for the put part of channelPutGet.</dd>
|
|
||||||
<dt>getPutData</dt>
|
|
||||||
<dd>
|
|
||||||
Returns the PvaClientData for the put part of channelPutGet.
|
|
||||||
</dd>
|
|
||||||
<dt>getGetData</dt>
|
|
||||||
<dd>
|
|
||||||
Returns the PvaClientData for the get part of channelPutGet.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<p>Look at javaDoc for details.</p>
|
|
||||||
|
|
||||||
<h2>PvaClientMultiChannel - Wrapper For Multiple Channels</h2>
|
|
||||||
<h3>PvaClientMultiChannel</h3>
|
|
||||||
<p>This provides methods for connecting to multiple channels.
|
|
||||||
</p>
|
|
||||||
<h3>PvaClientMultiGetDouble</h3>
|
|
||||||
<p>This provides support for channelGet to multiple channels where each channel has a value field that is a numeric scalar.
|
|
||||||
</p>
|
|
||||||
<h3>PvaClientMultiPutDouble</h3>
|
|
||||||
<p>This provides support for channelPut to multiple channels where each channel has a value field that is a numeric scalar.
|
|
||||||
</p>
|
|
||||||
<h3>PvaClientMultiMonitorDouble</h3>
|
|
||||||
<p>This provides support for monitoring changes to multiple channels where each channel has a value field that is a numeric scalar.
|
|
||||||
</p>
|
|
||||||
<h3>PvaClientNTMultiGet</h3>
|
|
||||||
<p>This provides support for channelGet to multiple channels where each channel has a value field that has any valid type.
|
|
||||||
</p>
|
|
||||||
<h3>PvaClientNTMultiPut</h3>
|
|
||||||
<p>This provides support for channelPut to multiple channels where each channel has a value
|
|
||||||
field that has any valid type.
|
|
||||||
</p>
|
|
||||||
<h3>PvaClientNTMultiMonitor</h3>
|
|
||||||
<p>This provides support for monitoring changes to multiple channels where each channel has a
|
|
||||||
value field that has any valid type.
|
|
||||||
</p>
|
|
||||||
<h3>PvaClientNTMultiData</h3>
|
|
||||||
<p>This provides support for monitoring changes to multiple channels where each channel has a value field that has any valid type.
|
|
||||||
The client can get the data as normative type NTMultiChannel.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div> <!-- class="contents" -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Makefile at top of application tree
|
|
||||||
|
|
||||||
TOP = .
|
|
||||||
include $(TOP)/configure/CONFIG
|
|
||||||
|
|
||||||
DIRS += configure
|
|
||||||
|
|
||||||
DIRS += src
|
|
||||||
src_DEPEND_DIRS = configure
|
|
||||||
|
|
||||||
include $(TOP)/configure/RULES_TOP
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# CONFIG - Load build configuration data
|
|
||||||
#
|
|
||||||
# Do not make changes to this file!
|
|
||||||
|
|
||||||
# Allow user to override where the build rules come from
|
|
||||||
RULES = $(EPICS_BASE)
|
|
||||||
|
|
||||||
# RELEASE files point to other application tops
|
|
||||||
include $(TOP)/configure/RELEASE
|
|
||||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
|
|
||||||
ifdef T_A
|
|
||||||
-include $(TOP)/configure/RELEASE.Common.$(T_A)
|
|
||||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
|
||||||
endif
|
|
||||||
|
|
||||||
CONFIG = $(RULES)/configure
|
|
||||||
include $(CONFIG)/CONFIG
|
|
||||||
|
|
||||||
# Override the Base definition:
|
|
||||||
INSTALL_LOCATION = $(TOP)
|
|
||||||
|
|
||||||
# CONFIG_SITE files contain other build configuration settings
|
|
||||||
include $(TOP)/configure/CONFIG_SITE
|
|
||||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
|
||||||
ifdef T_A
|
|
||||||
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
|
|
||||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
|
||||||
endif
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# CONFIG_SITE
|
|
||||||
|
|
||||||
# Make any application-specific changes to the EPICS build
|
|
||||||
# configuration variables in this file.
|
|
||||||
#
|
|
||||||
# Host/target specific settings can be specified in files named
|
|
||||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
|
||||||
# CONFIG_SITE.Common.$(T_A)
|
|
||||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
|
||||||
|
|
||||||
# CHECK_RELEASE controls the consistency checking of the support
|
|
||||||
# applications pointed to by the RELEASE* files.
|
|
||||||
# Normally CHECK_RELEASE should be set to YES.
|
|
||||||
# Set CHECK_RELEASE to NO to disable checking completely.
|
|
||||||
# Set CHECK_RELEASE to WARN to perform consistency checking but
|
|
||||||
# continue building anyway if conflicts are found.
|
|
||||||
CHECK_RELEASE = WARN
|
|
||||||
|
|
||||||
# To install files into a location other than $(TOP) define
|
|
||||||
# INSTALL_LOCATION here.
|
|
||||||
#INSTALL_LOCATION=</path/name/to/install/top>
|
|
||||||
|
|
||||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
|
||||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
|
||||||
|
|
||||||
-include $(TOP)/../../CONFIG_SITE.local
|
|
||||||
-include $(TOP)/../configure/CONFIG_SITE.local
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
EPICS_BASE=/home/install/epics/base
|
|
||||||
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
|
||||||
EPICSV4HOME=/home/hg
|
|
||||||
PVCOMMON=${EPICSV4HOME}/pvCommonCPP
|
|
||||||
PVDATA=${EPICSV4HOME}/pvDataCPP
|
|
||||||
PVACCESS=${EPICSV4HOME}/pvAccessCPP
|
|
||||||
EASYPVA==${EPICSV4HOME}/easyPVACPP
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
TOP=..
|
|
||||||
|
|
||||||
include $(TOP)/configure/CONFIG
|
|
||||||
|
|
||||||
TARGETS = $(CONFIG_TARGETS)
|
|
||||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
|
||||||
|
|
||||||
include $(TOP)/configure/RULES
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
# pvDatabaseCPP/example RELEASE - Location of external support modules
|
|
||||||
#
|
|
||||||
# IF YOU CHANGE this file or any file it includes you must
|
|
||||||
# subsequently do a "gnumake rebuild" in the application's
|
|
||||||
# top level directory.
|
|
||||||
#
|
|
||||||
# The build process does not check dependencies against files
|
|
||||||
# that are outside this application, thus you should also do a
|
|
||||||
# "gnumake rebuild" in the top level directory after EPICS_BASE
|
|
||||||
# or any other external module pointed to below is rebuilt.
|
|
||||||
#
|
|
||||||
# Host- or target-specific settings can be given in files named
|
|
||||||
# RELEASE.$(EPICS_HOST_ARCH).Common
|
|
||||||
# RELEASE.Common.$(T_A)
|
|
||||||
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
|
||||||
|
|
||||||
# EPICS V4 Developers: Do not edit the locations in this file!
|
|
||||||
#
|
|
||||||
# Create a file RELEASE.local pointing to your PVASRV, PVACCESS,
|
|
||||||
# PVDATA, PVCOMMON and EPICS_BASE build directories, e.g.
|
|
||||||
# PVASRV = /path/to/epics/pvaSrvCPP
|
|
||||||
# PVACCESS = /path/to/epics/pvAccessCPP
|
|
||||||
# PVDATA = /path/to/epics/pvDataCPP
|
|
||||||
# PVCOMMON = /path/to/epics/pvCommonCPP
|
|
||||||
# EPICS_BASE = /path/to/epics/base
|
|
||||||
|
|
||||||
# If this example is built in a directory under pvDatabaseCPP,
|
|
||||||
# use the following definitions:
|
|
||||||
|
|
||||||
EASYPVA = $(TOP)/..
|
|
||||||
|
|
||||||
-include $(TOP)/../configure/RELEASE.local
|
|
||||||
-include $(TOP)/../../RELEASE.local
|
|
||||||
|
|
||||||
# If you copied this example from pvDatabaseCPP to be built as a
|
|
||||||
# standalone TOP, adjust and use the following definitions:
|
|
||||||
|
|
||||||
#EASYPVA = /path/to/epics/easyPVACPP
|
|
||||||
|
|
||||||
#-include $(TOP)/../RELEASE.local
|
|
||||||
#-include $(TOP)/configure/RELEASE.local
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
# RULES
|
|
||||||
|
|
||||||
include $(CONFIG)/RULES
|
|
||||||
|
|
||||||
# Library should be rebuilt because LIBOBJS may have changed.
|
|
||||||
$(LIBNAME): ../Makefile
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#RULES.ioc
|
|
||||||
include $(CONFIG)/RULES.ioc
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#RULES_DIRS
|
|
||||||
include $(CONFIG)/RULES_DIRS
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#RULES_TOP
|
|
||||||
include $(CONFIG)/RULES_TOP
|
|
||||||
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
TOP=..
|
|
||||||
|
|
||||||
include $(TOP)/configure/CONFIG
|
|
||||||
#----------------------------------------
|
|
||||||
# ADD MACRO DEFINITIONS AFTER THIS LINE
|
|
||||||
|
|
||||||
|
|
||||||
PROD_HOST += examplePvaClientProcess
|
|
||||||
examplePvaClientProcess_SRCS += examplePvaClientProcess.cpp
|
|
||||||
examplePvaClientProcess_LIBS += pvaClient
|
|
||||||
examplePvaClientProcess_LIBS += pvAccess
|
|
||||||
examplePvaClientProcess_LIBS += pvData
|
|
||||||
examplePvaClientProcess_LIBS += Com
|
|
||||||
|
|
||||||
PROD_HOST += examplePvaClientGet
|
|
||||||
examplePvaClientGet_SRCS += examplePvaClientGet.cpp
|
|
||||||
examplePvaClientGet_LIBS += pvaClient
|
|
||||||
examplePvaClientGet_LIBS += pvAccess
|
|
||||||
examplePvaClientGet_LIBS += pvData
|
|
||||||
examplePvaClientGet_LIBS += Com
|
|
||||||
|
|
||||||
PROD_HOST += examplePvaClientPut
|
|
||||||
examplePvaClientPut_SRCS += examplePvaClientPut.cpp
|
|
||||||
examplePvaClientPut_LIBS += pvaClient
|
|
||||||
examplePvaClientPut_LIBS += pvAccess
|
|
||||||
examplePvaClientPut_LIBS += pvData
|
|
||||||
examplePvaClientPut_LIBS += Com
|
|
||||||
|
|
||||||
PROD_HOST += examplePvaClientMonitor
|
|
||||||
examplePvaClientMonitor_SRCS += examplePvaClientMonitor.cpp
|
|
||||||
examplePvaClientMonitor_LIBS += pvaClient
|
|
||||||
examplePvaClientMonitor_LIBS += pvAccess
|
|
||||||
examplePvaClientMonitor_LIBS += pvData
|
|
||||||
examplePvaClientMonitor_LIBS += Com
|
|
||||||
|
|
||||||
PROD_HOST += examplePvaClientMultiDouble
|
|
||||||
examplePvaClientMultiDouble_SRCS += examplePvaClientMultiDouble.cpp
|
|
||||||
examplePvaClientMultiDouble_LIBS += pvaClient
|
|
||||||
examplePvaClientMultiDouble_LIBS += pvAccess
|
|
||||||
examplePvaClientMultiDouble_LIBS += pvData
|
|
||||||
examplePvaClientMultiDouble_LIBS += Com
|
|
||||||
|
|
||||||
PROD_HOST += examplePvaClientNTMulti
|
|
||||||
examplePvaClientNTMulti_SRCS += examplePvaClientNTMulti.cpp
|
|
||||||
examplePvaClientNTMulti_LIBS += pvaClient
|
|
||||||
examplePvaClientNTMulti_LIBS += pvAccess
|
|
||||||
examplePvaClientNTMulti_LIBS += pvData
|
|
||||||
examplePvaClientNTMulti_LIBS += Com
|
|
||||||
|
|
||||||
PROD_HOST += helloWorldRPC
|
|
||||||
helloWorldRPC_SRCS += helloWorldRPC.cpp
|
|
||||||
helloWorldRPC_LIBS += pvaClient
|
|
||||||
helloWorldRPC_LIBS += pvAccess
|
|
||||||
helloWorldRPC_LIBS += nt
|
|
||||||
helloWorldRPC_LIBS += pvData
|
|
||||||
helloWorldRPC_LIBS += Com
|
|
||||||
|
|
||||||
PROD_HOST += helloWorldPutGet
|
|
||||||
helloWorldPutGet_SRCS += helloWorldPutGet.cpp
|
|
||||||
helloWorldPutGet_LIBS += pvaClient
|
|
||||||
helloWorldPutGet_LIBS += pvAccess
|
|
||||||
helloWorldPutGet_LIBS += nt
|
|
||||||
helloWorldPutGet_LIBS += pvData
|
|
||||||
helloWorldPutGet_LIBS += Com
|
|
||||||
|
|
||||||
#===========================
|
|
||||||
|
|
||||||
include $(TOP)/configure/RULES
|
|
||||||
#----------------------------------------
|
|
||||||
# ADD RULES AFTER THIS LINE
|
|
||||||
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
/*examplePvaClientGet.cpp */
|
|
||||||
/**
|
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
||||||
* in file LICENSE that is included with this distribution.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @author mrk
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvaClient;
|
|
||||||
|
|
||||||
|
|
||||||
static void exampleDouble(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "example double scalar\n";
|
|
||||||
double value;
|
|
||||||
try {
|
|
||||||
cout << "short way\n";
|
|
||||||
value = pva->channel("exampleDouble")->get()->getData()->getDouble();
|
|
||||||
cout << "as double " << value << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
cout << "long way\n";
|
|
||||||
PvaClientChannelPtr pvaChannel = pva->createChannel("exampleDouble");
|
|
||||||
pvaChannel->issueConnect();
|
|
||||||
Status status = pvaChannel->waitConnect(2.0);
|
|
||||||
if(!status.isOK()) {cout << " connect failed\n"; return;}
|
|
||||||
PvaClientGetPtr pvaGet = pvaChannel->createGet();
|
|
||||||
pvaGet->issueConnect();
|
|
||||||
status = pvaGet->waitConnect();
|
|
||||||
if(!status.isOK()) {cout << " createGet failed\n"; return;}
|
|
||||||
PvaClientGetDataPtr pvaData = pvaGet->getData();
|
|
||||||
value = pvaData->getDouble();
|
|
||||||
cout << "as double " << value << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void exampleDoubleArray(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "example double array\n";
|
|
||||||
shared_vector<const double> value;
|
|
||||||
try {
|
|
||||||
cout << "short way\n";
|
|
||||||
value = pva->channel("exampleDoubleArray")->get()->getData()->getDoubleArray();
|
|
||||||
cout << "as doubleArray " << value << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
cout << "long way\n";
|
|
||||||
PvaClientChannelPtr pvaChannel = pva->createChannel("exampleDoubleArray");
|
|
||||||
pvaChannel->connect(2.0);
|
|
||||||
PvaClientGetPtr pvaGet = pvaChannel->createGet();
|
|
||||||
PvaClientGetDataPtr pvaData = pvaGet->getData();
|
|
||||||
value = pvaData->getDoubleArray();
|
|
||||||
cout << "as doubleArray " << value << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void examplePowerSupply(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "example powerSupply\n";
|
|
||||||
PVStructurePtr pvStructure;
|
|
||||||
try {
|
|
||||||
cout << "short way\n";
|
|
||||||
pvStructure = pva->channel("examplePowerSupply")->
|
|
||||||
get("field()")->getData()->getPVStructure();
|
|
||||||
cout << pvStructure << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void exampleCADouble(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "example double scalar\n";
|
|
||||||
double value;
|
|
||||||
try {
|
|
||||||
cout << "short way\n";
|
|
||||||
value = pva->channel("double00","ca",5.0)->get()->getData()->getDouble();
|
|
||||||
cout << "as double " << value << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
cout << "long way\n";
|
|
||||||
PvaClientChannelPtr pvaChannel = pva->createChannel("double00","ca");
|
|
||||||
pvaChannel->issueConnect();
|
|
||||||
Status status = pvaChannel->waitConnect(2.0);
|
|
||||||
if(!status.isOK()) {cout << " connect failed\n"; return;}
|
|
||||||
PvaClientGetPtr pvaGet = pvaChannel->createGet();
|
|
||||||
pvaGet->issueConnect();
|
|
||||||
status = pvaGet->waitConnect();
|
|
||||||
if(!status.isOK()) {cout << " createGet failed\n"; return;}
|
|
||||||
PvaClientGetDataPtr pvaData = pvaGet->getData();
|
|
||||||
value = pvaData->getDouble();
|
|
||||||
cout << "as double " << value << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void exampleCADoubleArray(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "example double array\n";
|
|
||||||
shared_vector<const double> value;
|
|
||||||
try {
|
|
||||||
cout << "short way\n";
|
|
||||||
value = pva->channel("doubleArray","ca",5.0)->get()->getData()->getDoubleArray();
|
|
||||||
cout << "as doubleArray " << value << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
cout << "long way\n";
|
|
||||||
PvaClientChannelPtr pvaChannel = pva->createChannel("doubleArray","ca");
|
|
||||||
pvaChannel->connect(2.0);
|
|
||||||
PvaClientGetPtr pvaGet = pvaChannel->createGet();
|
|
||||||
PvaClientGetDataPtr pvaData = pvaGet->getData();
|
|
||||||
value = pvaData->getDoubleArray();
|
|
||||||
cout << "as doubleArray " << value << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
PvaClientPtr pva= PvaClient::create();
|
|
||||||
exampleDouble(pva);
|
|
||||||
exampleDoubleArray(pva);
|
|
||||||
examplePowerSupply(pva);
|
|
||||||
exampleCADouble(pva);
|
|
||||||
exampleCADoubleArray(pva);
|
|
||||||
cout << "done\n";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/*examplePvaClientMonitor.cpp */
|
|
||||||
/**
|
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
||||||
* in file LICENSE that is included with this distribution.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @author mrk
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <epicsThread.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvaClient;
|
|
||||||
|
|
||||||
|
|
||||||
static void exampleMonitor(PvaClientPtr const &pva,string provider)
|
|
||||||
{
|
|
||||||
PvaClientMonitorPtr monitor = pva->channel("double00",provider,2.0)->monitor("");
|
|
||||||
PvaClientMonitorDataPtr monitorData = monitor->getData();
|
|
||||||
PvaClientPutPtr put = pva->channel("double00",provider,2.0)->put("");
|
|
||||||
PvaClientPutDataPtr putData = put->getData();
|
|
||||||
for(size_t ntimes=0; ntimes<5; ++ntimes)
|
|
||||||
{
|
|
||||||
double value = ntimes;
|
|
||||||
cout << "put " << value << endl;
|
|
||||||
putData->putDouble(value); put->put();
|
|
||||||
if(!monitor->waitEvent(.1)) {
|
|
||||||
cout << "waitEvent returned false. Why???";
|
|
||||||
continue;
|
|
||||||
} else while(true) {
|
|
||||||
cout << "monitor " << monitorData->getDouble() << endl;
|
|
||||||
cout << "changed\n";
|
|
||||||
monitorData->showChanged(cout);
|
|
||||||
cout << "overrun\n";
|
|
||||||
monitorData->showOverrun(cout);
|
|
||||||
monitor->releaseEvent();
|
|
||||||
if(!monitor->poll()) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
PvaClientPtr pva = PvaClient::create();
|
|
||||||
cout << "exampleMonitor pva\n";
|
|
||||||
exampleMonitor(pva,"pva");
|
|
||||||
cout << "exampleMonitor ca\n";
|
|
||||||
exampleMonitor(pva,"ca");
|
|
||||||
cout << "done\n";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
/*examplePvaClientMultiDouble.cpp */
|
|
||||||
/**
|
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
||||||
* in file LICENSE that is included with this distribution.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @author mrk
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvaClient;
|
|
||||||
|
|
||||||
static void example(
|
|
||||||
PvaClientPtr const &pva,
|
|
||||||
string provider,
|
|
||||||
shared_vector<const string> const &channelNames)
|
|
||||||
{
|
|
||||||
|
|
||||||
size_t num = channelNames.size();
|
|
||||||
cout << "num " << num << " names " << channelNames << endl;
|
|
||||||
PvaClientMultiChannelPtr multiChannel(
|
|
||||||
PvaClientMultiChannel::create(pva,channelNames,provider));
|
|
||||||
PvaClientMultiGetDoublePtr multiGet(multiChannel->createGet());
|
|
||||||
PvaClientMultiPutDoublePtr multiPut(multiChannel->createPut());
|
|
||||||
PvaClientMultiMonitorDoublePtr multiMonitor(multiChannel->createMonitor());
|
|
||||||
shared_vector<double> data(num,0);
|
|
||||||
for(double value = 0.2; value< 2.3; value+= 1.0) {
|
|
||||||
try {
|
|
||||||
for(size_t i=0; i<num; ++i) data[i] = value + i;
|
|
||||||
cout << "put " << data << endl;
|
|
||||||
multiPut->put(data);
|
|
||||||
data = multiGet->get();
|
|
||||||
cout << "get " << data << endl;
|
|
||||||
bool result = multiMonitor->waitEvent(.1);
|
|
||||||
while(result) {
|
|
||||||
cout << "monitor data " << multiMonitor->get() << endl;
|
|
||||||
result = multiMonitor->poll();
|
|
||||||
}
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
PvaClientPtr pva = PvaClient::create();
|
|
||||||
size_t num = 5;
|
|
||||||
shared_vector<string> channelNames(num);
|
|
||||||
channelNames[0] = "double01";
|
|
||||||
channelNames[1] = "int01";
|
|
||||||
channelNames[2] = "double03";
|
|
||||||
channelNames[3] = "double04";
|
|
||||||
channelNames[4] = "double05";
|
|
||||||
cout << "double pva\n";
|
|
||||||
shared_vector<const string> names(freeze(channelNames));
|
|
||||||
example(pva,"pva",names);
|
|
||||||
cout << "double ca\n";
|
|
||||||
example(pva,"ca",names);
|
|
||||||
channelNames = shared_vector<string>(num);
|
|
||||||
channelNames[0] = "exampleDouble01";
|
|
||||||
channelNames[1] = "exampleInt";
|
|
||||||
channelNames[2] = "exampleDouble03";
|
|
||||||
channelNames[3] = "exampleDouble04";
|
|
||||||
channelNames[4] = "exampleDouble05";
|
|
||||||
names = freeze(channelNames);
|
|
||||||
cout << "exampleDouble pva\n";
|
|
||||||
example(pva,"pva",names);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
/*examplePvaClientNTMulti.cpp */
|
|
||||||
/**
|
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
||||||
* in file LICENSE that is included with this distribution.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @author mrk
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
#include <pv/convert.h>
|
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace std;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvaClient;
|
|
||||||
|
|
||||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
|
|
||||||
static void setValue(PVUnionPtr const &pvUnion, double value)
|
|
||||||
{
|
|
||||||
UnionConstPtr u = pvUnion->getUnion();
|
|
||||||
FieldConstPtr field = u->getField(0);
|
|
||||||
Type type = field->getType();
|
|
||||||
if(type==scalar) {
|
|
||||||
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
|
|
||||||
ScalarType scalarType = scalar->getScalarType();
|
|
||||||
if(scalarType==pvDouble) {
|
|
||||||
PVDoublePtr pvValue = static_pointer_cast<PVDouble>(
|
|
||||||
pvDataCreate->createPVScalar(pvDouble));
|
|
||||||
pvValue->put(value);
|
|
||||||
pvUnion->set(0,pvValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(scalarType==pvString) {
|
|
||||||
PVStringPtr pvValue = static_pointer_cast<PVString>(
|
|
||||||
pvDataCreate->createPVScalar(pvString));
|
|
||||||
stringstream ss;
|
|
||||||
ss << "value" << value;
|
|
||||||
pvValue->put(ss.str());
|
|
||||||
pvUnion->set(0,pvValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw std::runtime_error("only pvDouble and pvString are supported");
|
|
||||||
}
|
|
||||||
if(type==scalarArray) {
|
|
||||||
ScalarArrayConstPtr scalarArray = static_pointer_cast<const ScalarArray>(field);
|
|
||||||
ScalarType scalarType = scalarArray->getElementType();
|
|
||||||
if(scalarType==pvDouble) {
|
|
||||||
size_t num = 5;
|
|
||||||
PVDoubleArrayPtr pvValue = static_pointer_cast<PVDoubleArray>(
|
|
||||||
pvDataCreate->createPVScalarArray(pvDouble));
|
|
||||||
shared_vector<double> data(num);
|
|
||||||
for(size_t i=0; i<num; ++i) data[i] = value +i;
|
|
||||||
pvValue->replace(freeze(data));
|
|
||||||
pvUnion->set(0,pvValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(scalarType==pvString) {
|
|
||||||
size_t num = 5;
|
|
||||||
PVStringArrayPtr pvValue = static_pointer_cast<PVStringArray>(
|
|
||||||
pvDataCreate->createPVScalarArray(pvString));
|
|
||||||
shared_vector<string> data(num);
|
|
||||||
for(size_t i=0; i<num; ++i) {
|
|
||||||
stringstream ss;
|
|
||||||
ss << "value" << value << i;
|
|
||||||
data[i] = ss.str();
|
|
||||||
}
|
|
||||||
pvValue->replace(freeze(data));
|
|
||||||
pvUnion->set(0,pvValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw std::runtime_error("only pvDouble and pvString are supported");
|
|
||||||
}
|
|
||||||
throw std::runtime_error("only scalar and scalarArray fields are supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void example(
|
|
||||||
PvaClientPtr const &pva,
|
|
||||||
string provider,
|
|
||||||
shared_vector<const string> const &channelNames)
|
|
||||||
{
|
|
||||||
|
|
||||||
size_t num = channelNames.size();
|
|
||||||
PvaClientMultiChannelPtr multiChannel(
|
|
||||||
PvaClientMultiChannel::create(pva,channelNames,provider));
|
|
||||||
PvaClientNTMultiGetPtr multiGet(multiChannel->createNTGet());
|
|
||||||
PvaClientNTMultiPutPtr multiPut(multiChannel->createNTPut());
|
|
||||||
PvaClientNTMultiMonitorPtr multiMonitor(multiChannel->createNTMonitor());
|
|
||||||
shared_vector<epics::pvData::PVUnionPtr> data = multiPut->getValues();
|
|
||||||
for(double value = 0.0; value< 2.1; value+= 1.0) {
|
|
||||||
for(size_t i=0; i<num ; ++i) {
|
|
||||||
PVUnionPtr pvUnion = data[i];
|
|
||||||
setValue(pvUnion,value);
|
|
||||||
}
|
|
||||||
multiPut->put();
|
|
||||||
multiGet->get();
|
|
||||||
PvaClientNTMultiDataPtr multiData = multiGet->getData();
|
|
||||||
PVStructurePtr pvStructure = multiData->getNTMultiChannel()->getPVStructure();
|
|
||||||
cout << "pvStructure\n" << pvStructure << endl;
|
|
||||||
bool result = multiMonitor->waitEvent(.1);
|
|
||||||
while(result) {
|
|
||||||
multiData = multiMonitor->getData();
|
|
||||||
pvStructure = multiData->getNTMultiChannel()->getPVStructure();
|
|
||||||
cout << "monitor pvStructure\n" << pvStructure << endl;
|
|
||||||
result = multiMonitor->poll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
PvaClientPtr pva = PvaClient::create();
|
|
||||||
size_t num = 4;
|
|
||||||
shared_vector<string> channelNames(num);
|
|
||||||
channelNames[0] = "double01";
|
|
||||||
channelNames[1] = "string01";
|
|
||||||
channelNames[2] = "doubleArray01";
|
|
||||||
channelNames[3] = "stringArray01";
|
|
||||||
cout << "dbRecord pva\n";
|
|
||||||
shared_vector<const string> names(freeze(channelNames));
|
|
||||||
example(pva,"pva",names);
|
|
||||||
cout << "dbRecord ca\n";
|
|
||||||
example(pva,"ca",names);
|
|
||||||
channelNames = shared_vector<string>(num);
|
|
||||||
channelNames[0] = "exampleDouble";
|
|
||||||
channelNames[1] = "exampleString";
|
|
||||||
channelNames[2] = "exampleDoubleArray";
|
|
||||||
channelNames[3] = "exampleStringArray";
|
|
||||||
names = freeze(channelNames);
|
|
||||||
cout << "pvRecord pva\n";
|
|
||||||
example(pva,"pva",names);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*examplePvaClientProcess.cpp */
|
|
||||||
/**
|
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
||||||
* in file LICENSE that is included with this distribution.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @author mrk
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvaClient;
|
|
||||||
|
|
||||||
|
|
||||||
static void exampleProcess(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "example process\n";
|
|
||||||
PvaClientChannelPtr channel = pva->channel("exampleDouble");
|
|
||||||
PvaClientProcessPtr process = channel->createProcess();
|
|
||||||
try {
|
|
||||||
process->process();
|
|
||||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
|
||||||
process->process();
|
|
||||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
PvaClientPtr pva = PvaClient::create();
|
|
||||||
exampleProcess(pva);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*examplePvaClientPut.cpp */
|
|
||||||
/**
|
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
||||||
* in file LICENSE that is included with this distribution.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @author mrk
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
#include <pv/convert.h>
|
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace std;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvaClient;
|
|
||||||
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
|
|
||||||
|
|
||||||
static void examplePut(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "example put\n";
|
|
||||||
PvaClientChannelPtr channel = pva->channel("exampleDouble");
|
|
||||||
PvaClientPutPtr put = channel->put();
|
|
||||||
PvaClientPutDataPtr putData = put->getData();
|
|
||||||
PvaClientMonitorPtr monitor = pva->channel("exampleDouble")->monitor("");
|
|
||||||
PvaClientMonitorDataPtr monitorData = monitor->getData();
|
|
||||||
try {
|
|
||||||
putData->putDouble(3.0); put->put();
|
|
||||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
|
||||||
putData->putDouble(4.0); put->put();
|
|
||||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
|
||||||
if(!monitor->waitEvent()) {
|
|
||||||
cout << "waitEvent returned false. Why???";
|
|
||||||
} else while(true) {
|
|
||||||
cout << "monitor changed\n" << monitorData->showChanged(cout);
|
|
||||||
monitor->releaseEvent();
|
|
||||||
if(!monitor->poll()) break;
|
|
||||||
}
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void examplePVFieldPut(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "example put\n";
|
|
||||||
PvaClientChannelPtr channel = pva->channel("exampleDouble");
|
|
||||||
PvaClientPutPtr put = channel->put();
|
|
||||||
PvaClientPutDataPtr putData = put->getData();
|
|
||||||
PVFieldPtr pvField = putData->getValue();
|
|
||||||
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
|
||||||
try {
|
|
||||||
convert->fromDouble(pvScalar,1.0); put->put();
|
|
||||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
|
||||||
convert->fromDouble(pvScalar,2.0); put->put();
|
|
||||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
PvaClientPtr pva = PvaClient::create();
|
|
||||||
examplePut(pva);
|
|
||||||
examplePVFieldPut(pva);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*helloWorldPutGet.cpp */
|
|
||||||
/**
|
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
||||||
* in file LICENSE that is included with this distribution.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @author mrk
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvaClient;
|
|
||||||
|
|
||||||
|
|
||||||
static void example(PvaClientPtr const &pva)
|
|
||||||
{
|
|
||||||
cout << "helloWorldPutGet\n";
|
|
||||||
try {
|
|
||||||
PvaClientChannelPtr channel = pva->channel("exampleHello");
|
|
||||||
PvaClientPutGetPtr putGet = channel->createPutGet();
|
|
||||||
putGet->connect();
|
|
||||||
PvaClientPutDataPtr putData = putGet->getPutData();
|
|
||||||
PVStructurePtr arg = putData->getPVStructure();
|
|
||||||
PVStringPtr pvValue = arg->getSubField<PVString>("argument.value");
|
|
||||||
pvValue->put("World");
|
|
||||||
putGet->putGet();
|
|
||||||
PvaClientGetDataPtr getData = putGet->getGetData();
|
|
||||||
cout << getData->getPVStructure() << endl;
|
|
||||||
} catch (std::runtime_error e) {
|
|
||||||
cout << "exception " << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
PvaClientPtr pva = PvaClient::create();
|
|
||||||
example(pva);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*helloWorldRPC.cpp */
|
|
||||||
/**
|
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
|
||||||
* in file LICENSE that is included with this distribution.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @author mrk
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <pv/pvData.h>
|
|
||||||
#include <pv/pvAccess.h>
|
|
||||||
#include <pv/rpcClient.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
|
|
||||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
|
||||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
|
||||||
|
|
||||||
|
|
||||||
static void exampleSimple()
|
|
||||||
{
|
|
||||||
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
|
||||||
add("value",pvString)->
|
|
||||||
createStructure();
|
|
||||||
PVStructurePtr pvRequest = pvDataCreate->createPVStructure(topStructure);
|
|
||||||
PVStringPtr pvArgument = pvRequest->getSubField<PVString>("value");
|
|
||||||
pvArgument->put("World");
|
|
||||||
cout << "example channeRPC simple\n";
|
|
||||||
try {
|
|
||||||
PVStructurePtr pvResult =
|
|
||||||
RPCClient::sendRequest("exampleHelloRPC", pvRequest);
|
|
||||||
cout << "result\n" << pvResult << endl;
|
|
||||||
} catch (RPCRequestException &e) {
|
|
||||||
cout << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void exampleMore()
|
|
||||||
{
|
|
||||||
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
|
||||||
add("value",pvString)->
|
|
||||||
createStructure();
|
|
||||||
PVStructurePtr pvRequest = pvDataCreate->createPVStructure(topStructure);
|
|
||||||
PVStringPtr pvArgument = pvRequest->getSubField<PVString>("value");
|
|
||||||
pvArgument->put("World");
|
|
||||||
cout << "example channeRPC more\n";
|
|
||||||
try {
|
|
||||||
RPCClient::shared_pointer client = RPCClient::create("exampleHelloRPC");
|
|
||||||
client->issueConnect();
|
|
||||||
if (client->waitConnect())
|
|
||||||
{
|
|
||||||
client->issueRequest(pvRequest);
|
|
||||||
PVStructure::shared_pointer result = client->waitResponse();
|
|
||||||
std::cout << *result << std::endl;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cout << "waitConnect timeout\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (RPCRequestException &e) {
|
|
||||||
cout << e.what() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
|
||||||
{
|
|
||||||
exampleSimple();
|
|
||||||
exampleMore();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
+32
-23
@@ -6,22 +6,37 @@
|
|||||||
#
|
#
|
||||||
# Author: Ralph Lange <ralph.lange@gmx.de>
|
# Author: Ralph Lange <ralph.lange@gmx.de>
|
||||||
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||||
# Copyright (C) 2014-2015 ITER Organization.
|
# Copyright (C) 2014-2016 ITER Organization.
|
||||||
# All rights reserved. Use is subject to license terms.
|
# All rights reserved. Use is subject to license terms.
|
||||||
|
|
||||||
|
installTool () {
|
||||||
|
local module=$1
|
||||||
|
local version=$2
|
||||||
|
|
||||||
|
wget -nv https://openepics.ci.cloudbees.com/job/${module}-${version}_Build/lastSuccessfulBuild/artifact/${module,,}-${version}.CB-dist.tar.gz
|
||||||
|
tar -xzf ${module,,}-${version}.CB-dist.tar.gz
|
||||||
|
}
|
||||||
|
|
||||||
|
installE4 () {
|
||||||
|
local module=$1
|
||||||
|
local branch=$2
|
||||||
|
|
||||||
|
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE}/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
|
||||||
|
tar -xzf ${module}.CB-dist.tar.gz
|
||||||
|
}
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Determine EPICS Base version
|
# Defaults for EPICS Base
|
||||||
|
|
||||||
DEFAULT_BASE=3.14.12.5
|
DEFAULT_BASE=3.15.4
|
||||||
|
BASE=${BASE:-${DEFAULT_BASE}}
|
||||||
|
|
||||||
BASE=${1:-${DEFAULT_BASE}}
|
###########################################
|
||||||
USE_MB=${2:-"MB_NO"}
|
# Dependent module branches
|
||||||
|
|
||||||
# Dependent module branches (empty = master)
|
PVDATA_BRANCH="master"
|
||||||
PVCOMMON_BRANCH="Release-4.1-"
|
PVACCESS_BRANCH="master"
|
||||||
PVDATA_BRANCH="Release-5.0-"
|
NORMATIVETYPES_BRANCH="master"
|
||||||
PVACCESS_BRANCH="Release-4.1-"
|
|
||||||
NORMATIVETYPES_BRANCH="Release-5.0-"
|
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Fetch and unpack dependencies
|
# Fetch and unpack dependencies
|
||||||
@@ -32,19 +47,12 @@ rm -fr ${STUFF}
|
|||||||
mkdir -p ${STUFF}
|
mkdir -p ${STUFF}
|
||||||
cd ${STUFF}
|
cd ${STUFF}
|
||||||
|
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/Base-${BASE}_Build/lastSuccessfulBuild/artifact/base-${BASE}.CB-dist.tar.gz
|
installTool Boost 1.61.0
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/pvDataCPP_${PVDATA_BRANCH}Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvData.CB-dist.tar.gz
|
installTool Base ${BASE}
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/pvAccessCPP_${PVACCESS_BRANCH}Build/BASE=${BASE},USE_MB=${USE_MB}/lastSuccessfulBuild/artifact/pvAccess.CB-dist.tar.gz
|
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/normativeTypesCPP_${NORMATIVETYPES_BRANCH}Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/normativeTypes.CB-dist.tar.gz
|
|
||||||
tar -xzf base-${BASE}.CB-dist.tar.gz
|
|
||||||
tar -xzf pvData.CB-dist.tar.gz
|
|
||||||
tar -xzf pvAccess.CB-dist.tar.gz
|
|
||||||
tar -xzf normativeTypes.CB-dist.tar.gz
|
|
||||||
|
|
||||||
if [ "${USE_MB}" = "MB_YES" ]; then
|
installE4 pvData ${PVDATA_BRANCH}
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/pvCommonCPP_${PVCOMMON_BRANCH}Build/BASE=${BASE},USE_MB=MB_YES/lastSuccessfulBuild/artifact/pvCommon.CB-dist.tar.gz
|
installE4 pvAccess ${PVACCESS_BRANCH}
|
||||||
tar -xzf pvCommon.CB-dist.tar.gz
|
installE4 normativeTypes ${NORMATIVETYPES_BRANCH}
|
||||||
fi
|
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Build
|
# Build
|
||||||
@@ -65,7 +73,8 @@ make distclean all
|
|||||||
###########################################
|
###########################################
|
||||||
# Test
|
# Test
|
||||||
|
|
||||||
make runtests
|
# no regression tests
|
||||||
|
#make runtests
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Create distribution
|
# Create distribution
|
||||||
|
|||||||
+26
-11
@@ -6,14 +6,32 @@
|
|||||||
#
|
#
|
||||||
# Author: Ralph Lange <ralph.lange@gmx.de>
|
# Author: Ralph Lange <ralph.lange@gmx.de>
|
||||||
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||||
# Copyright (C) 2014-2015 ITER Organization.
|
# Copyright (C) 2014-2016 ITER Organization.
|
||||||
# All rights reserved. Use is subject to license terms.
|
# All rights reserved. Use is subject to license terms.
|
||||||
|
|
||||||
###########################################
|
installTool () {
|
||||||
# Set EPICS Base version and upload target
|
local module=$1
|
||||||
|
local version=$2
|
||||||
|
|
||||||
BASE=3.15.2
|
wget -nv https://openepics.ci.cloudbees.com/job/${module}-${version}_Build/lastSuccessfulBuild/artifact/${module,,}-${version}.CB-dist.tar.gz
|
||||||
PUBLISH=${1:-DONT}
|
tar -xzf ${module,,}-${version}.CB-dist.tar.gz
|
||||||
|
}
|
||||||
|
|
||||||
|
installE4 () {
|
||||||
|
local module=$1
|
||||||
|
local branch=$2
|
||||||
|
|
||||||
|
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE}/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
|
||||||
|
tar -xzf ${module}.CB-dist.tar.gz
|
||||||
|
}
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Defaults for EPICS Base and parameters
|
||||||
|
|
||||||
|
BASE=3.15.4
|
||||||
|
PUBLISH=${PUBLISH:-NO}
|
||||||
|
BRANCH=${BRANCH:-master}
|
||||||
|
MB=NO_MICROBENCH
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Fetch and unpack dependencies
|
# Fetch and unpack dependencies
|
||||||
@@ -24,16 +42,14 @@ rm -fr ${STUFF}
|
|||||||
mkdir -p ${STUFF}
|
mkdir -p ${STUFF}
|
||||||
cd ${STUFF}
|
cd ${STUFF}
|
||||||
|
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
|
installTool Doxygen 1.8.11
|
||||||
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
|
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Generate
|
# Generate
|
||||||
|
|
||||||
cd ${WORKSPACE}
|
cd ${WORKSPACE}
|
||||||
|
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/pvaClientCPP_Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvaClient.CB-dist.tar.gz
|
installE4 pvaClient ${BRANCH}
|
||||||
tar -xzf pvaClient.CB-dist.tar.gz
|
|
||||||
|
|
||||||
export PATH=${STUFF}/bin:${PATH}
|
export PATH=${STUFF}/bin:${PATH}
|
||||||
|
|
||||||
@@ -45,7 +61,6 @@ doxygen
|
|||||||
if [ "${PUBLISH}" != "DONT" ]; then
|
if [ "${PUBLISH}" != "DONT" ]; then
|
||||||
# Upload explicit dummy to ensure target directory exists
|
# Upload explicit dummy to ensure target directory exists
|
||||||
echo "Created by CloudBees Jenkins upload job. Should be deleted as part of the job." > DUMMY
|
echo "Created by CloudBees Jenkins upload job. Should be deleted as part of the job." > DUMMY
|
||||||
rsync -q -e ssh DUMMY epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/
|
rsync -q -e ssh DUMMY epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/DUMMY
|
||||||
|
|
||||||
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/
|
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/
|
||||||
fi
|
fi
|
||||||
|
|||||||
+10
-5
@@ -5,10 +5,14 @@ include $(TOP)/configure/CONFIG
|
|||||||
|
|
||||||
LIBRARY += pvaClient
|
LIBRARY += pvaClient
|
||||||
|
|
||||||
INC += pvaClient.h
|
# shared library ABI version.
|
||||||
INC += pvaClientMultiChannel.h
|
SHRLIB_VERSION ?= $(EPICS_PVACLIENT_MAJOR_VERSION).$(EPICS_PVACLIENT_MINOR_VERSION).$(EPICS_PVACLIENT_MAINTENANCE_VERSION)
|
||||||
|
|
||||||
|
INC += pv/pvaClient.h
|
||||||
|
INC += pv/pvaClientMultiChannel.h
|
||||||
|
|
||||||
LIBSRCS += pvaClient.cpp
|
LIBSRCS += pvaClient.cpp
|
||||||
|
LIBSRCS += pvaClientData.cpp
|
||||||
LIBSRCS += pvaClientPutData.cpp
|
LIBSRCS += pvaClientPutData.cpp
|
||||||
LIBSRCS += pvaClientGetData.cpp
|
LIBSRCS += pvaClientGetData.cpp
|
||||||
LIBSRCS += pvaClientMonitorData.cpp
|
LIBSRCS += pvaClientMonitorData.cpp
|
||||||
@@ -26,9 +30,10 @@ LIBSRCS += pvaClientNTMultiPut.cpp
|
|||||||
LIBSRCS += pvaClientNTMultiData.cpp
|
LIBSRCS += pvaClientNTMultiData.cpp
|
||||||
LIBSRCS += pvaClientNTMultiGet.cpp
|
LIBSRCS += pvaClientNTMultiGet.cpp
|
||||||
LIBSRCS += pvaClientNTMultiMonitor.cpp
|
LIBSRCS += pvaClientNTMultiMonitor.cpp
|
||||||
|
LIBSRCS += pvaClientRPC.cpp
|
||||||
|
|
||||||
pvaClient_LIBS += pvAccess pvData nt Com
|
pvaClient_LIBS += nt
|
||||||
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
|
pvaClient_LIBS += $(EPICS_BASE_PVA_CORE_LIBS)
|
||||||
|
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||||
|
|
||||||
include $(TOP)/configure/RULES
|
include $(TOP)/configure/RULES
|
||||||
|
|
||||||
|
|||||||
+1805
File diff suppressed because it is too large
Load Diff
@@ -12,16 +12,23 @@
|
|||||||
#define PVACLIENTMULTICHANNEL_H
|
#define PVACLIENTMULTICHANNEL_H
|
||||||
|
|
||||||
#ifdef epicsExportSharedSymbols
|
#ifdef epicsExportSharedSymbols
|
||||||
# define pvaClientEpicsExportSharedSymbols
|
# define pvaClientMultiChannelEpicsExportSharedSymbols
|
||||||
# undef epicsExportSharedSymbols
|
# undef epicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
#include <pv/ntmultiChannel.h>
|
#include <pv/ntmultiChannel.h>
|
||||||
#include <pv/createRequest.h>
|
#include <pv/createRequest.h>
|
||||||
|
|
||||||
|
#ifdef pvaClientMultiChannelEpicsExportSharedSymbols
|
||||||
|
# define epicsExportSharedSymbols
|
||||||
|
# undef pvaClientMultiChannelEpicsExportSharedSymbols
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
|
|
||||||
class PvaClientMultiChannel;
|
class PvaClientMultiChannel;
|
||||||
@@ -55,135 +62,122 @@ class epicsShareClass PvaClientMultiChannel :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PvaClientMultiChannel);
|
POINTER_DEFINITIONS(PvaClientMultiChannel);
|
||||||
/** Create a PvaClientMultiChannel.
|
/** @brief Create a PvaClientMultiChannel.
|
||||||
* @param pvaClient The interface to pvaClient.
|
* @param pvaClient The interface to pvaClient.
|
||||||
* @param channelNames The names of the channel..
|
* @param channelNames The names of the channel..
|
||||||
* @param providerName The name of the provider.
|
* @param providerName The name of the provider.
|
||||||
|
* This is also used for the provider for all channels
|
||||||
|
* with providerNames.size less than channelNames.size()
|
||||||
* @param maxNotConnected The maximum number of channels that can be disconnected.
|
* @param maxNotConnected The maximum number of channels that can be disconnected.
|
||||||
|
* @param providerNames The providerName for each Channells
|
||||||
* @return The interface to the PvaClientMultiChannel
|
* @return The interface to the PvaClientMultiChannel
|
||||||
*/
|
*/
|
||||||
static PvaClientMultiChannelPtr create(
|
static PvaClientMultiChannelPtr create(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
epics::pvData::shared_vector<const std::string> const & channelNames,
|
epics::pvData::shared_vector<const std::string> const & channelNames,
|
||||||
std::string const & providerName = "pva",
|
std::string const & providerName = "pva",
|
||||||
size_t maxNotConnected=0
|
size_t maxNotConnected=0,
|
||||||
|
epics::pvData::shared_vector<const std::string> const & providerNames
|
||||||
|
= epics::pvData::shared_vector<const std::string>()
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* @brief Destructor
|
||||||
*/
|
*/
|
||||||
~PvaClientMultiChannel();
|
~PvaClientMultiChannel();
|
||||||
/** Destroy the pvAccess connections.
|
/** @brief Get the channelNames.
|
||||||
*/
|
|
||||||
void destroy();
|
|
||||||
/** Get the channelNames.
|
|
||||||
* @return The names.
|
* @return The names.
|
||||||
*/
|
*/
|
||||||
epics::pvData::shared_vector<const std::string> getChannelNames();
|
epics::pvData::shared_vector<const std::string> getChannelNames();
|
||||||
/** Connect to the channels.
|
/** @brief Connect to the channels.
|
||||||
|
*
|
||||||
* This calls issueConnect and waitConnect.
|
* This calls issueConnect and waitConnect.
|
||||||
* An exception is thrown if connect fails.
|
* An exception is thrown if connect fails.
|
||||||
* @param timeout The time to wait for connecting to the channel.
|
* @param timeout The time to wait for connecting to the channel.
|
||||||
* @return status of request
|
* @return status of request
|
||||||
*/
|
*/
|
||||||
epics::pvData::Status connect(double timeout=5);
|
epics::pvData::Status connect(double timeout=5);
|
||||||
/** Are all channels connected?
|
/** @brief Are all channels connected?
|
||||||
* @return if all are connected.
|
* @return if all are connected.
|
||||||
*/
|
*/
|
||||||
bool allConnected();
|
bool allConnected();
|
||||||
/** Has a connection state change occured?
|
/** @brief Has a connection state change occured?
|
||||||
* @return (true, false) if (at least one, no) channel has changed state.
|
* @return (true, false) if (at least one, no) channel has changed state.
|
||||||
*/
|
*/
|
||||||
bool connectionChange();
|
bool connectionChange();
|
||||||
/** Get the connection state of each channel.
|
/** @brief Get the connection state of each channel.
|
||||||
* @return The state of each channel.
|
* @return The state of each channel.
|
||||||
*/
|
*/
|
||||||
epics::pvData::shared_vector<epics::pvData::boolean> getIsConnected();
|
epics::pvData::shared_vector<epics::pvData::boolean> getIsConnected();
|
||||||
/** Get the pvaClientChannelArray.
|
/** @brief Get the pvaClientChannelArray.
|
||||||
* @return The shared pointer.
|
* @return The shared pointer.
|
||||||
*/
|
*/
|
||||||
PvaClientChannelArray getPvaClientChannelArray();
|
PvaClientChannelArray getPvaClientChannelArray();
|
||||||
/** Get pvaClient.
|
/** @brief Get pvaClient.
|
||||||
* @return The shared pointer.
|
* @return The shared pointer.
|
||||||
*/
|
*/
|
||||||
PvaClientPtr getPvaClient();
|
PvaClientPtr getPvaClient();
|
||||||
/**
|
/**
|
||||||
* create a pvaClientMultiGetDouble
|
* @brief create a pvaClientMultiGetDouble
|
||||||
* @return The interface.
|
* @return The interface.
|
||||||
*/
|
*/
|
||||||
PvaClientMultiGetDoublePtr createGet();
|
PvaClientMultiGetDoublePtr createGet();
|
||||||
/**
|
/**
|
||||||
* create a pvaClientMultiPutDouble
|
* @brief Create a pvaClientMultiPutDouble.
|
||||||
* @return The interface.
|
* @return The interface.
|
||||||
*/
|
*/
|
||||||
PvaClientMultiPutDoublePtr createPut();
|
PvaClientMultiPutDoublePtr createPut();
|
||||||
/**
|
/**
|
||||||
* Create a pvaClientMultiMonitorDouble.
|
* @brief Create a pvaClientMultiMonitorDouble.
|
||||||
* @return The interface.
|
* @return The interface.
|
||||||
*/
|
*/
|
||||||
PvaClientMultiMonitorDoublePtr createMonitor();
|
PvaClientMultiMonitorDoublePtr createMonitor();
|
||||||
/**
|
/**
|
||||||
* Create a pvaClientNTMultiPut.
|
* @brief Create a pvaClientNTMultiPut.
|
||||||
* @return The interface.
|
* @return The interface.
|
||||||
*/
|
*/
|
||||||
PvaClientNTMultiPutPtr createNTPut();
|
PvaClientNTMultiPutPtr createNTPut();
|
||||||
/**
|
/**
|
||||||
* Create a pvaClientNTMultiGet.
|
* @brief Create a pvaClientNTMultiGet;
|
||||||
* This calls the next method with request = "value,alarm,timeStamp"
|
|
||||||
* @return The interface.
|
|
||||||
*/
|
|
||||||
PvaClientNTMultiGetPtr createNTGet();
|
|
||||||
/**
|
|
||||||
* Create a pvaClientNTMultiGet;
|
|
||||||
* @param request The request for each channel.
|
* @param request The request for each channel.
|
||||||
* @return The interface.
|
* @return The interface.
|
||||||
*/
|
*/
|
||||||
PvaClientNTMultiGetPtr createNTGet(std::string const &request);
|
PvaClientNTMultiGetPtr createNTGet(
|
||||||
|
std::string const &request = "field(value,alarm,timeStamp)");
|
||||||
/**
|
/**
|
||||||
* Create a pvaClientNTMultiMonitor.
|
* @brief Create a pvaClientNTMultiPut.
|
||||||
* This calls the next method with request = "value,alarm,timeStamp"
|
|
||||||
* @return The interface.
|
|
||||||
*/
|
|
||||||
PvaClientNTMultiMonitorPtr createNTMonitor();
|
|
||||||
/**
|
|
||||||
* Create a pvaClientNTMultiPut.
|
|
||||||
* @param request The request for each channel.
|
* @param request The request for each channel.
|
||||||
* @return The interface.
|
* @return The interface.
|
||||||
*/
|
*/
|
||||||
PvaClientNTMultiMonitorPtr createNTMonitor(std::string const &request);
|
PvaClientNTMultiMonitorPtr createNTMonitor(
|
||||||
/** Get the shared pointer to self.
|
std::string const &request= "field(value,alarm,timeStamp)");
|
||||||
* @return The shared pointer.
|
|
||||||
*/
|
|
||||||
PvaClientMultiChannelPtr getPtrSelf()
|
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
PvaClientMultiChannel(
|
PvaClientMultiChannel(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
epics::pvData::shared_vector<const std::string> const & channelName,
|
epics::pvData::shared_vector<const std::string> const & channelNames,
|
||||||
std::string const & providerName,
|
std::string const & providerName,
|
||||||
size_t maxNotConnected);
|
size_t maxNotConnected,
|
||||||
|
epics::pvData::shared_vector<const std::string> const & providerNames);
|
||||||
void checkConnected();
|
void checkConnected();
|
||||||
|
|
||||||
PvaClientPtr pvaClient;
|
PvaClientPtr pvaClient;
|
||||||
epics::pvData::shared_vector<const std::string> channelName;
|
epics::pvData::shared_vector<const std::string> channelNames;
|
||||||
std::string providerName;
|
std::string providerName;
|
||||||
size_t maxNotConnected;
|
size_t maxNotConnected;
|
||||||
|
epics::pvData::shared_vector<const std::string> const & providerNames;
|
||||||
|
|
||||||
size_t numChannel;
|
size_t numChannel;
|
||||||
|
size_t numProviderNames;
|
||||||
epics::pvData::Mutex mutex;
|
epics::pvData::Mutex mutex;
|
||||||
|
|
||||||
size_t numConnected;
|
size_t numConnected;
|
||||||
|
bool firstConnect;
|
||||||
PvaClientChannelArray pvaClientChannelArray;
|
PvaClientChannelArray pvaClientChannelArray;
|
||||||
epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
|
epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
|
||||||
epics::pvData::CreateRequest::shared_pointer createRequest;
|
epics::pvData::CreateRequest::shared_pointer createRequest;
|
||||||
bool isDestroyed;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This provides channelGet to multiple channels where each channel has a numeric scalar value field.
|
* @brief Provides channelGet to multiple channels where each channel has a numeric scalar value field.
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PvaClientMultiGetDouble :
|
class epicsShareClass PvaClientMultiGetDouble :
|
||||||
public std::tr1::enable_shared_from_this<PvaClientMultiGetDouble>
|
public std::tr1::enable_shared_from_this<PvaClientMultiGetDouble>
|
||||||
@@ -191,38 +185,25 @@ class epicsShareClass PvaClientMultiGetDouble :
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PvaClientMultiGetDouble);
|
POINTER_DEFINITIONS(PvaClientMultiGetDouble);
|
||||||
|
protected:
|
||||||
/**
|
|
||||||
* Factory method that creates a PvaClientMultiGetDouble.
|
|
||||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
|
||||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
|
||||||
* @return The interface.
|
|
||||||
*/
|
|
||||||
static PvaClientMultiGetDoublePtr create(
|
static PvaClientMultiGetDoublePtr create(
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray);
|
PvaClientChannelArray const &pvaClientChannelArray);
|
||||||
|
friend class PvaClientMultiChannel;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
~PvaClientMultiGetDouble();
|
~PvaClientMultiGetDouble();
|
||||||
|
|
||||||
/** Destroy the pvAccess connection.
|
|
||||||
*/
|
|
||||||
void destroy();
|
|
||||||
/**
|
/**
|
||||||
* Create a channelGet for each channel.
|
* @brief Create a channelGet for each channel.
|
||||||
*/
|
*/
|
||||||
void connect();
|
void connect();
|
||||||
/**
|
/**
|
||||||
* get the data.
|
* @brief Get the data.
|
||||||
* @return The double[] where each element is the value field of the corresponding channel.
|
* @return The double[] where each element is the value field of the corresponding channel.
|
||||||
*/
|
*/
|
||||||
epics::pvData::shared_vector<double> get();
|
epics::pvData::shared_vector<double> get();
|
||||||
/** Get the shared pointer to self.
|
|
||||||
* @return The shared pointer.
|
|
||||||
*/
|
|
||||||
PvaClientMultiGetDoublePtr getPtrSelf()
|
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
PvaClientMultiGetDouble(
|
PvaClientMultiGetDouble(
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
@@ -232,15 +213,14 @@ private:
|
|||||||
PvaClientChannelArray pvaClientChannelArray;
|
PvaClientChannelArray pvaClientChannelArray;
|
||||||
size_t nchannel;
|
size_t nchannel;
|
||||||
epics::pvData::Mutex mutex;
|
epics::pvData::Mutex mutex;
|
||||||
|
|
||||||
epics::pvData::shared_vector<double> doubleValue;
|
epics::pvData::shared_vector<double> doubleValue;
|
||||||
std::vector<PvaClientGetPtr> pvaClientGet;
|
std::vector<PvaClientGetPtr> pvaClientGet;
|
||||||
bool isGetConnected;
|
bool isGetConnected;
|
||||||
bool isDestroyed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This provides channelPut to multiple channels where each channel has a numeric scalar value field.
|
* @brief Provides channelPut to multiple channels where each channel has a numeric scalar value field.
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PvaClientMultiPutDouble :
|
class epicsShareClass PvaClientMultiPutDouble :
|
||||||
public std::tr1::enable_shared_from_this<PvaClientMultiPutDouble>
|
public std::tr1::enable_shared_from_this<PvaClientMultiPutDouble>
|
||||||
@@ -248,36 +228,25 @@ class epicsShareClass PvaClientMultiPutDouble :
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PvaClientMultiPutDouble);
|
POINTER_DEFINITIONS(PvaClientMultiPutDouble);
|
||||||
|
protected:
|
||||||
/**
|
|
||||||
* Factory method that creates a PvaClientMultiPutDouble.
|
|
||||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
|
||||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
|
||||||
* @return The interface.
|
|
||||||
*/
|
|
||||||
static PvaClientMultiPutDoublePtr create(
|
static PvaClientMultiPutDoublePtr create(
|
||||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray);
|
PvaClientChannelArray const &pvaClientChannelArray);
|
||||||
~PvaClientMultiPutDouble();
|
friend class PvaClientMultiChannel;
|
||||||
|
public:
|
||||||
/** Destroy the pvAccess connection.
|
/**
|
||||||
|
* @brief Destructor
|
||||||
*/
|
*/
|
||||||
void destroy();
|
~PvaClientMultiPutDouble();
|
||||||
/**
|
/**
|
||||||
* Create a channelPut for each channel.
|
* @brief Create a channelPut for each channel.
|
||||||
*/
|
*/
|
||||||
void connect();
|
void connect();
|
||||||
/** put data to each channel as a double
|
/** @brief put data to each channel as a double
|
||||||
* @param data The array of data for each channel.
|
* @param data The array of data for each channel.
|
||||||
*/
|
*/
|
||||||
void put(epics::pvData::shared_vector<double> const &data);
|
void put(epics::pvData::shared_vector<double> const &data);
|
||||||
/** Get the shared pointer to self.
|
|
||||||
* @return The shared pointer.
|
|
||||||
*/
|
|
||||||
PvaClientMultiPutDoublePtr getPtrSelf()
|
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
PvaClientMultiPutDouble(
|
PvaClientMultiPutDouble(
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
@@ -290,11 +259,10 @@ private:
|
|||||||
|
|
||||||
std::vector<PvaClientPutPtr> pvaClientPut;
|
std::vector<PvaClientPutPtr> pvaClientPut;
|
||||||
bool isPutConnected;
|
bool isPutConnected;
|
||||||
bool isDestroyed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This provides a monitor to multiple channels where each channel has a numeric scalar value field.
|
* @brief Provides a monitor to multiple channels where each channel has a numeric scalar value field.
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PvaClientMultiMonitorDouble :
|
class epicsShareClass PvaClientMultiMonitorDouble :
|
||||||
public std::tr1::enable_shared_from_this<PvaClientMultiMonitorDouble>
|
public std::tr1::enable_shared_from_this<PvaClientMultiMonitorDouble>
|
||||||
@@ -302,50 +270,40 @@ class epicsShareClass PvaClientMultiMonitorDouble :
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
|
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
|
||||||
|
protected:
|
||||||
/**
|
|
||||||
* Factory method that creates a PvaClientMultiMonitorDouble.
|
|
||||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
|
||||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
|
||||||
* @return The interface.
|
|
||||||
*/
|
|
||||||
static PvaClientMultiMonitorDoublePtr create(
|
static PvaClientMultiMonitorDoublePtr create(
|
||||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray);
|
PvaClientChannelArray const &pvaClientChannelArray);
|
||||||
|
friend class PvaClientMultiChannel;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
~PvaClientMultiMonitorDouble();
|
~PvaClientMultiMonitorDouble();
|
||||||
|
|
||||||
/** Destroy the pvAccess connection.
|
|
||||||
*/
|
|
||||||
void destroy();
|
|
||||||
/**
|
/**
|
||||||
* Create a channel monitor for each channel.
|
* @brief Connect a channel monitor for each channel.
|
||||||
*/
|
*/
|
||||||
void connect();
|
void connect();
|
||||||
/**
|
/**
|
||||||
* poll each channel.
|
* @brief Poll each channel.
|
||||||
|
*
|
||||||
* If any has new data it is used to update the double[].
|
* If any has new data it is used to update the double[].
|
||||||
* @return (false,true) if (no, at least one) value was updated.
|
* @return (false,true) if (no, at least one) value was updated.
|
||||||
*/
|
*/
|
||||||
bool poll();
|
bool poll();
|
||||||
/**
|
/**
|
||||||
* Wait until poll returns true.
|
* @brief Wait until poll returns true.
|
||||||
* @param waitForEvent The time to keep trying.
|
* @param secondsToWait The time to keep trying.
|
||||||
* A thread sleep of .1 seconds occurs between each call to poll.
|
* A thread sleep of .1 seconds occurs between each call to poll.
|
||||||
* @return (false,true) if (timeOut, poll returned true).
|
* @return (false,true) if (timeOut, poll returned true).
|
||||||
*/
|
*/
|
||||||
bool waitEvent(double waitForEvent);
|
bool waitEvent(double secondsToWait);
|
||||||
/**
|
/**
|
||||||
* get the data.
|
* get the data.
|
||||||
* @return The double[] where each element is the value field of the corresponding channel.
|
* @return The double[] where each element is the value field of the corresponding channel.
|
||||||
*/
|
*/
|
||||||
epics::pvData::shared_vector<double> get();
|
epics::pvData::shared_vector<double> get();
|
||||||
/** Monitor the shared pointer to self.
|
|
||||||
* @return The shared pointer.
|
|
||||||
*/
|
|
||||||
PvaClientMultiMonitorDoublePtr getPtrSelf()
|
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
PvaClientMultiMonitorDouble(
|
PvaClientMultiMonitorDouble(
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
@@ -359,11 +317,10 @@ private:
|
|||||||
epics::pvData::shared_vector<double> doubleValue;
|
epics::pvData::shared_vector<double> doubleValue;
|
||||||
std::vector<PvaClientMonitorPtr> pvaClientMonitor;
|
std::vector<PvaClientMonitorPtr> pvaClientMonitor;
|
||||||
bool isMonitorConnected;
|
bool isMonitorConnected;
|
||||||
bool isDestroyed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This provides channelGet to multiple channels where the value field of each channel is presented as a union.
|
* @brief Provides channelGet to multiple channels where the value field of each channel is presented as a union.
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PvaClientNTMultiGet :
|
class epicsShareClass PvaClientNTMultiGet :
|
||||||
public std::tr1::enable_shared_from_this<PvaClientNTMultiGet>
|
public std::tr1::enable_shared_from_this<PvaClientNTMultiGet>
|
||||||
@@ -371,43 +328,33 @@ class epicsShareClass PvaClientNTMultiGet :
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PvaClientNTMultiGet);
|
POINTER_DEFINITIONS(PvaClientNTMultiGet);
|
||||||
/**
|
protected:
|
||||||
* Factory method that creates a PvaClientNTMultiGet.
|
|
||||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
|
||||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
|
||||||
* @param pvRequest The pvRequest for each channel.
|
|
||||||
* @return The interface.
|
|
||||||
*/
|
|
||||||
static PvaClientNTMultiGetPtr create(
|
static PvaClientNTMultiGetPtr create(
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
epics::pvData::PVStructurePtr const & pvRequest);
|
epics::pvData::PVStructurePtr const & pvRequest);
|
||||||
|
friend class PvaClientMultiChannel;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
~PvaClientNTMultiGet();
|
~PvaClientNTMultiGet();
|
||||||
|
|
||||||
/** Destroy the pvAccess connection.
|
|
||||||
*/
|
|
||||||
void destroy();
|
|
||||||
/**
|
/**
|
||||||
* Create a channelGet for each channel.
|
* @brief Connect a channelGet for each channel.
|
||||||
*/
|
*/
|
||||||
void connect();
|
void connect();
|
||||||
/**
|
/**
|
||||||
* get data for each channel.
|
* @brief Get each channel.
|
||||||
|
*
|
||||||
|
* @param valueOnly use only value for union.
|
||||||
*/
|
*/
|
||||||
void get();
|
void get(bool valueOnly = true);
|
||||||
/**
|
/**
|
||||||
* get the data.
|
* @brief Get the data from the last get.
|
||||||
* @return the pvaClientNTMultiData.
|
* @return the pvaClientNTMultiData.
|
||||||
*/
|
*/
|
||||||
PvaClientNTMultiDataPtr getData();
|
PvaClientNTMultiDataPtr getData();
|
||||||
/** Get the shared pointer to self.
|
|
||||||
* @return The shared pointer.
|
|
||||||
*/
|
|
||||||
PvaClientNTMultiGetPtr getPtrSelf()
|
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
PvaClientNTMultiGet(
|
PvaClientNTMultiGet(
|
||||||
epics::pvData::UnionConstPtr const & u,
|
epics::pvData::UnionConstPtr const & u,
|
||||||
@@ -420,16 +367,14 @@ private:
|
|||||||
epics::pvData::PVStructurePtr pvRequest;
|
epics::pvData::PVStructurePtr pvRequest;
|
||||||
size_t nchannel;
|
size_t nchannel;
|
||||||
epics::pvData::Mutex mutex;
|
epics::pvData::Mutex mutex;
|
||||||
|
|
||||||
|
|
||||||
PvaClientNTMultiDataPtr pvaClientNTMultiData;
|
PvaClientNTMultiDataPtr pvaClientNTMultiData;
|
||||||
std::vector<PvaClientGetPtr> pvaClientGet;
|
std::vector<PvaClientGetPtr> pvaClientGet;
|
||||||
bool isConnected;
|
bool isConnected;
|
||||||
bool isDestroyed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This provides channelPut to multiple channels where the value field of each channel is presented as a union.
|
* @brief Provides channelPut to multiple channels where the value field of each channel is presented as a union.
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PvaClientNTMultiPut :
|
class epicsShareClass PvaClientNTMultiPut :
|
||||||
public std::tr1::enable_shared_from_this<PvaClientNTMultiPut>
|
public std::tr1::enable_shared_from_this<PvaClientNTMultiPut>
|
||||||
@@ -437,40 +382,30 @@ class epicsShareClass PvaClientNTMultiPut :
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PvaClientNTMultiPut);
|
POINTER_DEFINITIONS(PvaClientNTMultiPut);
|
||||||
/**
|
protected:
|
||||||
* Factory method that creates a PvaClientNTMultiPut.
|
|
||||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
|
||||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
|
||||||
* @return The interface.
|
|
||||||
*/
|
|
||||||
static PvaClientNTMultiPutPtr create(
|
static PvaClientNTMultiPutPtr create(
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray);
|
PvaClientChannelArray const &pvaClientChannelArray);
|
||||||
~PvaClientNTMultiPut();
|
friend class PvaClientMultiChannel;
|
||||||
|
public:
|
||||||
/** Destroy the pvAccess connection.
|
/**
|
||||||
|
* @brief Destructor
|
||||||
*/
|
*/
|
||||||
void destroy();
|
~PvaClientNTMultiPut();
|
||||||
/**
|
/**
|
||||||
* Create a channelPut for each channel.
|
* @brief Connect a channelPut for each channel.
|
||||||
*/
|
*/
|
||||||
void connect();
|
void connect();
|
||||||
/**
|
/**
|
||||||
* get the value field of each channel as a union.
|
* @brief Get the value field of each channel as a union.
|
||||||
* @return A shared vector of union.
|
* @return A shared vector of union.
|
||||||
*/
|
*/
|
||||||
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
|
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
|
||||||
/**
|
/**
|
||||||
* put the data to each channel.
|
* @brief Issue a put for each channel.
|
||||||
' */
|
|
||||||
void put();
|
|
||||||
/** Get the shared pointer to self.
|
|
||||||
* @return The shared pointer.
|
|
||||||
*/
|
*/
|
||||||
PvaClientNTMultiPutPtr getPtrSelf()
|
void put();
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
PvaClientNTMultiPut(
|
PvaClientNTMultiPut(
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
@@ -485,11 +420,10 @@ private:
|
|||||||
epics::pvData::shared_vector<epics::pvData::PVFieldPtr> value;
|
epics::pvData::shared_vector<epics::pvData::PVFieldPtr> value;
|
||||||
std::vector<PvaClientPutPtr> pvaClientPut;
|
std::vector<PvaClientPutPtr> pvaClientPut;
|
||||||
bool isConnected;
|
bool isConnected;
|
||||||
bool isDestroyed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This provides channel monitor to multiple channels where the value field of each channel is presented as a union.
|
* @brief Provides channel monitor to multiple channels where the value field of each channel is presented as a union.
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PvaClientNTMultiMonitor :
|
class epicsShareClass PvaClientNTMultiMonitor :
|
||||||
public std::tr1::enable_shared_from_this<PvaClientNTMultiMonitor>
|
public std::tr1::enable_shared_from_this<PvaClientNTMultiMonitor>
|
||||||
@@ -497,51 +431,42 @@ class epicsShareClass PvaClientNTMultiMonitor :
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
|
POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
|
||||||
/**
|
protected:
|
||||||
* Factory method that creates a PvaClientNTMultiMonitor.
|
|
||||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
|
||||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
|
||||||
* @param pvRequest The pvRequest for each channel.
|
|
||||||
* @return The interface.
|
|
||||||
*/
|
|
||||||
static PvaClientNTMultiMonitorPtr create(
|
static PvaClientNTMultiMonitorPtr create(
|
||||||
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
epics::pvData::PVStructurePtr const & pvRequest);
|
epics::pvData::PVStructurePtr const & pvRequest);
|
||||||
|
friend class PvaClientMultiChannel;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
~PvaClientNTMultiMonitor();
|
~PvaClientNTMultiMonitor();
|
||||||
|
|
||||||
/** Destroy the pvAccess connection.
|
|
||||||
*/
|
|
||||||
void destroy();
|
|
||||||
/**
|
/**
|
||||||
* Create a channel monitor for each channel.
|
* @brief Connect to a channel monitor for each channel.
|
||||||
*/
|
*/
|
||||||
void connect();
|
void connect();
|
||||||
/**
|
/**
|
||||||
* poll each channel.
|
* @brief Poll each channel.
|
||||||
|
*
|
||||||
|
* @param valueOnly use only value for union.
|
||||||
* If any has new data it is used to update the double[].
|
* If any has new data it is used to update the double[].
|
||||||
* @return (false,true) if (no, at least one) value was updated.
|
* @return (false,true) if (no, at least one) value was updated.
|
||||||
*/
|
*/
|
||||||
bool poll();
|
bool poll(bool valueOnly = true);
|
||||||
/**
|
/**
|
||||||
* Wait until poll returns true.
|
* @brief Wait until poll returns true.
|
||||||
* @param waitForEvent The time to keep trying.
|
* @param secondsToWait The time to keep trying.
|
||||||
* A thread sleep of .1 seconds occurs between each call to poll.
|
* A thread sleep of .1 seconds occurs between each call to poll.
|
||||||
* @return (false,true) if (timeOut, poll returned true).
|
* @return (false,true) if (timeOut, poll returned true).
|
||||||
*/
|
*/
|
||||||
bool waitEvent(double waitForEvent);
|
bool waitEvent(double secondsToWait);
|
||||||
/**
|
/**
|
||||||
* get the data.
|
* @brief Get the data for the last successfull poll.
|
||||||
* @return the pvaClientNTMultiData.
|
* @return the pvaClientNTMultiData.
|
||||||
*/
|
*/
|
||||||
PvaClientNTMultiDataPtr getData();
|
PvaClientNTMultiDataPtr getData();
|
||||||
/** Monitor the shared pointer to self.
|
|
||||||
* @return The shared pointer.
|
|
||||||
*/
|
|
||||||
PvaClientNTMultiMonitorPtr getPtrSelf()
|
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
PvaClientNTMultiMonitor(
|
PvaClientNTMultiMonitor(
|
||||||
epics::pvData::UnionConstPtr const & u,
|
epics::pvData::UnionConstPtr const & u,
|
||||||
@@ -557,11 +482,10 @@ private:
|
|||||||
PvaClientNTMultiDataPtr pvaClientNTMultiData;
|
PvaClientNTMultiDataPtr pvaClientNTMultiData;
|
||||||
std::vector<PvaClientMonitorPtr> pvaClientMonitor;
|
std::vector<PvaClientMonitorPtr> pvaClientMonitor;
|
||||||
bool isConnected;
|
bool isConnected;
|
||||||
bool isDestroyed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor.
|
* @brief Provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor.
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PvaClientNTMultiData :
|
class epicsShareClass PvaClientNTMultiData :
|
||||||
public std::tr1::enable_shared_from_this<PvaClientNTMultiData>
|
public std::tr1::enable_shared_from_this<PvaClientNTMultiData>
|
||||||
@@ -569,64 +493,43 @@ class epicsShareClass PvaClientNTMultiData :
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PvaClientNTMultiData);
|
POINTER_DEFINITIONS(PvaClientNTMultiData);
|
||||||
/**
|
|
||||||
* Factory method that creates a PvaClientNTMultiData.
|
|
||||||
* Normally only called by PvaClientNTMultiGet and PvaClientNTMultiMonitor.
|
|
||||||
* @param u The union interface for the value field of each channel.
|
|
||||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
|
||||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
|
||||||
* @param pvRequest The pvRequest for each channel.
|
|
||||||
*/
|
|
||||||
static PvaClientNTMultiDataPtr create(
|
|
||||||
epics::pvData::UnionConstPtr const & u,
|
|
||||||
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
|
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
|
||||||
epics::pvData::PVStructurePtr const & pvRequest);
|
|
||||||
~PvaClientNTMultiData();
|
~PvaClientNTMultiData();
|
||||||
/** Destroy the pvAccess connection.
|
/**
|
||||||
*/
|
* @brief Get the number of channels.
|
||||||
void destroy();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of channels.
|
|
||||||
* @return The number of channels.
|
* @return The number of channels.
|
||||||
*/
|
*/
|
||||||
size_t getNumber();
|
size_t getNumber();
|
||||||
|
/**
|
||||||
/**
|
* @brief Get the time when the last get was made.
|
||||||
* Set the timeStamp base for computing deltaTimes.
|
|
||||||
*/
|
|
||||||
void startDeltaTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update NTMultiChannel fields.
|
|
||||||
*/
|
|
||||||
void endDeltaTime();
|
|
||||||
/**
|
|
||||||
* Get the time when the last get was made.
|
|
||||||
* @return The timeStamp.
|
* @return The timeStamp.
|
||||||
*/
|
*/
|
||||||
epics::pvData::TimeStamp getTimeStamp();
|
epics::pvData::TimeStamp getTimeStamp();
|
||||||
/**
|
/**
|
||||||
* Get the NTMultiChannel.
|
* @brief Get the NTMultiChannel.
|
||||||
* @return The value.
|
* @return The value.
|
||||||
*/
|
*/
|
||||||
epics::nt::NTMultiChannelPtr getNTMultiChannel();
|
epics::nt::NTMultiChannelPtr getNTMultiChannel();
|
||||||
/** Get the shared pointer to self.
|
/**
|
||||||
* @return The shared pointer.
|
* @brief Get channel change flags.
|
||||||
|
* @return Array of boolean fields that are set to true if corresponding channel changed
|
||||||
*/
|
*/
|
||||||
PvaClientNTMultiDataPtr getPtrSelf()
|
epics::pvData::shared_vector<epics::pvData::boolean> getChannelChangeFlags();
|
||||||
{
|
protected:
|
||||||
return shared_from_this();
|
static PvaClientNTMultiDataPtr create(
|
||||||
}
|
epics::pvData::UnionConstPtr const & u,
|
||||||
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
|
epics::pvData::PVStructurePtr const & pvRequest);
|
||||||
|
void startDeltaTime();
|
||||||
|
void endDeltaTime(bool valueOnly = true);
|
||||||
|
friend class PvaClientNTMultiGet;
|
||||||
|
friend class PvaClientNTMultiMonitor;
|
||||||
private:
|
private:
|
||||||
PvaClientNTMultiData(
|
PvaClientNTMultiData(
|
||||||
epics::pvData::UnionConstPtr const & u,
|
epics::pvData::UnionConstPtr const & u,
|
||||||
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
|
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
epics::pvData::PVStructurePtr const & pvRequest);
|
epics::pvData::PVStructurePtr const & pvRequest);
|
||||||
void setStructure(epics::pvData::StructureConstPtr const & structure,size_t index);
|
|
||||||
void setPVStructure(
|
void setPVStructure(
|
||||||
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
|
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
|
||||||
|
|
||||||
@@ -638,8 +541,8 @@ private:
|
|||||||
std::vector<epics::pvData::PVStructurePtr> topPVStructure;
|
std::vector<epics::pvData::PVStructurePtr> topPVStructure;
|
||||||
bool gotAlarm;
|
bool gotAlarm;
|
||||||
bool gotTimeStamp;
|
bool gotTimeStamp;
|
||||||
bool isDestroyed;
|
|
||||||
|
|
||||||
|
epics::pvData::shared_vector<epics::pvData::boolean> changeFlags;
|
||||||
epics::pvData::StructureConstPtr ntMultiChannelStructure;
|
epics::pvData::StructureConstPtr ntMultiChannelStructure;
|
||||||
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
|
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
|
||||||
epics::pvData::shared_vector<epics::pvData::int32> severity;
|
epics::pvData::shared_vector<epics::pvData::int32> severity;
|
||||||
@@ -651,19 +554,9 @@ private:
|
|||||||
epics::pvData::Alarm alarm;
|
epics::pvData::Alarm alarm;
|
||||||
epics::pvData::TimeStamp timeStamp;;
|
epics::pvData::TimeStamp timeStamp;;
|
||||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||||
friend class PvaClientNTMultiGet;
|
|
||||||
friend class PvaClientNTMultiPut;
|
|
||||||
friend class PvaClientNTMultiMonitor;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#endif /* PVACLIENTMULTICHANNEL_H */
|
#endif /* PVACLIENTMULTICHANNEL_H */
|
||||||
|
|
||||||
/** @page Overview Documentation
|
|
||||||
*
|
|
||||||
* <a href = "../pvaClientOverview.html">pvaClientOverview.html</a>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
+88
-91
@@ -9,86 +9,40 @@
|
|||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
#include <pv/createRequest.h>
|
#include <pv/createRequest.h>
|
||||||
#include <pv/clientFactory.h>
|
#include <pv/clientFactory.h>
|
||||||
#include <pv/caProvider.h>
|
#include <pv/caProvider.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::pvAccess::ca;
|
using namespace epics::pvAccess::ca;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
|
||||||
static const string pvaClientName = "pvaClient";
|
|
||||||
static const string defaultProvider = "pva";
|
|
||||||
static UnionConstPtr variantUnion = fieldCreate->createVariantUnion();
|
|
||||||
|
|
||||||
namespace pvaClientPvt {
|
class epicsShareClass PvaClientChannelCache
|
||||||
|
|
||||||
static size_t numberPvaClient = 0;
|
|
||||||
static bool firstTime = true;
|
|
||||||
static Mutex mutex;
|
|
||||||
|
|
||||||
class StartStopClientFactory {
|
|
||||||
public:
|
|
||||||
static void PvaClientBeingConstructed()
|
|
||||||
{
|
|
||||||
bool saveFirst = false;
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
++numberPvaClient;
|
|
||||||
saveFirst = firstTime;
|
|
||||||
firstTime = false;
|
|
||||||
}
|
|
||||||
if(saveFirst) {
|
|
||||||
ClientFactory::start();
|
|
||||||
CAClientFactory::start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PvaClientBeingDestroyed() {
|
|
||||||
size_t numLeft = 0;
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
--numberPvaClient;
|
|
||||||
numLeft = numberPvaClient;
|
|
||||||
}
|
|
||||||
if(numLeft<=0) {
|
|
||||||
ClientFactory::stop();
|
|
||||||
CAClientFactory::stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace pvaClientPvt
|
|
||||||
|
|
||||||
class PvaClientChannelCache
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PvaClientChannelCache(){}
|
PvaClientChannelCache(){}
|
||||||
~PvaClientChannelCache(){
|
~PvaClientChannelCache(){
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout << "PvaClientChannelCache::~PvaClientChannelCache\n";
|
||||||
}
|
}
|
||||||
void destroy() {
|
|
||||||
pvaClientChannelMap.clear();
|
|
||||||
}
|
|
||||||
PvaClientChannelPtr getChannel(
|
PvaClientChannelPtr getChannel(
|
||||||
string const & channelName,
|
string const & channelName,
|
||||||
string const & providerName);
|
string const & providerName);
|
||||||
void addChannel(PvaClientChannelPtr const & pvaClientChannel);
|
void addChannel(PvaClientChannelPtr const & pvaClientChannel);
|
||||||
void removeChannel(string const & channelName,string const & providerName);
|
|
||||||
void showCache();
|
void showCache();
|
||||||
size_t cacheSize();
|
size_t cacheSize();
|
||||||
private:
|
private:
|
||||||
map<string,PvaClientChannelPtr> pvaClientChannelMap;
|
map<string,PvaClientChannelPtr> pvaClientChannelMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
PvaClientChannelPtr PvaClientChannelCache::getChannel(
|
PvaClientChannelPtr PvaClientChannelCache::getChannel(
|
||||||
string const & channelName,
|
string const & channelName,
|
||||||
string const & providerName)
|
string const & providerName)
|
||||||
@@ -104,17 +58,12 @@ void PvaClientChannelCache::addChannel(PvaClientChannelPtr const & pvaClientChan
|
|||||||
Channel::shared_pointer channel = pvaClientChannel->getChannel();
|
Channel::shared_pointer channel = pvaClientChannel->getChannel();
|
||||||
string name = channel->getChannelName()
|
string name = channel->getChannelName()
|
||||||
+ channel->getProvider()->getProviderName();
|
+ channel->getProvider()->getProviderName();
|
||||||
pvaClientChannelMap.insert(std::pair<string,PvaClientChannelPtr>(
|
|
||||||
name,pvaClientChannel));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientChannelCache::removeChannel(
|
|
||||||
string const & channelName,
|
|
||||||
string const & providerName)
|
|
||||||
{
|
|
||||||
string name = channelName + providerName;
|
|
||||||
map<string,PvaClientChannelPtr>::iterator iter = pvaClientChannelMap.find(name);
|
map<string,PvaClientChannelPtr>::iterator iter = pvaClientChannelMap.find(name);
|
||||||
if(iter!=pvaClientChannelMap.end()) pvaClientChannelMap.erase(iter);
|
if(iter!=pvaClientChannelMap.end()) {
|
||||||
|
throw std::runtime_error("pvaClientChannelCache::addChannel channel already cached");
|
||||||
|
}
|
||||||
|
pvaClientChannelMap.insert(std::pair<string,PvaClientChannelPtr>(
|
||||||
|
name,pvaClientChannel));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientChannelCache::showCache()
|
void PvaClientChannelCache::showCache()
|
||||||
@@ -127,10 +76,8 @@ void PvaClientChannelCache::showCache()
|
|||||||
string channelName = channel->getChannelName();
|
string channelName = channel->getChannelName();
|
||||||
string providerName = channel->getProvider()->getProviderName();
|
string providerName = channel->getProvider()->getProviderName();
|
||||||
cout << "channel " << channelName << " provider " << providerName << endl;
|
cout << "channel " << channelName << " provider " << providerName << endl;
|
||||||
cout << " get and put cacheSize " << pvaChannel->cacheSize() << endl;
|
|
||||||
pvaChannel->showCache();
|
pvaChannel->showCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PvaClientChannelCache::cacheSize()
|
size_t PvaClientChannelCache::cacheSize()
|
||||||
@@ -139,35 +86,82 @@ size_t PvaClientChannelCache::cacheSize()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace epics::pvaClient::pvaClientPvt;
|
// MSVC doesn't like making this a class static data member:
|
||||||
|
static bool debug = 0;
|
||||||
|
|
||||||
PvaClientPtr PvaClient::create()
|
void PvaClient::setDebug(bool value)
|
||||||
{
|
{
|
||||||
PvaClientPtr xx(new PvaClient());
|
debug = value;
|
||||||
StartStopClientFactory::PvaClientBeingConstructed();
|
|
||||||
return xx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PvaClient::getDebug()
|
||||||
PvaClient::PvaClient()
|
|
||||||
: pvaClientChannelCache(new PvaClientChannelCache()),
|
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
PvaClientPtr PvaClient::get(std::string const & providerNames)
|
||||||
|
{
|
||||||
|
static PvaClientPtr master;
|
||||||
|
static Mutex mutex;
|
||||||
|
Lock xx(mutex);
|
||||||
|
if(!master) {
|
||||||
|
master = PvaClientPtr(new PvaClient(providerNames));
|
||||||
|
}
|
||||||
|
return master;
|
||||||
|
}
|
||||||
|
|
||||||
|
PvaClientPtr PvaClient::create() {return get();}
|
||||||
|
|
||||||
|
PvaClient::PvaClient(std::string const & providerNames)
|
||||||
|
: pvaClientChannelCache(new PvaClientChannelCache()),
|
||||||
|
pvaStarted(false),
|
||||||
|
caStarted(false),
|
||||||
|
channelRegistry(ChannelProviderRegistry::clients())
|
||||||
|
{
|
||||||
|
stringstream ss(providerNames);
|
||||||
|
string providerName;
|
||||||
|
if(getDebug()) {
|
||||||
|
cout<< "PvaClient::PvaClient()\n";
|
||||||
|
}
|
||||||
|
while (getline(ss, providerName, ' '))
|
||||||
|
{
|
||||||
|
if(providerName=="pva") {
|
||||||
|
if(getDebug()) {
|
||||||
|
cout<< "calling ClientFactory::start()\n";
|
||||||
|
}
|
||||||
|
ClientFactory::start();
|
||||||
|
pvaStarted = true;
|
||||||
|
} else if(providerName=="ca") {
|
||||||
|
if(getDebug()) {
|
||||||
|
cout<< "calling CAClientFactory::start()\n";
|
||||||
|
}
|
||||||
|
CAClientFactory::start();
|
||||||
|
caStarted = true;
|
||||||
|
} else {
|
||||||
|
if(!channelRegistry->getProvider(providerName)) {
|
||||||
|
cerr << "PvaClient::get provider " << providerName << " not known" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClient::~PvaClient() {
|
PvaClient::~PvaClient() {
|
||||||
destroy();
|
if(getDebug()) {
|
||||||
}
|
cout<< "PvaClient::~PvaClient()\n"
|
||||||
|
<< "pvaChannel cache:\n";
|
||||||
void PvaClient::destroy()
|
showCache();
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
}
|
||||||
pvaClientChannelCache.reset();
|
if(pvaStarted){
|
||||||
StartStopClientFactory::PvaClientBeingDestroyed();
|
if(getDebug()) cout<< "calling ClientFactory::stop()\n";
|
||||||
|
ClientFactory::stop();
|
||||||
|
if(getDebug()) cout<< "after calling ClientFactory::stop()\n";
|
||||||
|
}
|
||||||
|
if(caStarted) {
|
||||||
|
if(getDebug()) cout<< "calling CAClientFactory::stop()\n";
|
||||||
|
CAClientFactory::stop();
|
||||||
|
if(getDebug()) cout<< "after calling CAClientFactory::stop()\n";
|
||||||
|
}
|
||||||
|
channelRegistry.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
string PvaClient:: getRequesterName()
|
string PvaClient:: getRequesterName()
|
||||||
@@ -197,7 +191,7 @@ PvaClientChannelPtr PvaClient::channel(
|
|||||||
std::string const & providerName,
|
std::string const & providerName,
|
||||||
double timeOut)
|
double timeOut)
|
||||||
{
|
{
|
||||||
PvaClientChannelPtr pvaClientChannel =
|
PvaClientChannelPtr pvaClientChannel =
|
||||||
pvaClientChannelCache->getChannel(channelName,providerName);
|
pvaClientChannelCache->getChannel(channelName,providerName);
|
||||||
if(pvaClientChannel) return pvaClientChannel;
|
if(pvaClientChannel) return pvaClientChannel;
|
||||||
pvaClientChannel = createChannel(channelName,providerName);
|
pvaClientChannel = createChannel(channelName,providerName);
|
||||||
@@ -208,7 +202,7 @@ PvaClientChannelPtr PvaClient::channel(
|
|||||||
|
|
||||||
PvaClientChannelPtr PvaClient::createChannel(string const & channelName, string const & providerName)
|
PvaClientChannelPtr PvaClient::createChannel(string const & channelName, string const & providerName)
|
||||||
{
|
{
|
||||||
return PvaClientChannel::create(getPtrSelf(),channelName,providerName);
|
return PvaClientChannel::create(shared_from_this(),channelName,providerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClient::setRequester(RequesterPtr const & requester)
|
void PvaClient::setRequester(RequesterPtr const & requester)
|
||||||
@@ -218,12 +212,16 @@ void PvaClient::setRequester(RequesterPtr const & requester)
|
|||||||
|
|
||||||
void PvaClient::clearRequester()
|
void PvaClient::clearRequester()
|
||||||
{
|
{
|
||||||
requester = Requester::weak_pointer();
|
requester.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClient::showCache()
|
void PvaClient::showCache()
|
||||||
{
|
{
|
||||||
pvaClientChannelCache->showCache();
|
if(pvaClientChannelCache->cacheSize()>=1) {
|
||||||
|
pvaClientChannelCache->showCache();
|
||||||
|
} else {
|
||||||
|
cout << "pvaClientChannelCache is empty\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -233,4 +231,3 @@ size_t PvaClient::cacheSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
-1348
File diff suppressed because it is too large
Load Diff
+254
-191
@@ -8,16 +8,16 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
#include <pv/createRequest.h>
|
#include <pv/createRequest.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -25,13 +25,13 @@ using namespace std;
|
|||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
|
|
||||||
class PvaClientGetCache
|
class epicsShareClass PvaClientGetCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PvaClientGetCache(){}
|
PvaClientGetCache(){}
|
||||||
~PvaClientGetCache();
|
~PvaClientGetCache()
|
||||||
void destroy() {
|
{
|
||||||
pvaClientGetMap.clear();
|
if(PvaClient::getDebug()) cout << "PvaClientGetCache::~PvaClientGetCache\n";
|
||||||
}
|
}
|
||||||
PvaClientGetPtr getGet(string const & request);
|
PvaClientGetPtr getGet(string const & request);
|
||||||
void addGet(string const & request,PvaClientGetPtr const & pvaClientGet);
|
void addGet(string const & request,PvaClientGetPtr const & pvaClientGet);
|
||||||
@@ -41,11 +41,6 @@ private:
|
|||||||
map<string,PvaClientGetPtr> pvaClientGetMap;
|
map<string,PvaClientGetPtr> pvaClientGetMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
PvaClientGetCache::~PvaClientGetCache()
|
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
PvaClientGetPtr PvaClientGetCache::getGet(string const & request)
|
PvaClientGetPtr PvaClientGetCache::getGet(string const & request)
|
||||||
{
|
{
|
||||||
map<string,PvaClientGetPtr>::iterator iter = pvaClientGetMap.find(request);
|
map<string,PvaClientGetPtr>::iterator iter = pvaClientGetMap.find(request);
|
||||||
@@ -55,8 +50,11 @@ PvaClientGetPtr PvaClientGetCache::getGet(string const & request)
|
|||||||
|
|
||||||
void PvaClientGetCache::addGet(string const & request,PvaClientGetPtr const & pvaClientGet)
|
void PvaClientGetCache::addGet(string const & request,PvaClientGetPtr const & pvaClientGet)
|
||||||
{
|
{
|
||||||
pvaClientGetMap.insert(std::pair<string,PvaClientGetPtr>(
|
map<string,PvaClientGetPtr>::iterator iter = pvaClientGetMap.find(request);
|
||||||
request,pvaClientGet));
|
if(iter!=pvaClientGetMap.end()) {
|
||||||
|
throw std::runtime_error("pvaClientGetCache::addGet pvaClientGet already cached");
|
||||||
|
}
|
||||||
|
pvaClientGetMap.insert(std::pair<string,PvaClientGetPtr>(request,pvaClientGet));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGetCache::showCache()
|
void PvaClientGetCache::showCache()
|
||||||
@@ -74,13 +72,13 @@ size_t PvaClientGetCache::cacheSize()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PvaClientPutCache
|
class epicsShareClass PvaClientPutCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PvaClientPutCache(){}
|
PvaClientPutCache(){}
|
||||||
~PvaClientPutCache();
|
~PvaClientPutCache()
|
||||||
void destroy() {
|
{
|
||||||
pvaClientPutMap.clear();
|
if(PvaClient::getDebug()) cout << "PvaClientPutCache::~PvaClientPutCache\n";
|
||||||
}
|
}
|
||||||
PvaClientPutPtr getPut(string const & request);
|
PvaClientPutPtr getPut(string const & request);
|
||||||
void addPut(string const & request,PvaClientPutPtr const & pvaClientPut);
|
void addPut(string const & request,PvaClientPutPtr const & pvaClientPut);
|
||||||
@@ -90,10 +88,6 @@ private:
|
|||||||
map<string,PvaClientPutPtr> pvaClientPutMap;
|
map<string,PvaClientPutPtr> pvaClientPutMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
PvaClientPutCache::~PvaClientPutCache()
|
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
PvaClientPutPtr PvaClientPutCache::getPut(string const & request)
|
PvaClientPutPtr PvaClientPutCache::getPut(string const & request)
|
||||||
{
|
{
|
||||||
@@ -104,6 +98,10 @@ PvaClientPutPtr PvaClientPutCache::getPut(string const & request)
|
|||||||
|
|
||||||
void PvaClientPutCache::addPut(string const & request,PvaClientPutPtr const & pvaClientPut)
|
void PvaClientPutCache::addPut(string const & request,PvaClientPutPtr const & pvaClientPut)
|
||||||
{
|
{
|
||||||
|
map<string,PvaClientPutPtr>::iterator iter = pvaClientPutMap.find(request);
|
||||||
|
if(iter!=pvaClientPutMap.end()) {
|
||||||
|
throw std::runtime_error("pvaClientPutCache::addPut pvaClientPut already cached");
|
||||||
|
}
|
||||||
pvaClientPutMap.insert(std::pair<string,PvaClientPutPtr>(
|
pvaClientPutMap.insert(std::pair<string,PvaClientPutPtr>(
|
||||||
request,pvaClientPut));
|
request,pvaClientPut));
|
||||||
}
|
}
|
||||||
@@ -123,29 +121,14 @@ size_t PvaClientPutCache::cacheSize()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChannelRequesterImpl : public ChannelRequester
|
PvaClientChannelPtr PvaClientChannel::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
string const & channelName,
|
||||||
|
string const & providerName)
|
||||||
{
|
{
|
||||||
PvaClientChannel *pvaClientChannel;
|
PvaClientChannelPtr channel(new PvaClientChannel(pvaClient,channelName,providerName));
|
||||||
public:
|
return channel;
|
||||||
ChannelRequesterImpl(PvaClientChannel *pvaClientChannel)
|
}
|
||||||
: pvaClientChannel(pvaClientChannel) {}
|
|
||||||
void channelCreated(
|
|
||||||
const Status& status,
|
|
||||||
Channel::shared_pointer const & channel)
|
|
||||||
{ pvaClientChannel->channelCreated(status,channel); }
|
|
||||||
void channelStateChange(
|
|
||||||
Channel::shared_pointer const & channel,
|
|
||||||
Channel::ConnectionState connectionState)
|
|
||||||
{pvaClientChannel->channelStateChange(channel,connectionState);}
|
|
||||||
tr1::shared_ptr<Channel> getChannel() {return pvaClientChannel->getChannel();}
|
|
||||||
string getRequesterName()
|
|
||||||
{return pvaClientChannel->getRequesterName();}
|
|
||||||
void message(
|
|
||||||
string const & message,
|
|
||||||
MessageType messageType)
|
|
||||||
{ pvaClientChannel->message(message,messageType); }
|
|
||||||
void destroy() {pvaClientChannel->destroy();}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientChannel::PvaClientChannel(
|
PvaClientChannel::PvaClientChannel(
|
||||||
@@ -156,52 +139,87 @@ PvaClientChannel::PvaClientChannel(
|
|||||||
channelName(channelName),
|
channelName(channelName),
|
||||||
providerName(providerName),
|
providerName(providerName),
|
||||||
connectState(connectIdle),
|
connectState(connectIdle),
|
||||||
isDestroyed(false),
|
|
||||||
createRequest(CreateRequest::create()),
|
createRequest(CreateRequest::create()),
|
||||||
pvaClientGetCache(new PvaClientGetCache()),
|
pvaClientGetCache(new PvaClientGetCache()),
|
||||||
pvaClientPutCache(new PvaClientPutCache())
|
pvaClientPutCache(new PvaClientPutCache())
|
||||||
{}
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientChannel::PvaClientChannel channelName " << channelName << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PvaClientChannel::~PvaClientChannel()
|
PvaClientChannel::~PvaClientChannel()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientChannel::~PvaClientChannel() "
|
||||||
|
<< " channelName " << channelName
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(PvaClient::getDebug()) showCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientChannel::channelCreated(const Status& status, Channel::shared_pointer const & channel)
|
void PvaClientChannel::channelCreated(const Status& status, Channel::shared_pointer const & channel)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(status.isOK()) {
|
cout << "PvaClientChannel::channelCreated"
|
||||||
this->channel = channel;
|
<< " channelName " << channelName
|
||||||
return;
|
<< " connectState " << connectState
|
||||||
|
<< " isConnected " << (channel->isConnected() ? "true" : "false")
|
||||||
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
Lock xx(mutex);
|
||||||
|
this->channel = channel;
|
||||||
|
if(connectState==connected) return;
|
||||||
|
if(connectState!=connectActive) {
|
||||||
|
string message("PvaClientChannel::channelCreated");
|
||||||
|
message += " channel " + channelName
|
||||||
|
+ " why was this called when connectState!=ConnectState.connectActive";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
if(!status.isOK()) {
|
||||||
|
string message("PvaClientChannel::channelCreated");
|
||||||
|
message += " channel " + channelName
|
||||||
|
+ " status " + status.getMessage() + " why??";
|
||||||
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
cout << "PvaClientChannel::channelCreated status " << status.getMessage() << " why??\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientChannel::channelStateChange(
|
void PvaClientChannel::channelStateChange(
|
||||||
Channel::shared_pointer const & channel,
|
Channel::shared_pointer const & channel,
|
||||||
Channel::ConnectionState connectionState)
|
Channel::ConnectionState connectionState)
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
if(PvaClient::getDebug()) {
|
||||||
if(isDestroyed) return;
|
cout << " PvaClientChannel::channelStateChange "
|
||||||
|
<< " channelName " << channelName
|
||||||
|
<< " " << Channel::ConnectionStateNames[connectionState]
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
bool waitingForConnect = false;
|
bool waitingForConnect = false;
|
||||||
if(connectState==connectActive) waitingForConnect = true;
|
if(connectState==connectActive) waitingForConnect = true;
|
||||||
if(connectionState!=Channel::CONNECTED) {
|
if(connectionState!=Channel::CONNECTED) {
|
||||||
string mess(channelName +
|
Lock xx(mutex);
|
||||||
" connection state " + Channel::ConnectionStateNames[connectionState]);
|
connectState = notConnected;
|
||||||
message(mess,errorMessage);
|
|
||||||
channelConnectStatus = Status(Status::STATUSTYPE_ERROR,mess);
|
|
||||||
connectState = notConnected;
|
|
||||||
} else {
|
} else {
|
||||||
connectState = connected;
|
Lock xx(mutex);
|
||||||
channelConnectStatus = Status::Ok;
|
this->channel = channel;
|
||||||
|
connectState = connected;
|
||||||
|
}
|
||||||
|
if(waitingForConnect) {
|
||||||
|
Lock xx(mutex);
|
||||||
|
waitForConnect.signal();
|
||||||
|
}
|
||||||
|
PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
bool value = (connectionState==Channel::CONNECTED ? true : false);
|
||||||
|
req->channelStateChange(shared_from_this(),value);
|
||||||
}
|
}
|
||||||
if(waitingForConnect) waitForConnect.signal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string PvaClientChannel::getRequesterName()
|
string PvaClientChannel::getRequesterName()
|
||||||
{
|
{
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
if(!yyy) return string("PvaClientChannel::getRequesterName() PvaClient isDestroyed");
|
||||||
return yyy->getRequesterName();
|
return yyy->getRequesterName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,99 +227,97 @@ void PvaClientChannel::message(
|
|||||||
string const & message,
|
string const & message,
|
||||||
MessageType messageType)
|
MessageType messageType)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
|
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
if(!yyy) return;
|
||||||
yyy->message(channelName + " " + message, messageType);
|
yyy->message(channelName + " " + message, messageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientChannel::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
if(channel) channel->destroy();
|
|
||||||
channel.reset();
|
|
||||||
pvaClientGetCache.reset();
|
|
||||||
pvaClientPutCache.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
string PvaClientChannel::getChannelName()
|
string PvaClientChannel::getChannelName()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
|
|
||||||
return channelName;
|
return channelName;
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel::shared_pointer PvaClientChannel::getChannel()
|
Channel::shared_pointer PvaClientChannel::getChannel()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
|
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PvaClientChannel::setStateChangeRequester(
|
||||||
|
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester)
|
||||||
|
{
|
||||||
|
this->stateChangeRequester = stateChangeRequester;
|
||||||
|
bool isConnected = false;
|
||||||
|
if(channel) isConnected = channel->isConnected();
|
||||||
|
stateChangeRequester->channelStateChange(shared_from_this(),isConnected);
|
||||||
|
}
|
||||||
|
|
||||||
void PvaClientChannel::connect(double timeout)
|
void PvaClientChannel::connect(double timeout)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientChannel::connect"
|
||||||
|
<< " channelName " << channelName << endl;
|
||||||
|
}
|
||||||
issueConnect();
|
issueConnect();
|
||||||
Status status = waitConnect(timeout);
|
Status status = waitConnect(timeout);
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + getChannelName()
|
if(PvaClient::getDebug()) cout << "PvaClientChannel::connect waitConnect failed\n";
|
||||||
|
string message = string("channel ") + channelName
|
||||||
+ " PvaClientChannel::connect " + status.getMessage();
|
+ " PvaClientChannel::connect " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientChannel::issueConnect()
|
void PvaClientChannel::issueConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState!=connectIdle) {
|
cout << "PvaClientChannel::issueConnect"
|
||||||
throw std::runtime_error("pvaClientChannel already connected");
|
<< " channelName " << channelName << endl;
|
||||||
}
|
}
|
||||||
channelRequester = ChannelRequester::shared_pointer(new ChannelRequesterImpl(this));
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
channelConnectStatus = Status(
|
if(connectState==connected) return;
|
||||||
Status::STATUSTYPE_ERROR,
|
if(connectState!=connectIdle) {
|
||||||
getChannelName() + " createChannel failed");
|
throw std::runtime_error("pvaClientChannel already connected");
|
||||||
connectState = connectActive;
|
}
|
||||||
ChannelProviderRegistry::shared_pointer reg = getChannelProviderRegistry();
|
connectState = connectActive;
|
||||||
ChannelProvider::shared_pointer provider = reg->getProvider(providerName);
|
|
||||||
if(!provider) {
|
|
||||||
throw std::runtime_error(getChannelName() + " provider " + providerName + " not registered");
|
|
||||||
}
|
}
|
||||||
channel = provider->createChannel(channelName,channelRequester,ChannelProvider::PRIORITY_DEFAULT);
|
ChannelProviderRegistry::shared_pointer reg(ChannelProviderRegistry::clients());
|
||||||
|
channelProvider = reg->getProvider(providerName);
|
||||||
|
if(!channelProvider) {
|
||||||
|
throw std::runtime_error(channelName + " provider " + providerName + " not registered");
|
||||||
|
}
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientChannel::issueConnect calling provider->createChannel\n";
|
||||||
|
channel = channelProvider->createChannel(channelName,shared_from_this(),ChannelProvider::PRIORITY_DEFAULT);
|
||||||
if(!channel) {
|
if(!channel) {
|
||||||
throw std::runtime_error(getChannelName() + " channelCreate failed ");
|
throw std::runtime_error(channelName + " channelCreate failed ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PvaClientChannel::waitConnect(double timeout)
|
Status PvaClientChannel::waitConnect(double timeout)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
waitForConnect.wait(timeout);
|
cout << "PvaClientChannel::waitConnect"
|
||||||
return channelConnectStatus;
|
<< " channelName " << channelName << endl;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
PvaClientFieldPtr PvaClientChannel::createField()
|
Lock xx(mutex);
|
||||||
{
|
if(!channel) return Status(Status::STATUSTYPE_ERROR,"");
|
||||||
return createField("");
|
if(channel->isConnected()) return Status::Ok;
|
||||||
}
|
}
|
||||||
|
if(timeout>0.0) {
|
||||||
PvaClientFieldPtr PvaClientChannel::createField(string const & subField)
|
waitForConnect.wait(timeout);
|
||||||
{
|
} else {
|
||||||
if(connectState!=connected) connect(5.0);
|
waitForConnect.wait();
|
||||||
throw std::runtime_error("PvaClientChannel::createField not implemented");
|
}
|
||||||
}
|
if(!channel) return Status(Status::STATUSTYPE_ERROR,"pvaClientChannel::waitConnect channel is null");
|
||||||
|
if(channel->isConnected()) return Status::Ok;
|
||||||
PvaClientProcessPtr PvaClientChannel::createProcess()
|
return Status(Status::STATUSTYPE_ERROR," not connected");
|
||||||
{
|
|
||||||
return createProcess("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientProcessPtr PvaClientChannel::createProcess(string const & request)
|
PvaClientProcessPtr PvaClientChannel::createProcess(string const & request)
|
||||||
{
|
{
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(!pvRequest) {
|
if(!pvRequest) {
|
||||||
string message = string("channel ") + getChannelName()
|
string message = string("channel ") + channelName
|
||||||
+ " PvaClientChannel::createProcess invalid pvRequest: "
|
+ " PvaClientChannel::createProcess invalid pvRequest: "
|
||||||
+ createRequest->getMessage();
|
+ createRequest->getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
@@ -314,31 +330,28 @@ PvaClientProcessPtr PvaClientChannel::createProcess(PVStructurePtr const & pvRe
|
|||||||
if(connectState!=connected) connect(5.0);
|
if(connectState!=connected) connect(5.0);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
||||||
return PvaClientProcess::create(yyy,channel,pvRequest);
|
return PvaClientProcess::create(yyy,shared_from_this(),pvRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientGetPtr PvaClientChannel::get() {return get("value,alarm,timeStamp");}
|
|
||||||
|
|
||||||
PvaClientGetPtr PvaClientChannel::get(string const & request)
|
PvaClientGetPtr PvaClientChannel::get(string const & request)
|
||||||
{
|
{
|
||||||
PvaClientGetPtr pvaClientGet = pvaClientGetCache->getGet(request);
|
PvaClientGetPtr pvaClientGet = pvaClientGetCache->getGet(request);
|
||||||
if(pvaClientGet) return pvaClientGet;
|
if(!pvaClientGet) {
|
||||||
pvaClientGet = createGet(request);
|
pvaClientGet = createGet(request);
|
||||||
pvaClientGet->connect();
|
pvaClientGet->connect();
|
||||||
pvaClientGetCache->addGet(request,pvaClientGet);
|
pvaClientGetCache->addGet(request,pvaClientGet);
|
||||||
|
}
|
||||||
|
pvaClientGet->get();
|
||||||
return pvaClientGet;
|
return pvaClientGet;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientGetPtr PvaClientChannel::createGet()
|
|
||||||
{
|
|
||||||
return PvaClientChannel::createGet("value,alarm,timeStamp");
|
|
||||||
}
|
|
||||||
|
|
||||||
PvaClientGetPtr PvaClientChannel::createGet(string const & request)
|
PvaClientGetPtr PvaClientChannel::createGet(string const & request)
|
||||||
{
|
{
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(!pvRequest) {
|
if(!pvRequest) {
|
||||||
string message = string("channel ") + getChannelName()
|
string message = string("channel ") + channelName
|
||||||
+ " PvaClientChannel::createGet invalid pvRequest: "
|
+ " PvaClientChannel::createGet invalid pvRequest: "
|
||||||
+ createRequest->getMessage();
|
+ createRequest->getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
@@ -351,32 +364,49 @@ PvaClientGetPtr PvaClientChannel::createGet(PVStructurePtr const & pvRequest)
|
|||||||
if(connectState!=connected) connect(5.0);
|
if(connectState!=connected) connect(5.0);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
||||||
return PvaClientGet::create(yyy,channel,pvRequest);
|
return PvaClientGet::create(yyy,shared_from_this(),pvRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
double PvaClientChannel::getDouble(string const & request)
|
||||||
|
{
|
||||||
|
return get(request)->getData()->getDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
string PvaClientChannel::getString(string const & request)
|
||||||
|
{
|
||||||
|
return get(request)->getData()->getString();
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_vector<const double> PvaClientChannel::getDoubleArray(string const & request)
|
||||||
|
{
|
||||||
|
return get(request)->getData()->getDoubleArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_vector<const std::string> PvaClientChannel::getStringArray(string const & request)
|
||||||
|
{
|
||||||
|
return get(request)->getData()->getStringArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutPtr PvaClientChannel::put() {return put("value");}
|
|
||||||
|
|
||||||
PvaClientPutPtr PvaClientChannel::put(string const & request)
|
PvaClientPutPtr PvaClientChannel::put(string const & request)
|
||||||
{
|
{
|
||||||
PvaClientPutPtr pvaClientPut = pvaClientPutCache->getPut(request);
|
PvaClientPutPtr pvaClientPut = pvaClientPutCache->getPut(request);
|
||||||
if(pvaClientPut) return pvaClientPut;
|
if(pvaClientPut) return pvaClientPut;
|
||||||
pvaClientPut = createPut(request);
|
if(!pvaClientPut) {
|
||||||
pvaClientPut->connect();
|
pvaClientPut = createPut(request);
|
||||||
pvaClientPut->get();
|
pvaClientPut->connect();
|
||||||
pvaClientPutCache->addPut(request,pvaClientPut);
|
pvaClientPut->get();
|
||||||
|
pvaClientPutCache->addPut(request,pvaClientPut);
|
||||||
|
}
|
||||||
return pvaClientPut;
|
return pvaClientPut;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutPtr PvaClientChannel::createPut()
|
|
||||||
{
|
|
||||||
return createPut("value");
|
|
||||||
}
|
|
||||||
|
|
||||||
PvaClientPutPtr PvaClientChannel::createPut(string const & request)
|
PvaClientPutPtr PvaClientChannel::createPut(string const & request)
|
||||||
{
|
{
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(!pvRequest) {
|
if(!pvRequest) {
|
||||||
string message = string("channel ") + getChannelName()
|
string message = string("channel ") + channelName
|
||||||
+ " PvaClientChannel::createPut invalid pvRequest: "
|
+ " PvaClientChannel::createPut invalid pvRequest: "
|
||||||
+ createRequest->getMessage();
|
+ createRequest->getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
@@ -389,19 +419,52 @@ PvaClientPutPtr PvaClientChannel::createPut(PVStructurePtr const & pvRequest)
|
|||||||
if(connectState!=connected) connect(5.0);
|
if(connectState!=connected) connect(5.0);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
||||||
return PvaClientPut::create(yyy,channel,pvRequest);
|
return PvaClientPut::create(yyy,shared_from_this(),pvRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutGetPtr PvaClientChannel::createPutGet()
|
void PvaClientChannel::putDouble(double value,string const & request)
|
||||||
{
|
{
|
||||||
return createPutGet("putField(argument)getField(result)");
|
PvaClientPutPtr clientPut = put(request);
|
||||||
|
PvaClientPutDataPtr putData = clientPut->getData();
|
||||||
|
putData->putDouble(value); clientPut->put();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientChannel::putString(std::string const & value,string const & request)
|
||||||
|
{
|
||||||
|
PvaClientPutPtr clientPut = put(request);
|
||||||
|
PvaClientPutDataPtr putData = clientPut->getData();
|
||||||
|
putData->putString(value); clientPut->put();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientChannel::putDoubleArray(
|
||||||
|
shared_vector<const double> const & value,
|
||||||
|
string const & request)
|
||||||
|
{
|
||||||
|
PvaClientPutPtr clientPut = put(request);
|
||||||
|
PvaClientPutDataPtr putData = clientPut->getData();
|
||||||
|
size_t n = value.size();
|
||||||
|
shared_vector<double> valueArray(n);
|
||||||
|
for(size_t i=0; i<n; ++i) valueArray[i] = value[i];
|
||||||
|
putData->putDoubleArray(freeze(valueArray)); clientPut->put();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientChannel::putStringArray(
|
||||||
|
shared_vector<const string> const & value,
|
||||||
|
string const & request)
|
||||||
|
{
|
||||||
|
PvaClientPutPtr clientPut = put(request);
|
||||||
|
PvaClientPutDataPtr putData = clientPut->getData();
|
||||||
|
size_t n = value.size();
|
||||||
|
shared_vector<string> valueArray(n);
|
||||||
|
for(size_t i=0; i<n; ++i) valueArray[i] = value[i];
|
||||||
|
putData->putStringArray(freeze(valueArray)); clientPut->put();
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request)
|
PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request)
|
||||||
{
|
{
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(!pvRequest) {
|
if(!pvRequest) {
|
||||||
string message = string("channel ") + getChannelName()
|
string message = string("channel ") + channelName
|
||||||
+ " PvaClientChannel::createPutGet invalid pvRequest: "
|
+ " PvaClientChannel::createPutGet invalid pvRequest: "
|
||||||
+ createRequest->getMessage();
|
+ createRequest->getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
@@ -414,36 +477,9 @@ PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvReque
|
|||||||
if(connectState!=connected) connect(5.0);
|
if(connectState!=connected) connect(5.0);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
||||||
return PvaClientPutGet::create(yyy,channel,pvRequest);
|
return PvaClientPutGet::create(yyy,shared_from_this(),pvRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientArrayPtr PvaClientChannel::createArray()
|
|
||||||
{
|
|
||||||
return createArray("value");
|
|
||||||
}
|
|
||||||
|
|
||||||
PvaClientArrayPtr PvaClientChannel::createArray(string const & request)
|
|
||||||
{
|
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
|
||||||
if(!pvRequest) {
|
|
||||||
string message = string("channel ") + getChannelName()
|
|
||||||
+ " PvaClientChannel::createArray invalid pvRequest: "
|
|
||||||
+ createRequest->getMessage();
|
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
|
||||||
return createArray(pvRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
PvaClientArrayPtr PvaClientChannel::createArray(PVStructurePtr const & pvRequest)
|
|
||||||
{
|
|
||||||
if(connectState!=connected) connect(5.0);
|
|
||||||
throw std::runtime_error("PvaClientChannel::createArray not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientMonitorPtr PvaClientChannel::monitor() {return monitor("value,alarm,timeStamp");}
|
|
||||||
|
|
||||||
PvaClientMonitorPtr PvaClientChannel::monitor(string const & request)
|
PvaClientMonitorPtr PvaClientChannel::monitor(string const & request)
|
||||||
{
|
{
|
||||||
PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
|
PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
|
||||||
@@ -454,7 +490,7 @@ PvaClientMonitorPtr PvaClientChannel::monitor(string const & request)
|
|||||||
|
|
||||||
PvaClientMonitorPtr PvaClientChannel::monitor(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester)
|
PvaClientMonitorPtr PvaClientChannel::monitor(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester)
|
||||||
{
|
{
|
||||||
return monitor("value,alarm,timeStamp",pvaClientMonitorRequester);
|
return monitor("field(value,alarm,timeStamp)",pvaClientMonitorRequester);
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientMonitorPtr PvaClientChannel::monitor(string const & request,
|
PvaClientMonitorPtr PvaClientChannel::monitor(string const & request,
|
||||||
@@ -467,16 +503,11 @@ PvaClientMonitorPtr PvaClientChannel::monitor(string const & request,
|
|||||||
return pvaClientMonitor;
|
return pvaClientMonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientMonitorPtr PvaClientChannel::createMonitor()
|
|
||||||
{
|
|
||||||
return createMonitor("value,alarm,timeStamp");
|
|
||||||
}
|
|
||||||
|
|
||||||
PvaClientMonitorPtr PvaClientChannel::createMonitor(string const & request)
|
PvaClientMonitorPtr PvaClientChannel::createMonitor(string const & request)
|
||||||
{
|
{
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(!pvRequest) {
|
if(!pvRequest) {
|
||||||
string message = string("channel ") + getChannelName()
|
string message = string("channel ") + channelName
|
||||||
+ " PvaClientChannel::createMonitor invalid pvRequest: "
|
+ " PvaClientChannel::createMonitor invalid pvRequest: "
|
||||||
+ createRequest->getMessage();
|
+ createRequest->getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
@@ -489,15 +520,55 @@ PvaClientMonitorPtr PvaClientChannel::createMonitor(PVStructurePtr const & pvR
|
|||||||
if(connectState!=connected) connect(5.0);
|
if(connectState!=connected) connect(5.0);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
||||||
return PvaClientMonitor::create(yyy,channel,pvRequest);
|
return PvaClientMonitor::create(yyy,shared_from_this(),pvRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVStructurePtr PvaClientChannel::rpc(
|
||||||
|
PVStructurePtr const & pvRequest,
|
||||||
|
PVStructurePtr const & pvArgument)
|
||||||
|
{
|
||||||
|
|
||||||
|
PvaClientRPCPtr rpc = createRPC(pvRequest);
|
||||||
|
return rpc->request(pvArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVStructurePtr PvaClientChannel::rpc(
|
||||||
|
PVStructurePtr const & pvArgument)
|
||||||
|
{
|
||||||
|
PvaClientRPCPtr rpc = createRPC();
|
||||||
|
return rpc->request(pvArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
PvaClientRPCPtr PvaClientChannel::createRPC()
|
||||||
|
{
|
||||||
|
if(connectState!=connected) connect(5.0);
|
||||||
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
|
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
||||||
|
return PvaClientRPC::create(yyy,channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
PvaClientRPCPtr PvaClientChannel::createRPC(PVStructurePtr const & pvRequest)
|
||||||
|
{
|
||||||
|
if(connectState!=connected) connect(5.0);
|
||||||
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
|
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
|
||||||
|
return PvaClientRPC::create(yyy,channel,pvRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientChannel::showCache()
|
void PvaClientChannel::showCache()
|
||||||
{
|
{
|
||||||
cout << " pvaClientGet" << endl;
|
if(pvaClientGetCache->cacheSize()>=1) {
|
||||||
pvaClientGetCache->showCache();
|
cout << " pvaClientGet cache" << endl;
|
||||||
cout << " pvaClientPut" << endl;
|
pvaClientGetCache->showCache();
|
||||||
pvaClientPutCache->showCache();
|
} else {
|
||||||
|
cout << " pvaClientGet cache is empty\n";
|
||||||
|
}
|
||||||
|
if(pvaClientPutCache->cacheSize()>=1) {
|
||||||
|
cout << " pvaClientPut cache" << endl;
|
||||||
|
pvaClientPutCache->showCache();
|
||||||
|
} else {
|
||||||
|
cout << " pvaClientPut cache is empty\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PvaClientChannel::cacheSize()
|
size_t PvaClientChannel::cacheSize()
|
||||||
@@ -506,13 +577,5 @@ size_t PvaClientChannel::cacheSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientChannelPtr PvaClientChannel::create(
|
|
||||||
PvaClientPtr const &pvaClient,
|
|
||||||
string const & channelName,
|
|
||||||
string const & providerName)
|
|
||||||
{
|
|
||||||
PvaClientChannelPtr channel(new PvaClientChannel(pvaClient,channelName,providerName));
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -0,0 +1,440 @@
|
|||||||
|
/* pvaClientData.cpp */
|
||||||
|
/**
|
||||||
|
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||||
|
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||||
|
* in file LICENSE that is included with this distribution.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @author mrk
|
||||||
|
* @date 2019.04
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <sstream>
|
||||||
|
#include <istream>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#include <pv/createRequest.h>
|
||||||
|
#include <pv/convert.h>
|
||||||
|
#include <pv/pvEnumerated.h>
|
||||||
|
|
||||||
|
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
||||||
|
# include <pv/json.h>
|
||||||
|
# define USE_JSON
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
|
using std::tr1::static_pointer_cast;
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
|
||||||
|
static ConvertPtr convert = getConvert();
|
||||||
|
static string noStructure("no pvStructure ");
|
||||||
|
static string noValue("no value field");
|
||||||
|
static string noScalar("value is not a scalar");
|
||||||
|
static string noArray("value is not an array");
|
||||||
|
static string noScalarArray("value is not a scalarArray");
|
||||||
|
static string noAlarm("no alarm");
|
||||||
|
static string noTimeStamp("no timeStamp");
|
||||||
|
|
||||||
|
PvaClientDataPtr PvaClientData::create(StructureConstPtr const & structure)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::create\n";
|
||||||
|
PvaClientDataPtr epv(new PvaClientData(structure));
|
||||||
|
return epv;
|
||||||
|
}
|
||||||
|
|
||||||
|
PvaClientData::PvaClientData(StructureConstPtr const & structure)
|
||||||
|
: structure(structure)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PVFieldPtr PvaClientData::getSinglePVField()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getSinglePVField\n";
|
||||||
|
PVStructurePtr pvStructure = getPVStructure();
|
||||||
|
while(true) {
|
||||||
|
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
||||||
|
if(fieldPtrArray.size()==0) {
|
||||||
|
throw std::logic_error("PvaClientData::getSinglePVField() pvRequest for empty structure");
|
||||||
|
}
|
||||||
|
if(fieldPtrArray.size()!=1) {
|
||||||
|
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
||||||
|
if(pvValue) {
|
||||||
|
Type type = pvValue->getField()->getType();
|
||||||
|
if(type!=epics::pvData::structure) return pvValue;
|
||||||
|
}
|
||||||
|
throw std::logic_error("PvaClientData::getSinglePVField() pvRequest for multiple fields");
|
||||||
|
}
|
||||||
|
PVFieldPtr pvField(fieldPtrArray[0]);
|
||||||
|
Type type = pvField->getField()->getType();
|
||||||
|
if(type!=epics::pvData::structure) return pvField;
|
||||||
|
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientData::checkValue()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n";
|
||||||
|
if(pvValue) return;
|
||||||
|
throw std::runtime_error(messagePrefix + noValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientData::setMessagePrefix(std::string const & value)
|
||||||
|
{
|
||||||
|
messagePrefix = value + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
StructureConstPtr PvaClientData::getStructure()
|
||||||
|
{
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVStructurePtr PvaClientData::getPVStructure()
|
||||||
|
{
|
||||||
|
if(pvStructure) return pvStructure;
|
||||||
|
throw std::runtime_error(messagePrefix + noStructure);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitSetPtr PvaClientData::getChangedBitSet()
|
||||||
|
{
|
||||||
|
if(bitSet)return bitSet;
|
||||||
|
throw std::runtime_error(messagePrefix + noStructure);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream & PvaClientData::showChanged(std::ostream & out)
|
||||||
|
{
|
||||||
|
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
|
||||||
|
size_t nextSet = bitSet->nextSetBit(0);
|
||||||
|
PVFieldPtr pvField;
|
||||||
|
while(nextSet!=string::npos) {
|
||||||
|
if(nextSet==0) {
|
||||||
|
pvField = pvStructure;
|
||||||
|
} else {
|
||||||
|
pvField = pvStructure->getSubField(nextSet);
|
||||||
|
}
|
||||||
|
string name = pvField->getFullName();
|
||||||
|
out << name << " = " << pvField << endl;
|
||||||
|
nextSet = bitSet->nextSetBit(nextSet+1);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientData::setData(
|
||||||
|
PVStructurePtr const & pvStructureFrom,
|
||||||
|
BitSetPtr const & bitSetFrom)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::setData\n";
|
||||||
|
pvStructure = pvStructureFrom;
|
||||||
|
bitSet = bitSetFrom;
|
||||||
|
pvValue = pvStructure->getSubField("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PvaClientData::hasValue()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";
|
||||||
|
if(!pvValue) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PvaClientData::isValueScalar()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalar\n";
|
||||||
|
if(!pvValue) return false;
|
||||||
|
if(pvValue->getField()->getType()==scalar) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PvaClientData::isValueScalarArray()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalarArray\n";
|
||||||
|
if(!pvValue) return false;
|
||||||
|
if(pvValue->getField()->getType()==scalarArray) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVFieldPtr PvaClientData::getValue()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getValue\n";
|
||||||
|
checkValue();
|
||||||
|
return pvValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVScalarPtr PvaClientData::getScalarValue()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getScalarValue\n";
|
||||||
|
checkValue();
|
||||||
|
if(pvValue->getField()->getType()!=scalar) {
|
||||||
|
throw std::runtime_error(messagePrefix + noScalar);
|
||||||
|
}
|
||||||
|
return pvStructure->getSubField<PVScalar>("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
PVArrayPtr PvaClientData::getArrayValue()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getArrayValue\n";
|
||||||
|
checkValue();
|
||||||
|
Type type = pvValue->getField()->getType();
|
||||||
|
if(type!=scalarArray && type!=structureArray && type!=unionArray) {
|
||||||
|
throw std::runtime_error(messagePrefix + noArray);
|
||||||
|
}
|
||||||
|
return pvStructure->getSubField<PVArray>("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
PVScalarArrayPtr PvaClientData::getScalarArrayValue()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getScalarArrayValue\n";
|
||||||
|
checkValue();
|
||||||
|
Type type = pvValue->getField()->getType();
|
||||||
|
if(type!=scalarArray) {
|
||||||
|
throw std::runtime_error(messagePrefix + noScalarArray);
|
||||||
|
}
|
||||||
|
return pvStructure->getSubField<PVScalarArray>("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
double PvaClientData::getDouble()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n";
|
||||||
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
|
Type type = pvField->getField()->getType();
|
||||||
|
if(type!=scalar) {
|
||||||
|
throw std::logic_error("PvaClientData::getDouble() did not find a scalar field");
|
||||||
|
}
|
||||||
|
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||||
|
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
||||||
|
if(scalarType==pvDouble) {
|
||||||
|
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
||||||
|
return pvDouble->get();
|
||||||
|
}
|
||||||
|
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
||||||
|
throw std::logic_error(
|
||||||
|
"PvaClientData::getDouble() did not find a numeric scalar field");
|
||||||
|
}
|
||||||
|
return convert->toDouble(pvScalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
string PvaClientData::getString()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getString\n";
|
||||||
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
|
Type type = pvField->getField()->getType();
|
||||||
|
if(type!=scalar) {
|
||||||
|
throw std::logic_error("PvaClientData::getString() did not find a scalar field");
|
||||||
|
}
|
||||||
|
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||||
|
return convert->toString(pvScalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_vector<const double> PvaClientData::getDoubleArray()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n";
|
||||||
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
|
Type type = pvField->getField()->getType();
|
||||||
|
if(type!=scalarArray) {
|
||||||
|
throw std::logic_error("PvaClientData::getDoubleArray() did not find a scalarArray field");
|
||||||
|
}
|
||||||
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
|
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
|
||||||
|
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
||||||
|
throw std::logic_error(
|
||||||
|
"PvaClientData::getDoubleArray() did not find a numeric scalarArray field");
|
||||||
|
}
|
||||||
|
shared_vector<const double> retValue;
|
||||||
|
pvScalarArray->getAs<const double>(retValue);
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_vector<const string> PvaClientData::getStringArray()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n";
|
||||||
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
|
Type type = pvField->getField()->getType();
|
||||||
|
if(type!=scalarArray) {
|
||||||
|
throw std::logic_error("PvaClientData::getStringArray() did not find a scalarArray field");
|
||||||
|
}
|
||||||
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
|
shared_vector<const string> retValue;
|
||||||
|
pvScalarArray->getAs<const string>(retValue);
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Alarm PvaClientData::getAlarm()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getAlarm\n";
|
||||||
|
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
|
||||||
|
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("alarm");
|
||||||
|
if(!pvs) throw std::runtime_error(messagePrefix + noAlarm);
|
||||||
|
pvAlarm.attach(pvs);
|
||||||
|
if(pvAlarm.isAttached()) {
|
||||||
|
Alarm alarm;
|
||||||
|
pvAlarm.get(alarm);
|
||||||
|
pvAlarm.detach();
|
||||||
|
return alarm;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(messagePrefix + noAlarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeStamp PvaClientData::getTimeStamp()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientData::getTimeStamp\n";
|
||||||
|
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
|
||||||
|
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("timeStamp");
|
||||||
|
if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp);
|
||||||
|
pvTimeStamp.attach(pvs);
|
||||||
|
if(pvTimeStamp.isAttached()) {
|
||||||
|
TimeStamp timeStamp;
|
||||||
|
pvTimeStamp.get(timeStamp);
|
||||||
|
pvTimeStamp.detach();
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(messagePrefix + noTimeStamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientData::zeroArrayLength()
|
||||||
|
{
|
||||||
|
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
|
||||||
|
zeroArrayLength(pvStructure);
|
||||||
|
}
|
||||||
|
void PvaClientData::parse(
|
||||||
|
const std::string &arg,const PVFieldPtr &dest,BitSetPtr & bitSet)
|
||||||
|
{
|
||||||
|
#ifdef USE_JSON
|
||||||
|
std::istringstream strm(arg);
|
||||||
|
parseJSON(strm, dest,&(*bitSet));
|
||||||
|
#else
|
||||||
|
throw std::runtime_error("JSON support not built");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientData::parse(
|
||||||
|
const std::string &arg,const PVUnionPtr &pvUnion)
|
||||||
|
{
|
||||||
|
if(pvUnion->getUnion()->isVariant()) {
|
||||||
|
throw std::runtime_error(messagePrefix + "varient union not implemented");
|
||||||
|
}
|
||||||
|
size_t iequals = arg.find_first_of('=');
|
||||||
|
string field;
|
||||||
|
string rest;
|
||||||
|
if(iequals==std::string::npos) {
|
||||||
|
string mess(arg);
|
||||||
|
mess += " was expected to start with field=";
|
||||||
|
throw std::runtime_error(messagePrefix + mess);
|
||||||
|
}
|
||||||
|
field = arg.substr(0,iequals);
|
||||||
|
rest = arg.substr(iequals+1);
|
||||||
|
PVFieldPtr pvField(pvUnion->select(field));
|
||||||
|
if(pvField->getField()->getType()==epics::pvData::union_) {
|
||||||
|
PVUnionPtr pvu = static_pointer_cast<PVUnion>(pvField);
|
||||||
|
parse(rest,pvu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BitSetPtr bs;
|
||||||
|
parse(rest,pvField,bs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientData::parse(const std::vector<std::string> &args)
|
||||||
|
{
|
||||||
|
if(!pvStructure) throw std::runtime_error(messagePrefix + noStructure);
|
||||||
|
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
|
||||||
|
size_t num = args.size();
|
||||||
|
if(num<1) throw std::runtime_error(messagePrefix + " no arguments");
|
||||||
|
for(size_t i=0; i<num; ++i)
|
||||||
|
{
|
||||||
|
string val = args[i];
|
||||||
|
size_t iequals = val.find_first_of('=');
|
||||||
|
string field;
|
||||||
|
string rest(val);
|
||||||
|
if(iequals==std::string::npos) {
|
||||||
|
parse(rest,pvStructure,bitSet);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
field = val.substr(0,iequals);
|
||||||
|
rest = val.substr(iequals+1);
|
||||||
|
if(field.size()==std::string::npos) {
|
||||||
|
parse(rest,pvStructure,bitSet);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
PVFieldPtr pvField(pvStructure->getSubField(field));
|
||||||
|
if(!pvField) throw std::runtime_error(messagePrefix + field +" does not exist");
|
||||||
|
// look for enumerated structure
|
||||||
|
PVEnumerated pvEnumerated;
|
||||||
|
bool result = pvEnumerated.attach(pvField);
|
||||||
|
if(result) {
|
||||||
|
PVStringArray::const_svector choices(pvEnumerated.getChoices());
|
||||||
|
for(size_t i=0; i<choices.size(); ++i) {
|
||||||
|
if(choices[i]==rest) {
|
||||||
|
pvEnumerated.setIndex(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// look for union
|
||||||
|
PVUnionPtr pvUnion(pvStructure->getSubField<PVUnion>(field));
|
||||||
|
if(pvUnion) {
|
||||||
|
parse(rest,pvUnion);
|
||||||
|
bitSet->set(pvUnion->getFieldOffset());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parse(rest,pvField,bitSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientData::streamJSON(
|
||||||
|
std::ostream& strm,
|
||||||
|
bool ignoreUnprintable,
|
||||||
|
bool multiLine)
|
||||||
|
{
|
||||||
|
#ifdef USE_JSON
|
||||||
|
JSONPrintOptions opts;
|
||||||
|
opts.ignoreUnprintable = ignoreUnprintable;
|
||||||
|
opts.multiLine = multiLine;
|
||||||
|
printJSON(strm,*pvStructure,*bitSet,opts);
|
||||||
|
#else
|
||||||
|
throw std::runtime_error("JSON support not built");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PvaClientData::zeroArrayLength(const PVStructurePtr &pvStructure)
|
||||||
|
{
|
||||||
|
const PVFieldPtrArray pvFields(pvStructure->getPVFields());
|
||||||
|
for(size_t i=0; i<pvFields.size(); ++i) {
|
||||||
|
PVFieldPtr pvField = pvFields[i];
|
||||||
|
Type type(pvField->getField()->getType());
|
||||||
|
switch(type) {
|
||||||
|
case scalarArray:
|
||||||
|
{
|
||||||
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
|
pvScalarArray->setLength(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case structureArray:
|
||||||
|
{
|
||||||
|
PVStructureArrayPtr pvStructureArray = static_pointer_cast<PVStructureArray>(pvField);
|
||||||
|
pvStructureArray->setLength(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case epics::pvData::structure:
|
||||||
|
{
|
||||||
|
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||||
|
zeroArrayLength(pvStructure);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
+174
-90
@@ -8,81 +8,140 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
|
|
||||||
class ChannelGetRequesterImpl : public ChannelGetRequester
|
class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||||
{
|
{
|
||||||
PvaClientGet * pvaClientGet;
|
PvaClientGet::weak_pointer pvaClientGet;
|
||||||
|
PvaClient::weak_pointer pvaClient;
|
||||||
public:
|
public:
|
||||||
ChannelGetRequesterImpl(PvaClientGet * pvaClientGet)
|
ChannelGetRequesterImpl(
|
||||||
: pvaClientGet(pvaClientGet) {}
|
PvaClientGetPtr const & pvaClientGet,
|
||||||
string getRequesterName()
|
PvaClientPtr const &pvaClient)
|
||||||
{return pvaClientGet->getRequesterName();}
|
: pvaClientGet(pvaClientGet),
|
||||||
void message(string const & message,MessageType messageType)
|
pvaClient(pvaClient)
|
||||||
{pvaClientGet->message(message,messageType);}
|
{}
|
||||||
void channelGetConnect(
|
virtual ~ChannelGetRequesterImpl() {
|
||||||
|
if(PvaClient::getDebug()) std::cout << "~ChannelGetRequesterImpl" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string getRequesterName() {
|
||||||
|
PvaClientGetPtr clientGet(pvaClientGet.lock());
|
||||||
|
if(!clientGet) return string("clientGet is null");
|
||||||
|
return clientGet->getRequesterName();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void message(std::string const & message, MessageType messageType) {
|
||||||
|
PvaClientGetPtr clientGet(pvaClientGet.lock());
|
||||||
|
if(!clientGet) return;
|
||||||
|
clientGet->message(message,messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void channelGetConnect(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelGet::shared_pointer const & channelGet,
|
ChannelGet::shared_pointer const & channelGet,
|
||||||
StructureConstPtr const & structure)
|
Structure::const_shared_pointer const & structure)
|
||||||
{pvaClientGet->channelGetConnect(status,channelGet,structure);}
|
{
|
||||||
void getDone(
|
PvaClientGetPtr clientGet(pvaClientGet.lock());
|
||||||
|
if(!clientGet) return;
|
||||||
|
clientGet->channelGetConnect(status,channelGet,structure);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getDone(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelGet::shared_pointer const & channelGet,
|
ChannelGet::shared_pointer const & channelGet,
|
||||||
PVStructurePtr const & pvStructure,
|
PVStructurePtr const & pvStructure,
|
||||||
BitSetPtr const & bitSet)
|
BitSet::shared_pointer const & bitSet)
|
||||||
{pvaClientGet->getDone(status,channelGet,pvStructure,bitSet);}
|
{
|
||||||
|
PvaClientGetPtr clientGet(pvaClientGet.lock());
|
||||||
|
if(!clientGet) return;
|
||||||
|
clientGet->getDone(status,channelGet,pvStructure,bitSet);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PvaClientGetPtr PvaClientGet::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
|
PVStructurePtr const &pvRequest)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientGet::create(pvaClient,channelName,pvRequest)\n"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< " pvRequest " << pvRequest
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
PvaClientGetPtr clientGet(new PvaClientGet(pvaClient,pvaClientChannel,pvRequest));
|
||||||
|
clientGet->channelGetRequester = ChannelGetRequesterImplPtr(
|
||||||
|
new ChannelGetRequesterImpl(clientGet,pvaClient));
|
||||||
|
return clientGet;
|
||||||
|
}
|
||||||
|
|
||||||
PvaClientGet::PvaClientGet(
|
PvaClientGet::PvaClientGet(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
Channel::shared_pointer const & channel,
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
PVStructurePtr const &pvRequest)
|
PVStructurePtr const &pvRequest)
|
||||||
: pvaClient(pvaClient),
|
: pvaClient(pvaClient),
|
||||||
channel(channel),
|
pvaClientChannel(pvaClientChannel),
|
||||||
pvRequest(pvRequest),
|
pvRequest(pvRequest),
|
||||||
isDestroyed(false),
|
|
||||||
connectState(connectIdle),
|
connectState(connectIdle),
|
||||||
getState(getIdle)
|
getState(getIdle)
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientGet::PvaClientGet channelName "
|
||||||
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientGet::~PvaClientGet()
|
PvaClientGet::~PvaClientGet()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientGet::~PvaClientGet channelName "
|
||||||
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGet::checkGetState()
|
|
||||||
|
void PvaClientGet::checkConnectState()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState==connectIdle) connect();
|
cout << "PvaClientGet::checkConnectState channelName "
|
||||||
if(getState==getIdle) get();
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
|
if(!pvaClientChannel->getChannel()->isConnected()) {
|
||||||
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientGet::checkConnectState channel not connected ";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
if(connectState==connectIdle) {
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
if(connectState==connectActive){
|
||||||
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " "
|
||||||
|
+ channelGetConnectStatus.getMessage();
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from ChannelGetRequester
|
|
||||||
string PvaClientGet::getRequesterName()
|
string PvaClientGet::getRequesterName()
|
||||||
{
|
{
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
return pvaClientChannel->getRequesterName();
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
return yyy->getRequesterName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGet::message(string const & message,MessageType messageType)
|
void PvaClientGet::message(string const & message,MessageType messageType)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
pvaClientChannel->message(message,messageType);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
yyy->message(message, messageType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGet::channelGetConnect(
|
void PvaClientGet::channelGetConnect(
|
||||||
@@ -90,16 +149,27 @@ void PvaClientGet::channelGetConnect(
|
|||||||
ChannelGet::shared_pointer const & channelGet,
|
ChannelGet::shared_pointer const & channelGet,
|
||||||
StructureConstPtr const & structure)
|
StructureConstPtr const & structure)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelGetConnectStatus = status;
|
cout << "PvaClientGet::channelGetConnect channelName "
|
||||||
this->channelGet = channelGet;
|
<< pvaClientChannel->getChannel()->getChannelName()
|
||||||
if(status.isOK()) {
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
pvaClientData = PvaClientGetData::create(structure);
|
<< "\n";
|
||||||
pvaClientData->setMessagePrefix(channel->getChannelName());
|
|
||||||
connectState = connected;
|
|
||||||
}
|
}
|
||||||
waitForConnect.signal();
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
channelGetConnectStatus = status;
|
||||||
|
if(status.isOK()) {
|
||||||
|
this->channelGet = channelGet;
|
||||||
|
connectState = connected;
|
||||||
|
pvaClientData = PvaClientGetData::create(structure);
|
||||||
|
pvaClientData->setMessagePrefix(channelGet->getChannel()->getChannelName());
|
||||||
|
}
|
||||||
|
waitForConnect.signal();
|
||||||
|
}
|
||||||
|
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->channelGetConnect(status,shared_from_this());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGet::getDone(
|
void PvaClientGet::getDone(
|
||||||
@@ -108,82 +178,90 @@ void PvaClientGet::getDone(
|
|||||||
PVStructurePtr const & pvStructure,
|
PVStructurePtr const & pvStructure,
|
||||||
BitSetPtr const & bitSet)
|
BitSetPtr const & bitSet)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelGetStatus = status;
|
cout << "PvaClientGet::getDone channelName "
|
||||||
if(status.isOK()) {
|
<< pvaClientChannel->getChannel()->getChannelName()
|
||||||
pvaClientData->setData(pvStructure,bitSet);
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
|
<< "\n";
|
||||||
}
|
}
|
||||||
waitForGet.signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// from PvaClientGet
|
|
||||||
void PvaClientGet::destroy()
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
if(isDestroyed) return;
|
channelGetStatus = status;
|
||||||
isDestroyed = true;
|
if(status.isOK()) {
|
||||||
|
pvaClientData->setData(pvStructure,bitSet);
|
||||||
|
}
|
||||||
|
getState = getComplete;
|
||||||
|
waitForGet.signal();
|
||||||
|
}
|
||||||
|
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->getDone(status,shared_from_this());
|
||||||
}
|
}
|
||||||
if(channelGet) channelGet->destroy();
|
|
||||||
channelGet.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGet::connect()
|
void PvaClientGet::connect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientGet::connect channelName "
|
||||||
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
issueConnect();
|
issueConnect();
|
||||||
Status status = waitConnect();
|
Status status = waitConnect();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientGet::connect " + status.getMessage();
|
+ " PvaClientGet::connect " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGet::issueConnect()
|
void PvaClientGet::issueConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientGet::issueConnect channelName "
|
||||||
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
if(connectState!=connectIdle) {
|
if(connectState!=connectIdle) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientGet already connected ";
|
+ " pvaClientGet already connected ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
getRequester = ChannelGetRequester::shared_pointer(new ChannelGetRequesterImpl(this));
|
|
||||||
connectState = connectActive;
|
connectState = connectActive;
|
||||||
channelGet = channel->createChannelGet(getRequester,pvRequest);
|
channelGetConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
|
||||||
|
channelGet = pvaClientChannel->getChannel()->createChannelGet(channelGetRequester,pvRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PvaClientGet::waitConnect()
|
Status PvaClientGet::waitConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState==connected) return channelGetConnectStatus;
|
cout << "PvaClientGet::waitConnect channelName "
|
||||||
if(connectState!=connectActive) {
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
string message = string("channel ") + channel->getChannelName()
|
|
||||||
+ " pvaClientGet illegal connect state ";
|
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForConnect.wait();
|
waitForConnect.wait();
|
||||||
connectState = channelGetConnectStatus.isOK() ? connected : connectIdle;
|
|
||||||
return channelGetConnectStatus;
|
return channelGetConnectStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGet::get()
|
void PvaClientGet::get()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientGet::get channelName "
|
||||||
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
issueGet();
|
issueGet();
|
||||||
Status status = waitGet();
|
Status status = waitGet();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientGet::get " + status.getMessage();
|
+ " PvaClientGet::get " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientGet::issueGet()
|
void PvaClientGet::issueGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientGet::issueGet channelName "
|
||||||
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
if(connectState==connectIdle) connect();
|
if(connectState==connectIdle) connect();
|
||||||
if(getState!=getIdle) {
|
if(getState==getActive) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientGet::issueGet get aleady active ";
|
+ " PvaClientGet::issueGet get aleady active ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
@@ -193,32 +271,38 @@ void PvaClientGet::issueGet()
|
|||||||
|
|
||||||
Status PvaClientGet::waitGet()
|
Status PvaClientGet::waitGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(getState!=getActive){
|
cout << "PvaClientGet::waitGet channelName "
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
+ " PvaClientGet::waitGet llegal get state";
|
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForGet.wait();
|
waitForGet.wait();
|
||||||
getState = getIdle;
|
|
||||||
if(channelGetStatus.isOK()) {
|
|
||||||
return Status::Ok;
|
|
||||||
}
|
|
||||||
return channelGetStatus;
|
return channelGetStatus;
|
||||||
}
|
}
|
||||||
PvaClientGetDataPtr PvaClientGet::getData()
|
PvaClientGetDataPtr PvaClientGet::getData()
|
||||||
{
|
{
|
||||||
checkGetState();
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientGet::getData channelName "
|
||||||
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
|
checkConnectState();
|
||||||
|
if(getState==getIdle) get();
|
||||||
return pvaClientData;
|
return pvaClientData;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientGetPtr PvaClientGet::create(
|
void PvaClientGet::setRequester(PvaClientGetRequesterPtr const & pvaClientGetRequester)
|
||||||
PvaClientPtr const &pvaClient,
|
|
||||||
Channel::shared_pointer const & channel,
|
|
||||||
PVStructurePtr const &pvRequest)
|
|
||||||
{
|
{
|
||||||
PvaClientGetPtr epv(new PvaClientGet(pvaClient,channel,pvRequest));
|
if(PvaClient::getDebug()) {
|
||||||
return epv;
|
cout << "PvaClientGet::setRequester channelName "
|
||||||
|
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||||
|
}
|
||||||
|
this->pvaClientGetRequester = pvaClientGetRequester;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PvaClientChannelPtr PvaClientGet::getPvaClientChannel()
|
||||||
|
{
|
||||||
|
return pvaClientChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
+7
-191
@@ -8,17 +8,17 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
#include <pv/createRequest.h>
|
#include <pv/createRequest.h>
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -26,199 +26,15 @@ using namespace std;
|
|||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
|
|
||||||
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
static string noStructure("no pvStructure ");
|
|
||||||
static string noValue("no value field");
|
|
||||||
static string noScalar("value is not a scalar");
|
|
||||||
static string notCompatibleScalar("value is not a compatible scalar");
|
|
||||||
static string noArray("value is not an array");
|
|
||||||
static string noScalarArray("value is not a scalarArray");
|
|
||||||
static string notDoubleArray("value is not a doubleArray");
|
|
||||||
static string notStringArray("value is not a stringArray");
|
|
||||||
static string noAlarm("no alarm");
|
|
||||||
static string noTimeStamp("no timeStamp");
|
|
||||||
|
|
||||||
PvaClientGetDataPtr PvaClientGetData::create(StructureConstPtr const & structure)
|
PvaClientGetDataPtr PvaClientGetData::create(StructureConstPtr const & structure)
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientGetData::create\n";
|
||||||
PvaClientGetDataPtr epv(new PvaClientGetData(structure));
|
PvaClientGetDataPtr epv(new PvaClientGetData(structure));
|
||||||
return epv;
|
return epv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientGetData::PvaClientGetData(StructureConstPtr const & structure)
|
PvaClientGetData::PvaClientGetData(StructureConstPtr const & structure)
|
||||||
: structure(structure)
|
: PvaClientData(structure)
|
||||||
{
|
{}
|
||||||
messagePrefix = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientGetData::checkValue()
|
|
||||||
{
|
|
||||||
if(pvValue) return;
|
|
||||||
throw std::runtime_error(messagePrefix + noValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientGetData::setMessagePrefix(std::string const & value)
|
|
||||||
{
|
|
||||||
messagePrefix = value + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
StructureConstPtr PvaClientGetData::getStructure()
|
|
||||||
{return structure;}
|
|
||||||
|
|
||||||
PVStructurePtr PvaClientGetData::getPVStructure()
|
|
||||||
{
|
|
||||||
if(pvStructure) return pvStructure;
|
|
||||||
throw std::runtime_error(messagePrefix + noStructure);
|
|
||||||
}
|
|
||||||
|
|
||||||
BitSetPtr PvaClientGetData::getChangedBitSet()
|
|
||||||
{
|
|
||||||
if(bitSet)return bitSet;
|
|
||||||
throw std::runtime_error(messagePrefix + noStructure);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream & PvaClientGetData::showChanged(std::ostream & out)
|
|
||||||
{
|
|
||||||
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
|
|
||||||
size_t nextSet = bitSet->nextSetBit(0);
|
|
||||||
PVFieldPtr pvField;
|
|
||||||
while(nextSet!=string::npos) {
|
|
||||||
if(nextSet==0) {
|
|
||||||
pvField = pvStructure;
|
|
||||||
} else {
|
|
||||||
pvField = pvStructure->getSubField(nextSet);
|
|
||||||
}
|
|
||||||
string name = pvField->getFullName();
|
|
||||||
out << name << " = " << pvField << endl;
|
|
||||||
nextSet = bitSet->nextSetBit(nextSet+1);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientGetData::setData(
|
|
||||||
PVStructurePtr const & pvStructureFrom,
|
|
||||||
BitSetPtr const & bitSetFrom)
|
|
||||||
{
|
|
||||||
pvStructure = pvStructureFrom;
|
|
||||||
bitSet = bitSetFrom;
|
|
||||||
pvValue = pvStructure->getSubField("value");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PvaClientGetData::hasValue()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PvaClientGetData::isValueScalar()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
if(pvValue->getField()->getType()==scalar) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PvaClientGetData::isValueScalarArray()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
if(pvValue->getField()->getType()==scalarArray) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVFieldPtr PvaClientGetData::getValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
return pvValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVScalarPtr PvaClientGetData::getScalarValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
|
|
||||||
if(!pv) throw std::runtime_error(messagePrefix + noScalar);
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVArrayPtr PvaClientGetData::getArrayValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
|
|
||||||
if(!pv) throw std::runtime_error(messagePrefix + noArray);
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVScalarArrayPtr PvaClientGetData::getScalarArrayValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
|
|
||||||
if(!pv) throw std::runtime_error(messagePrefix + noScalarArray);
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
double PvaClientGetData::getDouble()
|
|
||||||
{
|
|
||||||
PVScalarPtr pvScalar = getScalarValue();
|
|
||||||
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
|
||||||
if(scalarType==pvDouble) {
|
|
||||||
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
|
||||||
return pvDouble->get();
|
|
||||||
}
|
|
||||||
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
|
||||||
throw std::runtime_error(messagePrefix + notCompatibleScalar);
|
|
||||||
}
|
|
||||||
return convert->toDouble(pvScalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
string PvaClientGetData::getString()
|
|
||||||
{
|
|
||||||
PVScalarPtr pvScalar = getScalarValue();
|
|
||||||
return convert->toString(pvScalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_vector<const double> PvaClientGetData::getDoubleArray()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
|
|
||||||
if(!pv) throw std::runtime_error(messagePrefix + notDoubleArray);
|
|
||||||
return pv->view();
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_vector<const string> PvaClientGetData::getStringArray()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
|
|
||||||
if(!pv) throw std::runtime_error(messagePrefix + notStringArray);
|
|
||||||
return pv->view();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Alarm PvaClientGetData::getAlarm()
|
|
||||||
{
|
|
||||||
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
|
|
||||||
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("alarm");
|
|
||||||
if(!pvs) throw std::runtime_error(messagePrefix + noAlarm);
|
|
||||||
pvAlarm.attach(pvs);
|
|
||||||
if(pvAlarm.isAttached()) {
|
|
||||||
Alarm alarm;
|
|
||||||
pvAlarm.get(alarm);
|
|
||||||
pvAlarm.detach();
|
|
||||||
return alarm;
|
|
||||||
}
|
|
||||||
throw std::runtime_error(messagePrefix + noAlarm);
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeStamp PvaClientGetData::getTimeStamp()
|
|
||||||
{
|
|
||||||
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
|
|
||||||
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("timeStamp");
|
|
||||||
if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp);
|
|
||||||
pvTimeStamp.attach(pvs);
|
|
||||||
if(pvTimeStamp.isAttached()) {
|
|
||||||
TimeStamp timeStamp;
|
|
||||||
pvTimeStamp.get(timeStamp);
|
|
||||||
pvTimeStamp.detach();
|
|
||||||
return timeStamp;
|
|
||||||
}
|
|
||||||
throw std::runtime_error(messagePrefix + noTimeStamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
+342
-97
@@ -8,84 +8,205 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.03
|
* @date 2015.03
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
#include <pv/bitSetUtil.h>
|
#include <pv/bitSetUtil.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
|
class MonitorRequesterImpl : public MonitorRequester
|
||||||
class ChannelMonitorRequester : public MonitorRequester
|
|
||||||
{
|
{
|
||||||
PvaClientMonitor * pvaClientMonitor;
|
PvaClientMonitor::weak_pointer pvaClientMonitor;
|
||||||
|
PvaClient::weak_pointer pvaClient;
|
||||||
public:
|
public:
|
||||||
ChannelMonitorRequester(PvaClientMonitor * pvaClientMonitor)
|
MonitorRequesterImpl(
|
||||||
: pvaClientMonitor(pvaClientMonitor) {}
|
PvaClientMonitorPtr const & pvaClientMonitor,
|
||||||
string getRequesterName()
|
PvaClientPtr const &pvaClient)
|
||||||
{return pvaClientMonitor->getRequesterName();}
|
: pvaClientMonitor(pvaClientMonitor),
|
||||||
void message(string const & message,MessageType messageType)
|
pvaClient(pvaClient)
|
||||||
{pvaClientMonitor->message(message,messageType);}
|
{}
|
||||||
void monitorConnect(
|
virtual ~MonitorRequesterImpl() {
|
||||||
|
if(PvaClient::getDebug()) std::cout << "~MonitorRequesterImpl" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string getRequesterName() {
|
||||||
|
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||||
|
if(!clientMonitor) return string("pvaClientMonitor is null");
|
||||||
|
return clientMonitor->getRequesterName();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void message(std::string const & message, MessageType messageType) {
|
||||||
|
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||||
|
if(!clientMonitor) return;
|
||||||
|
clientMonitor->message(message,messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void monitorConnect(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
Monitor::shared_pointer const & monitor,
|
Monitor::shared_pointer const & monitor,
|
||||||
StructureConstPtr const & structure)
|
Structure::const_shared_pointer const & structure)
|
||||||
{pvaClientMonitor->monitorConnect(status,monitor,structure);}
|
|
||||||
void monitorEvent(MonitorPtr const & monitor)
|
|
||||||
{
|
{
|
||||||
pvaClientMonitor->monitorEvent(monitor);
|
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||||
|
if(!clientMonitor) return;
|
||||||
|
clientMonitor->monitorConnect(status,monitor,structure);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void unlisten(MonitorPtr const & monitor)
|
||||||
|
{
|
||||||
|
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||||
|
if(!clientMonitor) return;
|
||||||
|
clientMonitor->unlisten(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void monitorEvent(MonitorPtr const & monitor)
|
||||||
|
{
|
||||||
|
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||||
|
if(!clientMonitor) return;
|
||||||
|
clientMonitor->monitorEvent(monitor);
|
||||||
}
|
}
|
||||||
void unlisten(MonitorPtr const & monitor)
|
|
||||||
{pvaClientMonitor->unlisten();}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PvaClientMonitorPtr PvaClientMonitor::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
|
PVStructurePtr const &pvRequest)
|
||||||
|
{
|
||||||
|
PvaClientMonitorPtr clientMonitor(new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
|
||||||
|
clientMonitor->monitorRequester = MonitorRequesterImplPtr(
|
||||||
|
new MonitorRequesterImpl(clientMonitor,pvaClient));
|
||||||
|
return clientMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
PvaClientMonitorPtr PvaClientMonitor::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
std::string const & channelName,
|
||||||
|
std::string const & providerName,
|
||||||
|
std::string const & request,
|
||||||
|
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester,
|
||||||
|
PvaClientMonitorRequesterPtr const & monitorRequester)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientMonitor::create(pvaClient,channelName,providerName,request,stateChangeRequester,monitorRequester)\n"
|
||||||
|
<< " channelName " << channelName
|
||||||
|
<< " providerName " << providerName
|
||||||
|
<< " request " << request
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
CreateRequest::shared_pointer createRequest(CreateRequest::create());
|
||||||
|
PVStructurePtr pvRequest(createRequest->createRequest(request));
|
||||||
|
if(!pvRequest) throw std::runtime_error(createRequest->getMessage());
|
||||||
|
PvaClientChannelPtr pvaClientChannel = pvaClient->createChannel(channelName,providerName);
|
||||||
|
PvaClientMonitorPtr clientMonitor(new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
|
||||||
|
clientMonitor->monitorRequester = MonitorRequesterImplPtr(
|
||||||
|
new MonitorRequesterImpl(clientMonitor,pvaClient));
|
||||||
|
if(stateChangeRequester) clientMonitor->pvaClientChannelStateChangeRequester = stateChangeRequester;
|
||||||
|
if(monitorRequester) clientMonitor->pvaClientMonitorRequester = monitorRequester;
|
||||||
|
pvaClientChannel->setStateChangeRequester(clientMonitor);
|
||||||
|
pvaClientChannel->issueConnect();
|
||||||
|
return clientMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientMonitor::PvaClientMonitor(
|
PvaClientMonitor::PvaClientMonitor(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
Channel::shared_pointer const & channel,
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
PVStructurePtr const &pvRequest)
|
PVStructurePtr const &pvRequest)
|
||||||
: pvaClient(pvaClient),
|
: pvaClient(pvaClient),
|
||||||
channel(channel),
|
pvaClientChannel(pvaClientChannel),
|
||||||
pvRequest(pvRequest),
|
pvRequest(pvRequest),
|
||||||
isDestroyed(false),
|
isStarted(false),
|
||||||
connectState(connectIdle),
|
connectState(connectIdle),
|
||||||
userPoll(false),
|
userPoll(false),
|
||||||
userWait(false)
|
userWait(false)
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientMonitor::PvaClientMonitor\n"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientMonitor::~PvaClientMonitor()
|
PvaClientMonitor::~PvaClientMonitor()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientMonitor::~PvaClientMonitor"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(monitor) {
|
||||||
|
if(isStarted) monitor->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientMonitor::channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientMonitor::channelStateChange"
|
||||||
|
<< " channelName " << channel->getChannelName()
|
||||||
|
<< " isConnected " << (isConnected ? "true" : "false")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(isConnected&&!monitor)
|
||||||
|
{
|
||||||
|
connectState = connectActive;
|
||||||
|
monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
|
||||||
|
}
|
||||||
|
PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->channelStateChange(channel,isConnected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientMonitor::event(PvaClientMonitorPtr const & monitor)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::event"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
|
||||||
|
if(req) req->event(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::checkMonitorState()
|
void PvaClientMonitor::checkMonitorState()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState==connectIdle) connect();
|
cout << "PvaClientMonitor::checkMonitorState"
|
||||||
if(connectState==connected) start();
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< " connectState " << connectState
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(connectState==connectIdle) {
|
||||||
|
connect();
|
||||||
|
if(!isStarted) start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(connectState==connectActive){
|
||||||
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " "
|
||||||
|
+ monitorConnectStatus.getMessage();
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from MonitorRequester
|
|
||||||
string PvaClientMonitor::getRequesterName()
|
string PvaClientMonitor::getRequesterName()
|
||||||
{
|
{
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
return pvaClientChannel->getRequesterName();
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
return yyy->getRequesterName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::message(string const & message,MessageType messageType)
|
void PvaClientMonitor::message(string const & message,MessageType messageType)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
pvaClientChannel->message(message,messageType);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
yyy->message(message, messageType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::monitorConnect(
|
void PvaClientMonitor::monitorConnect(
|
||||||
@@ -93,119 +214,234 @@ void PvaClientMonitor::monitorConnect(
|
|||||||
Monitor::shared_pointer const & monitor,
|
Monitor::shared_pointer const & monitor,
|
||||||
StructureConstPtr const & structure)
|
StructureConstPtr const & structure)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
connectStatus = status;
|
cout << "PvaClientMonitor::monitorConnect"
|
||||||
this->monitor = monitor;
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
if(status.isOK()) {
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
pvaClientData = PvaClientMonitorData::create(structure);
|
<< endl;
|
||||||
pvaClientData->setMessagePrefix(channel->getChannelName());
|
|
||||||
}
|
}
|
||||||
waitForConnect.signal();
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
monitorConnectStatus = status;
|
||||||
|
if(status.isOK()) {
|
||||||
|
this->monitor = monitor;
|
||||||
|
} else {
|
||||||
|
stringstream ss;
|
||||||
|
ss << pvRequest;
|
||||||
|
string message = string("\nPvaClientMonitor::monitorConnect)")
|
||||||
|
+ "\nchannelName=" + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ "\npvRequest\n" + ss.str()
|
||||||
|
+ "\nerror\n" + status.getMessage();
|
||||||
|
monitorConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
|
||||||
|
waitForConnect.signal();
|
||||||
|
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
|
||||||
|
if(req) req->monitorConnect(status,shared_from_this(),structure);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool signal = (connectState==connectWait) ? true : false;
|
||||||
|
connectState = connected;
|
||||||
|
if(isStarted) {
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::monitorConnect"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< " is already started "
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
waitForConnect.signal();
|
||||||
|
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
|
||||||
|
if(req) req->monitorConnect(status,shared_from_this(),structure);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pvaClientData = PvaClientMonitorData::create(structure);
|
||||||
|
pvaClientData->setMessagePrefix(pvaClientChannel->getChannel()->getChannelName());
|
||||||
|
if(signal) {
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::monitorConnect calling waitForConnect.signal\n";
|
||||||
|
}
|
||||||
|
waitForConnect.signal();
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::monitorConnect calling start\n";
|
||||||
|
}
|
||||||
|
start();
|
||||||
|
} else {
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::monitorConnect calling start\n";
|
||||||
|
}
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
|
||||||
|
if(req) req->monitorConnect(status,shared_from_this(),structure);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor)
|
void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::monitorEvent"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
|
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
|
||||||
if(req) req->event(getPtrSelf());
|
if(req) req->event(shared_from_this());
|
||||||
if(userWait) waitForEvent.signal();
|
if(userWait) waitForEvent.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::unlisten()
|
void PvaClientMonitor::unlisten(MonitorPtr const & monitor)
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout << "PvaClientMonitor::unlisten\n";
|
||||||
|
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
|
||||||
|
if(req) {
|
||||||
|
req->unlisten();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
if(monitor) monitor->destroy();
|
|
||||||
monitor.reset();
|
|
||||||
monitorElement.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientMonitor::connect()
|
void PvaClientMonitor::connect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) cout << "PvaClientMonitor::connect\n";
|
||||||
issueConnect();
|
issueConnect();
|
||||||
Status status = waitConnect();
|
Status status = waitConnect();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientMonitor::connect " + status.getMessage();
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientMonitor::connect "
|
||||||
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::issueConnect()
|
void PvaClientMonitor::issueConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) cout << "PvaClientMonitor::issueConnect\n";
|
||||||
if(connectState!=connectIdle) {
|
if(connectState!=connectIdle) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientMonitor already connected ";
|
+ " pvaClientMonitor already connected ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
monitorRequester = ChannelMonitorRequester::shared_pointer(new ChannelMonitorRequester(this));
|
connectState = connectWait;
|
||||||
connectState = connectActive;
|
monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
|
||||||
monitor = channel->createMonitor(monitorRequester,pvRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PvaClientMonitor::waitConnect()
|
Status PvaClientMonitor::waitConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState!=connectActive) {
|
cout << "PvaClientMonitor::waitConnect "
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientMonitor illegal connect state ";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForConnect.wait();
|
waitForConnect.wait();
|
||||||
connectState = connectStatus.isOK() ? connected : connectIdle;
|
if(PvaClient::getDebug()) {
|
||||||
return connectStatus;
|
cout << "PvaClientMonitor::waitConnect"
|
||||||
|
<< " monitorConnectStatus " << (monitorConnectStatus.isOK() ? "connected" : "not connected")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
return monitorConnectStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::setRequester(PvaClientMonitorRequesterPtr const & pvaClientMonitorrRequester)
|
void PvaClientMonitor::setRequester(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester)
|
||||||
{
|
{
|
||||||
this->pvaClientMonitorRequester = pvaClientMonitorrRequester;
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::setRequester"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
this->pvaClientMonitorRequester = pvaClientMonitorRequester;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitor::start()
|
void PvaClientMonitor::start()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState==monitorStarted) return;
|
cout << "PvaClientMonitor::start"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< " connectState " << connectState
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(isStarted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(connectState==connectIdle) connect();
|
if(connectState==connectIdle) connect();
|
||||||
if(connectState!=connected) throw std::runtime_error("PvaClientMonitor::start illegal state");
|
if(connectState!=connected) {
|
||||||
connectState = monitorStarted;
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientMonitor::start illegal state ";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
isStarted = true;
|
||||||
monitor->start();
|
monitor->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PvaClientMonitor::start(string const & request)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaMonitor::start(request)"
|
||||||
|
<< " request " << request
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
PvaClientPtr client(pvaClient.lock());
|
||||||
|
if(!client) throw std::runtime_error("pvaClient was deleted");
|
||||||
|
if(!pvaClientChannel->getChannel()->isConnected()) {
|
||||||
|
client->message(
|
||||||
|
"PvaClientMonitor::start(request) but not connected",
|
||||||
|
errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CreateRequest::shared_pointer createRequest(CreateRequest::create());
|
||||||
|
PVStructurePtr pvr(createRequest->createRequest(request));
|
||||||
|
if(!pvr) throw std::runtime_error(createRequest->getMessage());
|
||||||
|
if(monitor) {
|
||||||
|
if(isStarted) monitor->stop();
|
||||||
|
}
|
||||||
|
monitorRequester.reset();
|
||||||
|
monitor.reset();
|
||||||
|
isStarted = false;
|
||||||
|
connectState = connectIdle;
|
||||||
|
userPoll = false;
|
||||||
|
userWait = false;
|
||||||
|
monitorRequester = MonitorRequesterImplPtr(
|
||||||
|
new MonitorRequesterImpl(shared_from_this(),client));
|
||||||
|
pvRequest = pvr;
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PvaClientMonitor::stop()
|
void PvaClientMonitor::stop()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState!=monitorStarted) return;
|
cout << "PvaClientMonitor::stop"
|
||||||
connectState = connected;
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(!isStarted) return;
|
||||||
|
isStarted = false;
|
||||||
monitor->stop();
|
monitor->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PvaClientMonitor::poll()
|
bool PvaClientMonitor::poll()
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::poll"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
checkMonitorState();
|
checkMonitorState();
|
||||||
if(connectState!=monitorStarted) throw std::runtime_error("PvaClientMonitor::poll illegal state");
|
|
||||||
if(userPoll) throw std::runtime_error("PvaClientMonitor::poll did not release last");
|
|
||||||
monitorElement = monitor->poll();
|
monitorElement = monitor->poll();
|
||||||
if(!monitorElement) return false;
|
if(!monitorElement) return false;
|
||||||
userPoll = true;
|
userPoll = true;
|
||||||
pvaClientData->setData(monitorElement);
|
pvaClientData->setData(monitorElement);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PvaClientMonitor::waitEvent(double secondsToWait)
|
bool PvaClientMonitor::waitEvent(double secondsToWait)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState!=monitorStarted) throw std::runtime_error("PvaClientMonitor::waitEvent illegal state");
|
cout << "PvaClientMonitor::waitEvent"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(!isStarted) {
|
||||||
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientMonitor::waitEvent illegal state ";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
if(poll()) return true;
|
if(poll()) return true;
|
||||||
userWait = true;
|
userWait = true;
|
||||||
if(secondsToWait==0.0) {
|
if(secondsToWait==0.0) {
|
||||||
@@ -219,26 +455,35 @@ bool PvaClientMonitor::waitEvent(double secondsToWait)
|
|||||||
|
|
||||||
void PvaClientMonitor::releaseEvent()
|
void PvaClientMonitor::releaseEvent()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState!=monitorStarted) throw std::runtime_error("PvaClientMonitor::poll illegal state");
|
cout << "PvaClientMonitor::releaseEvent"
|
||||||
if(!userPoll) throw std::runtime_error("PvaClientMonitor::releaseEvent did not call poll");
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(!userPoll) {
|
||||||
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientMonitor::releaseEvent did not call poll";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
userPoll = false;
|
userPoll = false;
|
||||||
monitor->release(monitorElement);
|
monitor->release(monitorElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PvaClientChannelPtr PvaClientMonitor::getPvaClientChannel()
|
||||||
|
{
|
||||||
|
return pvaClientChannel;
|
||||||
|
}
|
||||||
|
|
||||||
PvaClientMonitorDataPtr PvaClientMonitor::getData()
|
PvaClientMonitorDataPtr PvaClientMonitor::getData()
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientMonitor::getData"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
checkMonitorState();
|
checkMonitorState();
|
||||||
return pvaClientData;
|
return pvaClientData;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientMonitorPtr PvaClientMonitor::create(
|
|
||||||
PvaClientPtr const &pvaClient,
|
|
||||||
Channel::shared_pointer const & channel,
|
|
||||||
PVStructurePtr const &pvRequest)
|
|
||||||
{
|
|
||||||
PvaClientMonitorPtr epv(new PvaClientMonitor(pvaClient,channel,pvRequest));
|
|
||||||
return epv;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
+10
-186
@@ -8,17 +8,17 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
#include <pv/createRequest.h>
|
#include <pv/createRequest.h>
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -52,43 +52,16 @@ PvaClientMonitorDataPtr PvaClientMonitorData::create(StructureConstPtr const & s
|
|||||||
}
|
}
|
||||||
|
|
||||||
PvaClientMonitorData::PvaClientMonitorData(StructureConstPtr const & structure)
|
PvaClientMonitorData::PvaClientMonitorData(StructureConstPtr const & structure)
|
||||||
: structure(structure)
|
: PvaClientData(structure)
|
||||||
{
|
{
|
||||||
messagePrefix = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMonitorData::setData(MonitorElementPtr const & monitorElement)
|
void PvaClientMonitorData::setData(MonitorElementPtr const & monitorElement)
|
||||||
{
|
{
|
||||||
pvStructure = monitorElement->pvStructurePtr;
|
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
|
||||||
changedBitSet = monitorElement->changedBitSet;
|
BitSetPtr changedBitSet = monitorElement->changedBitSet;
|
||||||
|
PvaClientData::setData(pvStructure,changedBitSet);
|
||||||
overrunBitSet = monitorElement->overrunBitSet;
|
overrunBitSet = monitorElement->overrunBitSet;
|
||||||
pvValue = pvStructure->getSubField("value");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientMonitorData::checkValue()
|
|
||||||
{
|
|
||||||
if(pvValue) return;
|
|
||||||
throw std::runtime_error(messagePrefix + noValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientMonitorData::setMessagePrefix(std::string const & value)
|
|
||||||
{
|
|
||||||
messagePrefix = value + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
StructureConstPtr PvaClientMonitorData::getStructure()
|
|
||||||
{return structure;}
|
|
||||||
|
|
||||||
PVStructurePtr PvaClientMonitorData::getPVStructure()
|
|
||||||
{
|
|
||||||
if(pvStructure) return pvStructure;
|
|
||||||
throw std::runtime_error(messagePrefix + noStructure);
|
|
||||||
}
|
|
||||||
|
|
||||||
BitSetPtr PvaClientMonitorData::getChangedBitSet()
|
|
||||||
{
|
|
||||||
if(!changedBitSet) throw std::runtime_error(messagePrefix + noStructure);
|
|
||||||
return changedBitSet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BitSetPtr PvaClientMonitorData::getOverrunBitSet()
|
BitSetPtr PvaClientMonitorData::getOverrunBitSet()
|
||||||
@@ -97,24 +70,6 @@ BitSetPtr PvaClientMonitorData::getOverrunBitSet()
|
|||||||
return overrunBitSet;
|
return overrunBitSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream & PvaClientMonitorData::showChanged(std::ostream & out)
|
|
||||||
{
|
|
||||||
if(!changedBitSet) throw std::runtime_error(messagePrefix + noStructure);
|
|
||||||
size_t nextSet = changedBitSet->nextSetBit(0);
|
|
||||||
PVFieldPtr pvField;
|
|
||||||
while(nextSet!=string::npos) {
|
|
||||||
if(nextSet==0) {
|
|
||||||
pvField = pvStructure;
|
|
||||||
} else {
|
|
||||||
pvField = pvStructure->getSubField(nextSet);
|
|
||||||
}
|
|
||||||
string name = pvField->getFullName();
|
|
||||||
out << name << " = " << pvField << endl;
|
|
||||||
nextSet = changedBitSet->nextSetBit(nextSet+1);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out)
|
std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out)
|
||||||
{
|
{
|
||||||
if(!overrunBitSet) throw std::runtime_error(messagePrefix + noStructure);
|
if(!overrunBitSet) throw std::runtime_error(messagePrefix + noStructure);
|
||||||
@@ -122,9 +77,9 @@ std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out)
|
|||||||
PVFieldPtr pvField;
|
PVFieldPtr pvField;
|
||||||
while(nextSet!=string::npos) {
|
while(nextSet!=string::npos) {
|
||||||
if(nextSet==0) {
|
if(nextSet==0) {
|
||||||
pvField = pvStructure;
|
pvField = getPVStructure();
|
||||||
} else {
|
} else {
|
||||||
pvField = pvStructure->getSubField(nextSet);
|
pvField = getPVStructure()->getSubField(nextSet);
|
||||||
}
|
}
|
||||||
string name = pvField->getFullName();
|
string name = pvField->getFullName();
|
||||||
out << name << " = " << pvField << endl;
|
out << name << " = " << pvField << endl;
|
||||||
@@ -133,135 +88,4 @@ std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PvaClientMonitorData::hasValue()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PvaClientMonitorData::isValueScalar()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
if(pvValue->getField()->getType()==scalar) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PvaClientMonitorData::isValueScalarArray()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
if(pvValue->getField()->getType()==scalarArray) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVFieldPtr PvaClientMonitorData::getValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
return pvValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVScalarPtr PvaClientMonitorData::getScalarValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
|
|
||||||
if(!pv) {
|
|
||||||
throw std::runtime_error(messagePrefix + noScalar);
|
|
||||||
}
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVArrayPtr PvaClientMonitorData::getArrayValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
|
|
||||||
if(!pv) {
|
|
||||||
throw std::runtime_error(messagePrefix + noArray);
|
|
||||||
}
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVScalarArrayPtr PvaClientMonitorData::getScalarArrayValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
|
|
||||||
if(!pv) {
|
|
||||||
throw std::runtime_error(messagePrefix + noScalarArray);
|
|
||||||
}
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
double PvaClientMonitorData::getDouble()
|
|
||||||
{
|
|
||||||
PVScalarPtr pvScalar = getScalarValue();
|
|
||||||
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
|
||||||
if(scalarType==pvDouble) {
|
|
||||||
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
|
||||||
return pvDouble->get();
|
|
||||||
}
|
|
||||||
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
|
||||||
throw std::runtime_error(messagePrefix + notCompatibleScalar);
|
|
||||||
}
|
|
||||||
return convert->toDouble(pvScalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
string PvaClientMonitorData::getString()
|
|
||||||
{
|
|
||||||
PVScalarPtr pvScalar = getScalarValue();
|
|
||||||
return convert->toString(pvScalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_vector<const double> PvaClientMonitorData::getDoubleArray()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
|
|
||||||
if(!pv) {
|
|
||||||
throw std::runtime_error(messagePrefix + notDoubleArray);
|
|
||||||
}
|
|
||||||
return pv->view();
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_vector<const string> PvaClientMonitorData::getStringArray()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
|
|
||||||
if(!pv) {
|
|
||||||
throw std::runtime_error(messagePrefix + notStringArray);
|
|
||||||
}
|
|
||||||
return pv->view();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Alarm PvaClientMonitorData::getAlarm()
|
|
||||||
{
|
|
||||||
if(!pvStructure) {
|
|
||||||
throw std::runtime_error(messagePrefix + noAlarm);
|
|
||||||
}
|
|
||||||
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("alarm");
|
|
||||||
if(!pvs) throw std::runtime_error(messagePrefix + noAlarm);
|
|
||||||
pvAlarm.attach(pvs);
|
|
||||||
if(pvAlarm.isAttached()) {
|
|
||||||
Alarm alarm;
|
|
||||||
pvAlarm.get(alarm);
|
|
||||||
pvAlarm.detach();
|
|
||||||
return alarm;
|
|
||||||
}
|
|
||||||
throw std::runtime_error(messagePrefix + noAlarm);
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeStamp PvaClientMonitorData::getTimeStamp()
|
|
||||||
{
|
|
||||||
if(!pvStructure) {
|
|
||||||
throw std::runtime_error(messagePrefix + noTimeStamp);
|
|
||||||
}
|
|
||||||
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("timeStamp");
|
|
||||||
if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp);
|
|
||||||
pvTimeStamp.attach(pvs);
|
|
||||||
if(pvTimeStamp.isAttached()) {
|
|
||||||
TimeStamp timeStamp;
|
|
||||||
pvTimeStamp.get(timeStamp);
|
|
||||||
pvTimeStamp.detach();
|
|
||||||
return timeStamp;
|
|
||||||
}
|
|
||||||
throw std::runtime_error(messagePrefix + noTimeStamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -8,16 +8,15 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
#include <pv/pvaClientMultiChannel.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -29,71 +28,74 @@ static CreateRequest::shared_pointer createRequestPvt = CreateRequest::create()
|
|||||||
|
|
||||||
PvaClientMultiChannelPtr PvaClientMultiChannel::create(
|
PvaClientMultiChannelPtr PvaClientMultiChannel::create(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
epics::pvData::shared_vector<const string> const & channelNames,
|
shared_vector<const string> const & channelNames,
|
||||||
string const & providerName,
|
string const & providerName,
|
||||||
size_t maxNotConnected)
|
size_t maxNotConnected,
|
||||||
|
shared_vector<const string> const & providerNames)
|
||||||
{
|
{
|
||||||
return PvaClientMultiChannelPtr(
|
return PvaClientMultiChannelPtr(
|
||||||
new PvaClientMultiChannel(pvaClient,channelNames,providerName,maxNotConnected));
|
new PvaClientMultiChannel(
|
||||||
|
pvaClient,channelNames,providerName,maxNotConnected,providerNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientMultiChannel::PvaClientMultiChannel(
|
PvaClientMultiChannel::PvaClientMultiChannel(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
epics::pvData::shared_vector<const string> const & channelName,
|
shared_vector<const string> const & channelNames,
|
||||||
string const & providerName,
|
string const & providerName,
|
||||||
size_t maxNotConnected)
|
size_t maxNotConnected,
|
||||||
|
shared_vector<const string> const & providerNames)
|
||||||
: pvaClient(pvaClient),
|
: pvaClient(pvaClient),
|
||||||
channelName(channelName),
|
channelNames(channelNames),
|
||||||
providerName(providerName),
|
providerName(providerName),
|
||||||
maxNotConnected(maxNotConnected),
|
maxNotConnected(maxNotConnected),
|
||||||
numChannel(channelName.size()),
|
providerNames(providerNames),
|
||||||
|
numChannel(channelNames.size()),
|
||||||
|
numProviderNames(providerNames.size()),
|
||||||
numConnected(0),
|
numConnected(0),
|
||||||
|
firstConnect(true),
|
||||||
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
|
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
|
||||||
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
|
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
|
||||||
createRequest(CreateRequest::create()),
|
createRequest(CreateRequest::create())
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout<< "PvaClientMultiChannel::PvaClientMultiChannel()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientMultiChannel::~PvaClientMultiChannel()
|
PvaClientMultiChannel::~PvaClientMultiChannel()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout<< "PvaClientMultiChannel::~PvaClientMultiChannel()\n";
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientMultiChannel::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
pvaClientChannelArray.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMultiChannel::checkConnected()
|
void PvaClientMultiChannel::checkConnected()
|
||||||
{
|
{
|
||||||
if(numConnected==0) connect(3.0);
|
if(firstConnect) {
|
||||||
|
connect();
|
||||||
|
firstConnect = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames()
|
shared_vector<const string> PvaClientMultiChannel::getChannelNames()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
return channelNames;
|
||||||
return channelName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PvaClientMultiChannel::connect(double timeout)
|
Status PvaClientMultiChannel::connect(double timeout)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
if(!firstConnect) return Status::Ok;
|
||||||
|
firstConnect = false;
|
||||||
for(size_t i=0; i< numChannel; ++i) {
|
for(size_t i=0; i< numChannel; ++i) {
|
||||||
pvaClientChannelArray[i] = pvaClient->createChannel(channelName[i],providerName);
|
if(numProviderNames<=i) {
|
||||||
|
pvaClientChannelArray[i] = pvaClient->createChannel(channelNames[i],providerName);
|
||||||
|
} else {
|
||||||
|
pvaClientChannelArray[i] = pvaClient->createChannel(channelNames[i],providerNames[i]);
|
||||||
|
}
|
||||||
pvaClientChannelArray[i]->issueConnect();
|
pvaClientChannelArray[i]->issueConnect();
|
||||||
}
|
}
|
||||||
Status returnStatus = Status::Ok;
|
Status returnStatus = Status::Ok;
|
||||||
Status status = Status::Ok;
|
Status status = Status::Ok;
|
||||||
size_t numBad = 0;
|
size_t numBad = 0;
|
||||||
for(size_t i=0; i< numChannel; ++i) {
|
for(size_t i=0; i< numChannel; ++i) {
|
||||||
if(numBad==0) {
|
if(numBad==0) {
|
||||||
status = pvaClientChannelArray[i]->waitConnect(timeout);
|
status = pvaClientChannelArray[i]->waitConnect(timeout);
|
||||||
} else {
|
} else {
|
||||||
status = pvaClientChannelArray[i]->waitConnect(.001);
|
status = pvaClientChannelArray[i]->waitConnect(.001);
|
||||||
@@ -101,11 +103,10 @@ Status PvaClientMultiChannel::connect(double timeout)
|
|||||||
if(status.isOK()) {
|
if(status.isOK()) {
|
||||||
++numConnected;
|
++numConnected;
|
||||||
isConnected[i] = true;
|
isConnected[i] = true;
|
||||||
continue;
|
} else {
|
||||||
|
if(returnStatus.isOK()) returnStatus = status;
|
||||||
|
++numBad;
|
||||||
}
|
}
|
||||||
if(returnStatus.isOK()) returnStatus = status;
|
|
||||||
++numBad;
|
|
||||||
if(numBad>maxNotConnected) break;
|
|
||||||
}
|
}
|
||||||
return numBad>maxNotConnected ? returnStatus : Status::Ok;
|
return numBad>maxNotConnected ? returnStatus : Status::Ok;
|
||||||
}
|
}
|
||||||
@@ -113,13 +114,11 @@ Status PvaClientMultiChannel::connect(double timeout)
|
|||||||
|
|
||||||
bool PvaClientMultiChannel::allConnected()
|
bool PvaClientMultiChannel::allConnected()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
|
||||||
return (numConnected==numChannel) ? true : false;
|
return (numConnected==numChannel) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PvaClientMultiChannel::connectionChange()
|
bool PvaClientMultiChannel::connectionChange()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
|
||||||
for(size_t i=0; i<numChannel; ++i) {
|
for(size_t i=0; i<numChannel; ++i) {
|
||||||
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
|
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
|
||||||
Channel::shared_pointer channel = pvaClientChannel->getChannel();
|
Channel::shared_pointer channel = pvaClientChannel->getChannel();
|
||||||
@@ -130,9 +129,8 @@ bool PvaClientMultiChannel::connectionChange()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
|
shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
|
||||||
for(size_t i=0; i<numChannel; ++i) {
|
for(size_t i=0; i<numChannel; ++i) {
|
||||||
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
|
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
|
||||||
if(!pvaClientChannel) {
|
if(!pvaClientChannel) {
|
||||||
@@ -148,50 +146,43 @@ epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::get
|
|||||||
|
|
||||||
PvaClientChannelArray PvaClientMultiChannel::getPvaClientChannelArray()
|
PvaClientChannelArray PvaClientMultiChannel::getPvaClientChannelArray()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
|
||||||
return pvaClientChannelArray;
|
return pvaClientChannelArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPtr PvaClientMultiChannel::getPvaClient()
|
PvaClientPtr PvaClientMultiChannel::getPvaClient()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
|
||||||
return pvaClient;
|
return pvaClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet()
|
PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet()
|
||||||
{
|
{
|
||||||
checkConnected();
|
checkConnected();
|
||||||
return PvaClientMultiGetDouble::create(getPtrSelf(),pvaClientChannelArray);
|
return PvaClientMultiGetDouble::create(shared_from_this(),pvaClientChannelArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientMultiPutDoublePtr PvaClientMultiChannel::createPut()
|
PvaClientMultiPutDoublePtr PvaClientMultiChannel::createPut()
|
||||||
{
|
{
|
||||||
checkConnected();
|
checkConnected();
|
||||||
return PvaClientMultiPutDouble::create(getPtrSelf(),pvaClientChannelArray);
|
return PvaClientMultiPutDouble::create(shared_from_this(),pvaClientChannelArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor()
|
PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor()
|
||||||
{
|
{
|
||||||
checkConnected();
|
checkConnected();
|
||||||
return PvaClientMultiMonitorDouble::create(getPtrSelf(), pvaClientChannelArray);
|
return PvaClientMultiMonitorDouble::create(shared_from_this(), pvaClientChannelArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientNTMultiPutPtr PvaClientMultiChannel::createNTPut()
|
PvaClientNTMultiPutPtr PvaClientMultiChannel::createNTPut()
|
||||||
{
|
{
|
||||||
checkConnected();
|
checkConnected();
|
||||||
return PvaClientNTMultiPut::create(getPtrSelf(), pvaClientChannelArray);
|
return PvaClientNTMultiPut::create(shared_from_this(), pvaClientChannelArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet()
|
|
||||||
{
|
|
||||||
return createNTGet("value,alarm,timeStamp");
|
|
||||||
}
|
|
||||||
|
|
||||||
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &request)
|
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &request)
|
||||||
{
|
{
|
||||||
checkConnected();
|
checkConnected();
|
||||||
@@ -201,13 +192,7 @@ PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &req
|
|||||||
+ createRequest->getMessage();
|
+ createRequest->getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
return PvaClientNTMultiGet::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
|
return PvaClientNTMultiGet::create(shared_from_this(), pvaClientChannelArray,pvRequest);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor()
|
|
||||||
{
|
|
||||||
return createNTMonitor("value,alarm,timeStamp");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string const &request)
|
PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string const &request)
|
||||||
@@ -219,7 +204,7 @@ PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string co
|
|||||||
+ createRequest->getMessage();
|
+ createRequest->getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
return PvaClientNTMultiMonitor::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
|
return PvaClientNTMultiMonitor::create(shared_from_this(), pvaClientChannelArray,pvRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,24 +9,19 @@
|
|||||||
* @date 2015.03
|
* @date 2015.03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
#include <pv/standardField.h>
|
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
#include <epicsMath.h>
|
#include <epicsMath.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClientMultiChannel.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::nt;
|
using namespace epics::nt;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
|
||||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
|
||||||
static StandardFieldPtr standardField = getStandardField();
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientMultiGetDoublePtr PvaClientMultiGetDouble::create(
|
PvaClientMultiGetDoublePtr PvaClientMultiGetDouble::create(
|
||||||
@@ -44,31 +39,21 @@ PvaClientMultiGetDouble::PvaClientMultiGetDouble(
|
|||||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||||
pvaClientChannelArray(pvaClientChannelArray),
|
pvaClientChannelArray(pvaClientChannelArray),
|
||||||
nchannel(pvaClientChannelArray.size()),
|
nchannel(pvaClientChannelArray.size()),
|
||||||
doubleValue(shared_vector<double>(nchannel)),
|
doubleValue( shared_vector<double>(nchannel)),
|
||||||
pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())),
|
pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())),
|
||||||
isGetConnected(false),
|
isGetConnected(false)
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout<< "PvaClientMultiGetDouble::PvaClientMultiGetDouble()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientMultiGetDouble::~PvaClientMultiGetDouble()
|
PvaClientMultiGetDouble::~PvaClientMultiGetDouble()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout<< "PvaClientMultiGetDouble::~PvaClientMultiGetDouble()\n";
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientMultiGetDouble::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
pvaClientChannelArray.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMultiGetDouble::connect()
|
void PvaClientMultiGetDouble::connect()
|
||||||
{
|
{
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean>isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
string request = "value";
|
string request = "value";
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
@@ -90,14 +75,14 @@ void PvaClientMultiGetDouble::connect()
|
|||||||
isGetConnected = true;
|
isGetConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
|
shared_vector<double> PvaClientMultiGetDouble::get()
|
||||||
{
|
{
|
||||||
if(!isGetConnected) connect();
|
if(!isGetConnected) connect();
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
|
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
|
if(!pvaClientGet[i]) pvaClientGet[i]=pvaClientChannelArray[i]->createGet("value");
|
||||||
pvaClientGet[i]->issueGet();
|
pvaClientGet[i]->issueGet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,13 +96,22 @@ epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
|
|||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i])
|
if(isConnected[i])
|
||||||
{
|
{
|
||||||
PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure();
|
PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure();
|
||||||
doubleValue[i] = convert->toDouble(pvStructure->getSubField<PVScalar>("value"));
|
PVScalarPtr pvScalar(pvStructure->getSubField<PVScalar>("value"));
|
||||||
|
if(pvScalar) {
|
||||||
|
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
||||||
|
if(ScalarTypeFunc::isNumeric(scalarType)) {
|
||||||
|
doubleValue[i] = getConvert()->toDouble(pvScalar);
|
||||||
|
} else {
|
||||||
|
doubleValue[i] = epicsNAN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
doubleValue[i] = epicsNAN;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
doubleValue[i] = epicsNAN;
|
doubleValue[i] = epicsNAN;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,25 +9,19 @@
|
|||||||
* @date 2015.03
|
* @date 2015.03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
#include <pv/standardField.h>
|
|
||||||
#include <pv/convert.h>
|
|
||||||
#include <epicsMath.h>
|
#include <epicsMath.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClientMultiChannel.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::nt;
|
using namespace epics::nt;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
|
||||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
|
||||||
static StandardFieldPtr standardField = getStandardField();
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create(
|
PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create(
|
||||||
@@ -47,24 +41,14 @@ PvaClientMultiMonitorDouble::PvaClientMultiMonitorDouble(
|
|||||||
nchannel(pvaClientChannelArray.size()),
|
nchannel(pvaClientChannelArray.size()),
|
||||||
doubleValue(shared_vector<double>(nchannel,epicsNAN)),
|
doubleValue(shared_vector<double>(nchannel,epicsNAN)),
|
||||||
pvaClientMonitor(std::vector<PvaClientMonitorPtr>(nchannel,PvaClientMonitorPtr())),
|
pvaClientMonitor(std::vector<PvaClientMonitorPtr>(nchannel,PvaClientMonitorPtr())),
|
||||||
isMonitorConnected(false),
|
isMonitorConnected(false)
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout<< "PvaClientMultiMonitorDouble::PvaClientMultiMonitorDouble()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble()
|
PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout<< "PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble()\n";
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientMultiMonitorDouble::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
pvaClientChannelArray.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMultiMonitorDouble::connect()
|
void PvaClientMultiMonitorDouble::connect()
|
||||||
@@ -99,13 +83,24 @@ bool PvaClientMultiMonitorDouble::poll()
|
|||||||
{
|
{
|
||||||
if(!isMonitorConnected){
|
if(!isMonitorConnected){
|
||||||
connect();
|
connect();
|
||||||
epicsThreadSleep(.01);
|
epicsThreadSleep(.1);
|
||||||
}
|
}
|
||||||
bool result = false;
|
bool result = false;
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
|
if(!pvaClientMonitor[i]){
|
||||||
|
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor("value");
|
||||||
|
pvaClientMonitor[i]->issueConnect();
|
||||||
|
Status status = pvaClientMonitor[i]->waitConnect();
|
||||||
|
if(!status.isOK()) {
|
||||||
|
string message = string("channel ") + pvaClientChannelArray[i]->getChannelName()
|
||||||
|
+ " PvaChannelMonitor::waitConnect " + status.getMessage();
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
pvaClientMonitor[i]->start();
|
||||||
|
}
|
||||||
if(pvaClientMonitor[i]->poll()) {
|
if(pvaClientMonitor[i]->poll()) {
|
||||||
doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble();
|
doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble();
|
||||||
pvaClientMonitor[i]->releaseEvent();
|
pvaClientMonitor[i]->releaseEvent();
|
||||||
@@ -132,7 +127,7 @@ bool PvaClientMultiMonitorDouble::waitEvent(double waitForEvent)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get()
|
shared_vector<double> PvaClientMultiMonitorDouble::get()
|
||||||
{
|
{
|
||||||
return doubleValue;
|
return doubleValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,25 +9,19 @@
|
|||||||
* @date 2015.03
|
* @date 2015.03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
#include <pv/standardField.h>
|
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
#include <epicsMath.h>
|
#include <epicsMath.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClientMultiChannel.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::nt;
|
using namespace epics::nt;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
|
||||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
|
||||||
static StandardFieldPtr standardField = getStandardField();
|
|
||||||
static CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create(
|
PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create(
|
||||||
@@ -46,27 +40,18 @@ PvaClientMultiPutDouble::PvaClientMultiPutDouble(
|
|||||||
pvaClientChannelArray(pvaClientChannelArray),
|
pvaClientChannelArray(pvaClientChannelArray),
|
||||||
nchannel(pvaClientChannelArray.size()),
|
nchannel(pvaClientChannelArray.size()),
|
||||||
pvaClientPut(std::vector<PvaClientPutPtr>(nchannel,PvaClientPutPtr())),
|
pvaClientPut(std::vector<PvaClientPutPtr>(nchannel,PvaClientPutPtr())),
|
||||||
isPutConnected(false),
|
isPutConnected(false)
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout<< "PvaClientMultiPutDouble::PvaClientMultiPutDouble()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientMultiPutDouble::~PvaClientMultiPutDouble()
|
PvaClientMultiPutDouble::~PvaClientMultiPutDouble()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout<< "PvaClientMultiPutDouble::~PvaClientMultiPutDouble()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMultiPutDouble::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
pvaClientChannelArray.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientMultiPutDouble::connect()
|
void PvaClientMultiPutDouble::connect()
|
||||||
{
|
{
|
||||||
@@ -91,7 +76,7 @@ void PvaClientMultiPutDouble::connect()
|
|||||||
isPutConnected = true;
|
isPutConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data)
|
void PvaClientMultiPutDouble::put(shared_vector<double> const &data)
|
||||||
{
|
{
|
||||||
if(!isPutConnected) connect();
|
if(!isPutConnected) connect();
|
||||||
if(data.size()!=nchannel) {
|
if(data.size()!=nchannel) {
|
||||||
@@ -101,10 +86,18 @@ void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &da
|
|||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
|
if(!pvaClientPut[i]) pvaClientPut[i]=pvaClientChannelArray[i]->createPut("value");
|
||||||
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
|
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
|
||||||
PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value");
|
PVScalarPtr pvScalar= pvTop->getSubField<PVScalar>("value");
|
||||||
convert->fromDouble(pvValue,data[i]);
|
if(pvScalar && ScalarTypeFunc::isNumeric(pvScalar->getScalar()->getScalarType())) {
|
||||||
pvaClientPut[i]->issuePut();
|
getConvert()->fromDouble(pvScalar,data[i]);
|
||||||
|
pvaClientPut[i]->issuePut();
|
||||||
|
} else {
|
||||||
|
string message = string("channel ")
|
||||||
|
+ pvaClientChannelArray[i]->getChannelName()
|
||||||
|
+ " is not a numeric scalar";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
Status status = pvaClientPut[i]->waitPut();
|
Status status = pvaClientPut[i]->waitPut();
|
||||||
|
|||||||
@@ -9,23 +9,21 @@
|
|||||||
* @date 2015.03
|
* @date 2015.03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
#include <epicsMath.h>
|
#include <epicsMath.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClientMultiChannel.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::nt;
|
using namespace epics::nt;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
|
PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
|
||||||
epics::pvData::UnionConstPtr const & u,
|
UnionConstPtr const & u,
|
||||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
PVStructurePtr const & pvRequest)
|
PVStructurePtr const & pvRequest)
|
||||||
@@ -35,23 +33,23 @@ PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
PvaClientNTMultiData::PvaClientNTMultiData(
|
PvaClientNTMultiData::PvaClientNTMultiData(
|
||||||
epics::pvData::UnionConstPtr const & u,
|
UnionConstPtr const & u,
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
epics::pvData::PVStructurePtr const & pvRequest)
|
PVStructurePtr const & pvRequest)
|
||||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||||
pvaClientChannelArray(pvaClientChannelArray),
|
pvaClientChannelArray(pvaClientChannelArray),
|
||||||
nchannel(pvaClientChannelArray.size()),
|
nchannel(pvaClientChannelArray.size()),
|
||||||
gotAlarm(false),
|
gotAlarm(false),
|
||||||
gotTimeStamp(false),
|
gotTimeStamp(false)
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
PVFieldPtr pvValue = pvRequest->getSubField("field.value");
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
|
||||||
if(!pvValue) {
|
changeFlags = shared_vector<epics::pvData::boolean>(nchannel);
|
||||||
throw std::runtime_error("pvRequest did not specify value");
|
|
||||||
}
|
|
||||||
topPVStructure.resize(nchannel);
|
topPVStructure.resize(nchannel);
|
||||||
|
|
||||||
unionValue.resize(nchannel);
|
unionValue.resize(nchannel);
|
||||||
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
for(size_t i=0; i< nchannel; ++i) {
|
for(size_t i=0; i< nchannel; ++i) {
|
||||||
topPVStructure[i] = PVStructurePtr();
|
topPVStructure[i] = PVStructurePtr();
|
||||||
unionValue[i] = pvDataCreate->createPVUnion(u);
|
unionValue[i] = pvDataCreate->createPVUnion(u);
|
||||||
@@ -68,7 +66,7 @@ PvaClientNTMultiData::PvaClientNTMultiData(
|
|||||||
severity.resize(nchannel);
|
severity.resize(nchannel);
|
||||||
status.resize(nchannel);
|
status.resize(nchannel);
|
||||||
message.resize(nchannel);
|
message.resize(nchannel);
|
||||||
|
|
||||||
}
|
}
|
||||||
if(pvRequest->getSubField("field.timeStamp")) {
|
if(pvRequest->getSubField("field.timeStamp")) {
|
||||||
gotTimeStamp = true;
|
gotTimeStamp = true;
|
||||||
@@ -86,28 +84,7 @@ PvaClientNTMultiData::PvaClientNTMultiData(
|
|||||||
|
|
||||||
PvaClientNTMultiData::~PvaClientNTMultiData()
|
PvaClientNTMultiData::~PvaClientNTMultiData()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::~PvaClientNTMultiData()\n";
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientNTMultiData::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
pvaClientChannelArray.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index)
|
|
||||||
{
|
|
||||||
FieldConstPtr field = structure->getField("value");
|
|
||||||
if(!field) {
|
|
||||||
string message = "channel "
|
|
||||||
+ pvaClientChannelArray[index]->getChannel()->getChannelName()
|
|
||||||
+ " does not have top level value field";
|
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientNTMultiData::setPVStructure(
|
void PvaClientNTMultiData::setPVStructure(
|
||||||
@@ -116,12 +93,18 @@ void PvaClientNTMultiData::setPVStructure(
|
|||||||
topPVStructure[index] = pvStructure;
|
topPVStructure[index] = pvStructure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_vector<epics::pvData::boolean> PvaClientNTMultiData::getChannelChangeFlags()
|
||||||
|
{
|
||||||
|
return changeFlags;
|
||||||
|
}
|
||||||
|
|
||||||
size_t PvaClientNTMultiData::getNumber()
|
size_t PvaClientNTMultiData::getNumber()
|
||||||
{
|
{
|
||||||
return nchannel;
|
return nchannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PvaClientNTMultiData::startDeltaTime()
|
void PvaClientNTMultiData::startDeltaTime()
|
||||||
{
|
{
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
@@ -147,29 +130,49 @@ void PvaClientNTMultiData::startDeltaTime()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PvaClientNTMultiData::endDeltaTime()
|
void PvaClientNTMultiData::endDeltaTime(bool valueOnly)
|
||||||
{
|
{
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
PVStructurePtr pvst = topPVStructure[i];
|
PVStructurePtr pvst = topPVStructure[i];
|
||||||
if(!pvst) {
|
changeFlags[i] = false;
|
||||||
unionValue[i] = PVUnionPtr();
|
if(pvst&&unionValue[i]) {
|
||||||
} else {
|
changeFlags[i] = true;
|
||||||
unionValue[i]->set(pvst->getSubField("value"));
|
if(valueOnly) {
|
||||||
|
PVFieldPtr pvValue = pvst->getSubField("value");
|
||||||
|
if(pvValue) {
|
||||||
|
unionValue[i]->set(pvst->getSubField("value"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unionValue[i]->set(pvst);
|
||||||
|
}
|
||||||
|
if(gotAlarm)
|
||||||
|
{
|
||||||
|
PVIntPtr pvSeverity = pvst->getSubField<PVInt>("alarm.severity");
|
||||||
|
PVIntPtr pvStatus = pvst->getSubField<PVInt>("alarm.status");
|
||||||
|
PVStringPtr pvMessage = pvst->getSubField<PVString>("alarm.message");
|
||||||
|
if(pvSeverity&&pvStatus&&pvMessage) {
|
||||||
|
severity[i] = pvSeverity->get();
|
||||||
|
status[i] = pvStatus->get();
|
||||||
|
message[i] = pvMessage->get();
|
||||||
|
} else {
|
||||||
|
severity[i] = undefinedAlarm;
|
||||||
|
status[i] = undefinedStatus;
|
||||||
|
message[i] = "no alarm field";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(gotTimeStamp)
|
||||||
|
{
|
||||||
|
PVLongPtr pvEpoch = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch");
|
||||||
|
PVIntPtr pvNano = pvst->getSubField<PVInt>("timeStamp.nanoseconds");
|
||||||
|
PVIntPtr pvTag = pvst->getSubField<PVInt>("timeStamp.userTag");
|
||||||
|
if(pvEpoch&&pvNano&&pvTag) {
|
||||||
|
secondsPastEpoch[i] = pvEpoch->get();
|
||||||
|
nanoseconds[i] = pvNano->get();
|
||||||
|
userTag[i] = pvTag->get();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(gotAlarm)
|
|
||||||
{
|
|
||||||
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get();
|
|
||||||
status[i] = pvst->getSubField<PVInt>("alarm.status")->get();
|
|
||||||
message[i] = pvst->getSubField<PVString>("alarm.message")->get();
|
|
||||||
}
|
|
||||||
if(gotTimeStamp)
|
|
||||||
{
|
|
||||||
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
|
|
||||||
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
|
|
||||||
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +184,10 @@ TimeStamp PvaClientNTMultiData::getTimeStamp()
|
|||||||
|
|
||||||
NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
|
NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
|
||||||
{
|
{
|
||||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(ntMultiChannelStructure);
|
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(ntMultiChannelStructure);
|
||||||
NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure);
|
NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure);
|
||||||
ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames());
|
ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames());
|
||||||
shared_vector<epics::pvData::PVUnionPtr> val(nchannel);
|
shared_vector<PVUnionPtr> val(nchannel);
|
||||||
for(size_t i=0; i<nchannel; ++i) val[i] = unionValue[i];
|
for(size_t i=0; i<nchannel; ++i) val[i] = unionValue[i];
|
||||||
ntMultiChannel->getValue()->replace(freeze(val));
|
ntMultiChannel->getValue()->replace(freeze(val));
|
||||||
shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected();
|
||||||
|
|||||||
+20
-35
@@ -9,24 +9,18 @@
|
|||||||
* @date 2015.03
|
* @date 2015.03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
#include <pv/standardField.h>
|
|
||||||
#include <pv/convert.h>
|
|
||||||
#include <epicsMath.h>
|
#include <epicsMath.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClientMultiChannel.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::nt;
|
using namespace epics::nt;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
|
||||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
|
||||||
static StandardFieldPtr standardField = getStandardField();
|
|
||||||
|
|
||||||
|
|
||||||
PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
|
PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
|
||||||
@@ -34,7 +28,7 @@ PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
|
|||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
PVStructurePtr const & pvRequest)
|
PVStructurePtr const & pvRequest)
|
||||||
{
|
{
|
||||||
UnionConstPtr u = fieldCreate->createVariantUnion();
|
UnionConstPtr u = getFieldCreate()->createVariantUnion();
|
||||||
PvaClientNTMultiGetPtr pvaClientNTMultiGet(
|
PvaClientNTMultiGetPtr pvaClientNTMultiGet(
|
||||||
new PvaClientNTMultiGet(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
|
new PvaClientNTMultiGet(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
|
||||||
return pvaClientNTMultiGet;
|
return pvaClientNTMultiGet;
|
||||||
@@ -44,7 +38,7 @@ PvaClientNTMultiGet::PvaClientNTMultiGet(
|
|||||||
UnionConstPtr const & u,
|
UnionConstPtr const & u,
|
||||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
epics::pvData::PVStructurePtr const & pvRequest)
|
PVStructurePtr const & pvRequest)
|
||||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||||
pvaClientChannelArray(pvaClientChannelArray),
|
pvaClientChannelArray(pvaClientChannelArray),
|
||||||
pvRequest(pvRequest),
|
pvRequest(pvRequest),
|
||||||
@@ -55,37 +49,24 @@ PvaClientNTMultiGet::PvaClientNTMultiGet(
|
|||||||
pvaClientMultiChannel,
|
pvaClientMultiChannel,
|
||||||
pvaClientChannelArray,
|
pvaClientChannelArray,
|
||||||
pvRequest)),
|
pvRequest)),
|
||||||
isConnected(false),
|
isConnected(false)
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiGet::PvaClientNTMultiGet()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientNTMultiGet::~PvaClientNTMultiGet()
|
PvaClientNTMultiGet::~PvaClientNTMultiGet()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiGet::~PvaClientNTMultiGet()\n";
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientNTMultiGet::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
pvaClientChannelArray.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientNTMultiGet::connect()
|
void PvaClientNTMultiGet::connect()
|
||||||
{
|
{
|
||||||
pvaClientGet.resize(nchannel);
|
pvaClientGet.resize(nchannel);
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
string request = "value";
|
|
||||||
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
|
|
||||||
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
|
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(request);
|
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(pvRequest);
|
||||||
pvaClientGet[i]->issueConnect();
|
pvaClientGet[i]->issueConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +75,7 @@ void PvaClientNTMultiGet::connect()
|
|||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
Status status = pvaClientGet[i]->waitConnect();
|
Status status = pvaClientGet[i]->waitConnect();
|
||||||
if(status.isOK()) continue;
|
if(status.isOK()) continue;
|
||||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||||
+ " PvaChannelGet::waitConnect " + status.getMessage();
|
+ " PvaChannelGet::waitConnect " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
@@ -102,14 +83,18 @@ void PvaClientNTMultiGet::connect()
|
|||||||
this->isConnected = true;
|
this->isConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientNTMultiGet::get()
|
void PvaClientNTMultiGet::get(bool valueOnly)
|
||||||
{
|
{
|
||||||
if(!isConnected) connect();
|
if(!isConnected) connect();
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
|
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
|
if(!pvaClientGet[i]){
|
||||||
|
pvaClientGet[i]=pvaClientChannelArray[i]->createGet(pvRequest);
|
||||||
|
pvaClientGet[i]->connect();
|
||||||
|
}
|
||||||
pvaClientGet[i]->issueGet();
|
pvaClientGet[i]->issueGet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +103,7 @@ void PvaClientNTMultiGet::get()
|
|||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
Status status = pvaClientGet[i]->waitGet();
|
Status status = pvaClientGet[i]->waitGet();
|
||||||
if(status.isOK()) continue;
|
if(status.isOK()) continue;
|
||||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||||
+ " PvaChannelGet::waitGet " + status.getMessage();
|
+ " PvaChannelGet::waitGet " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
@@ -130,7 +115,7 @@ void PvaClientNTMultiGet::get()
|
|||||||
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
|
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pvaClientNTMultiData->endDeltaTime();
|
pvaClientNTMultiData->endDeltaTime(valueOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
|
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
|
||||||
|
|||||||
@@ -9,29 +9,28 @@
|
|||||||
* @date 2015.03
|
* @date 2015.03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
#include <pv/standardField.h>
|
#include <pv/standardField.h>
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
#include <epicsMath.h>
|
#include <epicsMath.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClientMultiChannel.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::nt;
|
using namespace epics::nt;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
|
||||||
|
|
||||||
PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
|
PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
|
||||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
epics::pvData::PVStructurePtr const & pvRequest)
|
PVStructurePtr const & pvRequest)
|
||||||
{
|
{
|
||||||
UnionConstPtr u = fieldCreate->createVariantUnion();
|
UnionConstPtr u = getFieldCreate()->createVariantUnion();
|
||||||
PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
|
PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
|
||||||
new PvaClientNTMultiMonitor(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
|
new PvaClientNTMultiMonitor(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
|
||||||
return pvaClientNTMultiMonitor;
|
return pvaClientNTMultiMonitor;
|
||||||
@@ -52,25 +51,15 @@ PvaClientNTMultiMonitor::PvaClientNTMultiMonitor(
|
|||||||
pvaClientMultiChannel,
|
pvaClientMultiChannel,
|
||||||
pvaClientChannelArray,
|
pvaClientChannelArray,
|
||||||
pvRequest)),
|
pvRequest)),
|
||||||
isConnected(false),
|
isConnected(false)
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiMonitor::PvaClientNTMultiMonitor()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientNTMultiMonitor::~PvaClientNTMultiMonitor()
|
PvaClientNTMultiMonitor::~PvaClientNTMultiMonitor()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiMonitor::~PvaClientNTMultiMonitor()\n";
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientNTMultiMonitor::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
pvaClientChannelArray.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -78,13 +67,10 @@ void PvaClientNTMultiMonitor::connect()
|
|||||||
{
|
{
|
||||||
pvaClientMonitor.resize(nchannel);
|
pvaClientMonitor.resize(nchannel);
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
string request = "value";
|
|
||||||
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
|
|
||||||
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
|
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request);
|
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(pvRequest);
|
||||||
pvaClientMonitor[i]->issueConnect();
|
pvaClientMonitor[i]->issueConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +79,7 @@ void PvaClientNTMultiMonitor::connect()
|
|||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
Status status = pvaClientMonitor[i]->waitConnect();
|
Status status = pvaClientMonitor[i]->waitConnect();
|
||||||
if(status.isOK()) continue;
|
if(status.isOK()) continue;
|
||||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||||
+ " PvaChannelMonitor::waitConnect " + status.getMessage();
|
+ " PvaChannelMonitor::waitConnect " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
@@ -105,24 +91,29 @@ void PvaClientNTMultiMonitor::connect()
|
|||||||
this->isConnected = true;
|
this->isConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PvaClientNTMultiMonitor::poll()
|
bool PvaClientNTMultiMonitor::poll(bool valueOnly)
|
||||||
{
|
{
|
||||||
if(!isConnected) connect();
|
if(!isConnected) connect();
|
||||||
bool result = false;
|
bool result = false;
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
pvaClientNTMultiData->startDeltaTime();
|
pvaClientNTMultiData->startDeltaTime();
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
if(pvaClientMonitor[i]->poll()) {
|
if(!pvaClientMonitor[i]){
|
||||||
|
pvaClientMonitor[i]=pvaClientChannelArray[i]->createMonitor(pvRequest);
|
||||||
|
pvaClientMonitor[i]->connect();
|
||||||
|
pvaClientMonitor[i]->start();
|
||||||
|
}
|
||||||
|
if(pvaClientMonitor[i]->poll()) {
|
||||||
pvaClientNTMultiData->setPVStructure(
|
pvaClientNTMultiData->setPVStructure(
|
||||||
pvaClientMonitor[i]->getData()->getPVStructure(),i);
|
pvaClientMonitor[i]->getData()->getPVStructure(),i);
|
||||||
pvaClientMonitor[i]->releaseEvent();
|
pvaClientMonitor[i]->releaseEvent();
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(result) pvaClientNTMultiData->endDeltaTime();
|
if(result) pvaClientNTMultiData->endDeltaTime(valueOnly);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+52
-32
@@ -9,23 +9,20 @@
|
|||||||
* @date 2015.03
|
* @date 2015.03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <pv/pvaClientMultiChannel.h>
|
|
||||||
#include <pv/standardField.h>
|
#include <pv/standardField.h>
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
#include <epicsMath.h>
|
#include <epicsMath.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClientMultiChannel.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::nt;
|
using namespace epics::nt;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
|
||||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
|
||||||
|
|
||||||
PvaClientNTMultiPutPtr PvaClientNTMultiPut::create(
|
PvaClientNTMultiPutPtr PvaClientNTMultiPut::create(
|
||||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||||
@@ -41,27 +38,17 @@ PvaClientNTMultiPut::PvaClientNTMultiPut(
|
|||||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||||
pvaClientChannelArray(pvaClientChannelArray),
|
pvaClientChannelArray(pvaClientChannelArray),
|
||||||
nchannel(pvaClientChannelArray.size()),
|
nchannel(pvaClientChannelArray.size()),
|
||||||
unionValue(shared_vector<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())),
|
unionValue(shared_vector<PVUnionPtr>(nchannel,PVUnionPtr())),
|
||||||
value(shared_vector<epics::pvData::PVFieldPtr>(nchannel,PVFieldPtr())),
|
value(shared_vector<PVFieldPtr>(nchannel,PVFieldPtr())),
|
||||||
isConnected(false),
|
isConnected(false)
|
||||||
isDestroyed(false)
|
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::PvaClientNTMultiPut()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientNTMultiPut::~PvaClientNTMultiPut()
|
PvaClientNTMultiPut::~PvaClientNTMultiPut()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::~PvaClientNTMultiPut()\n";
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientNTMultiPut::destroy()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
pvaClientChannelArray.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientNTMultiPut::connect()
|
void PvaClientNTMultiPut::connect()
|
||||||
@@ -80,7 +67,7 @@ void PvaClientNTMultiPut::connect()
|
|||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
Status status = pvaClientPut[i]->waitConnect();
|
Status status = pvaClientPut[i]->waitConnect();
|
||||||
if(status.isOK()) continue;
|
if(status.isOK()) continue;
|
||||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||||
+ " PvaChannelPut::waitConnect " + status.getMessage();
|
+ " PvaChannelPut::waitConnect " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
@@ -96,11 +83,13 @@ void PvaClientNTMultiPut::connect()
|
|||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
Status status = pvaClientPut[i]->waitGet();
|
Status status = pvaClientPut[i]->waitGet();
|
||||||
if(status.isOK()) continue;
|
if(status.isOK()) continue;
|
||||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||||
+ " PvaChannelPut::waitGet " + status.getMessage();
|
+ " PvaChannelPut::waitGet " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
@@ -113,9 +102,26 @@ void PvaClientNTMultiPut::connect()
|
|||||||
this->isConnected = true;
|
this->isConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_vector<epics::pvData::PVUnionPtr> PvaClientNTMultiPut::getValues()
|
shared_vector<PVUnionPtr> PvaClientNTMultiPut::getValues()
|
||||||
{
|
{
|
||||||
if(!isConnected) connect();
|
if(!isConnected) connect();
|
||||||
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
|
{
|
||||||
|
if(isConnected[i]) {
|
||||||
|
if(!pvaClientPut[i]){
|
||||||
|
pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
|
||||||
|
pvaClientPut[i]->connect();
|
||||||
|
pvaClientPut[i]->get();
|
||||||
|
value[i] = pvaClientPut[i]->getData()->getValue();
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
|
FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
|
||||||
|
builder->add("value",value[i]->getField());
|
||||||
|
unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return unionValue;
|
return unionValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,15 +132,29 @@ void PvaClientNTMultiPut::put()
|
|||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
|
if(!pvaClientPut[i]){
|
||||||
|
pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
|
||||||
|
pvaClientPut[i]->connect();
|
||||||
|
pvaClientPut[i]->get();
|
||||||
|
value[i] = pvaClientPut[i]->getData()->getValue();
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
|
FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
|
||||||
|
builder->add("value",value[i]->getField());
|
||||||
|
unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
|
||||||
|
}
|
||||||
value[i]->copy(*unionValue[i]->get());
|
value[i]->copy(*unionValue[i]->get());
|
||||||
pvaClientPut[i]->issuePut();
|
pvaClientPut[i]->issuePut();
|
||||||
}
|
}
|
||||||
if(isConnected[i]) {
|
}
|
||||||
Status status = pvaClientPut[i]->waitPut();
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
if(status.isOK()) continue;
|
{
|
||||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
if(isConnected[i]) {
|
||||||
+ " PvaChannelPut::waitPut " + status.getMessage();
|
Status status = pvaClientPut[i]->waitPut();
|
||||||
throw std::runtime_error(message);
|
if(status.isOK()) continue;
|
||||||
|
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||||
|
+ " PvaChannelPut::waitPut " + status.getMessage();
|
||||||
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+154
-74
@@ -8,160 +8,234 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
|
|
||||||
class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
||||||
{
|
{
|
||||||
PvaClientProcess * pvaClientProcess;
|
PvaClientProcess::weak_pointer pvaClientProcess;
|
||||||
|
PvaClient::weak_pointer pvaClient;
|
||||||
public:
|
public:
|
||||||
ChannelProcessRequesterImpl(PvaClientProcess * pvaClientProcess)
|
ChannelProcessRequesterImpl(
|
||||||
: pvaClientProcess(pvaClientProcess) {}
|
PvaClientProcessPtr const & pvaClientProcess,
|
||||||
string getRequesterName()
|
PvaClientPtr const &pvaClient)
|
||||||
{return pvaClientProcess->getRequesterName();}
|
: pvaClientProcess(pvaClientProcess),
|
||||||
void message(string const & message,MessageType messageType)
|
pvaClient(pvaClient)
|
||||||
{pvaClientProcess->message(message,messageType);}
|
{}
|
||||||
void channelProcessConnect(
|
virtual ~ChannelProcessRequesterImpl() {
|
||||||
|
if(PvaClient::getDebug()) std::cout << "~ChannelProcessRequesterImpl" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string getRequesterName() {
|
||||||
|
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
|
||||||
|
if(!clientProcess) return string("clientProcess is null");
|
||||||
|
return clientProcess->getRequesterName();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void message(std::string const & message, MessageType messageType) {
|
||||||
|
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
|
||||||
|
if(!clientProcess) return;
|
||||||
|
clientProcess->message(message,messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void channelProcessConnect(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelProcess::shared_pointer const & channelProcess)
|
ChannelProcess::shared_pointer const & channelProcess)
|
||||||
{pvaClientProcess->channelProcessConnect(status,channelProcess);}
|
{
|
||||||
void processDone(
|
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
|
||||||
|
if(!clientProcess) return;
|
||||||
|
clientProcess->channelProcessConnect(status,channelProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void processDone(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelProcess::shared_pointer const & channelProcess)
|
ChannelProcess::shared_pointer const & ChannelProcess)
|
||||||
{pvaClientProcess->processDone(status,channelProcess);}
|
{
|
||||||
|
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
|
||||||
|
if(!clientProcess) return;
|
||||||
|
clientProcess->processDone(status,ChannelProcess);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PvaClientProcessPtr PvaClientProcess::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
|
PVStructurePtr const &pvRequest)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientProcess::create(pvaClient,channelName,pvRequest)\n"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< " pvRequest " << pvRequest
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
PvaClientProcessPtr channelProcess(new PvaClientProcess(pvaClient,pvaClientChannel,pvRequest));
|
||||||
|
channelProcess->channelProcessRequester = ChannelProcessRequesterImplPtr(
|
||||||
|
new ChannelProcessRequesterImpl(channelProcess,pvaClient));
|
||||||
|
return channelProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientProcess::PvaClientProcess(
|
PvaClientProcess::PvaClientProcess(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
Channel::shared_pointer const & channel,
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
PVStructurePtr const &pvRequest)
|
PVStructurePtr const &pvRequest)
|
||||||
: pvaClient(pvaClient),
|
: pvaClient(pvaClient),
|
||||||
channel(channel),
|
pvaClientChannel(pvaClientChannel),
|
||||||
pvRequest(pvRequest),
|
pvRequest(pvRequest),
|
||||||
isDestroyed(false),
|
|
||||||
connectState(connectIdle),
|
connectState(connectIdle),
|
||||||
processState(processIdle)
|
processState(processIdle)
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientProcess::PvaClientProcess()"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientProcess::~PvaClientProcess()
|
PvaClientProcess::~PvaClientProcess()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientProcess::~PvaClientProcess()"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from ChannelProcessRequester
|
|
||||||
string PvaClientProcess::getRequesterName()
|
string PvaClientProcess::getRequesterName()
|
||||||
{
|
{
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
return pvaClientChannel->getRequesterName();
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
return yyy->getRequesterName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientProcess::message(string const & message,MessageType messageType)
|
void PvaClientProcess::message(string const & message,MessageType messageType)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
|
pvaClientChannel->message(message,messageType);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
yyy->message(message, messageType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientProcess::channelProcessConnect(
|
void PvaClientProcess::channelProcessConnect(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelProcess::shared_pointer const & channelProcess)
|
ChannelProcess::shared_pointer const & channelProcess)
|
||||||
{
|
{
|
||||||
if(isDestroyed) return;
|
if(PvaClient::getDebug()) {
|
||||||
channelProcessConnectStatus = status;
|
cout << "PvaClientProcess::channelProcessConnect"
|
||||||
this->channelProcess = channelProcess;
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
waitForConnect.signal();
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
channelProcessConnectStatus = status;
|
||||||
|
if(status.isOK()) {
|
||||||
|
this->channelProcess = channelProcess;
|
||||||
|
connectState = connected;
|
||||||
|
}
|
||||||
|
waitForConnect.signal();
|
||||||
|
}
|
||||||
|
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->channelProcessConnect(status,shared_from_this());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientProcess::processDone(
|
void PvaClientProcess::processDone(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelProcess::shared_pointer const & channelProcess)
|
ChannelProcess::shared_pointer const & channelProcess)
|
||||||
{
|
{
|
||||||
if(isDestroyed) return;
|
if(PvaClient::getDebug()) {
|
||||||
channelProcessStatus = status;
|
cout << "PvaClientProcess::processDone"
|
||||||
waitForProcess.signal();
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
}
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
// from PvaClientProcess
|
|
||||||
void PvaClientProcess::destroy()
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
if(isDestroyed) return;
|
channelProcessStatus = status;
|
||||||
isDestroyed = true;
|
processState = processComplete;
|
||||||
|
waitForProcess.signal();
|
||||||
|
}
|
||||||
|
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->processDone(status,shared_from_this());
|
||||||
}
|
}
|
||||||
if(channelProcess) channelProcess->destroy();
|
|
||||||
channelProcess.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientProcess::connect()
|
void PvaClientProcess::connect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientProcess::connect"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issueConnect();
|
issueConnect();
|
||||||
Status status = waitConnect();
|
Status status = waitConnect();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientProcess::connect " + status.getMessage();
|
+ " PvaClientProcess::connect " + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientProcess::issueConnect()
|
void PvaClientProcess::issueConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientProcess::issueConnect"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState!=connectIdle) {
|
if(connectState!=connectIdle) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientProcess already connected ";
|
+ " pvaClientProcess already connected ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
processRequester = ChannelProcessRequester::shared_pointer(new ChannelProcessRequesterImpl(this));
|
|
||||||
connectState = connectActive;
|
connectState = connectActive;
|
||||||
channelProcess = channel->createChannelProcess(processRequester,pvRequest);
|
channelProcessConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
|
||||||
|
channelProcess = pvaClientChannel->getChannel()->createChannelProcess(channelProcessRequester,pvRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PvaClientProcess::waitConnect()
|
Status PvaClientProcess::waitConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState!=connectActive) {
|
cout << "PvaClientProcess::waitConnect"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientProcess illegal connect state ";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForConnect.wait();
|
waitForConnect.wait();
|
||||||
connectState = channelProcessConnectStatus.isOK() ? connected : connectIdle;
|
|
||||||
return channelProcessConnectStatus;
|
return channelProcessConnectStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientProcess::process()
|
void PvaClientProcess::process()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientProcess::process"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issueProcess();
|
issueProcess();
|
||||||
Status status = waitProcess();
|
Status status = waitProcess();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientProcess::process" + status.getMessage();
|
+ " PvaClientProcess::process" + status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientProcess::issueProcess()
|
void PvaClientProcess::issueProcess()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientProcess::issueProcess"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState==connectIdle) connect();
|
if(connectState==connectIdle) connect();
|
||||||
if(processState!=processIdle) {
|
if(processState==processActive) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientProcess::issueProcess process aleady active ";
|
+ " PvaClientProcess::issueProcess process aleady active ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
@@ -171,24 +245,30 @@ void PvaClientProcess::issueProcess()
|
|||||||
|
|
||||||
Status PvaClientProcess::waitProcess()
|
Status PvaClientProcess::waitProcess()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(processState!=processActive){
|
cout << "PvaClientProcess::waitProcess"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientProcess::waitProcess llegal process state";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForProcess.wait();
|
waitForProcess.wait();
|
||||||
processState = processIdle;
|
processState = processComplete;
|
||||||
return channelProcessStatus;
|
return channelProcessStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientProcessPtr PvaClientProcess::create(
|
void PvaClientProcess::setRequester(PvaClientProcessRequesterPtr const & pvaClientProcessRequester)
|
||||||
PvaClientPtr const &pvaClient,
|
|
||||||
Channel::shared_pointer const & channel,
|
|
||||||
PVStructurePtr const &pvRequest)
|
|
||||||
{
|
{
|
||||||
PvaClientProcessPtr epv(new PvaClientProcess(pvaClient,channel,pvRequest));
|
if(PvaClient::getDebug()) {
|
||||||
return epv;
|
cout << "PvaClientProcess::setRequester"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
this->pvaClientProcessRequester = pvaClientProcessRequester;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PvaClientChannelPtr PvaClientProcess::getPvaClientChannel()
|
||||||
|
{
|
||||||
|
return pvaClientChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
+233
-113
@@ -8,12 +8,13 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
#include <pv/pvaClient.h>
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -22,72 +23,127 @@ namespace epics { namespace pvaClient {
|
|||||||
|
|
||||||
class ChannelPutRequesterImpl : public ChannelPutRequester
|
class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||||
{
|
{
|
||||||
PvaClientPut * pvaClientPut;
|
PvaClientPut::weak_pointer pvaClientPut;
|
||||||
|
PvaClient::weak_pointer pvaClient;
|
||||||
public:
|
public:
|
||||||
ChannelPutRequesterImpl(PvaClientPut * pvaClientPut)
|
ChannelPutRequesterImpl(
|
||||||
: pvaClientPut(pvaClientPut) {}
|
PvaClientPutPtr const & pvaClientPut,
|
||||||
string getRequesterName()
|
PvaClientPtr const &pvaClient)
|
||||||
{return pvaClientPut->getRequesterName();}
|
: pvaClientPut(pvaClientPut),
|
||||||
void message(string const & message,MessageType messageType)
|
pvaClient(pvaClient)
|
||||||
{pvaClientPut->message(message,messageType);}
|
{}
|
||||||
void channelPutConnect(
|
virtual ~ChannelPutRequesterImpl() {
|
||||||
|
if(PvaClient::getDebug()) std::cout << "~ChannelPutRequesterImpl" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string getRequesterName() {
|
||||||
|
PvaClientPutPtr clientPut(pvaClientPut.lock());
|
||||||
|
if(!clientPut) return string("clientPut is null");
|
||||||
|
return clientPut->getRequesterName();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void message(std::string const & message, MessageType messageType) {
|
||||||
|
PvaClientPutPtr clientPut(pvaClientPut.lock());
|
||||||
|
if(!clientPut) return;
|
||||||
|
clientPut->message(message,messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void channelPutConnect(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelPut::shared_pointer const & channelPut,
|
ChannelPut::shared_pointer const & channelPut,
|
||||||
StructureConstPtr const & structure)
|
Structure::const_shared_pointer const & structure)
|
||||||
{pvaClientPut->channelPutConnect(status,channelPut,structure);}
|
{
|
||||||
void getDone(
|
PvaClientPutPtr clientPut(pvaClientPut.lock());
|
||||||
|
if(!clientPut) return;
|
||||||
|
clientPut->channelPutConnect(status,channelPut,structure);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getDone(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelPut::shared_pointer const & channelPut,
|
ChannelPut::shared_pointer const & channelPut,
|
||||||
PVStructurePtr const & pvStructure,
|
PVStructurePtr const & pvStructure,
|
||||||
BitSetPtr const & bitSet)
|
BitSet::shared_pointer const & bitSet)
|
||||||
{pvaClientPut->getDone(status,channelPut,pvStructure,bitSet);}
|
{
|
||||||
void putDone(
|
PvaClientPutPtr clientPut(pvaClientPut.lock());
|
||||||
|
if(!clientPut) return;
|
||||||
|
clientPut->getDone(status,channelPut,pvStructure,bitSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void putDone(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelPut::shared_pointer const & channelPut)
|
ChannelPut::shared_pointer const & channelPut)
|
||||||
{pvaClientPut->putDone(status,channelPut);}
|
{
|
||||||
|
PvaClientPutPtr clientPut(pvaClientPut.lock());
|
||||||
|
if(!clientPut) return;
|
||||||
|
clientPut->putDone(status,channelPut);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PvaClientPutPtr PvaClientPut::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
|
PVStructurePtr const &pvRequest)
|
||||||
|
{
|
||||||
|
PvaClientPutPtr clientPut(new PvaClientPut(pvaClient,pvaClientChannel,pvRequest));
|
||||||
|
clientPut->channelPutRequester = ChannelPutRequesterImplPtr(
|
||||||
|
new ChannelPutRequesterImpl(clientPut,pvaClient));
|
||||||
|
return clientPut;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PvaClientPut::PvaClientPut(
|
PvaClientPut::PvaClientPut(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
Channel::shared_pointer const & channel,
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
PVStructurePtr const &pvRequest)
|
PVStructurePtr const &pvRequest)
|
||||||
: pvaClient(pvaClient),
|
: pvaClient(pvaClient),
|
||||||
channel(channel),
|
pvaClientChannel(pvaClientChannel),
|
||||||
pvRequest(pvRequest),
|
pvRequest(pvRequest),
|
||||||
isDestroyed(false),
|
|
||||||
connectState(connectIdle),
|
connectState(connectIdle),
|
||||||
putState(putIdle)
|
putState(putIdle)
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientPut::PvaClientPut"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPut::~PvaClientPut()
|
PvaClientPut::~PvaClientPut()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) {
|
||||||
}
|
cout<< "PvaClientPut::~PvaClientPut"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
void PvaClientPut::checkPutState()
|
<< endl;
|
||||||
{
|
}
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
}
|
||||||
if(connectState==connectIdle){
|
|
||||||
connect();
|
|
||||||
get();
|
void PvaClientPut::checkConnectState()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPut::checkConnectState"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(connectState==connectIdle){
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
if(connectState==connectActive){
|
||||||
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " "
|
||||||
|
+ channelPutConnectStatus.getMessage();
|
||||||
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from ChannelPutRequester
|
|
||||||
string PvaClientPut::getRequesterName()
|
string PvaClientPut::getRequesterName()
|
||||||
{
|
{
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
return pvaClientChannel->getRequesterName();
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
return yyy->getRequesterName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::message(string const & message,MessageType messageType)
|
void PvaClientPut::message(string const & message,MessageType messageType)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
pvaClientChannel->message(message,messageType);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
yyy->message(message, messageType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::channelPutConnect(
|
void PvaClientPut::channelPutConnect(
|
||||||
@@ -95,15 +151,27 @@ void PvaClientPut::channelPutConnect(
|
|||||||
ChannelPut::shared_pointer const & channelPut,
|
ChannelPut::shared_pointer const & channelPut,
|
||||||
StructureConstPtr const & structure)
|
StructureConstPtr const & structure)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelPutConnectStatus = status;
|
cout << "PvaClientPut::channelPutConnect"
|
||||||
this->channelPut = channelPut;
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
if(status.isOK()) {
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
pvaClientData = PvaClientPutData::create(structure);
|
<< endl;
|
||||||
pvaClientData->setMessagePrefix(channel->getChannelName());
|
}
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
channelPutConnectStatus = status;
|
||||||
|
if(status.isOK()) {
|
||||||
|
this->channelPut = channelPut;
|
||||||
|
connectState = connected;
|
||||||
|
pvaClientData = PvaClientPutData::create(structure);
|
||||||
|
pvaClientData->setMessagePrefix(channelPut->getChannel()->getChannelName());
|
||||||
|
}
|
||||||
|
waitForConnect.signal();
|
||||||
|
}
|
||||||
|
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->channelPutConnect(status,shared_from_this());
|
||||||
}
|
}
|
||||||
waitForConnect.signal();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::getDone(
|
void PvaClientPut::getDone(
|
||||||
@@ -112,133 +180,175 @@ void PvaClientPut::getDone(
|
|||||||
PVStructurePtr const & pvStructure,
|
PVStructurePtr const & pvStructure,
|
||||||
BitSetPtr const & bitSet)
|
BitSetPtr const & bitSet)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelGetPutStatus = status;
|
cout << "PvaClientPut::getDone"
|
||||||
if(status.isOK()) {
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
PVStructurePtr pvs = pvaClientData->getPVStructure();
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
pvs->copyUnchecked(*pvStructure,*bitSet);
|
<< endl;
|
||||||
BitSetPtr bs = pvaClientData->getChangedBitSet();
|
}
|
||||||
bs->clear();
|
{
|
||||||
*bs |= *bitSet;
|
Lock xx(mutex);
|
||||||
|
channelGetPutStatus = status;
|
||||||
|
if(status.isOK()) {
|
||||||
|
PVStructurePtr pvs = pvaClientData->getPVStructure();
|
||||||
|
pvs->copyUnchecked(*pvStructure,*bitSet);
|
||||||
|
BitSetPtr bs = pvaClientData->getChangedBitSet();
|
||||||
|
bs->clear();
|
||||||
|
*bs |= *bitSet;
|
||||||
|
}
|
||||||
|
putState = putComplete;
|
||||||
|
waitForGetPut.signal();
|
||||||
|
}
|
||||||
|
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->getDone(status,shared_from_this());
|
||||||
}
|
}
|
||||||
waitForGetPut.signal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::putDone(
|
void PvaClientPut::putDone(
|
||||||
const Status& status,
|
const Status& status,
|
||||||
ChannelPut::shared_pointer const & channelPut)
|
ChannelPut::shared_pointer const & channelPut)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelGetPutStatus = status;
|
cout << "PvaClientPut::putDone"
|
||||||
waitForGetPut.signal();
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
}
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
// from PvaClientPut
|
|
||||||
void PvaClientPut::destroy()
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
if(isDestroyed) return;
|
channelGetPutStatus = status;
|
||||||
isDestroyed = true;
|
putState = putComplete;
|
||||||
|
waitForGetPut.signal();
|
||||||
}
|
}
|
||||||
if(channelPut) channelPut->destroy();
|
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
|
||||||
channelPut.reset();
|
if(req) { req->putDone(status,shared_from_this());}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::connect()
|
void PvaClientPut::connect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPut::connect"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issueConnect();
|
issueConnect();
|
||||||
Status status = waitConnect();
|
Status status = waitConnect();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPut::connect " + status.getMessage();
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPut::connect "
|
||||||
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::issueConnect()
|
void PvaClientPut::issueConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPut::issueConnect"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState!=connectIdle) {
|
if(connectState!=connectIdle) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientPut already connected ";
|
+ " pvaClientPut already connected ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
putRequester = ChannelPutRequester::shared_pointer(new ChannelPutRequesterImpl(this));
|
|
||||||
connectState = connectActive;
|
connectState = connectActive;
|
||||||
channelPut = channel->createChannelPut(putRequester,pvRequest);
|
channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
|
||||||
|
channelPut = pvaClientChannel->getChannel()->createChannelPut(channelPutRequester,pvRequest);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PvaClientPut::waitConnect()
|
Status PvaClientPut::waitConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState!=connectActive) {
|
cout << "PvaClientPut::waitConnect"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientPut illegal connect state ";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForConnect.wait();
|
waitForConnect.wait();
|
||||||
connectState = channelPutConnectStatus.isOK() ? connected : connectIdle;
|
|
||||||
return channelPutConnectStatus;
|
return channelPutConnectStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::get()
|
void PvaClientPut::get()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPut::get"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issueGet();
|
issueGet();
|
||||||
Status status = waitGet();
|
Status status = waitGet();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPut::get " + status.getMessage();
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPut::get "
|
||||||
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::issueGet()
|
void PvaClientPut::issueGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPut::issueGet"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState==connectIdle) connect();
|
if(connectState==connectIdle) connect();
|
||||||
if(putState!=putIdle) {
|
if(putState==getActive || putState==putActive) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ "PvaClientPut::issueGet get or put aleady active ";
|
+ "PvaClientPut::issueGet get or put aleady active ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
putState = getActive;
|
putState = getActive;
|
||||||
pvaClientData->getChangedBitSet()->clear();
|
|
||||||
channelPut->get();
|
channelPut->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PvaClientPut::waitGet()
|
Status PvaClientPut::waitGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(putState!=getActive){
|
cout << "PvaClientPut::waitGet"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientPut::waitGet llegal put state";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForGetPut.wait();
|
waitForGetPut.wait();
|
||||||
putState = putIdle;
|
putState = putComplete;
|
||||||
return channelGetPutStatus;
|
return channelGetPutStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::put()
|
void PvaClientPut::put()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPut::put"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issuePut();
|
issuePut();
|
||||||
Status status = waitPut();
|
Status status = waitPut();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPut::put " + status.getMessage();
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPut::put "
|
||||||
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPut::issuePut()
|
void PvaClientPut::issuePut()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPut::issuePut"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< " pvStructure\n" << pvaClientData->getPVStructure()
|
||||||
|
<< " bitSet " << *pvaClientData->getChangedBitSet() << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState==connectIdle) connect();
|
if(connectState==connectIdle) connect();
|
||||||
if(putState!=putIdle) {
|
if(putState==getActive || putState==putActive) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ "PvaClientPut::issueGet get or put aleady active ";
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPut::issuePut get or put aleady active ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
putState = putActive;
|
putState = putActive;
|
||||||
@@ -247,32 +357,42 @@ void PvaClientPut::issuePut()
|
|||||||
|
|
||||||
Status PvaClientPut::waitPut()
|
Status PvaClientPut::waitPut()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(putState!=putActive){
|
cout << "PvaClientPut::waitPut"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientPut::waitPut llegal put state";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForGetPut.wait();
|
waitForGetPut.wait();
|
||||||
putState = putIdle;
|
putState = putComplete;
|
||||||
if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear();
|
if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear();
|
||||||
return channelGetPutStatus;
|
return channelGetPutStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutDataPtr PvaClientPut::getData()
|
PvaClientPutDataPtr PvaClientPut::getData()
|
||||||
{
|
{
|
||||||
checkPutState();
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientPut::getData"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
checkConnectState();
|
||||||
|
if(putState==putIdle) get();
|
||||||
return pvaClientData;
|
return pvaClientData;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutPtr PvaClientPut::create(
|
void PvaClientPut::setRequester(PvaClientPutRequesterPtr const & pvaClientPutRequester)
|
||||||
PvaClientPtr const &pvaClient,
|
|
||||||
Channel::shared_pointer const & channel,
|
|
||||||
PVStructurePtr const &pvRequest)
|
|
||||||
{
|
{
|
||||||
PvaClientPutPtr epv(new PvaClientPut(pvaClient,channel,pvRequest));
|
if(PvaClient::getDebug()) {
|
||||||
return epv;
|
cout << "PvaClientPut::setRequester"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
this->pvaClientPutRequester = pvaClientPutRequester;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PvaClientChannelPtr PvaClientPut::getPvaClientChannel()
|
||||||
|
{
|
||||||
|
return pvaClientChannel;
|
||||||
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
+70
-179
@@ -8,15 +8,16 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <pv/pvaClient.h>
|
|
||||||
#include <pv/createRequest.h>
|
#include <pv/createRequest.h>
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
using std::tr1::static_pointer_cast;
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -24,40 +25,36 @@ using namespace epics::pvAccess;
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace epics { namespace pvaClient {
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
class PvaClientPostHandlerPvt: public PostHandler
|
|
||||||
{
|
|
||||||
PvaClientPutData * easyData;
|
|
||||||
size_t fieldNumber;
|
|
||||||
public:
|
|
||||||
PvaClientPostHandlerPvt(PvaClientPutData *easyData,size_t fieldNumber)
|
|
||||||
: easyData(easyData),fieldNumber(fieldNumber){}
|
|
||||||
void postPut() { easyData->postPut(fieldNumber);}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
|
|
||||||
static ConvertPtr convert = getConvert();
|
static ConvertPtr convert = getConvert();
|
||||||
static string noValue("no value field");
|
|
||||||
static string notScalar("value is not a scalar");
|
|
||||||
static string notCompatibleScalar("value is not a compatible scalar");
|
static string notCompatibleScalar("value is not a compatible scalar");
|
||||||
static string notArray("value is not an array");
|
|
||||||
static string notScalarArray("value is not a scalarArray");
|
|
||||||
static string notDoubleArray("value is not a doubleArray");
|
static string notDoubleArray("value is not a doubleArray");
|
||||||
static string notStringArray("value is not a stringArray");
|
static string notStringArray("value is not a stringArray");
|
||||||
|
|
||||||
|
class PvaClientPostHandlerPvt: public PostHandler
|
||||||
|
{
|
||||||
|
PvaClientPutData * putData;
|
||||||
|
size_t fieldNumber;
|
||||||
|
public:
|
||||||
|
PvaClientPostHandlerPvt(PvaClientPutData *putData,size_t fieldNumber)
|
||||||
|
: putData(putData),fieldNumber(fieldNumber){}
|
||||||
|
void postPut() { putData->postPut(fieldNumber);}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
PvaClientPutDataPtr PvaClientPutData::create(StructureConstPtr const & structure)
|
PvaClientPutDataPtr PvaClientPutData::create(StructureConstPtr const & structure)
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::create\n";
|
||||||
PvaClientPutDataPtr epv(new PvaClientPutData(structure));
|
PvaClientPutDataPtr epv(new PvaClientPutData(structure));
|
||||||
return epv;
|
return epv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
|
PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
|
||||||
: structure(structure),
|
: PvaClientData(structure)
|
||||||
pvStructure(getPVDataCreate()->createPVStructure(structure)),
|
|
||||||
bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields())))
|
|
||||||
{
|
{
|
||||||
messagePrefix = "";
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::PvaClientPutData\n";
|
||||||
|
PVStructurePtr pvStructure(getPVDataCreate()->createPVStructure(structure));
|
||||||
|
BitSetPtr bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields())));
|
||||||
|
setData(pvStructure,bitSet);
|
||||||
size_t nfields = pvStructure->getNumberFields();
|
size_t nfields = pvStructure->getNumberFields();
|
||||||
postHandler.resize(nfields);
|
postHandler.resize(nfields);
|
||||||
PVFieldPtr pvField;
|
PVFieldPtr pvField;
|
||||||
@@ -71,145 +68,18 @@ PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
|
|||||||
}
|
}
|
||||||
pvField->setPostHandler(postHandler[i]);
|
pvField->setPostHandler(postHandler[i]);
|
||||||
}
|
}
|
||||||
pvValue = pvStructure->getSubField("value");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutData::checkValue()
|
|
||||||
{
|
|
||||||
if(pvValue) return;
|
|
||||||
throw std::runtime_error(messagePrefix + noValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientPutData::postPut(size_t fieldNumber)
|
|
||||||
{
|
|
||||||
bitSet->set(fieldNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientPutData::setMessagePrefix(std::string const & value)
|
|
||||||
{
|
|
||||||
messagePrefix = value + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
StructureConstPtr PvaClientPutData::getStructure()
|
|
||||||
{return structure;}
|
|
||||||
|
|
||||||
PVStructurePtr PvaClientPutData::getPVStructure()
|
|
||||||
{return pvStructure;}
|
|
||||||
|
|
||||||
BitSetPtr PvaClientPutData::getChangedBitSet()
|
|
||||||
{return bitSet;}
|
|
||||||
|
|
||||||
std::ostream & PvaClientPutData::showChanged(std::ostream & out)
|
|
||||||
{
|
|
||||||
size_t nextSet = bitSet->nextSetBit(0);
|
|
||||||
PVFieldPtr pvField;
|
|
||||||
while(nextSet!=string::npos) {
|
|
||||||
if(nextSet==0) {
|
|
||||||
pvField = pvStructure;
|
|
||||||
} else {
|
|
||||||
pvField = pvStructure->getSubField(nextSet);
|
|
||||||
}
|
|
||||||
string name = pvField->getFullName();
|
|
||||||
out << name << " = " << pvField << endl;
|
|
||||||
nextSet = bitSet->nextSetBit(nextSet+1);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PvaClientPutData::hasValue()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PvaClientPutData::isValueScalar()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
if(pvValue->getField()->getType()==scalar) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PvaClientPutData::isValueScalarArray()
|
|
||||||
{
|
|
||||||
if(!pvValue) return false;
|
|
||||||
if(pvValue->getField()->getType()==scalarArray) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVFieldPtr PvaClientPutData::getValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
return pvValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVScalarPtr PvaClientPutData::getScalarValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
|
|
||||||
if(!pv) throw std::runtime_error(messagePrefix + notScalar);
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVArrayPtr PvaClientPutData::getArrayValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
|
|
||||||
if(!pv) throw std::runtime_error(messagePrefix + notArray);
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVScalarArrayPtr PvaClientPutData::getScalarArrayValue()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
|
|
||||||
if(!pv) throw std::runtime_error(messagePrefix + notScalarArray);
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
double PvaClientPutData::getDouble()
|
|
||||||
{
|
|
||||||
PVScalarPtr pvScalar = getScalarValue();
|
|
||||||
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
|
||||||
if(scalarType==pvDouble) {
|
|
||||||
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
|
||||||
return pvDouble->get();
|
|
||||||
}
|
|
||||||
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
|
||||||
throw std::runtime_error(messagePrefix + notCompatibleScalar);
|
|
||||||
}
|
|
||||||
return convert->toDouble(pvScalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
string PvaClientPutData::getString()
|
|
||||||
{
|
|
||||||
PVScalarPtr pvScalar = getScalarValue();
|
|
||||||
return convert->toString(pvScalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_vector<const double> PvaClientPutData::getDoubleArray()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
|
|
||||||
if(!pv) {
|
|
||||||
throw std::runtime_error(messagePrefix + notDoubleArray);
|
|
||||||
}
|
|
||||||
return pv->view();
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_vector<const string> PvaClientPutData::getStringArray()
|
|
||||||
{
|
|
||||||
checkValue();
|
|
||||||
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
|
|
||||||
if(!pv) {
|
|
||||||
throw std::runtime_error(messagePrefix + notStringArray);
|
|
||||||
}
|
|
||||||
return pv->view();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void PvaClientPutData::putDouble(double value)
|
void PvaClientPutData::putDouble(double value)
|
||||||
{
|
{
|
||||||
PVScalarPtr pvScalar = getScalarValue();
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDouble\n";
|
||||||
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
|
Type type = pvField->getField()->getType();
|
||||||
|
if(type!=scalar) {
|
||||||
|
throw std::logic_error("PvaClientData::putDouble() did not find a scalar field");
|
||||||
|
}
|
||||||
|
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||||
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
||||||
if(scalarType==pvDouble) {
|
if(scalarType==pvDouble) {
|
||||||
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
||||||
@@ -217,47 +87,68 @@ void PvaClientPutData::putDouble(double value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
||||||
throw std::runtime_error(messagePrefix + notCompatibleScalar);
|
throw std::logic_error(
|
||||||
|
"PvaClientData::putDouble() did not find a numeric scalar field");
|
||||||
}
|
}
|
||||||
convert->fromDouble(pvScalar,value);
|
convert->fromDouble(pvScalar,value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutData::putString(std::string const & value)
|
void PvaClientPutData::putString(std::string const & value)
|
||||||
{
|
{
|
||||||
PVScalarPtr pvScalar = getScalarValue();
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::putString\n";
|
||||||
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
|
Type type = pvField->getField()->getType();
|
||||||
|
if(type!=scalar) {
|
||||||
|
throw std::logic_error("PvaClientData::putString() did not find a scalar field");
|
||||||
|
}
|
||||||
|
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||||
convert->fromString(pvScalar,value);
|
convert->fromString(pvScalar,value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
|
void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
|
||||||
{
|
{
|
||||||
checkValue();
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n";
|
||||||
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
if(!pv) {
|
Type type = pvField->getField()->getType();
|
||||||
throw std::runtime_error(messagePrefix + notDoubleArray);
|
if(type!=scalarArray) {
|
||||||
|
throw std::logic_error("PvaClientData::putDoubleArray() did not find a scalarArray field");
|
||||||
}
|
}
|
||||||
pv->replace(value);
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
|
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
|
||||||
|
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
||||||
|
throw std::logic_error(
|
||||||
|
"PvaClientData::putDoubleArray() did not find a numeric scalarArray field");
|
||||||
|
}
|
||||||
|
pvScalarArray->putFrom<const double>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutData::putStringArray(shared_vector<const std::string> const & value)
|
void PvaClientPutData::putStringArray(shared_vector<const std::string> const & value)
|
||||||
{
|
{
|
||||||
checkValue();
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n";
|
||||||
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
if(!pv) {
|
Type type = pvField->getField()->getType();
|
||||||
throw std::runtime_error(messagePrefix + notStringArray);
|
if(type!=scalarArray) {
|
||||||
|
throw std::logic_error("PvaClientData::putStringArray() did not find a scalarArray field");
|
||||||
}
|
}
|
||||||
pv->replace(value);
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
|
pvScalarArray->putFrom<const string>(value);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutData::putStringArray(std::vector<std::string> const & value)
|
void PvaClientPutData::putStringArray(std::vector<string> const & value)
|
||||||
{
|
{
|
||||||
checkValue();
|
size_t length = value.size();
|
||||||
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
|
shared_vector<string> val(length);
|
||||||
if(!pv) {
|
for(size_t i=0; i < length; ++i) val[i] = value[i];
|
||||||
throw std::runtime_error(messagePrefix + notScalarArray);
|
putStringArray(freeze(val));
|
||||||
}
|
return;
|
||||||
convert->fromStringArray(pv,0,value.size(),value,0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PvaClientPutData::postPut(size_t fieldNumber)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::postPut\n";
|
||||||
|
getChangedBitSet()->set(fieldNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
+298
-149
@@ -8,12 +8,12 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2015.02
|
* @date 2015.02
|
||||||
*/
|
*/
|
||||||
|
#include <pv/event.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
#include <pv/event.h>
|
|
||||||
#include <pv/pvaClient.h>
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -22,89 +22,140 @@ namespace epics { namespace pvaClient {
|
|||||||
|
|
||||||
class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
|
class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
|
||||||
{
|
{
|
||||||
PvaClientPutGet * pvaClientPutGet;
|
PvaClientPutGet::weak_pointer pvaClientPutGet;
|
||||||
|
PvaClient::weak_pointer pvaClient;
|
||||||
public:
|
public:
|
||||||
ChannelPutGetRequesterImpl(PvaClientPutGet * pvaClientPutGet)
|
ChannelPutGetRequesterImpl(
|
||||||
: pvaClientPutGet(pvaClientPutGet) {}
|
PvaClientPutGetPtr const & pvaClientPutGet,
|
||||||
string getRequesterName()
|
PvaClientPtr const &pvaClient)
|
||||||
{return pvaClientPutGet->getRequesterName();}
|
: pvaClientPutGet(pvaClientPutGet),
|
||||||
void message(string const & message,MessageType messageType)
|
pvaClient(pvaClient)
|
||||||
{pvaClientPutGet->message(message,messageType);}
|
{}
|
||||||
void channelPutGetConnect(
|
virtual ~ChannelPutGetRequesterImpl() {
|
||||||
const epics::pvData::Status& status,
|
if(PvaClient::getDebug()) std::cout << "~ChannelPutGetRequesterImpl" << std::endl;
|
||||||
epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
|
|
||||||
epics::pvData::StructureConstPtr const & putStructure,
|
|
||||||
epics::pvData::StructureConstPtr const & getStructure)
|
|
||||||
{
|
|
||||||
pvaClientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
|
|
||||||
}
|
}
|
||||||
void putGetDone(
|
|
||||||
const epics::pvData::Status& status,
|
virtual std::string getRequesterName() {
|
||||||
epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
|
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
|
||||||
epics::pvData::PVStructurePtr const & getPVStructure,
|
if(!clientPutGet) return string("clientPutGet is null");
|
||||||
epics::pvData::BitSetPtr const & getChangedBitSet)
|
return clientPutGet->getRequesterName();
|
||||||
{
|
|
||||||
pvaClientPutGet->putGetDone(status,channelPutGet,getPVStructure,getChangedBitSet);
|
|
||||||
}
|
}
|
||||||
void getPutDone(
|
|
||||||
const epics::pvData::Status& status,
|
virtual void message(std::string const & message, MessageType messageType) {
|
||||||
epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
|
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
|
||||||
epics::pvData::PVStructurePtr const & putPVStructure,
|
if(!clientPutGet) return;
|
||||||
epics::pvData::BitSet::shared_pointer const & putBitSet)
|
clientPutGet->message(message,messageType);
|
||||||
{
|
|
||||||
pvaClientPutGet->getPutDone(status,channelPutGet,putPVStructure,putBitSet);
|
|
||||||
}
|
}
|
||||||
void getGetDone(
|
|
||||||
const epics::pvData::Status& status,
|
virtual void channelPutGetConnect(
|
||||||
epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
|
const Status& status,
|
||||||
epics::pvData::PVStructurePtr const & getPVStructure,
|
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||||
epics::pvData::BitSet::shared_pointer const & getChangedBitSet)
|
Structure::const_shared_pointer const & putStructure,
|
||||||
|
Structure::const_shared_pointer const & getStructure)
|
||||||
{
|
{
|
||||||
pvaClientPutGet->getGetDone(status,channelPutGet,getPVStructure,getChangedBitSet);
|
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
|
||||||
|
if(!clientPutGet) return;
|
||||||
|
clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void putGetDone(
|
||||||
|
const Status& status,
|
||||||
|
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||||
|
PVStructurePtr const & getPVStructure,
|
||||||
|
BitSet::shared_pointer const & getBitSet)
|
||||||
|
{
|
||||||
|
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
|
||||||
|
if(!clientPutGet) return;
|
||||||
|
clientPutGet->putGetDone(status,channelPutGet,getPVStructure,getBitSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getPutDone(
|
||||||
|
const Status& status,
|
||||||
|
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||||
|
PVStructurePtr const & putPVStructure,
|
||||||
|
BitSet::shared_pointer const & putBitSet)
|
||||||
|
{
|
||||||
|
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
|
||||||
|
if(!clientPutGet) return;
|
||||||
|
clientPutGet->getPutDone(status,channelPutGet,putPVStructure,putBitSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void getGetDone(
|
||||||
|
const Status& status,
|
||||||
|
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||||
|
PVStructurePtr const & getPVStructure,
|
||||||
|
BitSet::shared_pointer const & getBitSet)
|
||||||
|
{
|
||||||
|
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
|
||||||
|
if(!clientPutGet) return;
|
||||||
|
clientPutGet->getGetDone(status,channelPutGet,getPVStructure,getBitSet);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PvaClientPutGetPtr PvaClientPutGet::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
|
PVStructurePtr const &pvRequest)
|
||||||
|
{
|
||||||
|
PvaClientPutGetPtr clientPutGet(new PvaClientPutGet(pvaClient,pvaClientChannel,pvRequest));
|
||||||
|
clientPutGet->channelPutGetRequester = ChannelPutGetRequesterImplPtr(
|
||||||
|
new ChannelPutGetRequesterImpl(clientPutGet,pvaClient));
|
||||||
|
return clientPutGet;
|
||||||
|
}
|
||||||
|
|
||||||
PvaClientPutGet::PvaClientPutGet(
|
PvaClientPutGet::PvaClientPutGet(
|
||||||
PvaClientPtr const &pvaClient,
|
PvaClientPtr const &pvaClient,
|
||||||
Channel::shared_pointer const & channel,
|
PvaClientChannelPtr const & pvaClientChannel,
|
||||||
PVStructurePtr const &pvRequest)
|
PVStructurePtr const &pvRequest)
|
||||||
: pvaClient(pvaClient),
|
: pvaClient(pvaClient),
|
||||||
channel(channel),
|
pvaClientChannel(pvaClientChannel),
|
||||||
pvRequest(pvRequest),
|
pvRequest(pvRequest),
|
||||||
isDestroyed(false),
|
|
||||||
connectState(connectIdle),
|
connectState(connectIdle),
|
||||||
putGetState(putGetIdle)
|
putGetState(putGetIdle)
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientPutGet::PvaClientPutGet"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutGet::~PvaClientPutGet()
|
PvaClientPutGet::~PvaClientPutGet()
|
||||||
{
|
{
|
||||||
destroy();
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientPutGet::~PvaClientPutGet"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::checkPutGetState()
|
void PvaClientPutGet::checkPutGetState()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::checkPutGetState"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState==connectIdle){
|
if(connectState==connectIdle){
|
||||||
connect();
|
connect();
|
||||||
getPut();
|
}
|
||||||
|
if(connectState==connectActive){
|
||||||
|
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " "
|
||||||
|
+ channelPutGetConnectStatus.getMessage();
|
||||||
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from ChannelPutGetRequester
|
|
||||||
string PvaClientPutGet::getRequesterName()
|
string PvaClientPutGet::getRequesterName()
|
||||||
{
|
{
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
return pvaClientChannel->getRequesterName();
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
return yyy->getRequesterName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::message(string const & message,MessageType messageType)
|
void PvaClientPutGet::message(string const & message,MessageType messageType)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
pvaClientChannel->message(message,messageType);
|
||||||
PvaClientPtr yyy = pvaClient.lock();
|
|
||||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
|
||||||
yyy->message(message, messageType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::channelPutGetConnect(
|
void PvaClientPutGet::channelPutGetConnect(
|
||||||
@@ -113,17 +164,29 @@ void PvaClientPutGet::channelPutGetConnect(
|
|||||||
StructureConstPtr const & putStructure,
|
StructureConstPtr const & putStructure,
|
||||||
StructureConstPtr const & getStructure)
|
StructureConstPtr const & getStructure)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelPutGetConnectStatus = status;
|
cout << "PvaClientPutGet::channelPutGetConnect"
|
||||||
this->channelPutGet = channelPutGet;
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
if(status.isOK()) {
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
pvaClientPutData = PvaClientPutData::create(putStructure);
|
<< endl;
|
||||||
pvaClientPutData->setMessagePrefix(channel->getChannelName());
|
}
|
||||||
pvaClientGetData = PvaClientGetData::create(getStructure);
|
{
|
||||||
pvaClientGetData->setMessagePrefix(channel->getChannelName());
|
Lock xx(mutex);
|
||||||
|
channelPutGetConnectStatus = status;
|
||||||
|
if(status.isOK()) {
|
||||||
|
this->channelPutGet = channelPutGet;
|
||||||
|
connectState = connected;
|
||||||
|
pvaClientPutData = PvaClientPutData::create(putStructure);
|
||||||
|
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
|
||||||
|
pvaClientGetData = PvaClientGetData::create(getStructure);
|
||||||
|
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
|
||||||
|
}
|
||||||
|
waitForConnect.signal();
|
||||||
|
}
|
||||||
|
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->channelPutGetConnect(status,shared_from_this());
|
||||||
}
|
}
|
||||||
waitForConnect.signal();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::putGetDone(
|
void PvaClientPutGet::putGetDone(
|
||||||
@@ -132,12 +195,25 @@ void PvaClientPutGet::putGetDone(
|
|||||||
PVStructurePtr const & getPVStructure,
|
PVStructurePtr const & getPVStructure,
|
||||||
BitSetPtr const & getChangedBitSet)
|
BitSetPtr const & getChangedBitSet)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelPutGetStatus = status;
|
cout << "PvaClientPutGet::putGetDone"
|
||||||
if(status.isOK()) {
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
channelPutGetStatus = status;
|
||||||
|
if(status.isOK()) {
|
||||||
|
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
|
||||||
|
}
|
||||||
|
putGetState = putGetComplete;
|
||||||
|
waitForPutGet.signal();
|
||||||
|
}
|
||||||
|
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->putGetDone(status,shared_from_this());
|
||||||
}
|
}
|
||||||
waitForPutGet.signal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::getPutDone(
|
void PvaClientPutGet::getPutDone(
|
||||||
@@ -146,16 +222,29 @@ void PvaClientPutGet::getPutDone(
|
|||||||
PVStructurePtr const & putPVStructure,
|
PVStructurePtr const & putPVStructure,
|
||||||
BitSetPtr const & putBitSet)
|
BitSetPtr const & putBitSet)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelPutGetStatus = status;
|
cout << "PvaClientPutGet::getPutDone"
|
||||||
if(status.isOK()) {
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
PVStructurePtr pvs = pvaClientPutData->getPVStructure();
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
pvs->copyUnchecked(*putPVStructure,*putBitSet);
|
<< endl;
|
||||||
BitSetPtr bs = pvaClientPutData->getChangedBitSet();
|
}
|
||||||
bs->clear();
|
{
|
||||||
*bs |= *putBitSet;
|
Lock xx(mutex);
|
||||||
|
channelPutGetStatus = status;
|
||||||
|
if(status.isOK()) {
|
||||||
|
PVStructurePtr pvs = pvaClientPutData->getPVStructure();
|
||||||
|
pvs->copyUnchecked(*putPVStructure,*putBitSet);
|
||||||
|
BitSetPtr bs = pvaClientPutData->getChangedBitSet();
|
||||||
|
bs->clear();
|
||||||
|
*bs |= *putBitSet;
|
||||||
|
}
|
||||||
|
putGetState = putGetComplete;
|
||||||
|
waitForPutGet.signal();
|
||||||
|
}
|
||||||
|
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->getPutDone(status,shared_from_this());
|
||||||
}
|
}
|
||||||
waitForPutGet.signal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::getGetDone(
|
void PvaClientPutGet::getGetDone(
|
||||||
@@ -164,84 +253,103 @@ void PvaClientPutGet::getGetDone(
|
|||||||
PVStructurePtr const & getPVStructure,
|
PVStructurePtr const & getPVStructure,
|
||||||
BitSetPtr const & getChangedBitSet)
|
BitSetPtr const & getChangedBitSet)
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
channelPutGetStatus = status;
|
cout << "PvaClientPutGet::getGetDone"
|
||||||
if(status.isOK()) {
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
|
<< endl;
|
||||||
}
|
}
|
||||||
waitForPutGet.signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// from PvaClientPutGet
|
|
||||||
void PvaClientPutGet::destroy()
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
if(isDestroyed) return;
|
channelPutGetStatus = status;
|
||||||
isDestroyed = true;
|
if(status.isOK()) {
|
||||||
|
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
|
||||||
|
}
|
||||||
|
putGetState = putGetComplete;
|
||||||
|
waitForPutGet.signal();
|
||||||
|
}
|
||||||
|
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
|
||||||
|
if(req) {
|
||||||
|
req->getGetDone(status,shared_from_this());
|
||||||
}
|
}
|
||||||
if(channelPutGet) channelPutGet->destroy();
|
|
||||||
channelPutGet.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::connect()
|
void PvaClientPutGet::connect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::connect"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issueConnect();
|
issueConnect();
|
||||||
Status status = waitConnect();
|
Status status = waitConnect();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPutGet::connect " + status.getMessage();
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPutGet::connect "
|
||||||
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::issueConnect()
|
void PvaClientPutGet::issueConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::issueConnect"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState!=connectIdle) {
|
if(connectState!=connectIdle) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientPutGet already connected ";
|
+ " pvaClientPutGet already connected ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
putGetRequester = ChannelPutGetRequester::shared_pointer(new ChannelPutGetRequesterImpl(this));
|
|
||||||
connectState = connectActive;
|
connectState = connectActive;
|
||||||
channelPutGet = channel->createChannelPutGet(putGetRequester,pvRequest);
|
channelPutGetConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
|
||||||
|
channelPutGet = pvaClientChannel->getChannel()->createChannelPutGet(channelPutGetRequester,pvRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PvaClientPutGet::waitConnect()
|
Status PvaClientPutGet::waitConnect()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(connectState!=connectActive) {
|
cout << "PvaClientPutGet::waitConnect"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " pvaClientPutGet illegal connect state ";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForConnect.wait();
|
waitForConnect.wait();
|
||||||
connectState = channelPutGetConnectStatus.isOK() ? connected : connectIdle;
|
|
||||||
return channelPutGetConnectStatus;
|
return channelPutGetConnectStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PvaClientPutGet::putGet()
|
void PvaClientPutGet::putGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::putGet"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issuePutGet();
|
issuePutGet();
|
||||||
Status status = waitPutGet();
|
Status status = waitPutGet();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPutGet::putGet " + status.getMessage();
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPut::putGet "
|
||||||
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::issuePutGet()
|
void PvaClientPutGet::issuePutGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::issuePutGet"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState==connectIdle) connect();
|
if(connectState==connectIdle) connect();
|
||||||
if(putGetState!=putGetIdle) {
|
if(putGetState==putGetActive) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPutGet::issueGet get or put aleady active ";
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPutGet::issuePutGet get or put aleady active ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
putGetState = putGetActive;
|
putGetState = putGetActive;
|
||||||
@@ -251,35 +359,45 @@ void PvaClientPutGet::issuePutGet()
|
|||||||
|
|
||||||
Status PvaClientPutGet::waitPutGet()
|
Status PvaClientPutGet::waitPutGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(putGetState!=putGetActive){
|
cout << "PvaClientPutGet::waitPutGet"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientPutGet::waitPutGet llegal put state";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForPutGet.wait();
|
waitForPutGet.wait();
|
||||||
putGetState = putGetIdle;
|
if(channelPutGetStatus.isOK()) pvaClientPutData->getChangedBitSet()->clear();
|
||||||
return channelPutGetStatus;
|
return channelPutGetStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::getGet()
|
void PvaClientPutGet::getGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::getGet"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issueGetGet();
|
issueGetGet();
|
||||||
Status status = waitGetGet();
|
Status status = waitGetGet();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPutGet::getGet " + status.getMessage();
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPut::getGet "
|
||||||
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::issueGetGet()
|
void PvaClientPutGet::issueGetGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::issueGetGet"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState==connectIdle) connect();
|
if(connectState==connectIdle) connect();
|
||||||
if(putGetState!=putGetIdle) {
|
if(putGetState==putGetActive) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPutGet::issueGetGet aleady active ";
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPutGet::issueGetGet get or put aleady active ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
putGetState = putGetActive;
|
putGetState = putGetActive;
|
||||||
@@ -288,35 +406,44 @@ void PvaClientPutGet::issueGetGet()
|
|||||||
|
|
||||||
Status PvaClientPutGet::waitGetGet()
|
Status PvaClientPutGet::waitGetGet()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(putGetState!=putGetActive){
|
cout << "PvaClientPutGet::waitGetGet"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientPutGet::waitGetGet illegal state";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForPutGet.wait();
|
waitForPutGet.wait();
|
||||||
putGetState = putGetIdle;
|
|
||||||
return channelPutGetStatus;
|
return channelPutGetStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::getPut()
|
void PvaClientPutGet::getPut()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::getGetPut"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
issueGetPut();
|
issueGetPut();
|
||||||
Status status = waitGetPut();
|
Status status = waitGetPut();
|
||||||
if(status.isOK()) return;
|
if(status.isOK()) return;
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPutGet::getPut " + status.getMessage();
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPut::getPut "
|
||||||
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutGet::issueGetPut()
|
void PvaClientPutGet::issueGetPut()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientPutGet::issueGetPut"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
if(connectState==connectIdle) connect();
|
if(connectState==connectIdle) connect();
|
||||||
if(putGetState!=putGetIdle) {
|
if(putGetState==putGetActive) {
|
||||||
string message = string("channel ") + channel->getChannelName()
|
string message = string("channel ")
|
||||||
+ " PvaClientPutGet::issueGetPut aleady active ";
|
+ pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
+ " PvaClientPutGet::issueGetPut get or put aleady active ";
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
}
|
}
|
||||||
putGetState = putGetActive;
|
putGetState = putGetActive;
|
||||||
@@ -325,37 +452,59 @@ void PvaClientPutGet::issueGetPut()
|
|||||||
|
|
||||||
Status PvaClientPutGet::waitGetPut()
|
Status PvaClientPutGet::waitGetPut()
|
||||||
{
|
{
|
||||||
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
|
if(PvaClient::getDebug()) {
|
||||||
if(putGetState!=putGetActive){
|
cout << "PvaClientPutGet::waitGetPut"
|
||||||
string message = string("channel ") + channel->getChannelName()
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
+ " PvaClientPutGet::waitGetPut illegal state";
|
<< endl;
|
||||||
throw std::runtime_error(message);
|
|
||||||
}
|
}
|
||||||
waitForPutGet.wait();
|
waitForPutGet.wait();
|
||||||
putGetState = putGetIdle;
|
|
||||||
return channelPutGetStatus;
|
return channelPutGetStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientGetDataPtr PvaClientPutGet::getGetData()
|
PvaClientGetDataPtr PvaClientPutGet::getGetData()
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientPutGet::getGetData"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
checkPutGetState();
|
checkPutGetState();
|
||||||
|
if(putGetState==putGetIdle){
|
||||||
|
getGet();
|
||||||
|
getPut();
|
||||||
|
}
|
||||||
return pvaClientGetData;
|
return pvaClientGetData;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutDataPtr PvaClientPutGet::getPutData()
|
PvaClientPutDataPtr PvaClientPutGet::getPutData()
|
||||||
{
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientPutGet::getPutData"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
checkPutGetState();
|
checkPutGetState();
|
||||||
|
if(putGetState==putGetIdle){
|
||||||
|
getGet();
|
||||||
|
getPut();
|
||||||
|
}
|
||||||
return pvaClientPutData;
|
return pvaClientPutData;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientPutGetPtr PvaClientPutGet::create(
|
void PvaClientPutGet::setRequester(PvaClientPutGetRequesterPtr const & pvaClientPutGetRequester)
|
||||||
PvaClientPtr const &pvaClient,
|
|
||||||
Channel::shared_pointer const & channel,
|
|
||||||
PVStructurePtr const &pvRequest)
|
|
||||||
{
|
{
|
||||||
PvaClientPutGetPtr epv(new PvaClientPutGet(pvaClient,channel,pvRequest));
|
if(PvaClient::getDebug()) {
|
||||||
return epv;
|
cout << "PvaClientPutGet::setRequester"
|
||||||
|
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
this->pvaClientPutGetRequester = pvaClientPutGetRequester;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PvaClientChannelPtr PvaClientPutGet::getPvaClientChannel()
|
||||||
|
{
|
||||||
|
return pvaClientChannel;
|
||||||
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -0,0 +1,352 @@
|
|||||||
|
/* pvaClientRPC.cpp */
|
||||||
|
/**
|
||||||
|
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||||
|
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||||
|
* in file LICENSE that is included with this distribution.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @author mrk
|
||||||
|
* @date 2015.03
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <pv/event.h>
|
||||||
|
#include <pv/bitSetUtil.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
|
#include <pv/pvaClient.h>
|
||||||
|
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace epics { namespace pvaClient {
|
||||||
|
|
||||||
|
class RPCRequesterImpl : public ChannelRPCRequester
|
||||||
|
{
|
||||||
|
PvaClientRPC::weak_pointer pvaClientRPC;
|
||||||
|
PvaClient::weak_pointer pvaClient;
|
||||||
|
public:
|
||||||
|
RPCRequesterImpl(
|
||||||
|
PvaClientRPCPtr const & pvaClientRPC,
|
||||||
|
PvaClientPtr const &pvaClient)
|
||||||
|
: pvaClientRPC(pvaClientRPC),
|
||||||
|
pvaClient(pvaClient)
|
||||||
|
{}
|
||||||
|
virtual ~RPCRequesterImpl() {
|
||||||
|
if(PvaClient::getDebug()) std::cout << "~RPCRequesterImpl" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string getRequesterName() {
|
||||||
|
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
|
||||||
|
if(!clientRPC) return string("pvaClientRPC is null");
|
||||||
|
return clientRPC->getRequesterName();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void message(std::string const & message, MessageType messageType) {
|
||||||
|
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
|
||||||
|
if(!clientRPC) return;
|
||||||
|
clientRPC->message(message,messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void channelRPCConnect(
|
||||||
|
const Status& status,
|
||||||
|
ChannelRPC::shared_pointer const & channelRPC)
|
||||||
|
{
|
||||||
|
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
|
||||||
|
if(!clientRPC) return;
|
||||||
|
clientRPC->rpcConnect(status,channelRPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void requestDone(
|
||||||
|
const Status& status,
|
||||||
|
ChannelRPC::shared_pointer const & channelRPC,
|
||||||
|
PVStructure::shared_pointer const & pvResponse)
|
||||||
|
{
|
||||||
|
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
|
||||||
|
if(!clientRPC) return;
|
||||||
|
clientRPC->requestDone(status,channelRPC,pvResponse);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PvaClientRPCPtr PvaClientRPC::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
Channel::shared_pointer const & channel)
|
||||||
|
{
|
||||||
|
StructureConstPtr structure(getFieldCreate()->createStructure());
|
||||||
|
PVStructurePtr pvRequest(getPVDataCreate()->createPVStructure(structure));
|
||||||
|
return create(pvaClient,channel,pvRequest);
|
||||||
|
}
|
||||||
|
PvaClientRPCPtr PvaClientRPC::create(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
Channel::shared_pointer const & channel,
|
||||||
|
PVStructurePtr const &pvRequest)
|
||||||
|
{
|
||||||
|
PvaClientRPCPtr epv(new PvaClientRPC(pvaClient,channel,pvRequest));
|
||||||
|
epv->rpcRequester = RPCRequesterImplPtr(
|
||||||
|
new RPCRequesterImpl(epv,pvaClient));
|
||||||
|
return epv;
|
||||||
|
}
|
||||||
|
|
||||||
|
PvaClientRPC::PvaClientRPC(
|
||||||
|
PvaClientPtr const &pvaClient,
|
||||||
|
Channel::shared_pointer const & channel,
|
||||||
|
PVStructurePtr const &pvRequest)
|
||||||
|
:
|
||||||
|
connectState(connectIdle),
|
||||||
|
pvaClient(pvaClient),
|
||||||
|
channel(channel),
|
||||||
|
pvRequest(pvRequest),
|
||||||
|
rpcState(rpcIdle),
|
||||||
|
responseTimeout(0.0)
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout<< "PvaClientRPC::PvaClientRPC()"
|
||||||
|
<< " channelName " << channel->getChannelName()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PvaClientRPC::~PvaClientRPC()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
string channelName("disconnected");
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
cout<< "PvaClientRPC::~PvaClientRPC"
|
||||||
|
<< " channelName " << channelName
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientRPC::checkRPCState()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
string channelName("disconnected");
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
cout << "PvaClientRPC::checkRPCState"
|
||||||
|
<< " channelName " << channelName
|
||||||
|
<< " connectState " << connectState
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(connectState==connectIdle) connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
string PvaClientRPC::getRequesterName()
|
||||||
|
{
|
||||||
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
|
if(!yyy) return string("PvaClientRPC::getRequesterName() PvaClient isDestroyed");
|
||||||
|
return yyy->getRequesterName();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientRPC::message(string const & message,MessageType messageType)
|
||||||
|
{
|
||||||
|
PvaClientPtr yyy = pvaClient.lock();
|
||||||
|
if(!yyy) return;
|
||||||
|
yyy->message(message, messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientRPC::rpcConnect(
|
||||||
|
const Status& status,
|
||||||
|
ChannelRPC::shared_pointer const & channelRPC)
|
||||||
|
{
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
string channelName("disconnected");
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
cout << "PvaClientRPC::rpcConnect"
|
||||||
|
<< " channelName " << channelName
|
||||||
|
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(!chan) return;
|
||||||
|
connectStatus = status;
|
||||||
|
connectState = connected;
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientRPC::rpcConnect calling waitForConnect.signal\n";
|
||||||
|
}
|
||||||
|
waitForConnect.signal();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientRPC::requestDone(
|
||||||
|
const Status& status,
|
||||||
|
ChannelRPC::shared_pointer const & channelRPC,
|
||||||
|
PVStructure::shared_pointer const & pvResponse)
|
||||||
|
{
|
||||||
|
PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock();
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
requestStatus = status;
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
string channelName("disconnected");
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
cout << "PvaClientRPC::requestDone"
|
||||||
|
<< " channelName " << channelName
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
if(rpcState!=rpcActive) {
|
||||||
|
string channelName("disconnected");
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
string message = "channel "
|
||||||
|
+ channelName
|
||||||
|
+" PvaClientRPC::requestDone"
|
||||||
|
+ " but not active";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
if(req && (responseTimeout<=0.0)) {
|
||||||
|
rpcState = rpcIdle;
|
||||||
|
} else {
|
||||||
|
rpcState = rpcComplete;
|
||||||
|
if(!req) this->pvResponse = pvResponse;
|
||||||
|
waitForDone.signal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(req) {
|
||||||
|
req->requestDone(status,shared_from_this(),pvResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientRPC::connect()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientRPC::connect\n";
|
||||||
|
issueConnect();
|
||||||
|
Status status = waitConnect();
|
||||||
|
if(status.isOK()) return;
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
string channelName("disconnected");
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
string message = string("channel ")
|
||||||
|
+ channelName
|
||||||
|
+ " PvaClientRPC::connect "
|
||||||
|
+ status.getMessage();
|
||||||
|
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PvaClientRPC::issueConnect()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientRPC::issueConnect\n";
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
if(connectState!=connectIdle) {
|
||||||
|
string channelName("disconnected");
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
string message = string("channel ")
|
||||||
|
+ channelName
|
||||||
|
+ " pvaClientRPC already connected ";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
if(chan) {
|
||||||
|
connectState = connectActive;
|
||||||
|
channelRPC = chan->createChannelRPC(rpcRequester,pvRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("PvaClientRPC::issueConnect() but channel disconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
Status PvaClientRPC::waitConnect()
|
||||||
|
{
|
||||||
|
if(PvaClient::getDebug()) cout << "PvaClientRPC::waitConnect\n";
|
||||||
|
if(connectState==connected) {
|
||||||
|
if(!connectStatus.isOK()) connectState = connectIdle;
|
||||||
|
return connectStatus;
|
||||||
|
}
|
||||||
|
if(connectState!=connectActive) {
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
string channelName("disconnected");
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
string message = string("channel ")
|
||||||
|
+ channelName
|
||||||
|
+ " PvaClientRPC::waitConnect illegal connect state ";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientRPC::waitConnect calling waitForConnect.wait\n";
|
||||||
|
}
|
||||||
|
waitForConnect.wait();
|
||||||
|
connectState = connectStatus.isOK() ? connected : connectIdle;
|
||||||
|
if(PvaClient::getDebug()) {
|
||||||
|
cout << "PvaClientRPC::waitConnect"
|
||||||
|
<< " connectStatus " << (connectStatus.isOK() ? "connected" : "not connected");
|
||||||
|
}
|
||||||
|
return connectStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVStructure::shared_pointer PvaClientRPC::request(PVStructure::shared_pointer const & pvArgument)
|
||||||
|
{
|
||||||
|
checkRPCState();
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
if(rpcState!=rpcIdle) {
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
string channelName("disconnected");
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
string message = "channel "
|
||||||
|
+ channelName
|
||||||
|
+ " PvaClientRPC::request request aleady active ";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
rpcState = rpcActive;
|
||||||
|
}
|
||||||
|
channelRPC->request(pvArgument);
|
||||||
|
if(responseTimeout>0.0) {
|
||||||
|
waitForDone.wait(responseTimeout);
|
||||||
|
} else {
|
||||||
|
waitForDone.wait();
|
||||||
|
}
|
||||||
|
Lock xx(mutex);
|
||||||
|
if(rpcState!=rpcComplete) {
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
string channelName("disconnected");
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
string message = "channel "
|
||||||
|
+ channelName
|
||||||
|
+ " PvaClientRPC::request request timeout ";
|
||||||
|
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
|
||||||
|
}
|
||||||
|
rpcState = rpcIdle;
|
||||||
|
if(requestStatus.isOK()) return pvResponse;
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
string channelName("disconnected");
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
string message = "channel "
|
||||||
|
+ channelName
|
||||||
|
+ " PvaClientRPC::request status ";
|
||||||
|
message += requestStatus.getMessage();
|
||||||
|
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PvaClientRPC::request(
|
||||||
|
PVStructure::shared_pointer const & pvArgument,
|
||||||
|
PvaClientRPCRequesterPtr const & pvaClientRPCRequester)
|
||||||
|
{
|
||||||
|
checkRPCState();
|
||||||
|
this->pvaClientRPCRequester = pvaClientRPCRequester;
|
||||||
|
if(responseTimeout<=0.0) {
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
if(rpcState!=rpcIdle) {
|
||||||
|
Channel::shared_pointer chan(channel.lock());
|
||||||
|
string channelName("disconnected");
|
||||||
|
if(chan) channelName = chan->getChannelName();
|
||||||
|
string message = "channel "
|
||||||
|
+ channelName
|
||||||
|
+ " PvaClientRPC::request request aleady active ";
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
|
rpcState = rpcActive;
|
||||||
|
}
|
||||||
|
channelRPC->request(pvArgument);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
request(pvArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
Reference in New Issue
Block a user